From 1720b3e398dec1a49252ca151971bbae5cca65ec Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Fri, 30 Jan 2026 16:04:06 +0100 Subject: [PATCH] Readd file viewer link again --- src/extension.ts | 102 +++++++++++++++++++++++----------- src/webview/logviewer/main.ts | 42 ++++++++++++++ 2 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 229ae1c..a16643f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2111,8 +2111,12 @@ class CopilotTokenTracker implements vscode.Disposable { const foundPaths: string[] = []; for (let i = 0; i < allVSCodePaths.length; i++) { const codeUserPath = allVSCodePaths[i]; - if (fs.existsSync(codeUserPath)) { - foundPaths.push(codeUserPath); + try { + if (fs.existsSync(codeUserPath)) { + foundPaths.push(codeUserPath); + } + } catch (checkError) { + this.warn(`Could not check path ${codeUserPath}: ${checkError}`); } // Update progress if ((i + 1) % 5 === 0 || i === allVSCodePaths.length - 1) { @@ -2130,53 +2134,89 @@ class CopilotTokenTracker implements vscode.Disposable { // Workspace storage sessions const workspaceStoragePath = path.join(codeUserPath, 'workspaceStorage'); - if (fs.existsSync(workspaceStoragePath)) { - const workspaceDirs = fs.readdirSync(workspaceStoragePath); - - for (const workspaceDir of workspaceDirs) { - const chatSessionsPath = path.join(workspaceStoragePath, workspaceDir, 'chatSessions'); - if (fs.existsSync(chatSessionsPath)) { - const sessionFiles2 = fs.readdirSync(chatSessionsPath) - .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) - .map(file => path.join(chatSessionsPath, file)); - if (sessionFiles2.length > 0) { - this.log(`๐Ÿ“„ Found ${sessionFiles2.length} session files in ${pathName}/workspaceStorage/${workspaceDir}`); - sessionFiles.push(...sessionFiles2); + try { + if (fs.existsSync(workspaceStoragePath)) { + try { + const workspaceDirs = fs.readdirSync(workspaceStoragePath); + + for (const workspaceDir of workspaceDirs) { + const chatSessionsPath = path.join(workspaceStoragePath, workspaceDir, 'chatSessions'); + try { + if (fs.existsSync(chatSessionsPath)) { + try { + const sessionFiles2 = fs.readdirSync(chatSessionsPath) + .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) + .map(file => path.join(chatSessionsPath, file)); + if (sessionFiles2.length > 0) { + this.log(`๐Ÿ“„ Found ${sessionFiles2.length} session files in ${pathName}/workspaceStorage/${workspaceDir}`); + sessionFiles.push(...sessionFiles2); + } + } catch (readError) { + this.warn(`Could not read chat sessions in ${chatSessionsPath}: ${readError}`); + } + } + } catch (checkError) { + this.warn(`Could not check chat sessions path ${chatSessionsPath}: ${checkError}`); + } } + } catch (readError) { + this.warn(`Could not read workspace storage in ${workspaceStoragePath}: ${readError}`); } } + } catch (checkError) { + this.warn(`Could not check workspace storage path ${workspaceStoragePath}: ${checkError}`); } // Global storage sessions (legacy emptyWindowChatSessions) const globalStoragePath = path.join(codeUserPath, 'globalStorage', 'emptyWindowChatSessions'); - if (fs.existsSync(globalStoragePath)) { - const globalSessionFiles = fs.readdirSync(globalStoragePath) - .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) - .map(file => path.join(globalStoragePath, file)); - if (globalSessionFiles.length > 0) { - this.log(`๐Ÿ“„ Found ${globalSessionFiles.length} session files in ${pathName}/globalStorage/emptyWindowChatSessions`); - sessionFiles.push(...globalSessionFiles); + try { + if (fs.existsSync(globalStoragePath)) { + try { + const globalSessionFiles = fs.readdirSync(globalStoragePath) + .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) + .map(file => path.join(globalStoragePath, file)); + if (globalSessionFiles.length > 0) { + this.log(`๐Ÿ“„ Found ${globalSessionFiles.length} session files in ${pathName}/globalStorage/emptyWindowChatSessions`); + sessionFiles.push(...globalSessionFiles); + } + } catch (readError) { + this.warn(`Could not read global storage in ${globalStoragePath}: ${readError}`); + } } + } catch (checkError) { + this.warn(`Could not check global storage path ${globalStoragePath}: ${checkError}`); } // GitHub Copilot Chat extension global storage const copilotChatGlobalPath = path.join(codeUserPath, 'globalStorage', 'github.copilot-chat'); - if (fs.existsSync(copilotChatGlobalPath)) { - this.log(`๐Ÿ“„ Scanning ${pathName}/globalStorage/github.copilot-chat`); - this.scanDirectoryForSessionFiles(copilotChatGlobalPath, sessionFiles); + try { + if (fs.existsSync(copilotChatGlobalPath)) { + this.log(`๐Ÿ“„ Scanning ${pathName}/globalStorage/github.copilot-chat`); + this.scanDirectoryForSessionFiles(copilotChatGlobalPath, sessionFiles); + } + } catch (checkError) { + this.warn(`Could not check Copilot Chat global storage path ${copilotChatGlobalPath}: ${checkError}`); } } // Check for Copilot CLI session-state directory (new location for agent mode sessions) const copilotCliSessionPath = path.join(os.homedir(), '.copilot', 'session-state'); - if (fs.existsSync(copilotCliSessionPath)) { - const cliSessionFiles = fs.readdirSync(copilotCliSessionPath) - .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) - .map(file => path.join(copilotCliSessionPath, file)); - if (cliSessionFiles.length > 0) { - this.log(`๐Ÿ“„ Found ${cliSessionFiles.length} session files in Copilot CLI directory`); - sessionFiles.push(...cliSessionFiles); + try { + if (fs.existsSync(copilotCliSessionPath)) { + try { + const cliSessionFiles = fs.readdirSync(copilotCliSessionPath) + .filter(file => file.endsWith('.json') || file.endsWith('.jsonl')) + .map(file => path.join(copilotCliSessionPath, file)); + if (cliSessionFiles.length > 0) { + this.log(`๐Ÿ“„ Found ${cliSessionFiles.length} session files in Copilot CLI directory`); + sessionFiles.push(...cliSessionFiles); + } + } catch (readError) { + this.warn(`Could not read Copilot CLI session path in ${copilotCliSessionPath}: ${readError}`); + } } + } catch (checkError) { + this.warn(`Could not check Copilot CLI session path ${copilotCliSessionPath}: ${checkError}`); } // Log summary diff --git a/src/webview/logviewer/main.ts b/src/webview/logviewer/main.ts index f1e5f17..d3101db 100644 --- a/src/webview/logviewer/main.ts +++ b/src/webview/logviewer/main.ts @@ -357,6 +357,15 @@ function renderLayout(data: SessionLogData): void { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.2); } + .filename-link { + cursor: pointer; + color: #60a5fa; + text-decoration: underline; + transition: color 0.2s; + } + .filename-link:hover { + color: #93c5fd; + } .summary-label { font-size: 14px; color: #b8b8c0; @@ -678,6 +687,36 @@ function renderLayout(data: SessionLogData): void {
${usageContextTotal}
#file ${usageContextRefs.file || 0} ยท @vscode ${usageContextRefs.vscode || 0} ยท @workspace ${usageContextRefs.workspace || 0}
+
+
๐Ÿ“ File Name
+
${escapeHtml(getFileName(data.file))}
+
Click to open in editor
+
+
+
๐Ÿ’ป Editor
+
${escapeHtml(data.editorName)}
+
Source editor
+
+
+
๐Ÿ“ฆ File Size
+
${formatFileSize(data.size)}
+
Total size on disk
+
+
+
๐Ÿ•’ Modified
+
${formatDate(data.modified)}
+
Last file modification
+
+
+
โ–ถ๏ธ First Interaction
+
${formatDate(data.firstInteraction)}
+
Session started
+
+
+
โน๏ธ Last Interaction
+
${formatDate(data.lastInteraction)}
+
Most recent activity
+
@@ -713,6 +752,9 @@ function renderLayout(data: SessionLogData): void { e.preventDefault(); vscode.postMessage({ command: 'openRawFile' }); }); + document.getElementById('open-file-link')?.addEventListener('click', () => { + vscode.postMessage({ command: 'openRawFile' }); + }); // Wire tool call clicks after DOM render so listeners bind correctly document.querySelectorAll('.tool-call-link').forEach(link => {