mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:10:43 +00:00
fix: keep plugin command status on cold index
This commit is contained in:
@@ -75,6 +75,8 @@ Docs: https://docs.openclaw.ai
|
||||
- Telegram: preserve exact selected quote text when sending native quote replies, and retry with legacy replies if Telegram rejects quote parameters. (#71952) Thanks @rubencu.
|
||||
- Plugins/CLI: preserve manifest name, description, format, and source metadata in cold `openclaw plugins list` output without importing plugin runtime. Thanks @shakkernerd.
|
||||
- Security/audit: read channel exposure and plugin allowlist ownership from read-only plugin index metadata so cold audits do not depend on loaded channel runtime. Thanks @shakkernerd.
|
||||
- Plugins/chat: keep `/plugins list`, `/plugins enable`, and `/plugins disable` on the persisted plugin index path so chat plugin management does not load diagnostic/runtime plugin registries before execution. Thanks @shakkernerd.
|
||||
- Plugins/doctor: read workspace plugin status and legacy web-search ownership through installed-index manifest metadata instead of broad manifest registry scans. Thanks @shakkernerd.
|
||||
- Logging: redact configured secret patterns at console and file-log sink exits
|
||||
so credentials that reach the logger are masked before terminal display or
|
||||
JSONL persistence. Fixes #67953. Thanks @Ziy1-Tan.
|
||||
|
||||
@@ -6,7 +6,7 @@ import { buildPluginsCommandParams } from "./commands.test-harness.js";
|
||||
const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn());
|
||||
const validateConfigObjectWithPluginsMock = vi.hoisted(() => vi.fn());
|
||||
const writeConfigFileMock = vi.hoisted(() => vi.fn(async () => undefined));
|
||||
const buildPluginSnapshotReportMock = vi.hoisted(() => vi.fn());
|
||||
const buildPluginRegistrySnapshotReportMock = vi.hoisted(() => vi.fn());
|
||||
const buildPluginDiagnosticsReportMock = vi.hoisted(() => vi.fn());
|
||||
const buildPluginInspectReportMock = vi.hoisted(() => vi.fn());
|
||||
const buildAllPluginInspectReportsMock = vi.hoisted(() => vi.fn());
|
||||
@@ -69,7 +69,7 @@ vi.mock("../../plugins/status.js", () => ({
|
||||
buildAllPluginInspectReports: buildAllPluginInspectReportsMock,
|
||||
buildPluginDiagnosticsReport: buildPluginDiagnosticsReportMock,
|
||||
buildPluginInspectReport: buildPluginInspectReportMock,
|
||||
buildPluginSnapshotReport: buildPluginSnapshotReportMock,
|
||||
buildPluginRegistrySnapshotReport: buildPluginRegistrySnapshotReportMock,
|
||||
formatPluginCompatibilityNotice: formatPluginCompatibilityNoticeMock,
|
||||
}));
|
||||
|
||||
@@ -121,7 +121,7 @@ describe("handlePluginsCommand", () => {
|
||||
config: buildCfg(),
|
||||
issues: [],
|
||||
});
|
||||
buildPluginSnapshotReportMock.mockReturnValue({
|
||||
buildPluginRegistrySnapshotReportMock.mockReturnValue({
|
||||
workspaceDir: "/tmp/plugins-workspace",
|
||||
plugins: [
|
||||
{
|
||||
@@ -260,8 +260,8 @@ describe("handlePluginsCommand", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("resolves write targets by runtime-derived plugin name", async () => {
|
||||
buildPluginDiagnosticsReportMock.mockReturnValue({
|
||||
it("resolves write targets by indexed plugin name without loading diagnostics", async () => {
|
||||
buildPluginRegistrySnapshotReportMock.mockReturnValue({
|
||||
workspaceDir: "/tmp/plugins-workspace",
|
||||
plugins: [
|
||||
{
|
||||
@@ -280,8 +280,8 @@ describe("handlePluginsCommand", () => {
|
||||
|
||||
const result = await handlePluginsCommand(params, true);
|
||||
expect(result?.reply?.text).toContain('Plugin "superpowers" enabled');
|
||||
expect(buildPluginDiagnosticsReportMock).toHaveBeenCalled();
|
||||
expect(buildPluginSnapshotReportMock).not.toHaveBeenCalled();
|
||||
expect(buildPluginRegistrySnapshotReportMock).toHaveBeenCalled();
|
||||
expect(buildPluginDiagnosticsReportMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns an explicit unauthorized reply for native /plugins list", async () => {
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
buildAllPluginInspectReports,
|
||||
buildPluginDiagnosticsReport,
|
||||
buildPluginInspectReport,
|
||||
buildPluginSnapshotReport,
|
||||
buildPluginRegistrySnapshotReport,
|
||||
formatPluginCompatibilityNotice,
|
||||
type PluginStatusReport,
|
||||
} from "../../plugins/status.js";
|
||||
@@ -308,7 +308,7 @@ async function loadPluginCommandState(
|
||||
report:
|
||||
options?.loadModules === true
|
||||
? buildPluginDiagnosticsReport({ config, workspaceDir })
|
||||
: buildPluginSnapshotReport({ config, workspaceDir }),
|
||||
: buildPluginRegistrySnapshotReport({ config, workspaceDir }),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ export const handlePluginsCommand: CommandHandler = async (params, allowTextComm
|
||||
}
|
||||
|
||||
const loaded = await loadPluginCommandState(params.workspaceDir, {
|
||||
loadModules: pluginsCommand.action !== "list",
|
||||
loadModules: pluginsCommand.action === "inspect",
|
||||
});
|
||||
if (!loaded.ok) {
|
||||
return {
|
||||
|
||||
@@ -11,7 +11,7 @@ const mocks = vi.hoisted(() => ({
|
||||
resolveAgentWorkspaceDir: vi.fn(),
|
||||
resolveDefaultAgentId: vi.fn(),
|
||||
buildWorkspaceSkillStatus: vi.fn(),
|
||||
buildPluginSnapshotReport: vi.fn(),
|
||||
buildPluginRegistrySnapshotReport: vi.fn(),
|
||||
buildPluginCompatibilityWarnings: vi.fn(),
|
||||
listTaskFlowRecords: vi.fn<() => unknown[]>(() => []),
|
||||
listTasksForFlowId: vi.fn<(flowId: string) => unknown[]>((_flowId: string) => []),
|
||||
@@ -27,7 +27,8 @@ vi.mock("../agents/skills-status.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/status.js", () => ({
|
||||
buildPluginSnapshotReport: (...args: unknown[]) => mocks.buildPluginSnapshotReport(...args),
|
||||
buildPluginRegistrySnapshotReport: (...args: unknown[]) =>
|
||||
mocks.buildPluginRegistrySnapshotReport(...args),
|
||||
buildPluginCompatibilityWarnings: (...args: unknown[]) =>
|
||||
mocks.buildPluginCompatibilityWarnings(...args),
|
||||
}));
|
||||
@@ -53,7 +54,7 @@ async function runNoteWorkspaceStatusForTest(
|
||||
mocks.buildWorkspaceSkillStatus.mockReturnValue({
|
||||
skills: [],
|
||||
});
|
||||
mocks.buildPluginSnapshotReport.mockReturnValue({
|
||||
mocks.buildPluginRegistrySnapshotReport.mockReturnValue({
|
||||
workspaceDir: "/workspace",
|
||||
...loadResult,
|
||||
});
|
||||
@@ -85,7 +86,7 @@ describe("noteWorkspaceStatus", () => {
|
||||
}),
|
||||
);
|
||||
try {
|
||||
expect(mocks.buildPluginSnapshotReport).toHaveBeenCalledWith({
|
||||
expect(mocks.buildPluginRegistrySnapshotReport).toHaveBeenCalledWith({
|
||||
config: {},
|
||||
workspaceDir: "/workspace",
|
||||
});
|
||||
@@ -183,7 +184,7 @@ describe("noteWorkspaceStatus", () => {
|
||||
"legacy-plugin still uses legacy before_agent_start",
|
||||
]);
|
||||
try {
|
||||
expect(mocks.buildPluginSnapshotReport).toHaveBeenCalledWith({
|
||||
expect(mocks.buildPluginRegistrySnapshotReport).toHaveBeenCalledWith({
|
||||
config: {},
|
||||
workspaceDir: "/workspace",
|
||||
});
|
||||
|
||||
@@ -2,7 +2,10 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent
|
||||
import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { buildPluginCompatibilityWarnings, buildPluginSnapshotReport } from "../plugins/status.js";
|
||||
import {
|
||||
buildPluginCompatibilityWarnings,
|
||||
buildPluginRegistrySnapshotReport,
|
||||
} from "../plugins/status.js";
|
||||
import { listTasksForFlowId } from "../tasks/runtime-internal.js";
|
||||
import { listTaskFlowRecords } from "../tasks/task-flow-runtime-internal.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
@@ -69,7 +72,7 @@ export function noteWorkspaceStatus(cfg: OpenClawConfig) {
|
||||
"Skills status",
|
||||
);
|
||||
|
||||
const pluginRegistry = buildPluginSnapshotReport({
|
||||
const pluginRegistry = buildPluginRegistrySnapshotReport({
|
||||
config: cfg,
|
||||
workspaceDir,
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../config/config.js";
|
||||
|
||||
vi.mock("../../../plugins/manifest-registry.js", () => ({
|
||||
loadPluginManifestRegistry: () => ({
|
||||
vi.mock("../../../plugins/plugin-registry.js", () => ({
|
||||
loadPluginManifestRegistryForPluginRegistry: () => ({
|
||||
plugins: [
|
||||
{
|
||||
id: "brave",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { mergeMissing } from "../../../config/legacy.shared.js";
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import { loadPluginManifestRegistry } from "../../../plugins/manifest-registry.js";
|
||||
import { resolveManifestContractOwnerPluginId } from "../../../plugins/plugin-registry.js";
|
||||
import {
|
||||
loadPluginManifestRegistryForPluginRegistry,
|
||||
resolveManifestContractOwnerPluginId,
|
||||
} from "../../../plugins/plugin-registry.js";
|
||||
import {
|
||||
cloneRecord,
|
||||
ensureRecord,
|
||||
@@ -20,7 +22,9 @@ let legacyWebSearchProviderIdsCache: string[] | undefined;
|
||||
let legacyWebSearchProviderIdSetCache: Set<string> | undefined;
|
||||
|
||||
function getLegacyWebSearchProviderIds(): string[] {
|
||||
legacyWebSearchProviderIdsCache ??= loadPluginManifestRegistry({ cache: true })
|
||||
legacyWebSearchProviderIdsCache ??= loadPluginManifestRegistryForPluginRegistry({
|
||||
includeDisabled: true,
|
||||
})
|
||||
.plugins.filter((plugin) => plugin.origin === "bundled")
|
||||
.flatMap((plugin) => plugin.contracts?.webSearchProviders ?? [])
|
||||
.filter((providerId) => !NON_MIGRATED_LEGACY_WEB_SEARCH_PROVIDER_IDS.has(providerId))
|
||||
|
||||
Reference in New Issue
Block a user