mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:50:43 +00:00
fix: preserve bundle format in plugin index
This commit is contained in:
@@ -55,6 +55,8 @@ const InstalledPluginIndexRecordSchema = z
|
||||
packageInstall: z.unknown().optional(),
|
||||
manifestPath: z.string(),
|
||||
manifestHash: z.string(),
|
||||
format: z.string().optional(),
|
||||
bundleFormat: z.string().optional(),
|
||||
source: z.string().optional(),
|
||||
setupSource: z.string().optional(),
|
||||
packageJson: z
|
||||
|
||||
@@ -66,12 +66,16 @@ function createPluginCandidate(params: {
|
||||
packageVersion?: string;
|
||||
packageDir?: string;
|
||||
packageManifest?: OpenClawPackageManifest;
|
||||
format?: PluginCandidate["format"];
|
||||
bundleFormat?: PluginCandidate["bundleFormat"];
|
||||
}): PluginCandidate {
|
||||
return {
|
||||
idHint: params.idHint ?? "demo",
|
||||
source: path.join(params.rootDir, "index.ts"),
|
||||
source: params.format === "bundle" ? params.rootDir : path.join(params.rootDir, "index.ts"),
|
||||
rootDir: params.rootDir,
|
||||
origin: params.origin ?? "global",
|
||||
format: params.format,
|
||||
bundleFormat: params.bundleFormat,
|
||||
packageName: params.packageName,
|
||||
packageVersion: params.packageVersion,
|
||||
packageDir: params.packageDir ?? params.rootDir,
|
||||
@@ -198,6 +202,39 @@ describe("installed plugin index", () => {
|
||||
expect(index.plugins[0]?.installRecordHash).toBeUndefined();
|
||||
});
|
||||
|
||||
it("keeps bundle format metadata needed for manifest reconstruction", () => {
|
||||
const rootDir = makeTempDir();
|
||||
fs.mkdirSync(path.join(rootDir, ".claude-plugin"), { recursive: true });
|
||||
fs.mkdirSync(path.join(rootDir, "commands"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, ".claude-plugin", "plugin.json"),
|
||||
JSON.stringify({
|
||||
name: "Claude Bundle",
|
||||
commands: "commands",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const index = loadInstalledPluginIndex({
|
||||
candidates: [
|
||||
createPluginCandidate({
|
||||
rootDir,
|
||||
idHint: "claude-bundle",
|
||||
format: "bundle",
|
||||
bundleFormat: "claude",
|
||||
}),
|
||||
],
|
||||
env: hermeticEnv(),
|
||||
});
|
||||
|
||||
expect(index.plugins[0]).toMatchObject({
|
||||
pluginId: "claude-bundle",
|
||||
format: "bundle",
|
||||
bundleFormat: "claude",
|
||||
source: rootDir,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps packageJson paths root-relative when packageDir is reached through a symlink", () => {
|
||||
const fixture = createRichPluginFixture();
|
||||
const linkParent = makeTempDir();
|
||||
|
||||
@@ -84,6 +84,8 @@ export type InstalledPluginIndexRecord = {
|
||||
packageInstall?: PluginInstallSourceInfo;
|
||||
manifestPath: string;
|
||||
manifestHash: string;
|
||||
format?: PluginManifestRecord["format"];
|
||||
bundleFormat?: PluginManifestRecord["bundleFormat"];
|
||||
source?: string;
|
||||
setupSource?: string;
|
||||
packageJson?: {
|
||||
@@ -516,6 +518,12 @@ function buildInstalledPluginIndex(
|
||||
startup: buildStartupInfo(record),
|
||||
compat: collectCompatCodes(record),
|
||||
};
|
||||
if (record.format && record.format !== "openclaw") {
|
||||
indexRecord.format = record.format;
|
||||
}
|
||||
if (record.bundleFormat) {
|
||||
indexRecord.bundleFormat = record.bundleFormat;
|
||||
}
|
||||
if (record.enabledByDefault === true) {
|
||||
indexRecord.enabledByDefault = true;
|
||||
}
|
||||
|
||||
@@ -89,4 +89,52 @@ describe("loadPluginManifestRegistryForInstalledIndex", () => {
|
||||
modelPrefixes: ["installed-"],
|
||||
});
|
||||
});
|
||||
|
||||
it("reconstructs bundle candidates with their bundle manifest format", () => {
|
||||
const rootDir = makeTempDir();
|
||||
fs.mkdirSync(path.join(rootDir, ".claude-plugin"), { recursive: true });
|
||||
fs.mkdirSync(path.join(rootDir, "commands"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(rootDir, ".claude-plugin", "plugin.json"),
|
||||
JSON.stringify({
|
||||
name: "Claude Bundle",
|
||||
commands: "commands",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const index = createIndex(rootDir);
|
||||
const registry = loadPluginManifestRegistryForInstalledIndex({
|
||||
index: {
|
||||
...index,
|
||||
plugins: [
|
||||
{
|
||||
...index.plugins[0],
|
||||
pluginId: "claude-bundle",
|
||||
manifestPath: path.join(rootDir, ".claude-plugin", "plugin.json"),
|
||||
source: rootDir,
|
||||
format: "bundle",
|
||||
bundleFormat: "claude",
|
||||
},
|
||||
],
|
||||
},
|
||||
env: {
|
||||
OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE: "1",
|
||||
OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE: "1",
|
||||
OPENCLAW_VERSION: "2026.4.25",
|
||||
VITEST: "true",
|
||||
},
|
||||
includeDisabled: true,
|
||||
});
|
||||
|
||||
expect(registry.diagnostics).toEqual([]);
|
||||
expect(registry.plugins).toEqual([
|
||||
expect.objectContaining({
|
||||
id: "claude-bundle",
|
||||
format: "bundle",
|
||||
bundleFormat: "claude",
|
||||
skills: ["commands"],
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,6 +24,8 @@ function toPluginCandidate(record: InstalledPluginIndexRecord): PluginCandidate
|
||||
...(record.setupSource ? { setupSource: record.setupSource } : {}),
|
||||
rootDir: record.rootDir,
|
||||
origin: record.origin,
|
||||
...(record.format ? { format: record.format } : {}),
|
||||
...(record.bundleFormat ? { bundleFormat: record.bundleFormat } : {}),
|
||||
...(record.packageName ? { packageName: record.packageName } : {}),
|
||||
...(record.packageVersion ? { packageVersion: record.packageVersion } : {}),
|
||||
packageDir: record.rootDir,
|
||||
|
||||
Reference in New Issue
Block a user