Files
horus-3d/server/studio-settings.js
Luke The Dev 4fa4f13558 First Release of Claw3D (#11)
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
2026-03-19 23:14:04 -05:00

125 lines
3.6 KiB
JavaScript

const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const LEGACY_STATE_DIRNAMES = [".clawdbot", ".moltbot"];
const NEW_STATE_DIRNAME = ".openclaw";
const resolveUserPath = (input) => {
const trimmed = String(input ?? "").trim();
if (!trimmed) return trimmed;
if (trimmed.startsWith("~")) {
const expanded = trimmed.replace(/^~(?=$|[\\/])/, os.homedir());
return path.resolve(expanded);
}
return path.resolve(trimmed);
};
const resolveDefaultHomeDir = () => {
const home = os.homedir();
if (home) {
try {
if (fs.existsSync(home)) return home;
} catch {}
}
return os.tmpdir();
};
const resolveStateDir = (env = process.env) => {
const override =
env.OPENCLAW_STATE_DIR?.trim() ||
env.MOLTBOT_STATE_DIR?.trim() ||
env.CLAWDBOT_STATE_DIR?.trim();
if (override) return resolveUserPath(override);
const home = resolveDefaultHomeDir();
const newDir = path.join(home, NEW_STATE_DIRNAME);
const legacyDirs = LEGACY_STATE_DIRNAMES.map((dir) => path.join(home, dir));
try {
if (fs.existsSync(newDir)) return newDir;
} catch {}
for (const dir of legacyDirs) {
try {
if (fs.existsSync(dir)) return dir;
} catch {}
}
return newDir;
};
const resolveStudioSettingsPath = (env = process.env) => {
return path.join(resolveStateDir(env), "claw3d", "settings.json");
};
const readJsonFile = (filePath) => {
if (!fs.existsSync(filePath)) return null;
const raw = fs.readFileSync(filePath, "utf8");
return JSON.parse(raw);
};
const DEFAULT_GATEWAY_URL = "ws://localhost:18789";
const OPENCLAW_CONFIG_FILENAME = "openclaw.json";
const LOOPBACK_HOSTNAMES = new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
const isRecord = (value) => Boolean(value && typeof value === "object");
const isLocalGatewayUrl = (value) => {
const trimmed = typeof value === "string" ? value.trim() : "";
if (!trimmed) return false;
try {
const parsed = new URL(trimmed);
return LOOPBACK_HOSTNAMES.has(parsed.hostname.toLowerCase());
} catch {
return false;
}
};
const readOpenclawGatewayDefaults = (env = process.env) => {
try {
const stateDir = resolveStateDir(env);
const configPath = path.join(stateDir, OPENCLAW_CONFIG_FILENAME);
const parsed = readJsonFile(configPath);
if (!isRecord(parsed)) return null;
const gateway = isRecord(parsed.gateway) ? parsed.gateway : null;
if (!gateway) return null;
const auth = isRecord(gateway.auth) ? gateway.auth : null;
const token = typeof auth?.token === "string" ? auth.token.trim() : "";
const port =
typeof gateway.port === "number" && Number.isFinite(gateway.port) ? gateway.port : null;
if (!token) return null;
const url = port ? `ws://localhost:${port}` : "";
if (!url) return null;
return { url, token };
} catch {
return null;
}
};
const loadUpstreamGatewaySettings = (env = process.env) => {
const settingsPath = resolveStudioSettingsPath(env);
const parsed = readJsonFile(settingsPath);
const gateway = parsed && typeof parsed === "object" ? parsed.gateway : null;
const url = typeof gateway?.url === "string" ? gateway.url.trim() : "";
const token = typeof gateway?.token === "string" ? gateway.token.trim() : "";
if (!token && (!url || isLocalGatewayUrl(url))) {
const defaults = readOpenclawGatewayDefaults(env);
if (defaults) {
return {
url: url || defaults.url,
token: defaults.token,
settingsPath,
};
}
}
return {
url: url || DEFAULT_GATEWAY_URL,
token,
settingsPath,
};
};
module.exports = {
resolveStateDir,
resolveStudioSettingsPath,
loadUpstreamGatewaySettings,
};