fix(doctor): keep plugin allowlists passive

This commit is contained in:
Vincent Koc
2026-05-03 19:22:54 -07:00
parent 30b201eff0
commit eeed33e61e
3 changed files with 18 additions and 4 deletions

View File

@@ -57,6 +57,7 @@ Docs: https://docs.openclaw.ai
- Gateway/restart: verify listener PIDs by argv when `lsof` reports only the Node process name, so stale gateway cleanup can find macOS `cnode` listeners. Fixes #70664.
- Gateway/logging: expand leading `~` in `logging.file` before creating the file logger, preventing startup crash loops for home-relative log paths. Fixes #73587.
- Channels/CLI: keep `openclaw channels list --json` usable when provider usage fetching fails, and report per-provider usage errors without aborting the channel list. Refs #67595.
- Doctor/plugins: do not treat `plugins.allow` entries as configured plugins during missing-plugin repair, so restrictive allowlists no longer install allowed-but-unused plugins. Thanks @vincentkoc.
- Agents/messaging: deliver distinct final commentary after same-target `message` tool sends while still deduping text/media already sent by the tool, so short closing remarks are no longer silently dropped. Fixes #76915. Thanks @hclsys.
- Agents/messaging: preserve string thread IDs when matching message-tool reply dedupe routes, avoiding precision loss on numeric-looking topic IDs before channel plugin comparison. Thanks @vincentkoc.
- Channels/streaming: honor `agents.defaults.toolProgressDetail: "raw"` in Slack, Discord, Telegram, Matrix, and Microsoft Teams progress drafts, so tool-start lines include raw command/detail output when debugging. Thanks @vincentkoc.

View File

@@ -939,6 +939,23 @@ describe("repairMissingConfiguredPluginInstalls", () => {
expect(result).toEqual({ changes: [], warnings: [] });
});
it("does not install plugins merely listed in plugins.allow", async () => {
const { repairMissingConfiguredPluginInstalls } =
await import("./missing-configured-plugin-install.js");
const result = await repairMissingConfiguredPluginInstalls({
cfg: {
plugins: {
allow: ["codex"],
},
},
env: {},
});
expect(mocks.installPluginFromNpmSpec).not.toHaveBeenCalled();
expect(mocks.writePersistedInstalledPluginIndexInstallRecords).not.toHaveBeenCalled();
expect(result).toEqual({ changes: [], warnings: [] });
});
it("installs a missing third-party downloadable plugin from npm only", async () => {
mocks.installPluginFromNpmSpec.mockResolvedValueOnce({
ok: true,

View File

@@ -109,10 +109,6 @@ function collectConfiguredPluginIds(cfg: OpenClawConfig, env?: NodeJS.ProcessEnv
if (plugins?.enabled === false) {
return ids;
}
const allow = Array.isArray(plugins?.allow) ? plugins.allow : [];
for (const value of allow) {
addConfiguredPluginId(ids, value);
}
const entries = asObjectRecord(plugins?.entries);
for (const [pluginId, entry] of Object.entries(entries ?? {})) {
if (asObjectRecord(entry)?.enabled === false) {