( limit?: number, )
| 4199 | } |
| 4200 | |
| 4201 | async function loadAllProjectsMessageLogsFull( |
| 4202 | limit?: number, |
| 4203 | ): Promise<LogOption[]> { |
| 4204 | const projectsDir = getProjectsDir() |
| 4205 | |
| 4206 | let dirents: Dirent[] |
| 4207 | try { |
| 4208 | dirents = await readdir(projectsDir, { withFileTypes: true }) |
| 4209 | } catch { |
| 4210 | return [] |
| 4211 | } |
| 4212 | |
| 4213 | const projectDirs = dirents |
| 4214 | .filter(dirent => dirent.isDirectory()) |
| 4215 | .map(dirent => join(projectsDir, dirent.name)) |
| 4216 | |
| 4217 | const logsPerProject = await Promise.all( |
| 4218 | projectDirs.map(projectDir => getLogsWithoutIndex(projectDir, limit)), |
| 4219 | ) |
| 4220 | const allLogs = logsPerProject.flat() |
| 4221 | |
| 4222 | // Deduplicate — same session+leaf can appear in multiple project dirs. |
| 4223 | // This path creates one LogOption per leaf, so use sessionId+leafUuid key. |
| 4224 | const deduped = new Map<string, LogOption>() |
| 4225 | for (const log of allLogs) { |
| 4226 | const key = `${log.sessionId ?? ''}:${log.leafUuid ?? ''}` |
| 4227 | const existing = deduped.get(key) |
| 4228 | if (!existing || log.modified.getTime() > existing.modified.getTime()) { |
| 4229 | deduped.set(key, log) |
| 4230 | } |
| 4231 | } |
| 4232 | |
| 4233 | // deduped values are fresh from getLogsWithoutIndex — safe to mutate |
| 4234 | const sorted = sortLogs([...deduped.values()]) |
| 4235 | sorted.forEach((log, i) => { |
| 4236 | log.value = i |
| 4237 | }) |
| 4238 | return sorted |
| 4239 | } |
| 4240 | |
| 4241 | export async function loadAllProjectsMessageLogsProgressive( |
| 4242 | limit?: number, |
no test coverage detected