mirror of
https://github.com/Heretek-AI/openclaw.git
synced 2026-07-19 19:23:35 -04:00
141 lines
4.6 KiB
JavaScript
141 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Build script using rolldown directly (tsdown's underlying bundler)
|
|
* This avoids the Node.js ESM loader bug (ERR_INTERNAL_ASSERTION)
|
|
* that affects tsdown 0.17.4-0.21.4 on Node.js 20+
|
|
*
|
|
* Root cause: tsdown's bundled code uses createRequire(import.meta.url)
|
|
* which triggers an assertion failure in Node.js 20+ ESM translator.
|
|
* See: https://github.com/nodejs/node/issues/51896
|
|
*/
|
|
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { build } from "rolldown";
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const rootDir = path.resolve(__dirname, "..");
|
|
|
|
const logLevel = process.env.OPENCLAW_BUILD_VERBOSE ? "info" : "silent";
|
|
|
|
function removeDistPluginNodeModulesSymlinks(rootDir) {
|
|
const extensionsDir = path.join(rootDir, "extensions");
|
|
if (!fs.existsSync(extensionsDir)) {
|
|
return;
|
|
}
|
|
|
|
for (const dirent of fs.readdirSync(extensionsDir, { withFileTypes: true })) {
|
|
if (!dirent.isDirectory()) {
|
|
continue;
|
|
}
|
|
const nodeModulesPath = path.join(extensionsDir, dirent.name, "node_modules");
|
|
try {
|
|
if (fs.lstatSync(nodeModulesPath).isSymbolicLink()) {
|
|
fs.rmSync(nodeModulesPath, { force: true, recursive: true });
|
|
}
|
|
} catch {
|
|
// Skip missing or unreadable paths
|
|
}
|
|
}
|
|
}
|
|
|
|
function pruneStaleRuntimeSymlinks() {
|
|
const cwd = process.cwd();
|
|
removeDistPluginNodeModulesSymlinks(path.join(cwd, "dist"));
|
|
removeDistPluginNodeModulesSymlinks(path.join(cwd, "dist-runtime"));
|
|
}
|
|
|
|
pruneStaleRuntimeSymlinks();
|
|
|
|
async function runBuild() {
|
|
try {
|
|
if (logLevel === "info") {
|
|
console.log("Starting rolldown build...");
|
|
}
|
|
|
|
// Build configuration matching tsdown setup from tsdown.config.ts
|
|
// Use the official plugin-sdk entry list
|
|
const { buildPluginSdkEntrySources } = await import("../scripts/lib/plugin-sdk-entries.mjs");
|
|
const pluginSdkEntries = buildPluginSdkEntrySources();
|
|
|
|
const entryPoints = {
|
|
index: "src/index.ts",
|
|
entry: "src/entry.ts",
|
|
"cli/daemon-cli": "src/cli/daemon-cli.ts",
|
|
"cli/memory-cli": "src/cli/memory-cli.ts",
|
|
extensionAPI: "src/extensionAPI.ts",
|
|
"infra/warning-filter": "src/infra/warning-filter.ts",
|
|
"telegram/audit": "extensions/telegram/src/audit.ts",
|
|
"telegram/token": "extensions/telegram/src/token.ts",
|
|
// memory-core extension — compiled fresh so chunk hashes match the build
|
|
"extensions/memory-core/index": "extensions/memory-core/index.ts",
|
|
"plugins/build-smoke-entry": "src/plugins/build-smoke-entry.ts",
|
|
"plugins/runtime/index": "src/plugins/runtime/index.ts",
|
|
"llm-slug-generator": "src/hooks/llm-slug-generator.ts",
|
|
// Add plugin-sdk entries
|
|
...Object.fromEntries(
|
|
Object.entries(pluginSdkEntries).map(([entry, source]) => [`plugin-sdk/${entry}`, source]),
|
|
),
|
|
};
|
|
|
|
// Add bundled plugin entries
|
|
const pluginsRoot = path.join(rootDir, "src", "plugins", "bundled");
|
|
if (fs.existsSync(pluginsRoot)) {
|
|
for (const dirent of fs.readdirSync(pluginsRoot, { withFileTypes: true })) {
|
|
if (!dirent.isDirectory()) {
|
|
continue;
|
|
}
|
|
const handlerPath = path.join(pluginsRoot, dirent.name, "handler.ts");
|
|
if (fs.existsSync(handlerPath)) {
|
|
entryPoints[`bundled/${dirent.name}/handler`] = handlerPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add bundled hook entries
|
|
const hooksRoot = path.join(rootDir, "src", "hooks", "bundled");
|
|
if (fs.existsSync(hooksRoot)) {
|
|
for (const dirent of fs.readdirSync(hooksRoot, { withFileTypes: true })) {
|
|
if (!dirent.isDirectory()) {
|
|
continue;
|
|
}
|
|
const handlerPath = path.join(hooksRoot, dirent.name, "handler.ts");
|
|
if (fs.existsSync(handlerPath)) {
|
|
entryPoints[`bundled/${dirent.name}/handler`] = handlerPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build with rolldown - externalize all node_modules
|
|
await build({
|
|
input: entryPoints,
|
|
cwd: rootDir,
|
|
output: {
|
|
dir: "dist",
|
|
format: "esm",
|
|
entryFileNames: "[name].mjs",
|
|
chunkFileNames: "chunks/[name]-[hash].mjs",
|
|
},
|
|
platform: "node",
|
|
// Externalize all packages - match any bare specifier (no . or / prefix)
|
|
external: (id) => !id.startsWith(".") && !id.startsWith("/") && !id.startsWith(rootDir),
|
|
treeshake: true,
|
|
});
|
|
|
|
if (logLevel === "info") {
|
|
console.log("rolldown build completed successfully");
|
|
}
|
|
process.exit(0);
|
|
} catch (error) {
|
|
console.error("Build failed:", error.message);
|
|
if (error.stack && logLevel === "info") {
|
|
console.error(error.stack);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
void runBuild();
|