From d60ac099250fca5c892e88124a700035112837eb Mon Sep 17 00:00:00 2001 From: iliya Date: Mon, 23 Feb 2026 15:12:39 +0200 Subject: [PATCH] feat: enhance project directory resolution and auto-refresh in MemberLogsTab - Updated `TeamMemberLogsFinder` to improve project directory resolution by falling back to `leadSessionId` if the encoded directory does not exist, enhancing reliability in locating project logs. - Refactored `MemberLogsTab` to implement an initial loading state and auto-refresh functionality for ongoing tasks, improving user experience during log retrieval. - Adjusted error handling and loading indicators to provide clearer feedback based on task status. --- .../services/team/TeamMemberLogsFinder.ts | 42 +++++++++++++++++-- .../components/team/members/MemberLogsTab.tsx | 25 ++++++++--- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/main/services/team/TeamMemberLogsFinder.ts b/src/main/services/team/TeamMemberLogsFinder.ts index d6c1251e..41802284 100644 --- a/src/main/services/team/TeamMemberLogsFinder.ts +++ b/src/main/services/team/TeamMemberLogsFinder.ts @@ -257,9 +257,45 @@ export class TeamMemberLogsFinder { } const normalizedProjectPath = trimTrailingSlashes(config.projectPath); - const projectId = encodePath(normalizedProjectPath); - const baseDir = extractBaseDir(projectId); - const projectDir = path.join(getProjectsBasePath(), baseDir); + let projectId = encodePath(normalizedProjectPath); + let baseDir = extractBaseDir(projectId); + let projectDir = path.join(getProjectsBasePath(), baseDir); + + // If the encoded directory doesn't exist (symlink/cwd mismatch), fall back to locating + // the project directory by leadSessionId which is unique and reliable. + try { + const stat = await fs.stat(projectDir); + if (!stat.isDirectory()) { + throw new Error('not a directory'); + } + } catch { + const leadSessionId = + typeof config.leadSessionId === 'string' && config.leadSessionId.trim().length > 0 + ? config.leadSessionId.trim() + : null; + if (leadSessionId) { + const projectsBase = getProjectsBasePath(); + try { + const entries = await fs.readdir(projectsBase, { withFileTypes: true }); + for (const entry of entries) { + if (!entry.isDirectory()) continue; + const candidateDir = path.join(projectsBase, entry.name); + const leadPath = path.join(candidateDir, `${leadSessionId}.jsonl`); + try { + await fs.access(leadPath); + projectDir = candidateDir; + projectId = entry.name; + baseDir = entry.name; + break; + } catch { + // not this project + } + } + } catch { + // ignore + } + } + } const knownSessionIds = new Set(); if (config.leadSessionId) { diff --git a/src/renderer/components/team/members/MemberLogsTab.tsx b/src/renderer/components/team/members/MemberLogsTab.tsx index dedd8e15..a9c5725e 100644 --- a/src/renderer/components/team/members/MemberLogsTab.tsx +++ b/src/renderer/components/team/members/MemberLogsTab.tsx @@ -41,15 +41,20 @@ export const MemberLogsTab = ({ useEffect(() => { let cancelled = false; - setLoading(true); - setError(null); + let isInitial = true; + const shouldAutoRefresh = taskId != null && taskStatus === 'in_progress'; - void (async () => { + const load = async (): Promise => { try { if (taskId == null && !memberName) { if (!cancelled) setLogs([]); return; } + if (isInitial) { + setLoading(true); + } + setError(null); + const result = taskId != null ? await api.teams.getLogsForTask(teamName, taskId, { @@ -65,14 +70,20 @@ export const MemberLogsTab = ({ setError(e instanceof Error ? e.message : 'Unknown error'); } } finally { - if (!cancelled) { + if (!cancelled && isInitial) { setLoading(false); } + isInitial = false; } - })(); + }; + + void load(); + + const interval = shouldAutoRefresh ? setInterval(() => void load(), 5000) : null; return () => { cancelled = true; + if (interval) clearInterval(interval); }; }, [teamName, memberName, taskId, taskOwner, taskStatus]); @@ -133,7 +144,9 @@ export const MemberLogsTab = ({ No logs found

{taskId != null - ? 'No session activity for this task yet' + ? taskStatus === 'in_progress' + ? 'Task is in progress — waiting for session activity (auto-refreshing)...' + : 'No session activity for this task yet' : 'This member has no recorded session activity yet'}