mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:00:42 +00:00
fix(plugins): declare host peer in npm runtime packs
This commit is contained in:
@@ -76,6 +76,8 @@ export function resolveAugmentedPluginNpmPackageJson(params) {
|
||||
const packageJson = {
|
||||
...plan.packageJson,
|
||||
files: plan.packageFiles,
|
||||
peerDependencies: plan.packagePeerMetadata.peerDependencies,
|
||||
peerDependenciesMeta: plan.packagePeerMetadata.peerDependenciesMeta,
|
||||
openclaw: {
|
||||
...plan.packageJson.openclaw,
|
||||
runtimeExtensions: plan.runtimeExtensions,
|
||||
|
||||
@@ -43,6 +43,21 @@ function collectExternalDependencyNames(packageJson) {
|
||||
);
|
||||
}
|
||||
|
||||
function getStringRecord(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
return Object.fromEntries(
|
||||
Object.entries(value).filter(
|
||||
([, entryValue]) => typeof entryValue === "string" && entryValue.trim().length > 0,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function getRecord(value) {
|
||||
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
||||
}
|
||||
|
||||
function createNeverBundleDependencyMatcher(packageJson) {
|
||||
const externalDependencies = collectExternalDependencyNames(packageJson);
|
||||
return (id) => {
|
||||
@@ -116,6 +131,51 @@ export function resolvePluginNpmRuntimePackageFiles(plan) {
|
||||
return [...merged];
|
||||
}
|
||||
|
||||
function normalizeOpenClawPeerRange(value) {
|
||||
const normalized = normalizePackageEntry(value);
|
||||
if (!normalized) {
|
||||
return "";
|
||||
}
|
||||
return /^[<>=~^*]|^(?:workspace|npm|file|link|portal|catalog):/u.test(normalized)
|
||||
? normalized
|
||||
: `>=${normalized}`;
|
||||
}
|
||||
|
||||
function resolveOpenClawPeerRange(packageJson, rootPackageJson) {
|
||||
return (
|
||||
normalizeOpenClawPeerRange(packageJson.openclaw?.compat?.pluginApi) ||
|
||||
normalizeOpenClawPeerRange(packageJson.peerDependencies?.openclaw) ||
|
||||
normalizeOpenClawPeerRange(packageJson.openclaw?.build?.openclawVersion) ||
|
||||
normalizeOpenClawPeerRange(rootPackageJson?.version) ||
|
||||
normalizeOpenClawPeerRange(packageJson.version)
|
||||
);
|
||||
}
|
||||
|
||||
export function resolvePluginNpmRuntimePackagePeerMetadata(plan) {
|
||||
const openclawPeerRange = resolveOpenClawPeerRange(plan.packageJson, plan.rootPackageJson);
|
||||
if (!openclawPeerRange) {
|
||||
throw new Error(
|
||||
`cannot infer openclaw peerDependency range for ${plan.pluginDir}; set openclaw.compat.pluginApi or package version`,
|
||||
);
|
||||
}
|
||||
const existingPeerDependencies = getStringRecord(plan.packageJson.peerDependencies);
|
||||
const existingPeerDependenciesMeta = getRecord(plan.packageJson.peerDependenciesMeta);
|
||||
const existingOpenClawMeta = getRecord(existingPeerDependenciesMeta.openclaw);
|
||||
return {
|
||||
peerDependencies: {
|
||||
...existingPeerDependencies,
|
||||
openclaw: openclawPeerRange,
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
...existingPeerDependenciesMeta,
|
||||
openclaw: {
|
||||
...existingOpenClawMeta,
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function resolvePluginNpmRuntimeBuildPlan(params) {
|
||||
const repoRoot = path.resolve(params.repoRoot ?? ".");
|
||||
const packageDir = resolvePackageDir(repoRoot, params.packageDir);
|
||||
@@ -124,6 +184,10 @@ export function resolvePluginNpmRuntimeBuildPlan(params) {
|
||||
return null;
|
||||
}
|
||||
const packageJson = readJsonFile(packageJsonPath);
|
||||
const rootPackageJsonPath = path.join(repoRoot, "package.json");
|
||||
const rootPackageJson = fs.existsSync(rootPackageJsonPath)
|
||||
? readJsonFile(rootPackageJsonPath)
|
||||
: undefined;
|
||||
if (!isPublishablePluginPackage(packageJson)) {
|
||||
return null;
|
||||
}
|
||||
@@ -153,6 +217,7 @@ export function resolvePluginNpmRuntimeBuildPlan(params) {
|
||||
packageDir,
|
||||
pluginDir,
|
||||
packageJson,
|
||||
rootPackageJson,
|
||||
sourceEntries,
|
||||
entry,
|
||||
outDir: path.join(packageDir, "dist"),
|
||||
@@ -171,6 +236,7 @@ export function resolvePluginNpmRuntimeBuildPlan(params) {
|
||||
...plan,
|
||||
runtimeBuildOutputs: listPluginNpmRuntimeBuildOutputs(plan),
|
||||
packageFiles: resolvePluginNpmRuntimePackageFiles(plan),
|
||||
packagePeerMetadata: resolvePluginNpmRuntimePackagePeerMetadata(plan),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ function writePublishablePluginPackage(repoDir: string): string {
|
||||
openclaw: {
|
||||
extensions: ["./index.ts"],
|
||||
setupEntry: "./setup-entry.ts",
|
||||
compat: {
|
||||
pluginApi: ">=2026.4.30",
|
||||
},
|
||||
release: {
|
||||
publishToNpm: true,
|
||||
},
|
||||
@@ -127,6 +130,14 @@ describe("plugin npm package manifest staging", () => {
|
||||
expect(resolved.changed).toBe(true);
|
||||
expect(resolved.packageJson).toMatchObject({
|
||||
files: ["dist/**", "openclaw.plugin.json", "README.md", "SKILL.md", "skills/**"],
|
||||
peerDependencies: {
|
||||
openclaw: ">=2026.4.30",
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
openclaw: {
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
openclaw: {
|
||||
runtimeExtensions: ["./dist/index.js"],
|
||||
runtimeSetupEntry: "./dist/setup-entry.js",
|
||||
@@ -141,6 +152,8 @@ describe("plugin npm package manifest staging", () => {
|
||||
expect(stagedPackageJson.openclaw.runtimeSetupEntry).toBe("./dist/setup-entry.js");
|
||||
expect(stagedPackageJson.files).toContain("dist/**");
|
||||
expect(stagedPackageJson.files).toContain("skills/**");
|
||||
expect(stagedPackageJson.peerDependencies.openclaw).toBe(">=2026.4.30");
|
||||
expect(stagedPackageJson.peerDependenciesMeta.openclaw.optional).toBe(true);
|
||||
});
|
||||
expect(readFileSync(join(packageDir, "package.json"), "utf8")).toBe(originalText);
|
||||
});
|
||||
|
||||
@@ -26,6 +26,10 @@ describe("plugin npm runtime build planning", () => {
|
||||
expect(plan?.runtimeExtensions.every((entry) => entry.startsWith("./dist/"))).toBe(true);
|
||||
expect(plan?.runtimeBuildOutputs.every((entry) => entry.startsWith("./dist/"))).toBe(true);
|
||||
expect(plan?.packageFiles).toContain("dist/**");
|
||||
expect(plan?.packagePeerMetadata.peerDependencies.openclaw).toBe(
|
||||
plan?.packageJson.openclaw.compat.pluginApi,
|
||||
);
|
||||
expect(plan?.packagePeerMetadata.peerDependenciesMeta.openclaw.optional).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user