@stackmemoryai/stackmemory
Version:
Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.
341 lines (340 loc) • 12.3 kB
JavaScript
import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { readFileSync, existsSync, readdirSync, statSync } from "fs";
import { join } from "path";
import { homedir } from "os";
import Database from "better-sqlite3";
function estimateTokensAccurate(text) {
const baseEstimate = text.length / 3.5;
const codeIndicators = (text.match(/[{}\[\]();=]/g) || []).length;
const codeScore = codeIndicators / text.length * 100;
if (codeScore > 5) {
return Math.ceil(baseEstimate * 1.2);
}
return Math.ceil(baseEstimate);
}
function measureHandoffs() {
const handoffPath = join(homedir(), ".stackmemory", "context.db");
const metrics = [];
if (!existsSync(handoffPath)) {
console.log("No context.db found at", handoffPath);
return metrics;
}
try {
const db = new Database(handoffPath, { readonly: true });
const tableCheck = db.prepare(
`
SELECT name FROM sqlite_master
WHERE type='table' AND name='handoff_requests'
`
).get();
if (!tableCheck) {
console.log("No handoff_requests table found");
db.close();
return metrics;
}
const handoffs = db.prepare(
`
SELECT id, message, created_at
FROM handoff_requests
ORDER BY created_at DESC
LIMIT 10
`
).all();
for (const h of handoffs) {
const message = h.message || "";
metrics.push({
handoffId: h.id,
handoffChars: message.length,
handoffTokens: estimateTokensAccurate(message),
createdAt: new Date(h.created_at).toISOString()
});
}
db.close();
} catch (err) {
console.log("Error reading handoffs:", err);
}
return metrics;
}
function measureLastHandoffFile() {
const handoffPath = join(process.cwd(), ".stackmemory", "last-handoff.md");
if (!existsSync(handoffPath)) {
const homeHandoff = join(homedir(), ".stackmemory", "last-handoff.md");
if (!existsSync(homeHandoff)) {
return null;
}
const content2 = readFileSync(homeHandoff, "utf-8");
return {
source: homeHandoff,
charCount: content2.length,
estimatedTokens: estimateTokensAccurate(content2),
lineCount: content2.split("\n").length
};
}
const content = readFileSync(handoffPath, "utf-8");
return {
source: handoffPath,
charCount: content.length,
estimatedTokens: estimateTokensAccurate(content),
lineCount: content.split("\n").length
};
}
function measureClaudeConversations() {
const claudeProjectsDir = join(homedir(), ".claude", "projects");
const metrics = [];
if (!existsSync(claudeProjectsDir)) {
return metrics;
}
const projectDirs = readdirSync(claudeProjectsDir);
for (const dir of projectDirs.slice(0, 5)) {
const projectPath = join(claudeProjectsDir, dir);
const stat = statSync(projectPath);
if (stat.isDirectory()) {
const files = readdirSync(projectPath).filter(
(f) => f.endsWith(".jsonl")
);
for (const file of files.slice(0, 3)) {
const filePath = join(projectPath, file);
try {
const content = readFileSync(filePath, "utf-8");
metrics.push({
source: file,
charCount: content.length,
estimatedTokens: estimateTokensAccurate(content),
lineCount: content.split("\n").length
});
} catch {
}
}
}
}
return metrics;
}
function measureFramesAndEvents() {
const dbPath = join(homedir(), ".stackmemory", "context.db");
if (!existsSync(dbPath)) {
return null;
}
try {
const db = new Database(dbPath, { readonly: true });
const frameResult = db.prepare(
`
SELECT COUNT(*) as count,
SUM(LENGTH(COALESCE(name, '') || COALESCE(json(inputs), '') || COALESCE(json(outputs), '') || COALESCE(json(digest_json), ''))) as totalChars
FROM frames
`
).get();
const eventResult = db.prepare(
`
SELECT COUNT(*) as count,
SUM(LENGTH(COALESCE(event_type, '') || COALESCE(json(payload), ''))) as totalChars
FROM events
`
).get();
db.close();
const frameChars = frameResult?.totalChars || 0;
const eventChars = eventResult?.totalChars || 0;
const totalChars = frameChars + eventChars;
return {
sessionId: "aggregate",
frameCount: frameResult?.count || 0,
eventCount: eventResult?.count || 0,
estimatedSessionTokens: estimateTokensAccurate(
String(totalChars).repeat(Math.floor(totalChars / 10) || 1)
)
};
} catch (err) {
console.log("Error measuring frames/events:", err);
return null;
}
}
function formatNumber(n) {
if (n >= 1e3) {
return (n / 1e3).toFixed(1) + "K";
}
return n.toString();
}
async function main() {
console.log("========================================");
console.log(" HANDOFF CONTEXT IMPACT ANALYSIS");
console.log(" (Actual Measurements)");
console.log("========================================\n");
console.log("1. LAST HANDOFF FILE");
console.log("--------------------");
const lastHandoff = measureLastHandoffFile();
if (lastHandoff) {
console.log(` Source: ${lastHandoff.source}`);
console.log(` Characters: ${formatNumber(lastHandoff.charCount)}`);
console.log(` Lines: ${lastHandoff.lineCount}`);
console.log(
` Estimated tokens: ${formatNumber(lastHandoff.estimatedTokens)}`
);
} else {
console.log(" No handoff file found");
}
console.log("");
console.log("2. HANDOFFS FROM DATABASE");
console.log("-------------------------");
const handoffs = measureHandoffs();
if (handoffs.length > 0) {
let totalTokens = 0;
for (const h of handoffs) {
console.log(
` ${h.handoffId.slice(0, 8)}: ${formatNumber(h.handoffTokens)} tokens (${formatNumber(h.handoffChars)} chars)`
);
totalTokens += h.handoffTokens;
}
const avgTokens = Math.round(totalTokens / handoffs.length);
console.log(` Average: ${formatNumber(avgTokens)} tokens per handoff`);
} else {
console.log(" No handoffs in database");
}
console.log("");
console.log("3. CLAUDE CONVERSATION FILES");
console.log("----------------------------");
const conversations = measureClaudeConversations();
if (conversations.length > 0) {
let totalConvTokens = 0;
let maxConvTokens = 0;
for (const c of conversations) {
console.log(
` ${c.source}: ${formatNumber(c.estimatedTokens)} tokens (${formatNumber(c.charCount)} chars, ${c.lineCount} lines)`
);
totalConvTokens += c.estimatedTokens;
maxConvTokens = Math.max(maxConvTokens, c.estimatedTokens);
}
const avgConvTokens = Math.round(totalConvTokens / conversations.length);
console.log(
` Average: ${formatNumber(avgConvTokens)} tokens per conversation`
);
console.log(` Max: ${formatNumber(maxConvTokens)} tokens`);
} else {
console.log(" No conversation files found");
}
console.log("");
console.log("4. STACKMEMORY DATABASE CONTENT");
console.log("-------------------------------");
const dbMetrics = measureFramesAndEvents();
if (dbMetrics) {
console.log(` Frames: ${dbMetrics.frameCount}`);
console.log(` Events: ${dbMetrics.eventCount}`);
console.log(
` Total stored data: ~${formatNumber(dbMetrics.estimatedSessionTokens)} tokens equivalent`
);
} else {
console.log(" No database metrics available");
}
console.log("");
console.log("5. COMPRESSION ANALYSIS");
console.log("-----------------------");
const avgHandoffTokens = handoffs.length > 0 ? Math.round(
handoffs.reduce((sum, h) => sum + h.handoffTokens, 0) / handoffs.length
) : lastHandoff?.estimatedTokens || 2e3;
const avgConversationTokens = conversations.length > 0 ? Math.round(
conversations.reduce((sum, c) => sum + c.estimatedTokens, 0) / conversations.length
) : 8e4;
const sessionSizes = {
short: 35e3,
// 2hr session
medium: 78e3,
// 4hr session
long: 142e3,
// 8hr session
actual: avgConversationTokens
};
console.log("\n Compression Ratios (using actual handoff size):");
console.log(` Handoff size: ${formatNumber(avgHandoffTokens)} tokens
`);
for (const [label, size] of Object.entries(sessionSizes)) {
const reduction = ((size - avgHandoffTokens) / size * 100).toFixed(1);
const saved = size - avgHandoffTokens;
console.log(
` ${label.padEnd(8)}: ${formatNumber(size)} -> ${formatNumber(avgHandoffTokens)} = ${reduction}% reduction (${formatNumber(saved)} saved)`
);
}
console.log("");
console.log("6. CONTEXT WINDOW IMPACT");
console.log("------------------------");
const contextWindow = 2e5;
const systemPrompt = 2e3;
const currentTools = 1e4;
const withoutHandoff = {
used: systemPrompt + avgConversationTokens + currentTools,
available: 0
};
withoutHandoff.available = contextWindow - withoutHandoff.used;
const withHandoff = {
used: systemPrompt + avgHandoffTokens + currentTools,
available: 0
};
withHandoff.available = contextWindow - withHandoff.used;
console.log(` Context window: ${formatNumber(contextWindow)} tokens`);
console.log(` System prompt: ${formatNumber(systemPrompt)} tokens`);
console.log(` Current tools: ${formatNumber(currentTools)} tokens
`);
console.log(" WITHOUT HANDOFF:");
console.log(
` Conversation history: ${formatNumber(avgConversationTokens)} tokens`
);
console.log(` Total used: ${formatNumber(withoutHandoff.used)} tokens`);
console.log(
` Available for work: ${formatNumber(withoutHandoff.available)} tokens (${(withoutHandoff.available / contextWindow * 100).toFixed(1)}%)`
);
console.log("");
console.log(" WITH HANDOFF:");
console.log(` Handoff summary: ${formatNumber(avgHandoffTokens)} tokens`);
console.log(` Total used: ${formatNumber(withHandoff.used)} tokens`);
console.log(
` Available for work: ${formatNumber(withHandoff.available)} tokens (${(withHandoff.available / contextWindow * 100).toFixed(1)}%)`
);
console.log("");
const improvement = withHandoff.available - withoutHandoff.available;
const improvementPct = (improvement / withoutHandoff.available * 100).toFixed(1);
console.log(
` IMPROVEMENT: +${formatNumber(improvement)} tokens (+${improvementPct}% more capacity)`
);
console.log("\n========================================");
console.log(" SUMMARY");
console.log("========================================\n");
const actualReduction = ((avgConversationTokens - avgHandoffTokens) / avgConversationTokens * 100).toFixed(1);
console.log(
` Actual handoff size: ${formatNumber(avgHandoffTokens)} tokens`
);
console.log(
` Actual conversation size: ${formatNumber(avgConversationTokens)} tokens`
);
console.log(` Actual compression: ${actualReduction}%`);
console.log(` Actual context freed: ${formatNumber(improvement)} tokens`);
console.log("");
console.log(" CLAIM VALIDATION:");
console.log(" -----------------");
const claimedReduction = "85-98%";
const claimedHandoff = "1K-5K tokens";
const claimedConversation = "50K-150K tokens";
console.log(` Claimed reduction: ${claimedReduction}`);
console.log(` Measured reduction: ${actualReduction}%`);
console.log(
` Status: ${parseFloat(actualReduction) >= 85 ? "VALIDATED" : "NEEDS REVISION"}`
);
console.log("");
console.log(` Claimed handoff size: ${claimedHandoff}`);
console.log(
` Measured handoff size: ${formatNumber(avgHandoffTokens)} tokens`
);
console.log(
` Status: ${avgHandoffTokens >= 1e3 && avgHandoffTokens <= 5e3 ? "VALIDATED" : "NEEDS REVISION"}`
);
console.log("");
console.log(` Claimed conversation: ${claimedConversation}`);
console.log(
` Measured conversation: ${formatNumber(avgConversationTokens)} tokens`
);
console.log(
` Status: ${avgConversationTokens >= 5e4 && avgConversationTokens <= 15e4 ? "VALIDATED" : "NEEDS REVISION"}`
);
}
main().catch(console.error);
//# sourceMappingURL=measure-handoff-impact.js.map