File size: 4,669 Bytes
20f108c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | // Phantom β Session persistence + knowledge graph
// Saves/restores minimal state across restarts.
// Linked knowledge: tool β book/CVE cross-reference.
import fs from "fs";
import { resolve } from "path";
import { MEMORY_DIR } from "./config.mjs";
const SESSION_FILE = resolve(MEMORY_DIR, "session.json");
const GRAPH_FILE = resolve(MEMORY_DIR, "graph.json");
// ββ Session ββ
export function saveSession(data) {
try {
const dir = MEMORY_DIR;
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
const existing = loadSession();
const merged = { ...existing, ...data, savedAt: Date.now() };
fs.writeFileSync(SESSION_FILE, JSON.stringify(merged, null, 2), "utf-8");
return true;
} catch { return false; }
}
export function loadSession() {
try {
if (!fs.existsSync(SESSION_FILE)) return {};
return JSON.parse(fs.readFileSync(SESSION_FILE, "utf-8"));
} catch { return {}; }
}
export function clearSession() {
try { if (fs.existsSync(SESSION_FILE)) fs.unlinkSync(SESSION_FILE); } catch {}
}
// ββ Knowledge Graph ββ
// Links tools to related books/CVEs/techniques
// Format: { "tool_name": { books: ["book1", "book2"], cves: ["CVE-2025-..."], tags: ["xss", "sqli"] } }
export function loadGraph() {
try {
if (!fs.existsSync(GRAPH_FILE)) return {};
return JSON.parse(fs.readFileSync(GRAPH_FILE, "utf-8"));
} catch { return {}; }
}
export function saveGraph(graph) {
try {
const dir = MEMORY_DIR;
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(GRAPH_FILE, JSON.stringify(graph, null, 2), "utf-8");
return true;
} catch { return false; }
}
export function linkTool(toolName, { books = [], cves = [], tags = [] } = {}) {
const graph = loadGraph();
if (!graph[toolName]) graph[toolName] = { books: [], cves: [], tags: [] };
if (books.length) graph[toolName].books = [...new Set([...graph[toolName].books, ...books])];
if (cves.length) graph[toolName].cves = [...new Set([...graph[toolName].cves, ...cves])];
if (tags.length) graph[toolName].tags = [...new Set([...graph[toolName].tags, ...tags])];
saveGraph(graph);
return graph[toolName];
}
export function queryGraph(query) {
const graph = loadGraph();
const q = query.toLowerCase();
const results = [];
for (const [tool, info] of Object.entries(graph)) {
let score = 0;
if (tool.includes(q)) score += 10;
if (info.tags?.some(t => t.includes(q))) score += 5;
if (info.cves?.some(c => c.toLowerCase().includes(q))) score += 3;
if (info.books?.some(b => b.toLowerCase().includes(q))) score += 2;
// Partial match
const words = q.split(/\s+/);
for (const w of words) {
if (w.length < 2) continue;
if (tool.includes(w)) score += 3;
if (info.tags?.some(t => t.includes(w))) score += 2;
if (info.books?.some(b => b.toLowerCase().includes(w))) score += 1;
}
if (score > 0) results.push({ tool, ...info, score });
}
return results.sort((a, b) => (b.score || 0) - (a.score || 0));
}
// ββ Auto-link from books directory ββ
// Scans books/ for filenames matching tool categories
export function autoLinkFromBooks() {
const booksDir = resolve(MEMORY_DIR, "../books");
if (!fs.existsSync(booksDir)) return 0;
const files = fs.readdirSync(booksDir).filter(f => f.endsWith(".txt"));
const graph = loadGraph();
let linked = 0;
for (const file of files) {
const name = file.replace(".txt", "").toLowerCase();
// Map book names to tool tags
const tagMap = {
sql_injection: ["sql_detect", "sqlmap", "sqli", "sql_injection"],
xss: ["xss_scan", "xss"],
ssrf: ["ssrf", "ssrf_test"],
nmap: ["nmap", "port_scan", "network_scan"],
cve: ["cve_search", "searchsploit", "vuln_scan", "vulners"],
pentest: ["nuclei", "metasploit", "exploit", "pentest"],
owasp: ["wafw00f", "whatweb", "nikto", "dirb"],
methodology: ["recon", "enumeration", "osint"],
shannon: ["gap_analysis", "self_improve", "evolve"],
auto: ["self_improve", "evolve", "code_gen"],
tool: ["workflow", "automation", "batch"],
reference: ["hash", "encode", "decode", "crypto"],
};
for (const [tag, tools] of Object.entries(tagMap)) {
if (name.includes(tag) || tag.includes(name)) {
for (const t of tools) {
if (!graph[t]) graph[t] = { books: [], cves: [], tags: [] };
if (!graph[t].books.includes(file)) { graph[t].books.push(file); linked++; }
if (!graph[t].tags.includes(tag)) { graph[t].tags.push(tag); }
}
}
}
}
if (linked > 0) saveGraph(graph);
return linked;
}
|