Fix/websocket streaming issues (#748)

This commit is contained in:
Haile
2026-05-08 22:51:03 +03:00
committed by GitHub
parent beb0a50413
commit 039696c2de
47 changed files with 2194 additions and 369 deletions

View File

@@ -42,7 +42,7 @@ async function unlinkJsonlIfExists(filePath: string): Promise<void> {
* Loads all session rows for the project path and removes each distinct `jsonl_path` file on disk.
*/
export async function deleteSessionJsonlFilesForProjectPath(projectPath: string): Promise<void> {
const sessions = sessionsDb.getSessionsByProjectPath(projectPath);
const sessions = sessionsDb.getSessionsByProjectPathIncludingArchived(projectPath);
const paths = uniqueJsonlPathsFromSessions(sessions);
for (const filePath of paths) {
@@ -73,3 +73,18 @@ export async function deleteOrArchiveProject(projectId: string, force: boolean):
sessionsDb.deleteSessionsByProjectPath(row.project_path);
projectsDb.deleteProjectById(projectId);
}
/**
* Restores one archived project row back into the active project list.
*/
export function restoreArchivedProject(projectId: string): void {
const row = projectsDb.getProjectById(projectId);
if (!row) {
throw new AppError(`Unknown projectId: ${projectId}`, {
code: 'PROJECT_NOT_FOUND',
statusCode: 404,
});
}
projectsDb.updateProjectIsArchivedById(projectId, false);
}

View File

@@ -40,6 +40,10 @@ export type ProjectListItem = {
};
};
export type ArchivedProjectListItem = ProjectListItem & {
isArchived: true;
};
type ProgressUpdate = {
phase: 'loading' | 'complete';
current: number;
@@ -150,6 +154,16 @@ function bucketSessionRowsByProvider(rows: SessionRepositoryRow[]): SessionsByPr
return byProvider;
}
function readProjectSessionsIncludingArchived(projectPath: string): ProjectSessionsPageResult {
const rows = sessionsDb.getSessionsByProjectPathIncludingArchived(projectPath) as SessionRepositoryRow[];
return {
sessionsByProvider: bucketSessionRowsByProvider(rows),
total: rows.length,
hasMore: false,
};
}
/**
* Reads one paginated project session slice from the DB and groups rows by provider.
*/
@@ -255,6 +269,56 @@ export async function getProjectsWithSessions(
return projects;
}
/**
* Reads archived projects from DB and includes every session row for each
* project path, because an archived workspace should surface all preserved
* conversation history in the archive view regardless of each session's flag.
*/
export async function getArchivedProjectsWithSessions(
options: Pick<GetProjectsWithSessionsOptions, 'skipSynchronization'> = {},
): Promise<ArchivedProjectListItem[]> {
if (!options.skipSynchronization) {
await sessionSynchronizerService.synchronizeSessions();
}
const projectRows = projectsDb.getArchivedProjectPaths() as Array<{
project_id: string;
project_path: string;
custom_project_name?: string | null;
isStarred?: number;
}>;
const archivedProjects: ArchivedProjectListItem[] = [];
for (const row of projectRows) {
const displayName =
row.custom_project_name && row.custom_project_name.trim().length > 0
? row.custom_project_name
: await generateDisplayName(path.basename(row.project_path) || row.project_path, row.project_path);
const sessionsPage = readProjectSessionsIncludingArchived(row.project_path);
archivedProjects.push({
projectId: row.project_id,
path: row.project_path,
displayName,
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,
sessionMeta: {
hasMore: sessionsPage.hasMore,
total: sessionsPage.total,
},
});
}
return archivedProjects;
}
/**
* Loads one paginated session slice for a specific project id.
*/