@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.
89 lines (88 loc) • 2.89 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 { basename } from "path";
const ESC = "\x1B";
const SAVE_CURSOR = `${ESC}7`;
const RESTORE_CURSOR = `${ESC}8`;
const CLEAR_LINE = `${ESC}[2K`;
const RESET = `${ESC}[0m`;
const BG_DARK = `${ESC}[48;5;236m`;
const FG_GRAY = `${ESC}[38;5;244m`;
const FG_CYAN = `${ESC}[38;5;37m`;
const FG_DIM = `${ESC}[2m`;
const BOLD = `${ESC}[1m`;
function moveTo(row, col) {
return `${ESC}[${row};${col}H`;
}
class StatusBar {
rows;
cols;
visible = false;
currentPrediction = "";
currentFile = "";
constructor() {
this.rows = process.stdout.rows || 24;
this.cols = process.stdout.columns || 80;
}
show(prediction, filePath, latencyMs) {
this.currentPrediction = prediction;
this.currentFile = filePath;
this.visible = true;
const file = basename(filePath);
const preview = this.truncatePreview(prediction);
const latency = `${latencyMs}ms`;
const label = `${FG_CYAN}${BOLD}[Sweep]${RESET}${BG_DARK}`;
const fileInfo = `${FG_GRAY} ${file}${RESET}${BG_DARK}`;
const content = `${FG_GRAY} ${preview}${RESET}${BG_DARK}`;
const time = `${FG_DIM}${BG_DARK} ${latency}${RESET}${BG_DARK}`;
const keys = `${BOLD}${BG_DARK} [Tab]${RESET}${BG_DARK}${FG_GRAY} Accept ${BOLD}${BG_DARK}[Esc]${RESET}${BG_DARK}${FG_GRAY} Dismiss${RESET}`;
const bar = `${BG_DARK}${label}${fileInfo}${content}${time}${keys}${RESET}`;
this.render(bar);
}
showLoading() {
this.visible = true;
const bar = `${BG_DARK}${FG_CYAN}${BOLD}[Sweep]${RESET}${BG_DARK}${FG_GRAY} Predicting next edit...${RESET}`;
this.render(bar);
}
hide() {
if (!this.visible) return;
this.visible = false;
this.currentPrediction = "";
this.currentFile = "";
const output = SAVE_CURSOR + moveTo(this.rows, 1) + CLEAR_LINE + RESTORE_CURSOR;
process.stdout.write(output);
}
resize(rows, cols) {
this.rows = rows;
this.cols = cols;
if (this.visible && this.currentPrediction) {
this.show(this.currentPrediction, this.currentFile, 0);
}
}
isVisible() {
return this.visible;
}
render(content) {
if (!process.stdout.isTTY) return;
const output = SAVE_CURSOR + moveTo(this.rows, 1) + CLEAR_LINE + content + RESTORE_CURSOR;
process.stdout.write(output);
}
truncatePreview(prediction) {
const lines = prediction.trim().split("\n");
let preview = lines[0] || "";
const maxLen = Math.max(10, this.cols - 55);
if (preview.length > maxLen) {
preview = preview.slice(0, maxLen - 3) + "...";
}
if (lines.length > 1) {
preview += ` (+${lines.length - 1} lines)`;
}
return preview;
}
}
export {
StatusBar
};
//# sourceMappingURL=status-bar.js.map