CODE · 3.0 KB
tools/index-source-assets.mjs
Workspace snapshot · 09/04 14:52
import { promises as fs } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const workspace = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const registryPath = path.join(workspace, "config", "source-registry.json");
const outputPath = path.join(workspace, "knowledge", "source-inventory.json");
const summaryPath = path.join(workspace, "knowledge", "source-inventory.md");
const ignored = new Set(["node_modules", ".git", "dist", "build", "vendor", "logs", "output"]);
async function scanLocalSource(source) {
const extensions = new Set(source.extensions || []);
const stack = [source.location];
let files = 0;
let bytes = 0;
let oldest = null;
let newest = null;
while (stack.length) {
const current = stack.pop();
let entries;
try {
entries = await fs.readdir(current, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
if (ignored.has(entry.name)) continue;
const fullPath = path.join(current, entry.name);
if (entry.isDirectory()) {
stack.push(fullPath);
continue;
}
if (!entry.isFile() || (extensions.size && !extensions.has(path.extname(entry.name).toLowerCase()))) continue;
try {
const stat = await fs.stat(fullPath);
const modified = stat.mtime.toISOString();
files += 1;
bytes += stat.size;
if (!oldest || modified < oldest) oldest = modified;
if (!newest || modified > newest) newest = modified;
} catch {
// A disconnected Drive item must not abort the whole inventory.
}
}
}
return { ...source, status: files ? "INDEXED" : "EMPTY_OR_UNAVAILABLE", files, bytes, oldest, newest };
}
const registry = JSON.parse(await fs.readFile(registryPath, "utf8"));
const results = [];
for (const source of registry.sources) {
if (["session", "local-project-assets"].includes(source.kind)) results.push(await scanLocalSource(source));
else results.push({ ...source, status: "REGISTERED_EXTERNAL" });
}
const inventory = { generatedAt: new Date().toISOString(), version: registry.version, sources: results };
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(outputPath, `${JSON.stringify(inventory, null, 2)}\n`, "utf8");
const rows = results.map((item) => `| ${item.id} | ${item.kind} | ${item.classification} | ${item.files ?? item.observedMinimumCount ?? "—"} | ${item.status} |`);
const markdown = [
"# Source Inventory",
"",
`Generated: ${inventory.generatedAt}`,
"",
"| Source | Kind | Classification | Files / observed minimum | Status |",
"|---|---|---|---:|---|",
...rows,
"",
"This inventory stores counts and source locations only. It does not copy session, meeting, chat, or client content.",
""
].join("\n");
await fs.writeFile(summaryPath, markdown, "utf8");
console.log(JSON.stringify({ outputPath, summaryPath, sources: results.map(({ id, files, status }) => ({ id, files, status })) }, null, 2));