ai-lens 0.8.87 → 0.8.89
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/CHANGELOG.md +8 -0
- package/cli/import/claude-code.js +6 -1
- package/cli/logger.js +36 -0
- package/package.json +1 -1
package/.commithash
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
690dd28
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
History of changes to the `ai-lens` CLI package on npm. New entries go on top. Format: `## X.Y.Z — YYYY-MM-DD`, followed by user-facing bullets.
|
|
4
4
|
|
|
5
|
+
## 0.8.89 — 2026-06-11
|
|
6
|
+
- improve: `ai-lens import claude-code` (and the import step inside `init`) now shows a live progress spinner — transcripts scanned, events collected, batches shipping — instead of sitting silent for minutes on a large history. Terminal-only; piped/CI output is unchanged.
|
|
7
|
+
|
|
8
|
+
## 0.8.88 — 2026-06-11
|
|
9
|
+
- fix: events now reach the server from behind corporate antivirus/proxy TLS inspection — on a certificate-trust error the sender automatically retries once trusting the OS certificate store (Node 22.15+; opt out with `AI_LENS_TLS_STRICT=1`)
|
|
10
|
+
- feat: `ai-lens status` now diagnoses TLS failures — it shows which certificate authority actually served the connection and names the likely interceptor instead of a bare error code
|
|
11
|
+
- improve: TLS send failures in `~/.ai-lens/sender.log` now include a self-heal status and a fix hint, not just an error counter
|
|
12
|
+
|
|
5
13
|
## 0.8.87 — 2026-06-11
|
|
6
14
|
- fix: the client version reported to the server (`X-Client-Version`) now describes the code that actually ran. Previously a repo-path install (`init --use-repo-path`) reported the version of the old copied client in `~/.ai-lens/client/` forever, making up-to-date setups look ancient in server logs and diagnostics.
|
|
7
15
|
|
|
@@ -30,7 +30,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
30
30
|
import { writeToSpool, canonicalizeProjectPath, deterministicEventId } from '../../client/capture.js';
|
|
31
31
|
import { PENDING_DIR, SENDING_DIR, DATA_DIR, ensureDataDir, getGitIdentity, getGitMetadata, getServerUrl, getAuthToken, getMonitoredProjects } from '../../client/config.js';
|
|
32
32
|
import { mapTranscript } from './transcript-map.js';
|
|
33
|
-
import { info, success, warn, error, heading, detail, blank } from '../logger.js';
|
|
33
|
+
import { info, success, warn, error, heading, detail, blank, progress, progressDone } from '../logger.js';
|
|
34
34
|
|
|
35
35
|
const PROJECTS_DIR = join(homedir(), '.claude', 'projects');
|
|
36
36
|
const LEDGER_PATH = join(DATA_DIR, 'import-state', 'claude-code.json');
|
|
@@ -348,6 +348,7 @@ export default async function importClaudeCode(flags) {
|
|
|
348
348
|
let drainFailed = false;
|
|
349
349
|
const flush = async () => {
|
|
350
350
|
if (dryRun) { inFlight = 0; return true; }
|
|
351
|
+
progress(`shipping ${inFlight} event(s) to the server…`);
|
|
351
352
|
const ok = await drainSpool();
|
|
352
353
|
if (!ok) { drainFailed = true; return false; }
|
|
353
354
|
inFlight = 0;
|
|
@@ -360,6 +361,7 @@ export default async function importClaudeCode(flags) {
|
|
|
360
361
|
// Pass 1 — cheap shortlist (mtime + ledger), no file reads. A transcript's
|
|
361
362
|
// filename basename IS the session UUID, so we can gather session ids for the
|
|
362
363
|
// coverage query without reading anything.
|
|
364
|
+
progress('scanning local transcripts…');
|
|
363
365
|
const candidates = [];
|
|
364
366
|
for (const filePath of allFiles) {
|
|
365
367
|
let st;
|
|
@@ -378,8 +380,11 @@ export default async function importClaudeCode(flags) {
|
|
|
378
380
|
)]);
|
|
379
381
|
|
|
380
382
|
// Pass 2 — read, map, de-overlap, ship.
|
|
383
|
+
let filesProcessed = 0;
|
|
381
384
|
for (const { filePath, fp } of candidates) {
|
|
382
385
|
if (drainFailed) break;
|
|
386
|
+
filesProcessed++;
|
|
387
|
+
progress(`${dryRun ? 'scanning' : 'importing'}… ${filesProcessed}/${candidates.length} transcript(s) · ${eventCount} event(s) from ${sessionCount} session(s)`);
|
|
383
388
|
const { lines, lastTs } = await readTranscript(filePath);
|
|
384
389
|
if (!lastTs || lastTs < cutoff) { filesSkipped++; continue; }
|
|
385
390
|
|
package/cli/logger.js
CHANGED
|
@@ -40,37 +40,73 @@ const YELLOW = useColor ? '\x1b[33m' : '';
|
|
|
40
40
|
const RED = useColor ? '\x1b[31m' : '';
|
|
41
41
|
const CYAN = useColor ? '\x1b[36m' : '';
|
|
42
42
|
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// Transient progress line (spinner). TTY-only: in pipes/CI it is a no-op, so
|
|
45
|
+
// scripted output and init.log stay exactly as before. Every regular print
|
|
46
|
+
// clears an active progress line first so interleaved warns don't garble it.
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
49
|
+
const PROGRESS_MIN_REPAINT_MS = 80; // cap repaints at ~12fps no matter how hot the caller loop is
|
|
50
|
+
let progressActive = false;
|
|
51
|
+
let progressFrame = 0;
|
|
52
|
+
let progressLastPaint = 0;
|
|
53
|
+
|
|
54
|
+
/** Show/update a transient one-line progress indicator (TTY only, throttled). */
|
|
55
|
+
export function progress(text) {
|
|
56
|
+
if (!useColor) return; // useColor === stdout.isTTY
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
if (progressActive && now - progressLastPaint < PROGRESS_MIN_REPAINT_MS) return;
|
|
59
|
+
progressLastPaint = now;
|
|
60
|
+
const frame = SPINNER_FRAMES[progressFrame++ % SPINNER_FRAMES.length];
|
|
61
|
+
process.stdout.write(`\r\x1b[2K${CYAN}${frame}${RESET} ${DIM}${text}${RESET}`);
|
|
62
|
+
progressActive = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Clear the progress line (safe to call when none is active). */
|
|
66
|
+
export function progressDone() {
|
|
67
|
+
if (!progressActive) return;
|
|
68
|
+
process.stdout.write('\r\x1b[2K');
|
|
69
|
+
progressActive = false;
|
|
70
|
+
}
|
|
71
|
+
|
|
43
72
|
export function info(msg) {
|
|
73
|
+
progressDone();
|
|
44
74
|
console.log(msg);
|
|
45
75
|
write('INFO', msg);
|
|
46
76
|
}
|
|
47
77
|
|
|
48
78
|
export function success(msg) {
|
|
79
|
+
progressDone();
|
|
49
80
|
console.log(`${GREEN}${msg}${RESET}`);
|
|
50
81
|
write('INFO', msg);
|
|
51
82
|
}
|
|
52
83
|
|
|
53
84
|
export function warn(msg) {
|
|
85
|
+
progressDone();
|
|
54
86
|
console.log(`${YELLOW}${msg}${RESET}`);
|
|
55
87
|
write('WARN', msg);
|
|
56
88
|
}
|
|
57
89
|
|
|
58
90
|
export function error(msg) {
|
|
91
|
+
progressDone();
|
|
59
92
|
console.log(`${RED}${msg}${RESET}`);
|
|
60
93
|
write('ERROR', msg);
|
|
61
94
|
}
|
|
62
95
|
|
|
63
96
|
export function heading(msg) {
|
|
97
|
+
progressDone();
|
|
64
98
|
console.log(`\n${BOLD}${CYAN}${msg}${RESET}`);
|
|
65
99
|
write('INFO', msg);
|
|
66
100
|
}
|
|
67
101
|
|
|
68
102
|
export function detail(msg) {
|
|
103
|
+
progressDone();
|
|
69
104
|
console.log(`${DIM} ${msg}${RESET}`);
|
|
70
105
|
write('INFO', msg);
|
|
71
106
|
}
|
|
72
107
|
|
|
73
108
|
export function blank() {
|
|
109
|
+
progressDone();
|
|
74
110
|
console.log();
|
|
75
111
|
}
|
|
76
112
|
|