@openguardrails/moltguard
Version:
AI agent security plugin for OpenClaw: prompt injection detection, PII sanitization, and monitoring dashboard
137 lines • 3.88 kB
JavaScript
/**
* Workspace MD File Scanner
*
* Scans OpenClaw workspace for all .md files and categorizes them:
* - soul.md (agent personality)
* - agent.md (agent configuration)
* - memories/*.md (conversation memories)
* - heartbeat.md (task scheduler)
* - Other md files in workspace root
*/
import fs from "node:fs";
import path from "node:path";
import { openclawHome } from "./env.js";
/**
* Get OpenClaw workspace directory
*/
function getWorkspaceDir() {
return openclawHome;
}
/**
* Categorize file by path
*/
function categorizeFile(relativePath) {
const lower = relativePath.toLowerCase();
if (lower === "soul.md")
return "soul";
if (lower === "agent.md")
return "agent";
if (lower === "heartbeat.md")
return "task";
if (lower.startsWith("memories/") || lower.startsWith("memories\\"))
return "memory";
if (lower.startsWith("skills/") || lower.startsWith("skills\\"))
return "skill";
if (lower.startsWith("plugins/") || lower.startsWith("plugins\\"))
return "plugin";
return "other";
}
/**
* Recursively find all .md files in a directory
*/
async function findMdFiles(dir, baseDir) {
const files = [];
try {
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// Skip node_modules, .git, dist, build directories
if (["node_modules", ".git", "dist", "build", ".cache"].includes(entry.name)) {
continue;
}
// Recursively scan subdirectories
const subFiles = await findMdFiles(fullPath, baseDir);
files.push(...subFiles);
}
else if (entry.isFile() && entry.name.endsWith(".md")) {
const relativePath = path.relative(baseDir, fullPath);
files.push(relativePath);
}
}
}
catch {
// Ignore permission errors, etc.
}
return files;
}
/**
* Read file content safely
*/
async function readFileSafe(filePath) {
try {
return await fs.promises.readFile(filePath, "utf-8");
}
catch {
return null;
}
}
/**
* Scan workspace for all .md files
*/
export async function scanWorkspaceMdFiles() {
const workspaceDir = getWorkspaceDir();
const files = [];
// Find all .md files
const mdFiles = await findMdFiles(workspaceDir, workspaceDir);
// Read each file
for (const relativePath of mdFiles) {
const absolutePath = path.join(workspaceDir, relativePath);
const content = await readFileSafe(absolutePath);
if (content === null)
continue; // Skip unreadable files
const type = categorizeFile(relativePath);
const sizeBytes = Buffer.byteLength(content, "utf-8");
files.push({
path: relativePath,
absolutePath,
content,
type,
sizeBytes,
});
}
return files;
}
/**
* Scan specific file types
*/
export async function scanFilesByType(types) {
const allFiles = await scanWorkspaceMdFiles();
return allFiles.filter(f => types.includes(f.type));
}
/**
* Get summary of workspace files
*/
export async function getWorkspaceSummary() {
const files = await scanWorkspaceMdFiles();
const byType = {
soul: 0,
agent: 0,
memory: 0,
task: 0,
skill: 0,
plugin: 0,
other: 0,
};
let totalSizeBytes = 0;
for (const file of files) {
byType[file.type]++;
totalSizeBytes += file.sizeBytes;
}
return {
totalFiles: files.length,
byType,
totalSizeBytes,
};
}
//# sourceMappingURL=workspace-scanner.js.map