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.

152 lines (151 loc) 3.5 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, readFileSync } from "fs"; import { join } from "path"; import { homedir } from "os"; import { writeFileSecure, ensureSecureDir } from "./secure-fs.js"; import { AutoBackgroundConfigSchema, parseConfigSafe } from "./schemas.js"; const DEFAULT_CONFIG = { enabled: true, timeoutMs: 5e3, // 5 seconds alwaysBackground: [ // Package managers "npm install", "npm ci", "yarn install", "pnpm install", "bun install", // Builds "npm run build", "yarn build", "pnpm build", "cargo build", "go build", "make", "cmake", // Tests "npm test", "npm run test", "yarn test", "pnpm test", "pytest", "jest", "vitest", "cargo test", "go test", // Docker "docker build", "docker-compose up", "docker compose up", // Git operations that can be slow "git clone", "git fetch --all", "git pull --all", // Type checking "npx tsc", "tsc --noEmit", // Linting large codebases "eslint .", "npm run lint" ], neverBackground: [ // Interactive commands "vim", "nvim", "nano", "less", "more", "top", "htop", // Quick commands "echo", "cat", "ls", "pwd", "cd", "which", "git status", "git diff", "git log" ], verbose: false }; const CONFIG_PATH = join(homedir(), ".stackmemory", "auto-background.json"); function loadConfig() { try { if (existsSync(CONFIG_PATH)) { const data = readFileSync(CONFIG_PATH, "utf8"); const parsed = JSON.parse(data); return parseConfigSafe( AutoBackgroundConfigSchema, { ...DEFAULT_CONFIG, ...parsed }, DEFAULT_CONFIG, "auto-background" ); } } catch { } return DEFAULT_CONFIG; } function saveConfig(config) { try { ensureSecureDir(join(homedir(), ".stackmemory")); writeFileSecure(CONFIG_PATH, JSON.stringify(config, null, 2)); } catch { } } function shouldAutoBackground(command, config) { const cfg = config || loadConfig(); if (!cfg.enabled) return false; const normalizedCmd = command.trim().toLowerCase(); for (const pattern of cfg.neverBackground) { if (normalizedCmd.startsWith(pattern.toLowerCase())) { return false; } } for (const pattern of cfg.alwaysBackground) { if (normalizedCmd.startsWith(pattern.toLowerCase())) { return true; } } return false; } function processToolUse(toolName, toolInput) { if (toolName !== "Bash") { return { decision: "allow" }; } const command = toolInput.command; if (!command) { return { decision: "allow" }; } if (toolInput.run_in_background === true) { return { decision: "allow" }; } const config = loadConfig(); if (shouldAutoBackground(command, config)) { if (config.verbose) { console.error( `[auto-background] Backgrounding: ${command.substring(0, 50)}...` ); } return { decision: "modify", modifiedInput: { ...toolInput, run_in_background: true }, reason: `Auto-backgrounded: matches pattern` }; } return { decision: "allow" }; } export { loadConfig, processToolUse, saveConfig, shouldAutoBackground }; //# sourceMappingURL=auto-background.js.map