ai-lens 0.8.30 → 0.8.32

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/.commithash CHANGED
@@ -1 +1 @@
1
- 6a194f8
1
+ 02e0ba4
package/cli/status.js CHANGED
@@ -326,7 +326,7 @@ function checkClientFiles() {
326
326
  versionDetail = `\n Client version: ${clientVersion} (${clientCommit})`;
327
327
  if (outdated) {
328
328
  versionDetail += `\n CLI version: ${cliVersion} (${cliCommit})`;
329
- versionDetail += `\n ! Client is outdated — run: npx -y ai-lens init`;
329
+ versionDetail += `\n ! Client is outdated — run: npx -y ai-lens init --yes`;
330
330
  }
331
331
  } catch {
332
332
  versionDetail = `\n Client version: unknown (version.json not found — run: npx -y ai-lens init)`;
package/client/capture.js CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  DEDUP_DIR,
19
19
  SESSION_PATHS_DIR,
20
20
  CAPTURE_LOG_PATH,
21
+ LOG_MAX_AGE_DAYS,
21
22
  captureLog,
22
23
  getServerUrl,
23
24
  getAuthToken,
@@ -42,6 +43,25 @@ function logDrop(reason, meta = {}) {
42
43
  } catch { /* best-effort */ }
43
44
  }
44
45
 
46
+ function rotateCaptureLog() {
47
+ try {
48
+ const content = readFileSync(CAPTURE_LOG_PATH, 'utf8');
49
+ const lines = content.split('\n');
50
+ if (lines.length < 1000) return;
51
+ const cutoff = Date.now() - LOG_MAX_AGE_DAYS * 86400000;
52
+ const kept = lines.filter(line => {
53
+ if (!line) return false;
54
+ try {
55
+ const m = line.match(/"ts":"([^"]+)"/);
56
+ return m && new Date(m[1]).getTime() >= cutoff;
57
+ } catch { return true; }
58
+ });
59
+ if (kept.length < lines.length) {
60
+ writeFileSync(CAPTURE_LOG_PATH, kept.join('\n') + '\n');
61
+ }
62
+ } catch { /* capture must not crash due to rotation */ }
63
+ }
64
+
45
65
  // =============================================================================
46
66
  // Identity Resolution
47
67
  // =============================================================================
@@ -573,6 +593,7 @@ async function main() {
573
593
  }
574
594
 
575
595
  ensureDataDir();
596
+ rotateCaptureLog();
576
597
 
577
598
  // Read stdin
578
599
  let input = '';
package/client/config.js CHANGED
@@ -20,6 +20,7 @@ export const SESSION_PATHS_DIR = join(DATA_DIR, 'session-paths');
20
20
  export const GIT_REMOTES_DIR = join(DATA_DIR, 'git-remotes');
21
21
  export const LOG_PATH = join(DATA_DIR, 'sender.log');
22
22
  export const CAPTURE_LOG_PATH = join(DATA_DIR, 'capture.log');
23
+ export const LOG_MAX_AGE_DAYS = 30;
23
24
 
24
25
  export function log(fields) {
25
26
  const entry = { ts: new Date().toISOString(), ...fields };
package/client/sender.js CHANGED
@@ -27,6 +27,8 @@ import {
27
27
  CURRENT_STORAGE_VERSION,
28
28
  QUEUE_PATH,
29
29
  SENDING_PATH,
30
+ LOG_PATH,
31
+ LOG_MAX_AGE_DAYS,
30
32
  getServerUrl,
31
33
  getAuthToken,
32
34
  getClientVersion,
@@ -34,6 +36,29 @@ import {
34
36
  log,
35
37
  } from './config.js';
36
38
 
39
+ // =============================================================================
40
+ // Log rotation
41
+ // =============================================================================
42
+
43
+ export function rotateLog(logPath = LOG_PATH, maxAgeDays = LOG_MAX_AGE_DAYS) {
44
+ try {
45
+ const content = readFileSync(logPath, 'utf8');
46
+ const lines = content.split('\n');
47
+ if (lines.length < 1000) return; // don't touch small logs
48
+ const cutoff = Date.now() - maxAgeDays * 86400000;
49
+ const kept = lines.filter(line => {
50
+ if (!line) return false;
51
+ try {
52
+ const m = line.match(/"ts":"([^"]+)"/);
53
+ return m && new Date(m[1]).getTime() >= cutoff;
54
+ } catch { return true; } // can't parse — keep
55
+ });
56
+ if (kept.length < lines.length) {
57
+ writeFileSync(logPath, kept.join('\n') + '\n');
58
+ }
59
+ } catch { /* sender must not crash due to rotation */ }
60
+ }
61
+
37
62
  export const MAX_QUEUE_SIZE = 10_000;
38
63
  export const MAX_CHUNK_BYTES = 4 * 1024 * 1024; // 4 MB per POST (Express limit is 50 MB)
39
64
  export const LOCK_MAX_AGE_MS = 5 * 60 * 1000; // 5 minutes
@@ -625,6 +650,8 @@ async function main() {
625
650
  const acquired = acquireQueue();
626
651
  if (!acquired) process.exit(0);
627
652
 
653
+ rotateLog();
654
+
628
655
  const { events, sendingDir, pendingDir: acquiredPendingDir, eventFileMap, acquiredFiles } = acquired;
629
656
  const lockPath = join(sendingDir, '.sender.lock');
630
657
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-lens",
3
- "version": "0.8.30",
3
+ "version": "0.8.32",
4
4
  "type": "module",
5
5
  "description": "Centralized session analytics for AI coding tools",
6
6
  "bin": {