import path from "node:path"; import { fileURLToPath } from "node:url"; import { runCommandWithTimeout } from "../process/exec.js"; import { defaultRuntime, type RuntimeEnv } from "../runtime.js"; import * as controlUiFsRuntime from "./control-ui-assets.fs.runtime.js"; import { resolveOpenClawPackageRoot, resolveOpenClawPackageRootSync } from "./openclaw-root.js";
const CONTROL_UI_DIST_PATH_SEGMENTS = ["dist", "control-ui", "index.html"] as const;
export function resolveControlUiDistIndexPathForRoot(root: string): string { return path.join(root, ...CONTROL_UI_DIST_PATH_SEGMENTS);
}
// Case 1: entrypoint is directly inside dist/ (e.g., dist/entry.js). // Include symlink-resolved argv1 so global wrappers (e.g. Bun) still map to dist/control-ui. for (const entrypoint of entrypointCandidates) { const distDir = path.dirname(entrypoint); if (path.basename(distDir) === "dist") { return path.join(distDir, "control-ui", "index.html");
}
}
// Fallback: traverse up and find package.json with name "openclaw" + dist/control-ui/index.html // This handles global installs where path-based resolution might fail. const fallbackStartDirs = new Set(
entrypointCandidates.map((candidate) => path.dirname(candidate)),
); for (const startDir of fallbackStartDirs) {
let dir = startDir; for (let i = 0; i < 8; i++) { const pkgJsonPath = path.join(dir, "package.json"); const indexPath = path.join(dir, "dist", "control-ui", "index.html"); if (controlUiFsRuntime.existsSync(pkgJsonPath)) { try { const raw = controlUiFsRuntime.readFileSync(pkgJsonPath, "utf-8"); const parsed = JSON.parse(raw) as { name?: unknown }; if (parsed.name === "openclaw") { return controlUiFsRuntime.existsSync(indexPath) ? indexPath : null;
} // Stop at the first package boundary to avoid resolving through unrelated ancestors. break;
} catch { // Invalid package.json at package boundary; abort this candidate chain. break;
}
} const parent = path.dirname(dir); if (parent === dir) { break;
}
dir = parent;
}
}
for (const dir of candidates) { const indexPath = path.join(dir, "index.html"); if (controlUiFsRuntime.existsSync(indexPath)) { return dir;
}
} returnnull;
}
if (!controlUiFsRuntime.existsSync(indexPath)) { return {
ok: false,
built: true,
message: `Control UI build completed but ${indexPath} is still missing.`,
};
}
return { ok: true, built: true };
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.4Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.