Plugins: cover non-object JSON5 manifest inputs

This commit is contained in:
masonxhuang
2026-04-02 21:57:41 +08:00
parent bc8ad82162
commit 58a4d537fc
2 changed files with 43 additions and 0 deletions

View File

@@ -373,6 +373,39 @@ describe("bundle manifest parsing", () => {
},
);
it.each([
{
name: "rejects JSON5 Codex bundle manifests that parse to non-objects",
bundleFormat: "codex" as const,
manifestRelativePath: CODEX_BUNDLE_MANIFEST_RELATIVE_PATH,
},
{
name: "rejects JSON5 Claude bundle manifests that parse to non-objects",
bundleFormat: "claude" as const,
manifestRelativePath: CLAUDE_BUNDLE_MANIFEST_RELATIVE_PATH,
},
{
name: "rejects JSON5 Cursor bundle manifests that parse to non-objects",
bundleFormat: "cursor" as const,
manifestRelativePath: CURSOR_BUNDLE_MANIFEST_RELATIVE_PATH,
},
] as const)("$name", ({ bundleFormat, manifestRelativePath }) => {
const rootDir = makeTempDir();
setupBundleFixture({
rootDir,
dirs: [path.dirname(manifestRelativePath)],
textFiles: {
[manifestRelativePath]: "'still not an object'",
},
});
const result = loadBundleManifest({ rootDir, bundleFormat });
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toContain("plugin manifest must be an object");
}
});
it.each([
{
name: "resolves Claude bundle hooks from default and declared paths",

View File

@@ -90,4 +90,14 @@ describe("loadPluginManifest JSON5 tolerance", () => {
expect(result.error).toContain("failed to parse plugin manifest");
}
});
it("rejects JSON5 values that parse but are not objects", () => {
const dir = makeTempDir();
fs.writeFileSync(path.join(dir, "openclaw.plugin.json"), "'just a string'", "utf-8");
const result = loadPluginManifest(dir, false);
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toContain("plugin manifest must be an object");
}
});
});