@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
61 lines (60 loc) • 1.85 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 * as path from "path";
class ProjectRegistryManager {
constructor(adapter) {
this.adapter = adapter;
}
/** Register a new project */
async register(projectId, repoPath, displayName) {
const dbPath = this.computeDbPath(repoPath);
await this.adapter.registerProject({
projectId,
repoPath,
displayName,
dbPath
});
}
/** List all registered projects */
async list() {
return this.adapter.getRegisteredProjects();
}
/** Switch active project */
async switchTo(projectId) {
const projects = await this.list();
if (!projects.find((p) => p.projectId === projectId)) return false;
await this.adapter.setActiveProject(projectId);
return true;
}
/** Remove a project from registry (doesn't delete data) */
async remove(projectId) {
return this.adapter.removeProject(projectId);
}
/** Get current active project */
async getActive() {
const activeId = await this.adapter.getActiveProject();
if (!activeId) return null;
const projects = await this.list();
return projects.find((p) => p.projectId === activeId) || null;
}
/** Auto-detect project from cwd */
async detectAndRegister(cwd) {
const projectId = path.basename(cwd);
const existing = await this.list();
const found = existing.find((p) => p.repoPath === cwd);
if (found) {
await this.adapter.touchProject(found.projectId);
return found.projectId;
}
await this.register(projectId, cwd);
return projectId;
}
computeDbPath(repoPath) {
return path.join(repoPath, ".stackmemory", "memory.db");
}
}
export {
ProjectRegistryManager
};