@stackmemoryai/stackmemory
Version:
Lossless, project-scoped memory for AI coding tools. Durable context across sessions with 56 MCP tools, FTS5 search, conductor orchestrator, loop/watch monitoring, snapshot capture, pre-flight overlap checks, Claude/Codex/OpenCode wrappers, Linear sync, a
189 lines (188 loc) • 5.09 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 { existsSync, readFileSync, writeFileSync } from "fs";
import { join } from "path";
function _getEnv(key, defaultValue) {
const value = process.env[key];
if (value === void 0) {
if (defaultValue !== void 0) return defaultValue;
throw new Error(`Environment variable ${key} is required`);
}
return value;
}
function _getOptionalEnv(key) {
return process.env[key];
}
class ProgressTracker {
progressFile;
data;
constructor(projectRoot) {
this.progressFile = join(projectRoot, ".stackmemory", "progress.json");
this.data = this.load();
}
/**
* Load progress data from file
*/
load() {
if (existsSync(this.progressFile)) {
try {
const content = readFileSync(this.progressFile, "utf-8");
return JSON.parse(content);
} catch {
}
}
return {
version: process.env["npm_package_version"] || "0.2.3",
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
recentChanges: []
};
}
/**
* Save progress data to file
*/
save() {
this.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
writeFileSync(this.progressFile, JSON.stringify(this.data, null, 2));
}
/**
* Start a new session
*/
startSession() {
this.data.currentSession = {
startTime: (/* @__PURE__ */ new Date()).toISOString(),
tasksCompleted: [],
inProgress: []
};
this.save();
}
/**
* Add a task as in progress
*/
startTask(task) {
if (!this.data.currentSession) {
this.startSession();
}
if (this.data.currentSession.inProgress.indexOf(task) === -1) {
this.data.currentSession.inProgress.push(task);
}
this.save();
}
/**
* Mark a task as completed
*/
completeTask(task, changes) {
if (!this.data.currentSession) {
this.startSession();
}
const index = this.data.currentSession.inProgress.indexOf(task);
if (index > -1) {
this.data.currentSession.inProgress.splice(index, 1);
}
this.data.currentSession.tasksCompleted.push({
task,
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
status: "completed",
changes
});
this.save();
}
/**
* Add a recent change
*/
addChange(change) {
this.data.recentChanges.unshift(change);
if (this.data.recentChanges.length > 20) {
this.data.recentChanges = this.data.recentChanges.slice(0, 20);
}
this.save();
}
/**
* Update Linear integration status
*/
updateLinearStatus(status) {
if (!this.data.linearIntegration) {
this.data.linearIntegration = {
status: "active"
};
}
Object.assign(this.data.linearIntegration, status);
this.save();
}
/**
* Add a note
*/
addNote(note) {
if (!this.data.notes) {
this.data.notes = [];
}
this.data.notes.unshift(note);
if (this.data.notes.length > 10) {
this.data.notes = this.data.notes.slice(0, 10);
}
this.save();
}
/**
* Get current progress
*/
getProgress() {
return this.data;
}
/**
* Get summary for display
*/
getSummary() {
const lines = [];
lines.push(`\u{1F4CA} StackMemory Progress (v${this.data.version})`);
lines.push(`Last updated: ${this.data.lastUpdated}`);
if (this.data.currentSession) {
lines.push("\n\u{1F4CD} Current Session:");
lines.push(` Started: ${this.data.currentSession.startTime}`);
lines.push(
` Completed: ${this.data.currentSession.tasksCompleted.length} tasks`
);
if (this.data.currentSession.inProgress.length > 0) {
lines.push(` In Progress:`);
this.data.currentSession.inProgress.forEach((task) => {
lines.push(` - ${task}`);
});
}
}
if (this.data.recentChanges.length > 0) {
lines.push("\n\u{1F504} Recent Changes:");
this.data.recentChanges.slice(0, 5).forEach((change) => {
lines.push(` [${change.date}] ${change.type}: ${change.description}`);
});
}
if (this.data.linearIntegration) {
lines.push("\n\u{1F517} Linear Integration:");
lines.push(` Status: ${this.data.linearIntegration.status}`);
if (this.data.linearIntegration.lastSync) {
lines.push(` Last sync: ${this.data.linearIntegration.lastSync}`);
}
if (this.data.linearIntegration.tasksSynced) {
lines.push(
` Tasks synced: ${this.data.linearIntegration.tasksSynced}`
);
}
}
if (this.data.notes && this.data.notes.length > 0) {
lines.push("\n\u{1F4DD} Recent Notes:");
this.data.notes.slice(0, 3).forEach((note) => {
lines.push(` \u2022 ${note}`);
});
}
return lines.join("\n");
}
/**
* Clear current session
*/
endSession() {
delete this.data.currentSession;
this.save();
}
}
export {
ProgressTracker
};