@qiaolei81/copilot-session-viewer 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/parsers/index.js +2 -2
- package/package.json +1 -1
- package/src/app.js +3 -0
- package/src/controllers/sessionController.js +3 -17
- package/src/controllers/uploadController.js +1 -1
- package/src/services/sessionRepository.js +12 -13
- package/src/services/sessionService.js +18 -21
- package/views/session-vue.ejs +9 -0
package/lib/parsers/index.js
CHANGED
|
@@ -2,7 +2,7 @@ const BaseSessionParser = require('./base-parser');
|
|
|
2
2
|
const CopilotSessionParser = require('./copilot-parser');
|
|
3
3
|
const ClaudeSessionParser = require('./claude-parser');
|
|
4
4
|
const PiMonoParser = require('./pi-mono-parser');
|
|
5
|
-
const VsCodeParser = require('./vscode-parser');
|
|
5
|
+
// const VsCodeParser = require('./vscode-parser'); // TODO: VSCode parser disabled
|
|
6
6
|
const ParserFactory = require('./parser-factory');
|
|
7
7
|
|
|
8
8
|
module.exports = {
|
|
@@ -10,6 +10,6 @@ module.exports = {
|
|
|
10
10
|
CopilotSessionParser,
|
|
11
11
|
ClaudeSessionParser,
|
|
12
12
|
PiMonoParser,
|
|
13
|
-
VsCodeParser,
|
|
13
|
+
// VsCodeParser, // TODO: VSCode parser disabled
|
|
14
14
|
ParserFactory
|
|
15
15
|
};
|
package/package.json
CHANGED
package/src/app.js
CHANGED
|
@@ -19,6 +19,9 @@ const UploadController = require('./controllers/uploadController');
|
|
|
19
19
|
function createApp(options = {}) {
|
|
20
20
|
const app = express();
|
|
21
21
|
|
|
22
|
+
// Disable Express's automatic ETag generation (prevents 304 on live/active session files)
|
|
23
|
+
app.set('etag', false);
|
|
24
|
+
|
|
22
25
|
// Create controller instances (with optional dependency injection)
|
|
23
26
|
const sessionController = new SessionController(options.sessionService);
|
|
24
27
|
const insightController = new InsightController(options.insightService, options.sessionService);
|
|
@@ -162,25 +162,12 @@ class SessionController {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
// Get session
|
|
165
|
+
// Get session (needed for findById, no caching)
|
|
166
166
|
const session = await this.sessionService.sessionRepository.findById(sessionId);
|
|
167
167
|
if (!session) {
|
|
168
168
|
return res.status(404).json({ error: 'Session not found' });
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
// Generate ETag from session ID + timestamp + pagination params (if used)
|
|
172
|
-
const crypto = require('crypto');
|
|
173
|
-
const etagBase = isPaginationRequested
|
|
174
|
-
? `${sessionId}-${session.updatedAt || session.createdAt}-${limit}-${offset}`
|
|
175
|
-
: `${sessionId}-${session.updatedAt || session.createdAt}`;
|
|
176
|
-
const etag = crypto.createHash('md5').update(etagBase).digest('hex');
|
|
177
|
-
|
|
178
|
-
// Check If-None-Match header (client cache)
|
|
179
|
-
const clientEtag = req.headers['if-none-match'];
|
|
180
|
-
if (clientEtag === etag) {
|
|
181
|
-
return res.status(304).end(); // Not Modified - use cached version
|
|
182
|
-
}
|
|
183
|
-
|
|
184
171
|
// Load events (with or without pagination)
|
|
185
172
|
if (isPaginationRequested) {
|
|
186
173
|
result = await this.sessionService.getSessionEvents(sessionId, { limit, offset });
|
|
@@ -190,10 +177,9 @@ class SessionController {
|
|
|
190
177
|
result = events; // Direct array
|
|
191
178
|
}
|
|
192
179
|
|
|
193
|
-
//
|
|
180
|
+
// No caching for events - session files are live/active
|
|
194
181
|
res.set({
|
|
195
|
-
'
|
|
196
|
-
'Cache-Control': 'private, max-age=0, no-cache', // Disable cache during development
|
|
182
|
+
'Cache-Control': 'no-store',
|
|
197
183
|
'Vary': 'Accept-Encoding'
|
|
198
184
|
});
|
|
199
185
|
|
|
@@ -10,7 +10,7 @@ const config = require('../config');
|
|
|
10
10
|
class UploadController {
|
|
11
11
|
constructor() {
|
|
12
12
|
this.SESSION_DIR = process.env.SESSION_DIR || path.join(os.homedir(), '.copilot', 'session-state');
|
|
13
|
-
this.uploadDir = path.join(os.tmpdir(), 'copilot-session-uploads');
|
|
13
|
+
this.uploadDir = process.env.UPLOAD_DIR || path.join(os.tmpdir(), 'copilot-session-uploads');
|
|
14
14
|
|
|
15
15
|
// Multi-format session directories
|
|
16
16
|
this.SESSION_DIRS = {
|
|
@@ -39,11 +39,12 @@ class SessionRepository {
|
|
|
39
39
|
dir: process.env.PI_MONO_SESSION_DIR ||
|
|
40
40
|
path.join(os.homedir(), '.pi', 'agent', 'sessions')
|
|
41
41
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
// TODO: VSCode parser disabled
|
|
43
|
+
// {
|
|
44
|
+
// type: 'vscode',
|
|
45
|
+
// dir: process.env.VSCODE_WORKSPACE_STORAGE_DIR ||
|
|
46
|
+
// path.join(os.homedir(), 'Library', 'Application Support', 'Code', 'User', 'workspaceStorage')
|
|
47
|
+
// }
|
|
47
48
|
];
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -110,12 +111,10 @@ class SessionRepository {
|
|
|
110
111
|
if (stats.isDirectory()) {
|
|
111
112
|
return this._scanPiMonoDir(fullPath, entry);
|
|
112
113
|
}
|
|
113
|
-
} else if (source.type === 'vscode') {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return this._scanVsCodeWorkspaceDir(fullPath);
|
|
118
|
-
}
|
|
114
|
+
// } else if (source.type === 'vscode') { // TODO: VSCode disabled
|
|
115
|
+
// if (stats.isDirectory()) {
|
|
116
|
+
// return this._scanVsCodeWorkspaceDir(fullPath);
|
|
117
|
+
// }
|
|
119
118
|
}
|
|
120
119
|
return null;
|
|
121
120
|
});
|
|
@@ -275,8 +274,8 @@ class SessionRepository {
|
|
|
275
274
|
session = await this._findClaudeSession(sessionId, source.dir);
|
|
276
275
|
} else if (source.type === 'pi-mono') {
|
|
277
276
|
session = await this._findPiMonoSession(sessionId, source.dir);
|
|
278
|
-
} else if (source.type === 'vscode') {
|
|
279
|
-
|
|
277
|
+
// } else if (source.type === 'vscode') { // TODO: VSCode disabled
|
|
278
|
+
// session = await this._findVsCodeSession(sessionId, source.dir);
|
|
280
279
|
}
|
|
281
280
|
|
|
282
281
|
if (session) return session;
|
|
@@ -151,27 +151,24 @@ class SessionService {
|
|
|
151
151
|
console.error('Error searching Pi-Mono sessions:', err);
|
|
152
152
|
return [];
|
|
153
153
|
}
|
|
154
|
-
} else if (session.source === 'vscode') {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
console.error('Error reading VSCode session:', err);
|
|
173
|
-
return [];
|
|
174
|
-
}
|
|
154
|
+
// } else if (session.source === 'vscode') { // TODO: VSCode disabled
|
|
155
|
+
// const { VsCodeParser } = require('../../lib/parsers');
|
|
156
|
+
// const vscodeParser = new VsCodeParser();
|
|
157
|
+
// try {
|
|
158
|
+
// const raw = await fs.promises.readFile(session.filePath, 'utf-8');
|
|
159
|
+
// let sessionJson;
|
|
160
|
+
// if (session.filePath.endsWith('.jsonl')) {
|
|
161
|
+
// sessionJson = this.sessionRepository._parseVsCodeJsonl(raw);
|
|
162
|
+
// } else {
|
|
163
|
+
// sessionJson = JSON.parse(raw);
|
|
164
|
+
// }
|
|
165
|
+
// if (!sessionJson) return [];
|
|
166
|
+
// const parsed = vscodeParser.parseVsCode(sessionJson);
|
|
167
|
+
// return this._expandVsCodeEvents(parsed.allEvents);
|
|
168
|
+
// } catch (err) {
|
|
169
|
+
// console.error('Error reading VSCode session:', err);
|
|
170
|
+
// return [];
|
|
171
|
+
// }
|
|
175
172
|
}
|
|
176
173
|
|
|
177
174
|
|
package/views/session-vue.ejs
CHANGED
|
@@ -1864,6 +1864,15 @@
|
|
|
1864
1864
|
}
|
|
1865
1865
|
|
|
1866
1866
|
console.log('[Navigation] Events loaded:', loadedEvents.value.length);
|
|
1867
|
+
|
|
1868
|
+
// Update 'Updated' time from last event timestamp (more accurate than file mtime)
|
|
1869
|
+
if (loadedEvents.value.length > 0) {
|
|
1870
|
+
const lastEvent = loadedEvents.value[loadedEvents.value.length - 1];
|
|
1871
|
+
const lastTime = lastEvent.timestamp || lastEvent.time || lastEvent.data?.timestamp;
|
|
1872
|
+
if (lastTime) {
|
|
1873
|
+
metadata.value.updated = new Date(lastTime);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1867
1876
|
|
|
1868
1877
|
// Check for URL query parameters and jump to event AFTER events are loaded
|
|
1869
1878
|
const urlParams = new URLSearchParams(window.location.search);
|