agentlytics 0.1.20 → 0.2.2

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.
@@ -927,10 +927,31 @@ function getUsage() {
927
927
  };
928
928
  }
929
929
 
930
- function resetCache() { _lsCache = null; _lsCacheCheckedAt = 0; _modelMap = null; }
930
+ function resetCache() { _lsCache = null; _lsCacheCheckedAt = 0; _modelMap = null; _sessionFolderMap = null; }
931
931
 
932
932
  const labels = { 'antigravity': 'Antigravity' };
933
933
 
934
+ // Cache session→folder mapping so we only build it once per process
935
+ let _sessionFolderMap = null;
936
+ function getSessionFolderMap() {
937
+ if (_sessionFolderMap) return _sessionFolderMap;
938
+ _sessionFolderMap = new Map();
939
+ try {
940
+ const chats = getChats();
941
+ for (const chat of chats) {
942
+ if (chat.composerId && chat.folder) {
943
+ _sessionFolderMap.set(chat.composerId, chat.folder);
944
+ }
945
+ }
946
+ } catch { /* skip */ }
947
+ return _sessionFolderMap;
948
+ }
949
+
950
+ function normalizePath(p) {
951
+ if (!p) return p;
952
+ return p.replace(/\/+$/, '').replace(/^file:\/\//, '');
953
+ }
954
+
934
955
  function getArtifacts(folder) {
935
956
  const { scanArtifacts } = require('./base');
936
957
  const artifacts = folder ? scanArtifacts(folder, {
@@ -941,38 +962,45 @@ function getArtifacts(folder) {
941
962
  }) : [];
942
963
 
943
964
  // Add brain artifacts (task.md, implementation_plan.md, walkthrough.md) per session
944
- if (fs.existsSync(ANTIGRAVITY_BRAIN_DIR)) {
945
- try {
946
- const sessions = fs.readdirSync(ANTIGRAVITY_BRAIN_DIR);
947
- const brainFileNames = ['task.md', 'implementation_plan.md', 'walkthrough.md'];
948
- for (const sessionId of sessions) {
949
- const sessionDir = path.join(ANTIGRAVITY_BRAIN_DIR, sessionId);
965
+ if (!folder || !fs.existsSync(ANTIGRAVITY_BRAIN_DIR)) return artifacts;
966
+
967
+ const sessionMap = getSessionFolderMap();
968
+ const normalizedFolder = normalizePath(folder);
969
+
970
+ try {
971
+ const sessions = fs.readdirSync(ANTIGRAVITY_BRAIN_DIR);
972
+ const brainFileNames = ['task.md', 'implementation_plan.md', 'walkthrough.md'];
973
+ for (const sessionId of sessions) {
974
+ // Only include sessions that belong to this project folder
975
+ const sessionFolder = normalizePath(sessionMap.get(sessionId));
976
+ if (!sessionFolder || sessionFolder !== normalizedFolder) continue;
977
+
978
+ const sessionDir = path.join(ANTIGRAVITY_BRAIN_DIR, sessionId);
979
+ try {
980
+ if (!fs.statSync(sessionDir).isDirectory()) continue;
981
+ } catch { continue; }
982
+ for (const fileName of brainFileNames) {
983
+ const filePath = path.join(sessionDir, fileName);
984
+ if (!fs.existsSync(filePath)) continue;
950
985
  try {
951
- if (!fs.statSync(sessionDir).isDirectory()) continue;
952
- } catch { continue; }
953
- for (const fileName of brainFileNames) {
954
- const filePath = path.join(sessionDir, fileName);
955
- if (!fs.existsSync(filePath)) continue;
956
- try {
957
- const stat = fs.statSync(filePath);
958
- const content = fs.readFileSync(filePath, 'utf-8');
959
- if (!content.trim()) continue;
960
- const lines = content.split('\n').length;
961
- artifacts.push({
962
- name: fileName,
963
- path: filePath,
964
- relativePath: `brain/${sessionId.slice(0, 8)}/${fileName}`,
965
- size: stat.size,
966
- lines,
967
- modifiedAt: stat.mtimeMs,
968
- editor: 'antigravity',
969
- editorLabel: 'Antigravity',
970
- });
971
- } catch { /* skip unreadable */ }
972
- }
986
+ const stat = fs.statSync(filePath);
987
+ const content = fs.readFileSync(filePath, 'utf-8');
988
+ if (!content.trim()) continue;
989
+ const lines = content.split('\n').length;
990
+ artifacts.push({
991
+ name: fileName,
992
+ path: filePath,
993
+ relativePath: `brain/${sessionId.slice(0, 8)}/${fileName}`,
994
+ size: stat.size,
995
+ lines,
996
+ modifiedAt: stat.mtimeMs,
997
+ editor: 'antigravity',
998
+ editorLabel: 'Antigravity',
999
+ });
1000
+ } catch { /* skip unreadable */ }
973
1001
  }
974
- } catch { /* skip if brain dir unreadable */ }
975
- }
1002
+ }
1003
+ } catch { /* skip if brain dir unreadable */ }
976
1004
 
977
1005
  return artifacts;
978
1006
  }
package/editors/codex.js CHANGED
@@ -5,17 +5,25 @@ const os = require('os');
5
5
  const name = 'codex';
6
6
  const DEFAULT_CODEX_HOME = path.join(os.homedir(), '.codex');
7
7
  const SESSION_SUBDIR = 'sessions';
8
+ const ARCHIVED_SESSION_SUBDIR = 'archived_sessions';
8
9
  const MAX_TOOL_RESULT_PREVIEW = 500;
9
10
 
10
11
  function getChats() {
11
- const sessionsDir = getSessionsDir();
12
- if (!fs.existsSync(sessionsDir)) return [];
13
-
12
+ const dirs = [getSessionsDir(), getArchivedSessionsDir()];
13
+ const seen = new Set();
14
14
  const chats = [];
15
- for (const filePath of walkJsonlFiles(sessionsDir)) {
16
- const chat = readChatMetadata(filePath);
17
- if (chat) chats.push(chat);
15
+
16
+ for (const dir of dirs) {
17
+ if (!fs.existsSync(dir)) continue;
18
+ for (const filePath of walkJsonlFiles(dir)) {
19
+ const chat = readChatMetadata(filePath);
20
+ if (!chat) continue;
21
+ if (seen.has(chat.composerId)) continue;
22
+ seen.add(chat.composerId);
23
+ chats.push(chat);
24
+ }
18
25
  }
26
+
19
27
  return chats;
20
28
  }
21
29
 
@@ -25,11 +33,18 @@ function getMessages(chat) {
25
33
  return parseSessionMessages(filePath);
26
34
  }
27
35
 
28
- function getSessionsDir() {
29
- const codexHome = process.env.CODEX_HOME && process.env.CODEX_HOME.trim()
36
+ function getCodexHome() {
37
+ return process.env.CODEX_HOME && process.env.CODEX_HOME.trim()
30
38
  ? path.resolve(process.env.CODEX_HOME.trim())
31
39
  : DEFAULT_CODEX_HOME;
32
- return path.join(codexHome, SESSION_SUBDIR);
40
+ }
41
+
42
+ function getSessionsDir() {
43
+ return path.join(getCodexHome(), SESSION_SUBDIR);
44
+ }
45
+
46
+ function getArchivedSessionsDir() {
47
+ return path.join(getCodexHome(), ARCHIVED_SESSION_SUBDIR);
33
48
  }
34
49
 
35
50
  function walkJsonlFiles(dir) {
@@ -442,12 +457,7 @@ function safeParseJson(value) {
442
457
  // ============================================================
443
458
 
444
459
  function getCodexAuth() {
445
- const authPath = path.join(
446
- process.env.CODEX_HOME && process.env.CODEX_HOME.trim()
447
- ? path.resolve(process.env.CODEX_HOME.trim())
448
- : DEFAULT_CODEX_HOME,
449
- 'auth.json'
450
- );
460
+ const authPath = path.join(getCodexHome(), 'auth.json');
451
461
  try {
452
462
  return JSON.parse(fs.readFileSync(authPath, 'utf-8'));
453
463
  } catch { return null; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlytics",
3
- "version": "0.1.20",
3
+ "version": "0.2.2",
4
4
  "description": "Comprehensive analytics dashboard for AI coding agents — Cursor, Windsurf, Claude Code, VS Code Copilot, Zed, Antigravity, OpenCode, Command Code",
5
5
  "main": "index.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -415,13 +415,6 @@ app.get('/api/artifact-content', (req, res) => {
415
415
  const artifacts = getAllArtifacts(project.folder);
416
416
  if (artifacts.some(a => a.path === filePath)) { allowed = true; break; }
417
417
  }
418
- // Also check global/editor-level artifacts not tied to any project (e.g. brain files)
419
- if (!allowed) {
420
- try {
421
- const artifacts = getAllArtifacts(null);
422
- if (artifacts.some(a => a.path === filePath)) allowed = true;
423
- } catch { /* skip */ }
424
- }
425
418
  if (!allowed) return res.status(403).json({ error: 'Not an artifact file' });
426
419
 
427
420
  if (!fs.existsSync(filePath)) return res.status(404).json({ error: 'File not found' });