Merge pull request #55 from proxikal/fix/perf-regression-agent-configs-and-search-stat
fix: resolve performance regression in transcript loading and session search
This commit is contained in:
commit
94a6599acc
2 changed files with 31 additions and 14 deletions
|
|
@ -43,11 +43,25 @@ export class LocalFileSystemProvider implements FileSystemProvider {
|
||||||
|
|
||||||
async readdir(dirPath: string): Promise<FsDirent[]> {
|
async readdir(dirPath: string): Promise<FsDirent[]> {
|
||||||
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
|
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
|
||||||
return entries.map((entry) => ({
|
// Stat all entries concurrently to populate mtimeMs, used by SessionSearcher's
|
||||||
name: entry.name,
|
// mtime-based cache invalidation. Failures are silently ignored (mtimeMs stays undefined).
|
||||||
isFile: () => entry.isFile(),
|
return Promise.all(
|
||||||
isDirectory: () => entry.isDirectory(),
|
entries.map(async (entry) => {
|
||||||
}));
|
let mtimeMs: number | undefined;
|
||||||
|
try {
|
||||||
|
const stat = await fs.promises.stat(`${dirPath}/${entry.name}`);
|
||||||
|
mtimeMs = stat.mtimeMs;
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: entry.name,
|
||||||
|
mtimeMs,
|
||||||
|
isFile: () => entry.isFile(),
|
||||||
|
isDirectory: () => entry.isDirectory(),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
createReadStream(filePath: string, opts?: ReadStreamOptions): fs.ReadStream {
|
createReadStream(filePath: string, opts?: ReadStreamOptions): fs.ReadStream {
|
||||||
|
|
|
||||||
|
|
@ -197,16 +197,19 @@ export const createSessionDetailSlice: StateCreator<AppState, [], [], SessionDet
|
||||||
let claudeMdStats: Map<string, ClaudeMdStats> | null = null;
|
let claudeMdStats: Map<string, ClaudeMdStats> | null = null;
|
||||||
let contextStats: Map<string, ContextStats> | null = null;
|
let contextStats: Map<string, ContextStats> | null = null;
|
||||||
let phaseInfo: ContextPhaseInfo | null = null;
|
let phaseInfo: ContextPhaseInfo | null = null;
|
||||||
// Fetch agent configs from .claude/agents/ (only when project changes)
|
// Fetch agent configs from .claude/agents/ (only when project changes).
|
||||||
|
// Fire-and-forget: don't block transcript rendering — color badges update async.
|
||||||
if (connectionMode !== 'ssh' && projectRoot && projectRoot !== agentConfigsCachedForProject) {
|
if (connectionMode !== 'ssh' && projectRoot && projectRoot !== agentConfigsCachedForProject) {
|
||||||
try {
|
agentConfigsCachedForProject = projectRoot; // Optimistic set to prevent duplicate fetches
|
||||||
const configs = await api.readAgentConfigs(projectRoot);
|
api
|
||||||
if (requestGeneration !== sessionDetailFetchGeneration) return;
|
.readAgentConfigs(projectRoot)
|
||||||
agentConfigsCachedForProject = projectRoot;
|
.then((configs) => {
|
||||||
set({ agentConfigs: configs });
|
set({ agentConfigs: configs });
|
||||||
} catch (err) {
|
})
|
||||||
logger.error('Failed to read agent configs:', err);
|
.catch((err) => {
|
||||||
}
|
logger.error('Failed to read agent configs:', err);
|
||||||
|
agentConfigsCachedForProject = ''; // Reset so it retries next time
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionMode !== 'ssh' && conversation?.items) {
|
if (connectionMode !== 'ssh' && conversation?.items) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue