mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:30:43 +00:00
fix: respect external channel owners in doctor blockers
This commit is contained in:
@@ -30,6 +30,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Cron/providers: preflight local Ollama and OpenAI-compatible provider endpoints before isolated cron agent turns, record unreachable local providers as skipped runs, and cache dead-endpoint probes so many jobs do not hammer the same stopped local server. Fixes #58584. Thanks @jpeghead.
|
||||
- Doctor/channels: suppress disabled bundled-plugin blocker warnings when a trusted external plugin owns the configured channel, so Lark/Feishu installs no longer get Feishu repair noise after switching to `openclaw-lark`. Fixes #56794. Thanks @wuji-tech-dev.
|
||||
- CLI/status: show skipped fast-path memory checks as `not checked` and report active custom memory plugin runtime status from `status --json --all` without requiring built-in `agents.defaults.memorySearch`, so plugins such as memory-lancedb-pro and memory-cms no longer look unavailable when their own runtime is healthy. Fixes #56968. Thanks @Tony-ooo and @aderius.
|
||||
- Gateway/channels: record and log unexpected clean channel monitor exits so channels that return without throwing no longer appear stopped with no error. Fixes #73099. Thanks @balaji1968-kingler.
|
||||
- Channels/Telegram: centralize polling update tracking so accepted offsets remain durable across restarts, same-process handler failures can still retry, and slow offset writes cannot overwrite newer accepted watermarks. Refs #73115. Thanks @vdruts.
|
||||
|
||||
@@ -106,4 +106,105 @@ describe("channel plugin blockers", () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not report a disabled bundled owner when a configured external plugin owns the channel", () => {
|
||||
vi.spyOn(manifestRegistry, "loadPluginManifestRegistry").mockReturnValue({
|
||||
plugins: [
|
||||
{
|
||||
id: "feishu",
|
||||
origin: "bundled",
|
||||
channels: ["feishu"],
|
||||
enabledByDefault: true,
|
||||
},
|
||||
{
|
||||
id: "openclaw-lark",
|
||||
origin: "config",
|
||||
channels: ["feishu"],
|
||||
enabledByDefault: false,
|
||||
channelConfigs: {
|
||||
feishu: {
|
||||
schema: {
|
||||
type: "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
diagnostics: [],
|
||||
} as unknown as ReturnType<typeof manifestRegistry.loadPluginManifestRegistry>);
|
||||
|
||||
const hits = scanConfiguredChannelPluginBlockers({
|
||||
plugins: {
|
||||
entries: {
|
||||
feishu: {
|
||||
enabled: false,
|
||||
},
|
||||
"openclaw-lark": {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
feishu: {
|
||||
footer: {
|
||||
model: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(hits).toEqual([]);
|
||||
});
|
||||
|
||||
it("still reports the disabled bundled owner when an external channel owner is not trusted", () => {
|
||||
vi.spyOn(manifestRegistry, "loadPluginManifestRegistry").mockReturnValue({
|
||||
plugins: [
|
||||
{
|
||||
id: "feishu",
|
||||
origin: "bundled",
|
||||
channels: ["feishu"],
|
||||
enabledByDefault: true,
|
||||
},
|
||||
{
|
||||
id: "openclaw-lark",
|
||||
origin: "config",
|
||||
channels: ["feishu"],
|
||||
enabledByDefault: false,
|
||||
channelConfigs: {
|
||||
feishu: {
|
||||
schema: {
|
||||
type: "object",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
diagnostics: [],
|
||||
} as unknown as ReturnType<typeof manifestRegistry.loadPluginManifestRegistry>);
|
||||
|
||||
const hits = scanConfiguredChannelPluginBlockers({
|
||||
plugins: {
|
||||
entries: {
|
||||
feishu: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
feishu: {
|
||||
footer: {
|
||||
model: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(hits).toEqual([
|
||||
{
|
||||
channelId: "feishu",
|
||||
pluginId: "feishu",
|
||||
reason: "disabled in config",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import type { OpenClawConfig } from "../../../config/types.openclaw.js";
|
||||
import { listExplicitConfiguredChannelIdsForConfig } from "../../../plugins/channel-plugin-ids.js";
|
||||
import {
|
||||
listExplicitConfiguredChannelIdsForConfig,
|
||||
resolveConfiguredChannelPresencePolicy,
|
||||
} from "../../../plugins/channel-plugin-ids.js";
|
||||
import {
|
||||
normalizePluginsConfig,
|
||||
resolveEffectivePluginActivationState,
|
||||
} from "../../../plugins/config-state.js";
|
||||
import { loadPluginManifestRegistryForPluginRegistry } from "../../../plugins/plugin-registry.js";
|
||||
import { normalizeOptionalLowercaseString } from "../../../shared/string-coerce.js";
|
||||
import { sanitizeForLog } from "../../../terminal/ansi.js";
|
||||
|
||||
export type ChannelPluginBlockerHit = {
|
||||
@@ -39,7 +43,11 @@ export function scanConfiguredChannelPluginBlockers(
|
||||
if (!hasExplicitChannelPluginBlockerConfig(cfg)) {
|
||||
return [];
|
||||
}
|
||||
const configuredChannelIds = new Set(listExplicitConfiguredChannelIdsForConfig(cfg));
|
||||
const configuredChannelIds = new Set(
|
||||
listExplicitConfiguredChannelIdsForConfig(cfg)
|
||||
.map((channelId) => normalizeOptionalLowercaseString(channelId))
|
||||
.filter((channelId): channelId is string => Boolean(channelId)),
|
||||
);
|
||||
if (configuredChannelIds.size === 0) {
|
||||
return [];
|
||||
}
|
||||
@@ -50,6 +58,16 @@ export function scanConfiguredChannelPluginBlockers(
|
||||
env,
|
||||
includeDisabled: true,
|
||||
});
|
||||
const activeConfiguredChannelIds = new Set(
|
||||
resolveConfiguredChannelPresencePolicy({
|
||||
config: cfg,
|
||||
env,
|
||||
includePersistedAuthState: false,
|
||||
manifestRecords: registry.plugins,
|
||||
})
|
||||
.filter((entry) => entry.effective)
|
||||
.map((entry) => entry.channelId),
|
||||
);
|
||||
const hits: ChannelPluginBlockerHit[] = [];
|
||||
|
||||
for (const plugin of registry.plugins) {
|
||||
@@ -73,10 +91,17 @@ export function scanConfiguredChannelPluginBlockers(
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const channelId of plugin.channels) {
|
||||
for (const rawChannelId of plugin.channels) {
|
||||
const channelId = normalizeOptionalLowercaseString(rawChannelId);
|
||||
if (!channelId) {
|
||||
continue;
|
||||
}
|
||||
if (!configuredChannelIds.has(channelId)) {
|
||||
continue;
|
||||
}
|
||||
if (activeConfiguredChannelIds.has(channelId)) {
|
||||
continue;
|
||||
}
|
||||
hits.push({
|
||||
channelId,
|
||||
pluginId: plugin.id,
|
||||
|
||||
Reference in New Issue
Block a user