refactor(channels): reuse runtime group policy helpers

This commit is contained in:
Peter Steinberger
2026-02-22 12:44:02 +01:00
parent 13944f773f
commit 6dd36a6b77
31 changed files with 119 additions and 40 deletions

View File

@@ -23,6 +23,7 @@ import {
resolveDiscordGroupRequireMention,
resolveDiscordGroupToolPolicy,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelMessageActionAdapter,
type ChannelPlugin,
@@ -131,7 +132,7 @@ export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
},
collectWarnings: ({ account, cfg }) => {
const warnings: string[] = [];
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.discord !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -7,6 +7,7 @@ import {
type HistoryEntry,
recordPendingHistoryEntryIfEnabled,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "openclaw/plugin-sdk";
import { resolveFeishuAccount } from "./accounts.js";
@@ -565,7 +566,7 @@ export async function handleFeishuMessage(params: {
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
if (isGroup) {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.feishu !== undefined,
groupPolicy: feishuCfg?.groupPolicy,

View File

@@ -5,6 +5,7 @@ import {
DEFAULT_ACCOUNT_ID,
PAIRING_APPROVED_MESSAGE,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
} from "openclaw/plugin-sdk";
import {
resolveFeishuAccount,
@@ -225,7 +226,7 @@ export const feishuPlugin: ChannelPlugin<ResolvedFeishuAccount> = {
collectWarnings: ({ cfg, accountId }) => {
const account = resolveFeishuAccount({ cfg, accountId });
const feishuCfg = account.config;
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.feishu !== undefined,
groupPolicy: feishuCfg?.groupPolicy,

View File

@@ -12,6 +12,7 @@ import {
resolveChannelMediaMaxBytes,
resolveGoogleChatGroupRequireMention,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelDock,
type ChannelMessageActionAdapter,
@@ -199,7 +200,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
},
collectWarnings: ({ account, cfg }) => {
const warnings: string[] = [];
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.googlechat !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -1,11 +1,13 @@
import type { IncomingMessage, ServerResponse } from "node:http";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
import {
GROUP_POLICY_BLOCKED_LABEL,
createReplyPrefixOptions,
readJsonBodyWithLimit,
registerWebhookTarget,
rejectNonPostWebhookRequest,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveSingleWebhookTargetAsync,
resolveWebhookPath,
resolveWebhookTargets,
@@ -428,7 +430,7 @@ async function processMessageWithPipeline(params: {
return;
}
const defaultGroupPolicy = config.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(config);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: config.channels?.googlechat !== undefined,
@@ -439,7 +441,7 @@ async function processMessageWithPipeline(params: {
providerMissingFallbackApplied,
providerKey: "googlechat",
accountId: account.accountId,
blockedLabel: "space messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.space,
log: (message) => logVerbose(core, runtime, message),
});
const groupConfigResolved = resolveGroupConfig({

View File

@@ -19,6 +19,7 @@ import {
resolveIMessageGroupRequireMention,
resolveIMessageGroupToolPolicy,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelPlugin,
type ResolvedIMessageAccount,
@@ -98,7 +99,7 @@ export const imessagePlugin: ChannelPlugin<ResolvedIMessageAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.imessage !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -5,6 +5,7 @@ import {
getChatChannelMeta,
PAIRING_APPROVED_MESSAGE,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
deleteAccountFromConfigSection,
type ChannelPlugin,
@@ -135,7 +136,7 @@ export const ircPlugin: ChannelPlugin<ResolvedIrcAccount, IrcProbe> = {
},
collectWarnings: ({ account, cfg }) => {
const warnings: string[] = [];
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.irc !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -1,8 +1,10 @@
import {
GROUP_POLICY_BLOCKED_LABEL,
createReplyPrefixOptions,
logInboundDrop,
resolveControlCommandGate,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
type OpenClawConfig,
type RuntimeEnv,
@@ -86,7 +88,7 @@ export async function handleIrcInbound(params: {
: message.senderNick;
const dmPolicy = account.config.dmPolicy ?? "pairing";
const defaultGroupPolicy = config.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(config);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: config.channels?.irc !== undefined,
@@ -97,7 +99,7 @@ export async function handleIrcInbound(params: {
providerMissingFallbackApplied,
providerKey: "irc",
accountId: account.accountId,
blockedLabel: "channel messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.channel,
log: (message) => runtime.log?.(message),
});

View File

@@ -4,6 +4,7 @@ import {
LineConfigSchema,
processLineMessage,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
type ChannelPlugin,
type ChannelStatusIssue,
type OpenClawConfig,
@@ -162,7 +163,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.line !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -7,6 +7,7 @@ import {
normalizeAccountId,
PAIRING_APPROVED_MESSAGE,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelPlugin,
} from "openclaw/plugin-sdk";
@@ -170,7 +171,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = (cfg as CoreConfig).channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg as CoreConfig);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: (cfg as CoreConfig).channels?.matrix !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -1,7 +1,9 @@
import { format } from "node:util";
import {
GROUP_POLICY_BLOCKED_LABEL,
mergeAllowlist,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
summarizeMapping,
warnMissingProviderGroupPolicyFallbackOnce,
type RuntimeEnv,
@@ -248,7 +250,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
setActiveMatrixClient(client, opts.accountId);
const mentionRegexes = core.channel.mentions.buildMentionRegexes(cfg);
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy: groupPolicyRaw, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.matrix !== undefined,
@@ -259,7 +261,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
providerMissingFallbackApplied,
providerKey: "matrix",
accountId: account.accountId,
blockedLabel: "room messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.room,
log: (message) => logVerboseMessage(message),
});
const groupPolicy = allowlistOnly && groupPolicyRaw === "open" ? "allowlist" : groupPolicyRaw;

View File

@@ -7,6 +7,7 @@ import {
migrateBaseNameToDefaultAccount,
normalizeAccountId,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelMessageActionAdapter,
type ChannelMessageActionName,
@@ -229,7 +230,7 @@ export const mattermostPlugin: ChannelPlugin<ResolvedMattermostAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.mattermost !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -17,6 +17,7 @@ import {
recordPendingHistoryEntryIfEnabled,
resolveControlCommandGate,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveChannelMediaMaxBytes,
warnMissingProviderGroupPolicyFallbackOnce,
type HistoryEntry,
@@ -244,7 +245,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {}
cfg.messages?.groupChat?.historyLimit ?? DEFAULT_GROUP_HISTORY_LIMIT,
);
const channelHistories = new Map<string, HistoryEntry[]>();
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.mattermost !== undefined,

View File

@@ -7,6 +7,7 @@ import {
MSTeamsConfigSchema,
PAIRING_APPROVED_MESSAGE,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
} from "openclaw/plugin-sdk";
import { listMSTeamsDirectoryGroupsLive, listMSTeamsDirectoryPeersLive } from "./directory-live.js";
import { msteamsOnboardingAdapter } from "./onboarding.js";
@@ -128,7 +129,7 @@ export const msteamsPlugin: ChannelPlugin<ResolvedMSTeamsAccount> = {
},
security: {
collectWarnings: ({ cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.msteams !== undefined,
groupPolicy: cfg.channels?.msteams?.groupPolicy,

View File

@@ -5,6 +5,7 @@ import {
logInboundDrop,
recordPendingHistoryEntryIfEnabled,
resolveControlCommandGate,
resolveDefaultGroupPolicy,
resolveMentionGating,
formatAllowlistMatchMeta,
type HistoryEntry,
@@ -174,7 +175,7 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
}
}
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const groupPolicy =
!isDirectMessage && msteamsCfg
? (msteamsCfg.groupPolicy ?? defaultGroupPolicy ?? "allowlist")

View File

@@ -6,6 +6,7 @@ import {
formatPairingApproveHint,
normalizeAccountId,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
setAccountEnabledInConfigSection,
type ChannelPlugin,
type OpenClawConfig,
@@ -129,7 +130,7 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent:
(cfg.channels as Record<string, unknown> | undefined)?.["nextcloud-talk"] !== undefined,

View File

@@ -1,8 +1,10 @@
import {
GROUP_POLICY_BLOCKED_LABEL,
createReplyPrefixOptions,
logInboundDrop,
resolveControlCommandGate,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
type OpenClawConfig,
type RuntimeEnv,
@@ -86,11 +88,7 @@ export async function handleNextcloudTalkInbound(params: {
statusSink?.({ lastInboundAt: message.timestamp });
const dmPolicy = account.config.dmPolicy ?? "pairing";
const defaultGroupPolicy = (
(config.channels as Record<string, unknown> | undefined)?.defaults as
| { groupPolicy?: string }
| undefined
)?.groupPolicy as GroupPolicy | undefined;
const defaultGroupPolicy = resolveDefaultGroupPolicy(config as OpenClawConfig);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent:
@@ -103,7 +101,7 @@ export async function handleNextcloudTalkInbound(params: {
providerMissingFallbackApplied,
providerKey: "nextcloud-talk",
accountId: account.accountId,
blockedLabel: "room messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.room,
log: (message) => runtime.log?.(message),
});

View File

@@ -18,6 +18,7 @@ import {
resolveChannelMediaMaxBytes,
resolveDefaultSignalAccountId,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveSignalAccount,
setAccountEnabledInConfigSection,
signalOnboardingAdapter,
@@ -124,7 +125,7 @@ export const signalPlugin: ChannelPlugin<ResolvedSignalAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.signal !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -20,6 +20,7 @@ import {
resolveSlackAccount,
resolveSlackReplyToMode,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveSlackGroupRequireMention,
resolveSlackGroupToolPolicy,
buildSlackThreadingToolContext,
@@ -151,7 +152,7 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
},
collectWarnings: ({ account, cfg }) => {
const warnings: string[] = [];
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.slack !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -18,6 +18,7 @@ import {
parseTelegramThreadId,
resolveDefaultTelegramAccountId,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveTelegramAccount,
resolveTelegramGroupRequireMention,
resolveTelegramGroupToolPolicy,
@@ -196,7 +197,7 @@ export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProb
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.telegram !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -20,6 +20,7 @@ import {
resolveDefaultWhatsAppAccountId,
resolveWhatsAppOutboundTarget,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveWhatsAppAccount,
resolveWhatsAppGroupRequireMention,
resolveWhatsAppGroupToolPolicy,
@@ -143,7 +144,7 @@ export const whatsappPlugin: ChannelPlugin<ResolvedWhatsAppAccount> = {
};
},
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy } = resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.whatsapp !== undefined,
groupPolicy: account.groupPolicy,

View File

@@ -4,6 +4,7 @@ import {
createReplyPrefixOptions,
mergeAllowlist,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveSenderCommandAuthorization,
summarizeMapping,
warnMissingProviderGroupPolicyFallbackOnce,
@@ -179,7 +180,7 @@ async function processMessage(
const groupName = metadata?.threadName ?? "";
const chatId = threadId;
const defaultGroupPolicy = config.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(config);
const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent: config.channels?.zalouser !== undefined,
groupPolicy: account.config.groupPolicy,

View File

@@ -1,11 +1,18 @@
import { describe, expect, it } from "vitest";
import { beforeEach, describe, expect, it } from "vitest";
import {
GROUP_POLICY_BLOCKED_LABEL,
resetMissingProviderGroupPolicyFallbackWarningsForTesting,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveOpenProviderRuntimeGroupPolicy,
resolveRuntimeGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "./runtime-group-policy.js";
beforeEach(() => {
resetMissingProviderGroupPolicyFallbackWarningsForTesting();
});
describe("resolveRuntimeGroupPolicy", () => {
it.each([
{
@@ -58,6 +65,15 @@ describe("resolveAllowlistProviderRuntimeGroupPolicy", () => {
});
});
describe("resolveDefaultGroupPolicy", () => {
it("returns channels.defaults.groupPolicy when present", () => {
const resolved = resolveDefaultGroupPolicy({
channels: { defaults: { groupPolicy: "disabled" } },
});
expect(resolved).toBe("disabled");
});
});
describe("warnMissingProviderGroupPolicyFallbackOnce", () => {
it("logs only once per provider/account key", () => {
const lines: string[] = [];
@@ -65,14 +81,14 @@ describe("warnMissingProviderGroupPolicyFallbackOnce", () => {
providerMissingFallbackApplied: true,
providerKey: "runtime-policy-test",
accountId: "account-a",
blockedLabel: "room messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.room,
log: (message) => lines.push(message),
});
const second = warnMissingProviderGroupPolicyFallbackOnce({
providerMissingFallbackApplied: true,
providerKey: "runtime-policy-test",
accountId: "account-a",
blockedLabel: "room messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.room,
log: (message) => lines.push(message),
});

View File

@@ -32,6 +32,26 @@ export type ResolveProviderRuntimeGroupPolicyParams = {
defaultGroupPolicy?: GroupPolicy;
};
export type GroupPolicyDefaultsConfig = {
channels?: {
defaults?: {
groupPolicy?: GroupPolicy;
};
};
};
export function resolveDefaultGroupPolicy(cfg: GroupPolicyDefaultsConfig): GroupPolicy | undefined {
return cfg.channels?.defaults?.groupPolicy;
}
export const GROUP_POLICY_BLOCKED_LABEL = {
group: "group messages",
guild: "guild messages",
room: "room messages",
channel: "channel messages",
space: "space messages",
} as const;
/**
* Standard provider runtime policy:
* - configured provider fallback: open
@@ -89,3 +109,10 @@ export function warnMissingProviderGroupPolicyFallbackOnce(params: {
);
return true;
}
/**
* Test helper. Keeps warning-cache state deterministic across test files.
*/
export function resetMissingProviderGroupPolicyFallbackWarningsForTesting(): void {
warnedMissingProviderGroupPolicy.clear();
}

View File

@@ -22,7 +22,9 @@ import {
import type { OpenClawConfig, ReplyToMode } from "../../config/config.js";
import { loadConfig } from "../../config/config.js";
import {
GROUP_POLICY_BLOCKED_LABEL,
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../config/runtime-group-policy.js";
import { danger, logVerbose, shouldLogVerbose, warn } from "../../globals.js";
@@ -256,7 +258,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
const discordRestFetch = resolveDiscordRestFetch(rawDiscordCfg.proxy, runtime);
const dmConfig = rawDiscordCfg.dm;
let guildEntries = rawDiscordCfg.guilds;
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const providerConfigPresent = cfg.channels?.discord !== undefined;
const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent,
@@ -269,7 +271,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
providerMissingFallbackApplied,
providerKey: "discord",
accountId: account.accountId,
blockedLabel: "guild messages",
blockedLabel: GROUP_POLICY_BLOCKED_LABEL.guild,
log: (message) => runtime.log?.(warn(message)),
});
let allowFrom = discordCfg.allowFrom ?? dmConfig?.allowFrom;
@@ -629,6 +631,7 @@ export const __testing = {
createDiscordGatewayPlugin,
dedupeSkillCommandsForDiscord,
resolveDiscordRuntimeGroupPolicy: resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveDiscordRestFetch,
resolveThreadBindingsEnabled,
};

View File

@@ -18,6 +18,7 @@ import { recordInboundSession } from "../../channels/session.js";
import { loadConfig } from "../../config/config.js";
import {
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../config/runtime-group-policy.js";
import { readSessionUpdatedAt, resolveStorePath } from "../../config/sessions.js";
@@ -147,7 +148,7 @@ export async function monitorIMessageProvider(opts: MonitorIMessageOpts = {}): P
imessageCfg.groupAllowFrom ??
(imessageCfg.allowFrom && imessageCfg.allowFrom.length > 0 ? imessageCfg.allowFrom : []),
);
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.imessage !== undefined,
groupPolicy: imessageCfg.groupPolicy,
@@ -525,4 +526,5 @@ export async function monitorIMessageProvider(opts: MonitorIMessageOpts = {}): P
export const __testing = {
resolveIMessageRuntimeGroupPolicy: resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
};

View File

@@ -10,6 +10,7 @@ import type {
import type { OpenClawConfig } from "../config/config.js";
import {
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../config/runtime-group-policy.js";
import { danger, logVerbose } from "../globals.js";
@@ -136,7 +137,7 @@ async function shouldProcessLineEvent(
storeAllowFrom,
dmPolicy,
});
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.line !== undefined,

View File

@@ -133,9 +133,13 @@ export type {
MSTeamsTeamConfig,
} from "../config/types.js";
export {
GROUP_POLICY_BLOCKED_LABEL,
resetMissingProviderGroupPolicyFallbackWarningsForTesting,
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
resolveOpenProviderRuntimeGroupPolicy,
resolveRuntimeGroupPolicy,
type GroupPolicyDefaultsConfig,
type RuntimeGroupPolicyResolution,
type RuntimeGroupPolicyParams,
type ResolveProviderRuntimeGroupPolicyParams,

View File

@@ -5,6 +5,7 @@ import type { OpenClawConfig } from "../config/config.js";
import { loadConfig } from "../config/config.js";
import {
resolveAllowlistProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../config/runtime-group-policy.js";
import type { SignalReactionNotificationMode } from "../config/types.js";
@@ -348,7 +349,7 @@ export async function monitorSignalProvider(opts: MonitorSignalOpts = {}): Promi
? accountInfo.config.allowFrom
: []),
);
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } =
resolveAllowlistProviderRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.signal !== undefined,

View File

@@ -12,6 +12,7 @@ import {
import { loadConfig } from "../../config/config.js";
import {
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../config/runtime-group-policy.js";
import type { SessionScope } from "../../config/sessions.js";
@@ -102,7 +103,7 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
const groupDmEnabled = dmConfig?.groupEnabled ?? false;
const groupDmChannels = dmConfig?.groupChannels;
let channelsConfig = slackCfg.channels;
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const providerConfigPresent = cfg.channels?.slack !== undefined;
const { groupPolicy, providerMissingFallbackApplied } = resolveOpenProviderRuntimeGroupPolicy({
providerConfigPresent,
@@ -369,4 +370,5 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
export const __testing = {
resolveSlackRuntimeGroupPolicy: resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
};

View File

@@ -1,6 +1,7 @@
import { loadConfig } from "../../config/config.js";
import {
resolveOpenProviderRuntimeGroupPolicy,
resolveDefaultGroupPolicy,
warnMissingProviderGroupPolicyFallbackOnce,
} from "../../config/runtime-group-policy.js";
import { logVerbose } from "../../globals.js";
@@ -100,7 +101,7 @@ export async function checkInboundAccessControl(params: {
// - "open": groups bypass allowFrom, only mention-gating applies
// - "disabled": block all group messages entirely
// - "allowlist": only allow group messages from senders in groupAllowFrom/allowFrom
const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
const defaultGroupPolicy = resolveDefaultGroupPolicy(cfg);
const { groupPolicy, providerMissingFallbackApplied } = resolveWhatsAppRuntimeGroupPolicy({
providerConfigPresent: cfg.channels?.whatsapp !== undefined,
groupPolicy: account.groupPolicy,