Files
claw/frontend/scene-generator/config-loader.js

105 lines
3.0 KiB
JavaScript

const fs = require("fs");
const path = require("path");
function resolveProjectRoot() {
const envRoot = process.env.SGCLAW_PROJECT_ROOT;
if (envRoot && fs.existsSync(envRoot)) {
return path.resolve(envRoot);
}
// Search for Cargo.toml to find the actual project root
const candidates = [
path.resolve(__dirname, "..", ".."), // claw-new (has Cargo.toml)
path.resolve(__dirname, "..", "..", "..", "claw-new"), // sgClaw/claw-new
path.resolve(__dirname, "..", "..", ".."), // sgClaw root
];
for (const p of candidates) {
if (fs.existsSync(path.join(p, "Cargo.toml"))) {
return p;
}
}
// Fallback: directory containing sgclaw_config.json
const configPath = resolveConfigPath();
if (configPath && fs.existsSync(configPath)) {
return path.dirname(configPath);
}
return path.resolve(__dirname);
}
function resolveConfigPath() {
const envPath = process.env.SGCLAW_CONFIG_PATH;
if (envPath && fs.existsSync(envPath)) {
return path.resolve(envPath);
}
const candidates = [
path.resolve(__dirname, "..", "..", "..", "sgclaw_config.json"), // Parent sgClaw directory
path.resolve(__dirname, "..", "..", "sgclaw_config.json"), // claw-new/sgclaw_config.json
path.resolve(__dirname, "..", "sgclaw_config.json"), // frontend/sgclaw_config.json
path.resolve(__dirname, "sgclaw_config.json"), // scene-generator/sgclaw_config.json
];
for (const p of candidates) {
if (fs.existsSync(p)) return p;
}
return null;
}
function loadConfig() {
const configPath = resolveConfigPath();
if (!configPath) {
throw new Error(
"sgclaw_config.json not found. Set SGCLAW_CONFIG_PATH or place it in the project root."
);
}
const raw = fs.readFileSync(configPath, "utf-8");
const config = JSON.parse(raw);
const apiKey = config.apiKey || "";
const baseUrl = config.baseUrl || "";
const model = config.model || "";
if (!apiKey) throw new Error("sgclaw_config.json: 'apiKey' is required");
if (!baseUrl) throw new Error("sgclaw_config.json: 'baseUrl' is required");
if (!model) throw new Error("sgclaw_config.json: 'model' is required");
return {
apiKey,
baseUrl: normalizeBaseUrl(baseUrl),
model,
projectRoot: resolveProjectRoot(),
configPath,
};
}
function normalizeBaseUrl(url) {
url = url.replace(/\/+$/, "");
url = url.replace(/\/v1\/?$/, "");
return url + "/v1";
}
function getDefaults() {
const config = loadConfig();
const projectRoot = config.projectRoot;
return {
outputRoot: path.join(projectRoot, "examples", "generated_scene_platform"),
lessonsPath: path.join(
projectRoot,
"docs",
"superpowers",
"references",
"tq-lineloss-lessons-learned.toml"
),
llmBaseUrl: config.baseUrl,
llmModel: config.model,
};
}
module.exports = { loadConfig, getDefaults, resolveProjectRoot, resolveConfigPath };