UNPKG

@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.

150 lines (149 loc) 4.13 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; import { join } from "path"; import { homedir } from "os"; const DEFAULT_DAEMON_CONFIG = { version: "1.0.0", context: { enabled: true, interval: 15, // 15 minutes checkpointMessage: "Auto-checkpoint" }, linear: { enabled: false, // Disabled by default, requires setup interval: 60, // 60 minutes quietHours: { start: 22, end: 7 }, retryAttempts: 3, retryDelay: 3e4 }, fileWatch: { enabled: false, // Disabled by default interval: 0, // Not interval-based paths: ["."], extensions: [".ts", ".js", ".tsx", ".jsx", ".py", ".go", ".rs"], ignore: ["node_modules", ".git", "dist", "build", ".stackmemory"], debounceMs: 2e3 }, heartbeatInterval: 60, // 1 minute inactivityTimeout: 0, // Disabled by default logLevel: "info" }; function getDaemonDir() { const dir = join(homedir(), ".stackmemory", "daemon"); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } return dir; } function getLogsDir() { const dir = join(homedir(), ".stackmemory", "logs"); if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } return dir; } function getDaemonPaths() { const daemonDir = getDaemonDir(); const logsDir = getLogsDir(); return { pidFile: join(daemonDir, "daemon.pid"), statusFile: join(daemonDir, "daemon.status"), configFile: join(daemonDir, "config.json"), logFile: join(logsDir, "daemon.log") }; } function loadDaemonConfig() { const { configFile } = getDaemonPaths(); if (!existsSync(configFile)) { return { ...DEFAULT_DAEMON_CONFIG }; } try { const content = readFileSync(configFile, "utf8"); const config = JSON.parse(content); return { ...DEFAULT_DAEMON_CONFIG, ...config, context: { ...DEFAULT_DAEMON_CONFIG.context, ...config.context }, linear: { ...DEFAULT_DAEMON_CONFIG.linear, ...config.linear }, fileWatch: { ...DEFAULT_DAEMON_CONFIG.fileWatch, ...config.fileWatch } }; } catch { return { ...DEFAULT_DAEMON_CONFIG }; } } function saveDaemonConfig(config) { const { configFile } = getDaemonPaths(); const currentConfig = loadDaemonConfig(); const newConfig = { ...currentConfig, ...config, context: { ...currentConfig.context, ...config.context }, linear: { ...currentConfig.linear, ...config.linear }, fileWatch: { ...currentConfig.fileWatch, ...config.fileWatch } }; writeFileSync(configFile, JSON.stringify(newConfig, null, 2)); } function readDaemonStatus() { const { statusFile, pidFile } = getDaemonPaths(); const defaultStatus = { running: false, services: { context: { enabled: false }, linear: { enabled: false }, fileWatch: { enabled: false } }, errors: [] }; if (!existsSync(pidFile)) { return defaultStatus; } try { const pidContent = readFileSync(pidFile, "utf8").trim(); const pid = parseInt(pidContent, 10); try { process.kill(pid, 0); } catch { return defaultStatus; } if (!existsSync(statusFile)) { return { ...defaultStatus, running: true, pid }; } const content = readFileSync(statusFile, "utf8"); const status = JSON.parse(content); return { ...status, running: true, pid, uptime: status.startTime ? Date.now() - status.startTime : void 0 }; } catch { return defaultStatus; } } function writeDaemonStatus(status) { const { statusFile } = getDaemonPaths(); const currentStatus = readDaemonStatus(); const newStatus = { ...currentStatus, ...status }; writeFileSync(statusFile, JSON.stringify(newStatus, null, 2)); } export { DEFAULT_DAEMON_CONFIG, getDaemonDir, getDaemonPaths, getLogsDir, loadDaemonConfig, readDaemonStatus, saveDaemonConfig, writeDaemonStatus }; //# sourceMappingURL=daemon-config.js.map