fix: ship bundled runtime support packages

This commit is contained in:
Peter Steinberger
2026-03-31 14:25:00 +01:00
parent 5b7443d175
commit 5a93344d82
4 changed files with 178 additions and 24 deletions

View File

@@ -26,6 +26,45 @@ export function rewritePackageExtensions(entries) {
});
}
function collectTopLevelPublicSurfaceEntries(pluginDir) {
if (!fs.existsSync(pluginDir)) {
return [];
}
return fs
.readdirSync(pluginDir, { withFileTypes: true })
.flatMap((dirent) => {
if (!dirent.isFile()) {
return [];
}
if (!/\.(?:[cm]?[jt]s)$/u.test(dirent.name) || dirent.name.endsWith(".d.ts")) {
return [];
}
const normalizedName = dirent.name.toLowerCase();
if (
normalizedName.includes(".test.") ||
normalizedName.includes(".spec.") ||
normalizedName.includes(".fixture.") ||
normalizedName.includes(".snap")
) {
return [];
}
return [dirent.name];
})
.toSorted((left, right) => left.localeCompare(right));
}
function isManifestlessBundledRuntimeSupportPackage(params) {
const packageName = typeof params.packageJson?.name === "string" ? params.packageJson.name : "";
if (packageName !== `@openclaw/${params.dirName}`) {
return false;
}
return params.topLevelPublicSurfaceEntries.length > 0;
}
function rewritePackageEntry(entry) {
if (typeof entry !== "string" || entry.trim().length === 0) {
return undefined;
@@ -193,35 +232,48 @@ export function copyBundledPluginMetadata(params = {}) {
const packageJson = fs.existsSync(packageJsonPath)
? JSON.parse(fs.readFileSync(packageJsonPath, "utf8"))
: undefined;
const topLevelPublicSurfaceEntries = collectTopLevelPublicSurfaceEntries(pluginDir);
if (!shouldBuildBundledCluster(dirent.name, env, { packageJson })) {
removePathIfExists(distPluginDir);
continue;
}
const isManifestlessSupportPackage =
!fs.existsSync(manifestPath) &&
isManifestlessBundledRuntimeSupportPackage({
dirName: dirent.name,
packageJson,
topLevelPublicSurfaceEntries,
});
sourcePluginDirs.add(dirent.name);
const distManifestPath = path.join(distPluginDir, "openclaw.plugin.json");
const distPackageJsonPath = path.join(distPluginDir, "package.json");
if (!fs.existsSync(manifestPath)) {
if (!fs.existsSync(manifestPath) && !isManifestlessSupportPackage) {
removePathIfExists(distPluginDir);
continue;
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
// Generated skill assets live under a dedicated dist-owned directory. Also
// remove the older bad node_modules tree so release packs cannot pick it up.
removePathIfExists(path.join(distPluginDir, GENERATED_BUNDLED_SKILLS_DIR));
removePathIfExists(path.join(distPluginDir, "node_modules"));
const copiedSkills = copyDeclaredPluginSkillPaths({
manifest,
pluginDir,
distPluginDir,
repoRoot,
});
const bundledManifest = Array.isArray(manifest.skills)
? { ...manifest, skills: copiedSkills }
: manifest;
writeTextFileIfChanged(distManifestPath, `${JSON.stringify(bundledManifest, null, 2)}\n`);
if (fs.existsSync(manifestPath)) {
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
// Generated skill assets live under a dedicated dist-owned directory. Also
// remove the older bad node_modules tree so release packs cannot pick it up.
removePathIfExists(path.join(distPluginDir, GENERATED_BUNDLED_SKILLS_DIR));
removePathIfExists(path.join(distPluginDir, "node_modules"));
const copiedSkills = copyDeclaredPluginSkillPaths({
manifest,
pluginDir,
distPluginDir,
repoRoot,
});
const bundledManifest = Array.isArray(manifest.skills)
? { ...manifest, skills: copiedSkills }
: manifest;
writeTextFileIfChanged(distManifestPath, `${JSON.stringify(bundledManifest, null, 2)}\n`);
} else {
removeFileIfExists(distManifestPath);
}
if (!fs.existsSync(packageJsonPath)) {
removeFileIfExists(distPackageJsonPath);

View File

@@ -20,6 +20,14 @@ function readBundledPluginPackageJson(packageJsonPath) {
}
}
function isManifestlessBundledRuntimeSupportPackage(params) {
const packageName = typeof params.packageJson?.name === "string" ? params.packageJson.name : "";
if (packageName !== `@openclaw/${params.dirName}`) {
return false;
}
return params.topLevelPublicSurfaceEntries.length > 0;
}
function collectPluginSourceEntries(packageJson) {
let packageEntries = Array.isArray(packageJson?.openclaw?.extensions)
? packageJson.openclaw.extensions.filter(
@@ -83,24 +91,33 @@ export function collectBundledPluginBuildEntries(params = {}) {
const pluginDir = path.join(extensionsRoot, dirent.name);
const manifestPath = path.join(pluginDir, "openclaw.plugin.json");
if (!fs.existsSync(manifestPath)) {
continue;
}
const hasManifest = fs.existsSync(manifestPath);
const packageJsonPath = path.join(pluginDir, "package.json");
const packageJson = readBundledPluginPackageJson(packageJsonPath);
const topLevelPublicSurfaceEntries = collectTopLevelPublicSurfaceEntries(pluginDir);
if (
!hasManifest &&
!isManifestlessBundledRuntimeSupportPackage({
dirName: dirent.name,
packageJson,
topLevelPublicSurfaceEntries,
})
) {
continue;
}
if (!shouldBuildBundledCluster(dirent.name, env, { packageJson })) {
continue;
}
entries.push({
id: dirent.name,
hasManifest,
hasPackageJson: packageJson !== null,
packageJson,
sourceEntries: Array.from(
new Set([
...collectPluginSourceEntries(packageJson),
...collectTopLevelPublicSurfaceEntries(pluginDir),
...(hasManifest ? collectPluginSourceEntries(packageJson) : []),
...topLevelPublicSurfaceEntries,
]),
),
});
@@ -125,8 +142,10 @@ export function listBundledPluginPackArtifacts(params = {}) {
const entries = collectBundledPluginBuildEntries(params);
const artifacts = new Set();
for (const { id, hasPackageJson, sourceEntries } of entries) {
artifacts.add(bundledDistPluginFile(id, "openclaw.plugin.json"));
for (const { id, hasManifest, hasPackageJson, sourceEntries } of entries) {
if (hasManifest) {
artifacts.add(bundledDistPluginFile(id, "openclaw.plugin.json"));
}
if (hasPackageJson) {
artifacts.add(bundledDistPluginFile(id, "package.json"));
}