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 CHANGED
@@ -1 +1 @@
1
- ecde7fc
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-lens",
3
- "version": "0.8.87",
3
+ "version": "0.8.89",
4
4
  "type": "module",
5
5
  "description": "Centralized session analytics for AI coding tools",
6
6
  "bin": {