fix: carry plugin compat into loader reports

This commit is contained in:
Shakker
2026-04-28 06:03:32 +01:00
parent d062f8130b
commit defddedbaf
3 changed files with 82 additions and 2 deletions

View File

@@ -76,7 +76,9 @@ function buildStartupInfo(record: PluginManifestRecord): InstalledPluginStartupI
};
}
function collectCompatCodes(record: PluginManifestRecord): readonly PluginCompatCode[] {
export function collectPluginManifestCompatCodes(
record: PluginManifestRecord,
): readonly PluginCompatCode[] {
const codes: PluginCompatCode[] = [];
if (isLegacyImplicitStartupSidecar(record)) {
codes.push("legacy-implicit-startup-sidecar");
@@ -271,7 +273,7 @@ export function buildInstalledPluginIndexRecords(params: {
origin: record.origin,
enabled,
startup: buildStartupInfo(record),
compat: collectCompatCodes(record),
compat: collectPluginManifestCompatCodes(record),
};
if (record.format && record.format !== "openclaw") {
indexRecord.format = record.format;

View File

@@ -57,6 +57,7 @@ import {
listRegisteredCompactionProviders,
restoreRegisteredCompactionProviders,
} from "./compaction-provider.js";
import type { PluginCompatCode } from "./compat/registry.js";
import {
applyTestPluginDefaults,
createPluginActivationSource,
@@ -71,6 +72,7 @@ import {
import { discoverOpenClawPlugins, type PluginCandidate } from "./discovery.js";
import { getGlobalHookRunner, initializeGlobalHookRunner } from "./hook-runner-global.js";
import { toSafeImportPath } from "./import-specifier.js";
import { collectPluginManifestCompatCodes } from "./installed-plugin-index-record-builder.js";
import { loadInstalledPluginIndexInstallRecordsSync } from "./installed-plugin-index-records.js";
import {
clearPluginInteractiveHandlers,
@@ -1755,6 +1757,7 @@ function createPluginRecord(params: {
origin: PluginRecord["origin"];
workspaceDir?: string;
enabled: boolean;
compat?: readonly PluginCompatCode[];
activationState?: PluginActivationState;
syntheticAuthRefs?: string[];
configSchema: boolean;
@@ -1773,6 +1776,7 @@ function createPluginRecord(params: {
origin: params.origin,
workspaceDir: params.workspaceDir,
enabled: params.enabled,
compat: params.compat,
explicitlyEnabled: params.activationState?.explicitlyEnabled,
activated: params.activationState?.activated,
activationSource: params.activationState?.source,
@@ -2435,6 +2439,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
origin: candidate.origin,
workspaceDir: candidate.workspaceDir,
enabled: false,
compat: collectPluginManifestCompatCodes(manifestRecord),
activationState,
syntheticAuthRefs: manifestRecord.syntheticAuthRefs,
configSchema: Boolean(manifestRecord.configSchema),
@@ -2469,6 +2474,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
origin: candidate.origin,
workspaceDir: candidate.workspaceDir,
enabled: enableState.enabled,
compat: collectPluginManifestCompatCodes(manifestRecord),
activationState,
syntheticAuthRefs: manifestRecord.syntheticAuthRefs,
configSchema: Boolean(manifestRecord.configSchema),
@@ -3342,6 +3348,7 @@ export async function loadOpenClawPluginCliRegistry(
origin: candidate.origin,
workspaceDir: candidate.workspaceDir,
enabled: false,
compat: collectPluginManifestCompatCodes(manifestRecord),
activationState,
syntheticAuthRefs: manifestRecord.syntheticAuthRefs,
configSchema: Boolean(manifestRecord.configSchema),
@@ -3376,6 +3383,7 @@ export async function loadOpenClawPluginCliRegistry(
origin: candidate.origin,
workspaceDir: candidate.workspaceDir,
enabled: enableState.enabled,
compat: collectPluginManifestCompatCodes(manifestRecord),
activationState,
syntheticAuthRefs: manifestRecord.syntheticAuthRefs,
configSchema: Boolean(manifestRecord.configSchema),

View File

@@ -0,0 +1,70 @@
import fs from "node:fs";
import path from "node:path";
import { afterAll, afterEach, describe, expect, it } from "vitest";
import { withEnv } from "../test-utils/env.js";
import {
cleanupPluginLoaderFixturesForTest,
makeTempDir,
resetPluginLoaderTestStateForTest,
useNoBundledPlugins,
writePlugin,
} from "./loader.test-fixtures.js";
import { buildPluginCompatibilitySnapshotNotices } from "./status.js";
function addStartupActivation(pluginDir: string, onStartup: boolean): void {
const manifestPath = path.join(pluginDir, "openclaw.plugin.json");
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as Record<string, unknown>;
fs.writeFileSync(
manifestPath,
`${JSON.stringify({ ...manifest, activation: { onStartup } }, null, 2)}\n`,
"utf-8",
);
}
function buildSnapshotCompatibilityNoticeCodes(plugin: { dir: string; file: string; id: string }) {
const stateDir = makeTempDir();
return withEnv({ OPENCLAW_STATE_DIR: stateDir }, () => {
useNoBundledPlugins();
return buildPluginCompatibilitySnapshotNotices({
config: {
plugins: {
load: { paths: [plugin.file] },
allow: [plugin.id],
},
},
workspaceDir: plugin.dir,
env: process.env,
}).map((notice) => notice.code);
});
}
describe("plugin compatibility snapshot notices", () => {
afterEach(() => {
resetPluginLoaderTestStateForTest();
});
afterAll(() => {
cleanupPluginLoaderFixturesForTest();
});
it("reports implicit startup sidecar compatibility from a real legacy manifest", () => {
const plugin = writePlugin({
id: "legacy-sidecar",
body: `module.exports = { id: "legacy-sidecar", register() {} };\n`,
});
expect(buildSnapshotCompatibilityNoticeCodes(plugin)).toEqual([
"legacy-implicit-startup-sidecar",
]);
});
it("does not report implicit startup compatibility for explicit startup-lazy manifests", () => {
const plugin = writePlugin({
id: "modern-startup-lazy",
body: `module.exports = { id: "modern-startup-lazy", register() {} };\n`,
});
addStartupActivation(plugin.dir, false);
expect(buildSnapshotCompatibilityNoticeCodes(plugin)).toEqual([]);
});
});