openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
57 lines (56 loc) • 1.94 kB
JavaScript
import { t as parseJsonWithJson5Fallback } from "./parse-json-compat-DvZKmwhP.js";
import { r as INCLUDE_KEY } from "./includes-Cf57krG9.js";
import path from "node:path";
import * as fs$1 from "node:fs/promises";
//#region src/config/includes-scan.ts
function listDirectIncludes(parsed) {
const out = [];
const visit = (value) => {
if (!value) return;
if (Array.isArray(value)) {
for (const item of value) visit(item);
return;
}
if (typeof value !== "object") return;
const rec = value;
const includeVal = rec[INCLUDE_KEY];
if (typeof includeVal === "string") out.push(includeVal);
else if (Array.isArray(includeVal)) {
for (const item of includeVal) if (typeof item === "string") out.push(item);
}
for (const v of Object.values(rec)) visit(v);
};
visit(parsed);
return out;
}
function resolveIncludePath(baseConfigPath, includePath) {
return path.normalize(path.isAbsolute(includePath) ? includePath : path.resolve(path.dirname(baseConfigPath), includePath));
}
/** Collects recursively referenced config include files without requiring a valid full config. */
async function collectIncludePathsRecursive(params) {
const visited = /* @__PURE__ */ new Set();
const result = [];
const walk = async (basePath, parsed, depth) => {
if (depth > 10) return;
for (const raw of listDirectIncludes(parsed)) {
const resolved = resolveIncludePath(basePath, raw);
if (visited.has(resolved)) continue;
visited.add(resolved);
result.push(resolved);
const rawText = await fs$1.readFile(resolved, "utf-8").catch(() => null);
if (!rawText) continue;
const nestedParsed = (() => {
try {
return parseJsonWithJson5Fallback(rawText);
} catch {
return null;
}
})();
if (nestedParsed) await walk(resolved, nestedParsed, depth + 1);
}
};
await walk(params.configPath, params.parsed, 0);
return result;
}
//#endregion
export { collectIncludePathsRecursive as t };