Files
mp-silma-ai-aide/scripts/generate-local-context.mjs
T

231 lines
6.0 KiB
JavaScript
Raw Normal View History

import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
import { basename, join, relative } from "node:path";
import { execFileSync } from "node:child_process";
2026-07-24 11:02:27 -05:00
import { fileURLToPath } from "node:url";
2026-07-24 11:02:27 -05:00
export const workspaceRoot =
process.env.WORKSPACE_FATHER_PATH || "/Users/Tabitha/.openclaw/workspace_Father";
const outputPath = join(process.cwd(), "public", "local-context.json");
const giteaBaseUrl = "http://gitea.orson.tealthrone";
2026-07-21 07:42:30 -05:00
const folderSearchRoots = (process.env.WORKSPACE_FOLDER_SEARCH_ROOTS || `/Users/Tabitha,${workspaceRoot}`)
.split(",")
.map((root) => root.trim())
.filter(Boolean);
const folderSearchMaxDepth = Number(process.env.WORKSPACE_FOLDER_SEARCH_MAX_DEPTH || 3);
const skippedFolderNames = new Set([
".git",
".Trash",
"Applications",
"Library",
"Movies",
"Music",
"node_modules",
"dist",
"build",
".next",
".vite"
]);
function runGit(args, cwd) {
try {
return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
} catch {
return "";
}
}
function findGitWorktrees(root, maxDepth = 4) {
const found = [];
function walk(dir, depth) {
if (depth > maxDepth) {
return;
}
if (existsSync(join(dir, ".git"))) {
found.push(dir);
return;
}
let entries = [];
try {
entries = readdirSync(dir, { withFileTypes: true });
} catch {
return;
}
for (const entry of entries) {
if (!entry.isDirectory() || entry.name === "node_modules" || entry.name === ".git") {
continue;
}
walk(join(dir, entry.name), depth + 1);
}
}
walk(root, 0);
return found.sort();
}
2026-07-21 07:42:30 -05:00
function findFolderCandidates(roots, maxDepth = 3) {
const found = new Map();
function addCandidate(path, source) {
found.set(path, {
name: basename(path),
path,
source
});
}
function walk(dir, depth, source) {
if (depth > maxDepth || found.has(dir)) {
return;
}
addCandidate(dir, source);
let entries = [];
try {
entries = readdirSync(dir, { withFileTypes: true });
} catch {
return;
}
for (const entry of entries) {
if (!entry.isDirectory() || skippedFolderNames.has(entry.name)) {
continue;
}
walk(join(dir, entry.name), depth + 1, source);
}
}
for (const root of roots) {
if (!existsSync(root)) {
continue;
}
walk(root, 0, root === workspaceRoot ? "workspace-root" : "folder-search");
}
return Array.from(found.values())
.filter((candidate) => candidate.path !== "/Users/Tabitha")
.sort((a, b) => a.path.localeCompare(b.path))
.slice(0, 2000);
}
function normalizeGiteaRemote(remoteUrl) {
if (!remoteUrl) {
return null;
}
const match = remoteUrl.match(
/(?:gitea\.orson\.tealthrone|100\.79\.253\.19(?::3000)?)[/:]([^/]+)\/([^/.]+)(?:\.git)?$/
);
if (!match) {
return null;
}
const [, owner, name] = match;
return {
fullName: `${owner}/${name}`,
owner,
name,
webUrl: `${giteaBaseUrl}/${owner}/${name}`,
cloneUrl: `http://100.79.253.19:3000/${owner}/${name}.git`
};
}
function repoForWorktree(path) {
const remoteNames = runGit(["remote"], path).split(/\s+/).filter(Boolean);
const orderedNames = ["gitea", "hagia", "origin", ...remoteNames].filter((name, index, names) => {
return remoteNames.includes(name) && names.indexOf(name) === index;
});
for (const remoteName of orderedNames) {
const repo = normalizeGiteaRemote(runGit(["remote", "get-url", remoteName], path));
if (repo) {
return repo;
}
}
return null;
}
2026-07-24 11:02:27 -05:00
export function buildContext() {
const topLevelWorkspaces = readdirSync(workspaceRoot, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => ({
name: entry.name,
path: join(workspaceRoot, entry.name)
}))
.sort((a, b) => a.name.localeCompare(b.name));
const gitWorktrees = findGitWorktrees(workspaceRoot).map((path) => {
const repo = repoForWorktree(path);
const topWorkspaceName = relative(workspaceRoot, path).split("/")[0] || basename(path);
return {
name: basename(path),
path,
relativePath: relative(workspaceRoot, path),
topWorkspaceName,
branch: runGit(["branch", "--show-current"], path) || null,
giteaRepo: repo
};
});
const workspaces = topLevelWorkspaces.map((workspace) => ({
...workspace,
linkedRepos: gitWorktrees
.filter((worktree) => worktree.topWorkspaceName === workspace.name && worktree.giteaRepo)
.map((worktree) => ({
worktreePath: worktree.path,
worktreeRelativePath: worktree.relativePath,
fullName: worktree.giteaRepo.fullName,
webUrl: worktree.giteaRepo.webUrl
}))
}));
const workspaceData = gitWorktrees.find(
(worktree) => worktree.path === join(workspaceRoot, "workspace_Data")
);
return {
generatedAt: "build-time-local-context",
workspaceRoot,
workspaces,
gitWorktrees,
2026-07-21 07:42:30 -05:00
folderCandidates: findFolderCandidates(folderSearchRoots, folderSearchMaxDepth),
knownUrls: [
{
label: "Automated Training Monitor",
url: "http://100.66.226.22:23030/",
workspacePath: join(workspaceRoot, "workspace_Data"),
workspaceName: "workspace_Data",
giteaRepo: workspaceData?.giteaRepo ?? {
fullName: "jacob-mathison/home-grown-llm-data",
webUrl: `${giteaBaseUrl}/jacob-mathison/home-grown-llm-data`
}
}
]
};
}
2026-07-24 11:02:27 -05:00
export function writeLocalContext() {
mkdirSync(join(process.cwd(), "public"), { recursive: true });
2026-07-24 11:02:27 -05:00
if (!existsSync(workspaceRoot)) {
if (existsSync(outputPath)) {
console.log(`Workspace root missing; preserving ${outputPath}`);
return;
}
throw new Error(`Workspace root does not exist: ${workspaceRoot}`);
}
2026-07-24 11:02:27 -05:00
const context = buildContext();
writeFileSync(outputPath, `${JSON.stringify(context, null, 2)}\n`);
console.log(`Wrote ${outputPath} with ${context.workspaces.length} workspaces`);
}
2026-07-24 11:02:27 -05:00
if (process.argv[1] === fileURLToPath(import.meta.url)) {
writeLocalContext();
}