@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
92 lines (91 loc) • 2.38 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 { execFileSync } from "child_process";
function getCurrentBranch(cwd) {
try {
return execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
cwd: cwd || process.cwd(),
encoding: "utf-8",
stdio: ["pipe", "pipe", "pipe"]
}).trim();
} catch {
return "unknown";
}
}
function detectBaseBranch(cwd) {
const dir = cwd || process.cwd();
for (const base of ["main", "master", "develop"]) {
try {
execFileSync("git", ["rev-parse", "--verify", base], {
cwd: dir,
encoding: "utf-8",
stdio: "pipe"
});
return base;
} catch {
continue;
}
}
return "main";
}
function getDiffStats(baseBranch, cwd) {
try {
const output = execFileSync(
"git",
["diff", "--name-status", `${baseBranch}...HEAD`],
{ cwd: cwd || process.cwd(), encoding: "utf-8", timeout: 1e4 }
);
const changed = [];
const created = [];
const deleted = [];
for (const line of output.split("\n").filter((l) => l.trim())) {
const [status, ...pathParts] = line.split(" ");
const filePath = pathParts.join(" ");
if (!filePath) continue;
switch (status.charAt(0)) {
case "A":
created.push(filePath);
break;
case "D":
deleted.push(filePath);
break;
case "M":
case "R":
case "C":
changed.push(filePath);
break;
}
}
return { changed, created, deleted };
} catch {
return { changed: [], created: [], deleted: [] };
}
}
function getCommitsSince(baseBranch, cwd) {
try {
const output = execFileSync(
"git",
[
"log",
`${baseBranch}..HEAD`,
"--pretty=format:%H%x00%s%x00%an%x00%aI",
"--no-merges"
],
{ cwd: cwd || process.cwd(), encoding: "utf-8", timeout: 1e4 }
);
return output.split("\n").filter((l) => l.trim()).map((line) => {
const [hash, message, author, date] = line.split("\0");
return { hash, message, author, date };
});
} catch {
return [];
}
}
export {
detectBaseBranch,
getCommitsSince,
getCurrentBranch,
getDiffStats
};