Skip to content

Commit 7727e10

Browse files
committed
fix: scope plugin inspect runtime loading
1 parent 1bd4b7a commit 7727e10

4 files changed

Lines changed: 55 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Docs: https://docs.openclaw.ai
3737
- Plugins/startup: precompute bundled runtime mirror fingerprints before taking the mirror lock and keep Docker bundled plugin runtime deps/mirrors in a Docker-managed volume instead of the Windows/WSL config bind mount, so cold starts avoid slow host-volume mirror writes. Fixes #73339. Thanks @1yihui.
3838
- Channels/LINE: persist inbound image, video, audio, and file downloads in `~/.openclaw/media/inbound/` instead of temporary files so agents can still read LINE media after `/tmp` cleanup. Fixes #73370. Thanks @hijirii and @wenxu007.
3939
- CLI/plugins: keep bundled plugin installs out of `plugins.load.paths` while preserving install records, so install/inspect/doctor loops no longer warn about the current bundled plugin directory. Thanks @vincentkoc.
40+
- CLI/plugins: scope `plugins inspect <id>` runtime loading to the matched plugin so single-plugin inspection does not load every plugin before checking the target. Thanks @shakkernerd.
4041
- CLI/plugins: remove managed copied-path plugin directories during uninstall and plan uninstall from metadata instead of runtime-loading plugins, so plugin lifecycle commands avoid unnecessary bundled runtime-deps work. Thanks @shakkernerd.
4142
- Cron tool: infer the creating session's agentId for `cron.add` jobs when `agentId` is omitted or passed as undefined, keeping scheduled agentTurn jobs routed to the session agent; #40571 identified the guard bug and supplied the focused regression coverage. Thanks @ChanningYul.
4243
- Cron/Telegram: add `--thread-id` to `openclaw cron add` and `openclaw cron edit`, preserving Telegram forum topic delivery targets across scheduled announcements. Carries forward #51581, #60373, and #60890. Thanks @ChunHao-dev.

src/cli/plugins-cli.list.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import {
44
buildPluginDiagnosticsReport,
55
buildPluginInspectReport,
66
buildPluginRegistrySnapshotReport,
7+
buildPluginSnapshotReport,
78
inspectPluginRegistry,
89
resetPluginsCliTestState,
910
refreshPluginRegistry,
1011
runPluginsCommand,
12+
runtimeErrors,
1113
runtimeLogs,
1214
} from "./plugins-cli-test-helpers.js";
1315

@@ -119,6 +121,10 @@ describe("plugins cli list", () => {
119121
});
120122

121123
it("shows conversation-access hook policy in inspect output", async () => {
124+
buildPluginSnapshotReport.mockReturnValue({
125+
plugins: [createPluginRecord({ id: "openclaw-mem0", name: "Mem0" })],
126+
diagnostics: [],
127+
});
122128
buildPluginInspectReport.mockReturnValue({
123129
workspaceDir: "/workspace",
124130
plugin: createPluginRecord({ id: "openclaw-mem0", name: "Mem0" }),
@@ -150,7 +156,26 @@ describe("plugins cli list", () => {
150156

151157
await runPluginsCommand(["plugins", "inspect", "openclaw-mem0"]);
152158

159+
expect(buildPluginDiagnosticsReport).toHaveBeenCalledWith({
160+
config: {},
161+
onlyPluginIds: ["openclaw-mem0"],
162+
});
153163
expect(runtimeLogs.join("\n")).toContain("Policy");
154164
expect(runtimeLogs.join("\n")).toContain("allowConversationAccess: true");
155165
});
166+
167+
it("does not runtime-load plugins when inspect target is missing", async () => {
168+
buildPluginSnapshotReport.mockReturnValue({
169+
plugins: [],
170+
diagnostics: [],
171+
});
172+
173+
await expect(runPluginsCommand(["plugins", "inspect", "missing-plugin"])).rejects.toThrow(
174+
"__exit__:1",
175+
);
176+
177+
expect(buildPluginSnapshotReport).toHaveBeenCalledWith({ config: {} });
178+
expect(buildPluginDiagnosticsReport).not.toHaveBeenCalled();
179+
expect(runtimeErrors.at(-1)).toContain("Plugin not found: missing-plugin");
180+
});
156181
});

src/cli/plugins-cli.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,24 +259,26 @@ export function registerPluginsCli(program: Command) {
259259
buildAllPluginInspectReports,
260260
buildPluginDiagnosticsReport,
261261
buildPluginInspectReport,
262+
buildPluginSnapshotReport,
262263
formatPluginCompatibilityNotice,
263264
} = await import("../plugins/status.js");
264265
const { loadInstalledPluginIndexInstallRecords } =
265266
await import("../plugins/installed-plugin-index-records.js");
266267
const cfg = getRuntimeConfig();
267268
const installRecords = await loadInstalledPluginIndexInstallRecords();
268-
const report = buildPluginDiagnosticsReport({
269-
config: cfg,
270-
...(opts.json ? { logger: quietPluginJsonLogger } : {}),
271-
});
269+
const loggerParams = opts.json ? { logger: quietPluginJsonLogger } : {};
272270
if (opts.all) {
273271
if (id) {
274272
defaultRuntime.error("Pass either a plugin id or --all, not both.");
275273
return defaultRuntime.exit(1);
276274
}
275+
const report = buildPluginDiagnosticsReport({
276+
config: cfg,
277+
...loggerParams,
278+
});
277279
const inspectAll = buildAllPluginInspectReports({
278280
config: cfg,
279-
...(opts.json ? { logger: quietPluginJsonLogger } : {}),
281+
...loggerParams,
280282
report,
281283
});
282284
const inspectAllWithInstall = inspectAll.map((inspect) => ({
@@ -342,10 +344,26 @@ export function registerPluginsCli(program: Command) {
342344
return defaultRuntime.exit(1);
343345
}
344346

347+
const snapshotReport = buildPluginSnapshotReport({
348+
config: cfg,
349+
...loggerParams,
350+
});
351+
const targetPlugin = snapshotReport.plugins.find(
352+
(entry) => entry.id === id || entry.name === id,
353+
);
354+
if (!targetPlugin) {
355+
defaultRuntime.error(`Plugin not found: ${id}`);
356+
return defaultRuntime.exit(1);
357+
}
358+
const report = buildPluginDiagnosticsReport({
359+
config: cfg,
360+
...loggerParams,
361+
onlyPluginIds: [targetPlugin.id],
362+
});
345363
const inspect = buildPluginInspectReport({
346-
id,
364+
id: targetPlugin.id,
347365
config: cfg,
348-
...(opts.json ? { logger: quietPluginJsonLogger } : {}),
366+
...loggerParams,
349367
report,
350368
});
351369
if (!inspect) {

src/plugins/status.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ function resolveReportedPluginVersion(
161161
type PluginReportParams = {
162162
config?: OpenClawConfig;
163163
effectiveOnly?: boolean;
164+
onlyPluginIds?: readonly string[];
164165
workspaceDir?: string;
165166
/** Use an explicit env when plugin roots should resolve independently from process.env. */
166167
env?: NodeJS.ProcessEnv;
@@ -295,7 +296,9 @@ function buildPluginReport(
295296
workspaceDir,
296297
env: params?.env ?? process.env,
297298
})
298-
: undefined;
299+
: params?.onlyPluginIds === undefined
300+
? undefined
301+
: [...params.onlyPluginIds];
299302

300303
const registry = loadModules
301304
? loadOpenClawPlugins(

0 commit comments

Comments
 (0)