mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:00:44 +00:00
feat(plugins): list from registry snapshot
This commit is contained in:
@@ -35,6 +35,7 @@ export const recordPluginInstall: UnknownMock = vi.fn();
|
||||
export const clearPluginManifestRegistryCache: UnknownMock = vi.fn();
|
||||
export const loadPluginManifestRegistry: UnknownMock = vi.fn();
|
||||
export const buildPluginSnapshotReport: UnknownMock = vi.fn();
|
||||
export const buildPluginRegistrySnapshotReport: UnknownMock = vi.fn();
|
||||
export const buildPluginInspectReport: UnknownMock = vi.fn();
|
||||
export const buildPluginDiagnosticsReport: UnknownMock = vi.fn();
|
||||
export const buildPluginCompatibilityNotices: UnknownMock = vi.fn();
|
||||
@@ -169,6 +170,18 @@ vi.mock("../plugins/status.js", () => ({
|
||||
buildPluginSnapshotReport,
|
||||
...args,
|
||||
)) as (typeof import("../plugins/status.js"))["buildPluginSnapshotReport"],
|
||||
buildPluginRegistrySnapshotReport: ((
|
||||
...args: Parameters<
|
||||
(typeof import("../plugins/status.js"))["buildPluginRegistrySnapshotReport"]
|
||||
>
|
||||
) =>
|
||||
invokeMock<
|
||||
Parameters<(typeof import("../plugins/status.js"))["buildPluginRegistrySnapshotReport"]>,
|
||||
ReturnType<(typeof import("../plugins/status.js"))["buildPluginRegistrySnapshotReport"]>
|
||||
>(
|
||||
buildPluginRegistrySnapshotReport,
|
||||
...args,
|
||||
)) as (typeof import("../plugins/status.js"))["buildPluginRegistrySnapshotReport"],
|
||||
buildPluginInspectReport: ((
|
||||
...args: Parameters<(typeof import("../plugins/status.js"))["buildPluginInspectReport"]>
|
||||
) =>
|
||||
@@ -414,6 +427,7 @@ export function resetPluginsCliTestState() {
|
||||
clearPluginManifestRegistryCache.mockReset();
|
||||
loadPluginManifestRegistry.mockReset();
|
||||
buildPluginSnapshotReport.mockReset();
|
||||
buildPluginRegistrySnapshotReport.mockReset();
|
||||
buildPluginInspectReport.mockReset();
|
||||
buildPluginDiagnosticsReport.mockReset();
|
||||
buildPluginCompatibilityNotices.mockReset();
|
||||
@@ -477,6 +491,11 @@ export function resetPluginsCliTestState() {
|
||||
diagnostics: [],
|
||||
};
|
||||
buildPluginSnapshotReport.mockReturnValue(defaultPluginReport);
|
||||
buildPluginRegistrySnapshotReport.mockReturnValue({
|
||||
...defaultPluginReport,
|
||||
registrySource: "derived",
|
||||
registryDiagnostics: [],
|
||||
});
|
||||
buildPluginDiagnosticsReport.mockReturnValue(defaultPluginReport);
|
||||
buildPluginCompatibilityNotices.mockReturnValue([]);
|
||||
const defaultRegistryIndex = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createPluginRecord } from "../plugins/status.test-helpers.js";
|
||||
import {
|
||||
buildPluginDiagnosticsReport,
|
||||
buildPluginInspectReport,
|
||||
buildPluginSnapshotReport,
|
||||
buildPluginRegistrySnapshotReport,
|
||||
inspectPluginRegistry,
|
||||
resetPluginsCliTestState,
|
||||
refreshPluginRegistry,
|
||||
@@ -17,8 +17,10 @@ describe("plugins cli list", () => {
|
||||
});
|
||||
|
||||
it("includes imported state in JSON output", async () => {
|
||||
buildPluginSnapshotReport.mockReturnValue({
|
||||
buildPluginRegistrySnapshotReport.mockReturnValue({
|
||||
workspaceDir: "/workspace",
|
||||
registrySource: "persisted",
|
||||
registryDiagnostics: [],
|
||||
plugins: [
|
||||
createPluginRecord({
|
||||
id: "demo",
|
||||
@@ -32,8 +34,9 @@ describe("plugins cli list", () => {
|
||||
|
||||
await runPluginsCommand(["plugins", "list", "--json"]);
|
||||
|
||||
expect(buildPluginSnapshotReport).toHaveBeenCalledWith(
|
||||
expect(buildPluginRegistrySnapshotReport).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
config: {},
|
||||
logger: expect.objectContaining({
|
||||
info: expect.any(Function),
|
||||
warn: expect.any(Function),
|
||||
@@ -44,6 +47,10 @@ describe("plugins cli list", () => {
|
||||
|
||||
expect(JSON.parse(runtimeLogs[0] ?? "null")).toEqual({
|
||||
workspaceDir: "/workspace",
|
||||
registry: {
|
||||
source: "persisted",
|
||||
diagnostics: [],
|
||||
},
|
||||
plugins: [
|
||||
expect.objectContaining({
|
||||
id: "demo",
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
buildPluginDiagnosticsReport,
|
||||
buildPluginCompatibilityNotices,
|
||||
buildPluginInspectReport,
|
||||
buildPluginSnapshotReport,
|
||||
buildPluginRegistrySnapshotReport,
|
||||
formatPluginCompatibilityNotice,
|
||||
} from "../plugins/status.js";
|
||||
import type { PluginLogger } from "../plugins/types.js";
|
||||
@@ -174,9 +174,11 @@ export function registerPluginsCli(program: Command) {
|
||||
.option("--enabled", "Only show enabled plugins", false)
|
||||
.option("--verbose", "Show detailed entries", false)
|
||||
.action((opts: PluginsListOptions) => {
|
||||
const report = buildPluginSnapshotReport(
|
||||
opts.json ? { logger: quietPluginJsonLogger } : undefined,
|
||||
);
|
||||
const cfg = loadConfig();
|
||||
const report = buildPluginRegistrySnapshotReport({
|
||||
config: cfg,
|
||||
...(opts.json ? { logger: quietPluginJsonLogger } : {}),
|
||||
});
|
||||
const list = opts.enabled
|
||||
? report.plugins.filter((p) => p.status === "loaded")
|
||||
: report.plugins;
|
||||
@@ -184,6 +186,10 @@ export function registerPluginsCli(program: Command) {
|
||||
if (opts.json) {
|
||||
const payload = {
|
||||
workspaceDir: report.workspaceDir,
|
||||
registry: {
|
||||
source: report.registrySource,
|
||||
diagnostics: report.registryDiagnostics,
|
||||
},
|
||||
plugins: list,
|
||||
diagnostics: report.diagnostics,
|
||||
};
|
||||
|
||||
@@ -19,8 +19,13 @@ import {
|
||||
} from "./inspect-shape.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import type { PluginDiagnostic } from "./manifest-types.js";
|
||||
import {
|
||||
loadPluginRegistrySnapshotWithMetadata,
|
||||
type PluginRegistrySnapshotDiagnostic,
|
||||
type PluginRegistrySnapshotSource,
|
||||
} from "./plugin-registry.js";
|
||||
import { resolveBundledProviderCompatPluginIds } from "./providers.js";
|
||||
import type { PluginRegistry } from "./registry.js";
|
||||
import { createEmptyPluginRegistry, type PluginRecord, type PluginRegistry } from "./registry.js";
|
||||
import { listImportedRuntimePluginIds } from "./runtime.js";
|
||||
import {
|
||||
buildPluginRuntimeLoadOptions,
|
||||
@@ -33,6 +38,11 @@ export type PluginStatusReport = PluginRegistry & {
|
||||
workspaceDir?: string;
|
||||
};
|
||||
|
||||
export type PluginRegistryStatusReport = PluginStatusReport & {
|
||||
registrySource: PluginRegistrySnapshotSource;
|
||||
registryDiagnostics: readonly PluginRegistrySnapshotDiagnostic[];
|
||||
};
|
||||
|
||||
export type { PluginCapabilityKind, PluginInspectShape } from "./inspect-shape.js";
|
||||
|
||||
export type PluginCompatibilityNotice = {
|
||||
@@ -143,6 +153,66 @@ type PluginReportParams = {
|
||||
logger?: PluginLogger;
|
||||
};
|
||||
|
||||
function buildPluginRecordFromInstalledIndex(
|
||||
plugin: import("./installed-plugin-index.js").InstalledPluginIndexRecord,
|
||||
): PluginRecord {
|
||||
return {
|
||||
id: plugin.pluginId,
|
||||
name: plugin.pluginId,
|
||||
...(plugin.packageVersion ? { version: plugin.packageVersion } : {}),
|
||||
format: "openclaw",
|
||||
source: plugin.manifestPath,
|
||||
rootDir: plugin.rootDir,
|
||||
origin: plugin.origin,
|
||||
enabled: plugin.enabled,
|
||||
status: plugin.enabled ? "loaded" : "disabled",
|
||||
toolNames: [],
|
||||
hookNames: [],
|
||||
channelIds: [...plugin.contributions.channels],
|
||||
cliBackendIds: [...plugin.contributions.cliBackends],
|
||||
providerIds: [...plugin.contributions.providers],
|
||||
speechProviderIds: [],
|
||||
realtimeTranscriptionProviderIds: [],
|
||||
realtimeVoiceProviderIds: [],
|
||||
mediaUnderstandingProviderIds: [],
|
||||
imageGenerationProviderIds: [],
|
||||
videoGenerationProviderIds: [],
|
||||
musicGenerationProviderIds: [],
|
||||
webFetchProviderIds: [],
|
||||
webSearchProviderIds: [],
|
||||
memoryEmbeddingProviderIds: [],
|
||||
agentHarnessIds: [],
|
||||
gatewayMethods: [],
|
||||
cliCommands: [],
|
||||
services: [],
|
||||
gatewayDiscoveryServiceIds: [],
|
||||
commands: [...plugin.contributions.commandAliases],
|
||||
httpRoutes: 0,
|
||||
hookCount: 0,
|
||||
configSchema: false,
|
||||
contracts: {},
|
||||
};
|
||||
}
|
||||
|
||||
export function buildPluginRegistrySnapshotReport(
|
||||
params?: PluginReportParams,
|
||||
): PluginRegistryStatusReport {
|
||||
const config = params?.config ?? loadConfig();
|
||||
const result = loadPluginRegistrySnapshotWithMetadata({
|
||||
config,
|
||||
env: params?.env,
|
||||
workspaceDir: params?.workspaceDir,
|
||||
});
|
||||
return {
|
||||
workspaceDir: params?.workspaceDir,
|
||||
...createEmptyPluginRegistry(),
|
||||
plugins: result.snapshot.plugins.map(buildPluginRecordFromInstalledIndex),
|
||||
diagnostics: [...result.snapshot.diagnostics],
|
||||
registrySource: result.source,
|
||||
registryDiagnostics: result.diagnostics,
|
||||
};
|
||||
}
|
||||
|
||||
function buildPluginReport(
|
||||
params: PluginReportParams | undefined,
|
||||
loadModules: boolean,
|
||||
|
||||
Reference in New Issue
Block a user