@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.
- package/package.json +1 -1
- 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.
|
|
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.
|
|
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
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
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(`
|
|
2452
|
+
console.log(`Tip: session-recall last 1 --before-compaction N (load phase N)`);
|
|
2409
2453
|
}
|
|
2410
2454
|
|
|
2411
2455
|
// ========== TANGENT COMMANDS ==========
|