@aiplumber/session-recall 1.8.5 → 1.8.7

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/session-recall +53 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiplumber/session-recall",
3
- "version": "1.8.5",
3
+ "version": "1.8.7",
4
4
  "description": "Pull context from previous Claude Code sessions. Sessions end, context resets - this tool lets you continue where you left off.",
5
5
  "bin": {
6
6
  "session-recall": "./session-recall"
package/session-recall CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const VERSION = '1.8.5';
3
+ const VERSION = '1.8.7';
4
4
 
5
5
  const fs = require('fs');
6
6
  const path = require('path');
@@ -49,10 +49,10 @@ function readJsonl(filePath) {
49
49
  const stats = fs.statSync(filePath);
50
50
  const sizeMB = stats.size / (1024 * 1024);
51
51
 
52
- if (sizeMB > LARGE_FILE_DANGER_MB) {
52
+ if (sizeMB > LARGE_FILE_DANGER_MB && !process.env.SESSION_RECALL_FORCE) {
53
53
  console.error(`[session-recall] ERROR: File is ${sizeMB.toFixed(0)}MB - too large, will crash.`);
54
54
  console.error(`Tip: Use 'session-recall last 1 --compactions' for just current phase`);
55
- console.error(`Or: NODE_OPTIONS="--max-old-space-size=8192" session-recall ...`);
55
+ console.error(`Or: SESSION_RECALL_FORCE=1 NODE_OPTIONS="--max-old-space-size=8192" session-recall ...`);
56
56
  process.exit(1);
57
57
  } else if (sizeMB > LARGE_FILE_WARNING_MB) {
58
58
  console.error(`[session-recall] WARNING: ${sizeMB.toFixed(0)}MB file - may be slow`);
@@ -2390,22 +2390,66 @@ function cmdCompactions(jsonlPath, opts) {
2390
2390
  return;
2391
2391
  }
2392
2392
 
2393
+ // Calculate token estimates for each phase
2394
+ function estimatePhaseTokens(startLine, endLine) {
2395
+ let tokens = 0;
2396
+ for (let j = startLine; j < endLine && j < messages.length; j++) {
2397
+ const msg = messages[j];
2398
+ if (msg.message?.content) {
2399
+ const content = msg.message.content;
2400
+ if (typeof content === 'string') {
2401
+ tokens += estimateTokens({ length: content.length });
2402
+ } else if (Array.isArray(content)) {
2403
+ for (const block of content) {
2404
+ if (block.text) tokens += estimateTokens({ length: block.text.length });
2405
+ }
2406
+ }
2407
+ }
2408
+ }
2409
+ return tokens;
2410
+ }
2411
+
2412
+ // Get file size
2413
+ let fileSizeMB = 0;
2414
+ try {
2415
+ const stats = fs.statSync(jsonlPath);
2416
+ fileSizeMB = stats.size / (1024 * 1024);
2417
+ } catch (e) {}
2418
+
2393
2419
  console.log(`=== COMPACTION EVENTS (${compactions.length} total) ===`);
2394
- console.log(`Source: ${path.basename(jsonlPath)}`);
2420
+ console.log(`Source: ${path.basename(jsonlPath)}${fileSizeMB > 0 ? ` (${fileSizeMB.toFixed(0)}MB)` : ''}`);
2395
2421
  console.log(``);
2422
+ console.log(`# TIME MSGS ~TOKENS PHASE`);
2423
+ console.log(`───────────────────────────────────────`);
2396
2424
 
2397
2425
  for (let i = 0; i < compactions.length; i++) {
2398
2426
  const c = compactions[i];
2399
2427
  const ts = c.timestamp ? new Date(c.timestamp).toISOString().substring(11, 19) : '??:??:??';
2400
- const retryInfo = c.retries > 0 ? `, +${c.retries} retries` : '';
2401
2428
 
2402
- console.log(`Compaction #${i + 1} @ ${ts} (line ${c.line}${retryInfo})`);
2403
- console.log(` Messages after: ${c.messagesAfter}`);
2404
- console.log(``);
2429
+ // Calculate phase boundaries
2430
+ const startLine = i === 0 ? 0 : compactions[i - 1].line;
2431
+ const endLine = c.line;
2432
+ const phaseTokens = estimatePhaseTokens(startLine, endLine);
2433
+ const tokensK = (phaseTokens / 1000).toFixed(0) + 'k';
2434
+
2435
+ const num = String(i + 1).padStart(2);
2436
+ const msgs = String(endLine - startLine).padStart(5);
2437
+ const toks = tokensK.padStart(8);
2438
+
2439
+ console.log(`${num} ${ts} ${msgs} ${toks} Phase ${i + 1}`);
2405
2440
  }
2406
2441
 
2442
+ // Current phase (after last compaction)
2443
+ const lastCompaction = compactions[compactions.length - 1];
2444
+ const currentMsgs = messages.length - lastCompaction.line;
2445
+ const currentTokens = estimatePhaseTokens(lastCompaction.line, messages.length);
2446
+ const currentK = (currentTokens / 1000).toFixed(0) + 'k';
2447
+ console.log(`───────────────────────────────────────`);
2448
+ console.log(` (current) ${String(currentMsgs).padStart(5)} ${currentK.padStart(8)} After #${compactions.length}`);
2449
+ console.log(``);
2450
+
2407
2451
  // Usage hint
2408
- console.log(`Use: session-recall last 1 --before-compaction to recall pre-compaction content`);
2452
+ console.log(`Tip: session-recall last 1 --before-compaction N (load phase N)`);
2409
2453
  }
2410
2454
 
2411
2455
  // ========== TANGENT COMMANDS ==========