mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-14 14:20:45 +00:00
fix: suppress disabled channel read-only presence
This commit is contained in:
@@ -958,6 +958,100 @@ describe("listConfiguredChannelIdsForReadOnlyScope", () => {
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("treats disabled channel config as a hard read-only env suppressor", () => {
|
||||
listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
|
||||
listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
|
||||
{ channelId: "demo-channel", source: "env" },
|
||||
]);
|
||||
|
||||
const config = {
|
||||
channels: {
|
||||
"Demo-Channel": {
|
||||
enabled: false,
|
||||
token: "stale-token",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
"demo-channel": {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
|
||||
expect(
|
||||
resolveConfiguredChannelPresencePolicy({
|
||||
config,
|
||||
workspaceDir: "/tmp",
|
||||
env: {
|
||||
DEMO_CHANNEL_TOKEN: "ambient",
|
||||
} as NodeJS.ProcessEnv,
|
||||
includePersistedAuthState: false,
|
||||
}),
|
||||
).toEqual([]);
|
||||
expect(
|
||||
listConfiguredChannelIdsForReadOnlyScope({
|
||||
config,
|
||||
workspaceDir: "/tmp",
|
||||
env: {
|
||||
DEMO_CHANNEL_TOKEN: "ambient",
|
||||
} as NodeJS.ProcessEnv,
|
||||
includePersistedAuthState: false,
|
||||
}),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("treats disabled channel config as a hard persisted-auth suppressor", () => {
|
||||
listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
|
||||
listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
|
||||
{ channelId: "demo-channel", source: "persisted-auth" },
|
||||
]);
|
||||
|
||||
expect(
|
||||
listConfiguredChannelIdsForReadOnlyScope({
|
||||
config: {
|
||||
channels: {
|
||||
"demo-channel": {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
entries: {
|
||||
"demo-channel": {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
workspaceDir: "/tmp",
|
||||
env: {},
|
||||
}),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("treats disabled channel config as a hard manifest-env suppressor", () => {
|
||||
expect(
|
||||
listConfiguredChannelIdsForReadOnlyScope({
|
||||
config: {
|
||||
channels: {
|
||||
"external-env-channel": {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
allow: ["external-env-channel-plugin"],
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
workspaceDir: "/tmp",
|
||||
env: {
|
||||
EXTERNAL_ENV_CHANNEL_TOKEN: "token",
|
||||
} as NodeJS.ProcessEnv,
|
||||
includePersistedAuthState: false,
|
||||
}),
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("lets explicit bundled channel config bypass restrictive allowlists", () => {
|
||||
const config = {
|
||||
channels: {
|
||||
|
||||
@@ -322,6 +322,24 @@ function addPolicySignal(
|
||||
sources.add(source);
|
||||
}
|
||||
|
||||
function listDisabledChannelIdsForConfig(config: OpenClawConfig): string[] {
|
||||
const channels = config.channels;
|
||||
if (!channels || typeof channels !== "object" || Array.isArray(channels)) {
|
||||
return [];
|
||||
}
|
||||
return Object.entries(channels)
|
||||
.filter(([, value]) => {
|
||||
return (
|
||||
value &&
|
||||
typeof value === "object" &&
|
||||
!Array.isArray(value) &&
|
||||
(value as { enabled?: unknown }).enabled === false
|
||||
);
|
||||
})
|
||||
.map(([channelId]) => normalizeOptionalLowercaseString(channelId))
|
||||
.filter((channelId): channelId is string => Boolean(channelId));
|
||||
}
|
||||
|
||||
export function resolveConfiguredChannelPresencePolicy(params: {
|
||||
config: OpenClawConfig;
|
||||
activationSourceConfig?: OpenClawConfig;
|
||||
@@ -344,6 +362,7 @@ export function resolveConfiguredChannelPresencePolicy(params: {
|
||||
cache: params.cache,
|
||||
}).plugins;
|
||||
|
||||
const disabledChannelIds = new Set(listDisabledChannelIdsForConfig(params.config));
|
||||
const entrySources = new Map<string, Set<ConfiguredChannelPresenceSource>>();
|
||||
for (const channelId of listExplicitConfiguredChannelIdsForConfig(params.config)) {
|
||||
addPolicySignal(entrySources, channelId, "explicit-config");
|
||||
@@ -364,6 +383,9 @@ export function resolveConfiguredChannelPresencePolicy(params: {
|
||||
})) {
|
||||
addPolicySignal(entrySources, signal.channelId, signal.source);
|
||||
}
|
||||
for (const channelId of disabledChannelIds) {
|
||||
entrySources.delete(channelId);
|
||||
}
|
||||
|
||||
const activationSource = createPluginActivationSource({
|
||||
config: params.activationSourceConfig ?? params.config,
|
||||
@@ -428,22 +450,7 @@ export function listConfiguredAnnounceChannelIdsForConfig(params: {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
cache?: boolean;
|
||||
}): string[] {
|
||||
const channels = params.config.channels;
|
||||
const disabledChannelIds = new Set(
|
||||
channels && typeof channels === "object" && !Array.isArray(channels)
|
||||
? Object.entries(channels)
|
||||
.filter(([, value]) => {
|
||||
return (
|
||||
value &&
|
||||
typeof value === "object" &&
|
||||
!Array.isArray(value) &&
|
||||
(value as { enabled?: unknown }).enabled === false
|
||||
);
|
||||
})
|
||||
.map(([channelId]) => normalizeOptionalLowercaseString(channelId))
|
||||
.filter((channelId): channelId is string => Boolean(channelId))
|
||||
: [],
|
||||
);
|
||||
const disabledChannelIds = new Set(listDisabledChannelIdsForConfig(params.config));
|
||||
return normalizeChannelIds([
|
||||
...listExplicitConfiguredChannelIdsForConfig(params.config),
|
||||
...listConfiguredChannelIdsForReadOnlyScope({
|
||||
|
||||
Reference in New Issue
Block a user