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 +1 -1
- package/cli/status.js +1 -1
- package/client/capture.js +21 -0
- package/client/config.js +1 -0
- package/client/sender.js +27 -0
- package/package.json +1 -1
package/.commithash
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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
|
|