mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor: share channel config security scaffolding
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
buildAccountScopedDmSecurityPolicy,
|
|
||||||
buildOpenGroupPolicyConfigureRouteAllowlistWarning,
|
buildOpenGroupPolicyConfigureRouteAllowlistWarning,
|
||||||
collectAllowlistProviderGroupPolicyWarnings,
|
collectAllowlistProviderGroupPolicyWarnings,
|
||||||
createScopedAccountConfigAccessors,
|
createScopedAccountConfigAccessors,
|
||||||
|
createScopedDmSecurityResolver,
|
||||||
formatNormalizedAllowFromEntries,
|
formatNormalizedAllowFromEntries,
|
||||||
} from "openclaw/plugin-sdk/compat";
|
} from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
@@ -84,6 +84,14 @@ const googleChatConfigBase = createScopedChannelConfigBase<ResolvedGoogleChatAcc
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resolveGoogleChatDmPolicy = createScopedDmSecurityResolver<ResolvedGoogleChatAccount>({
|
||||||
|
channelKey: "googlechat",
|
||||||
|
resolvePolicy: (account) => account.config.dm?.policy,
|
||||||
|
resolveAllowFrom: (account) => account.config.dm?.allowFrom,
|
||||||
|
allowFromPathSuffix: "dm.",
|
||||||
|
normalizeEntry: (raw) => formatAllowFromEntry(raw),
|
||||||
|
});
|
||||||
|
|
||||||
export const googlechatDock: ChannelDock = {
|
export const googlechatDock: ChannelDock = {
|
||||||
id: "googlechat",
|
id: "googlechat",
|
||||||
capabilities: {
|
capabilities: {
|
||||||
@@ -170,18 +178,7 @@ export const googlechatPlugin: ChannelPlugin<ResolvedGoogleChatAccount> = {
|
|||||||
...googleChatConfigAccessors,
|
...googleChatConfigAccessors,
|
||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
resolveDmPolicy: resolveGoogleChatDmPolicy,
|
||||||
return buildAccountScopedDmSecurityPolicy({
|
|
||||||
cfg,
|
|
||||||
channelKey: "googlechat",
|
|
||||||
accountId,
|
|
||||||
fallbackAccountId: account.accountId ?? DEFAULT_ACCOUNT_ID,
|
|
||||||
policy: account.config.dm?.policy,
|
|
||||||
allowFrom: account.config.dm?.allowFrom ?? [],
|
|
||||||
allowFromPathSuffix: "dm.",
|
|
||||||
normalizeEntry: (raw) => formatAllowFromEntry(raw),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
collectWarnings: ({ account, cfg }) => {
|
collectWarnings: ({ account, cfg }) => {
|
||||||
const warnings = collectAllowlistProviderGroupPolicyWarnings({
|
const warnings = collectAllowlistProviderGroupPolicyWarnings({
|
||||||
cfg,
|
cfg,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
buildAccountScopedDmSecurityPolicy,
|
|
||||||
createScopedAccountConfigAccessors,
|
|
||||||
collectAllowlistProviderRestrictSendersWarnings,
|
collectAllowlistProviderRestrictSendersWarnings,
|
||||||
|
createScopedAccountConfigAccessors,
|
||||||
|
createScopedChannelConfigBase,
|
||||||
|
createScopedDmSecurityResolver,
|
||||||
} from "openclaw/plugin-sdk/compat";
|
} from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
buildChannelConfigSchema,
|
buildChannelConfigSchema,
|
||||||
@@ -43,6 +44,24 @@ const lineConfigAccessors = createScopedAccountConfigAccessors({
|
|||||||
.map((entry) => entry.replace(/^line:(?:user:)?/i, "")),
|
.map((entry) => entry.replace(/^line:(?:user:)?/i, "")),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const lineConfigBase = createScopedChannelConfigBase<ResolvedLineAccount, OpenClawConfig>({
|
||||||
|
sectionKey: "line",
|
||||||
|
listAccountIds: (cfg) => getLineRuntime().channel.line.listLineAccountIds(cfg),
|
||||||
|
resolveAccount: (cfg, accountId) =>
|
||||||
|
getLineRuntime().channel.line.resolveLineAccount({ cfg, accountId: accountId ?? undefined }),
|
||||||
|
defaultAccountId: (cfg) => getLineRuntime().channel.line.resolveDefaultLineAccountId(cfg),
|
||||||
|
clearBaseFields: ["channelSecret", "tokenFile", "secretFile"],
|
||||||
|
});
|
||||||
|
|
||||||
|
const resolveLineDmPolicy = createScopedDmSecurityResolver<ResolvedLineAccount>({
|
||||||
|
channelKey: "line",
|
||||||
|
resolvePolicy: (account) => account.config.dmPolicy,
|
||||||
|
resolveAllowFrom: (account) => account.config.allowFrom,
|
||||||
|
policyPathSuffix: "dmPolicy",
|
||||||
|
approveHint: "openclaw pairing approve line <code>",
|
||||||
|
normalizeEntry: (raw) => raw.replace(/^line:(?:user:)?/i, ""),
|
||||||
|
});
|
||||||
|
|
||||||
function patchLineAccountConfig(
|
function patchLineAccountConfig(
|
||||||
cfg: OpenClawConfig,
|
cfg: OpenClawConfig,
|
||||||
lineConfig: LineConfig,
|
lineConfig: LineConfig,
|
||||||
@@ -113,40 +132,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
|
|||||||
reload: { configPrefixes: ["channels.line"] },
|
reload: { configPrefixes: ["channels.line"] },
|
||||||
configSchema: buildChannelConfigSchema(LineConfigSchema),
|
configSchema: buildChannelConfigSchema(LineConfigSchema),
|
||||||
config: {
|
config: {
|
||||||
listAccountIds: (cfg) => getLineRuntime().channel.line.listLineAccountIds(cfg),
|
...lineConfigBase,
|
||||||
resolveAccount: (cfg, accountId) =>
|
|
||||||
getLineRuntime().channel.line.resolveLineAccount({ cfg, accountId: accountId ?? undefined }),
|
|
||||||
defaultAccountId: (cfg) => getLineRuntime().channel.line.resolveDefaultLineAccountId(cfg),
|
|
||||||
setAccountEnabled: ({ cfg, accountId, enabled }) => {
|
|
||||||
const lineConfig = (cfg.channels?.line ?? {}) as LineConfig;
|
|
||||||
return patchLineAccountConfig(cfg, lineConfig, accountId, { enabled });
|
|
||||||
},
|
|
||||||
deleteAccount: ({ cfg, accountId }) => {
|
|
||||||
const lineConfig = (cfg.channels?.line ?? {}) as LineConfig;
|
|
||||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
||||||
// oxlint-disable-next-line no-unused-vars
|
|
||||||
const { channelSecret, tokenFile, secretFile, ...rest } = lineConfig;
|
|
||||||
return {
|
|
||||||
...cfg,
|
|
||||||
channels: {
|
|
||||||
...cfg.channels,
|
|
||||||
line: rest,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const accounts = { ...lineConfig.accounts };
|
|
||||||
delete accounts[accountId];
|
|
||||||
return {
|
|
||||||
...cfg,
|
|
||||||
channels: {
|
|
||||||
...cfg.channels,
|
|
||||||
line: {
|
|
||||||
...lineConfig,
|
|
||||||
accounts: Object.keys(accounts).length > 0 ? accounts : undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
isConfigured: (account) =>
|
isConfigured: (account) =>
|
||||||
Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim()),
|
Boolean(account.channelAccessToken?.trim() && account.channelSecret?.trim()),
|
||||||
describeAccount: (account) => ({
|
describeAccount: (account) => ({
|
||||||
@@ -159,19 +145,7 @@ export const linePlugin: ChannelPlugin<ResolvedLineAccount> = {
|
|||||||
...lineConfigAccessors,
|
...lineConfigAccessors,
|
||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
resolveDmPolicy: resolveLineDmPolicy,
|
||||||
return buildAccountScopedDmSecurityPolicy({
|
|
||||||
cfg,
|
|
||||||
channelKey: "line",
|
|
||||||
accountId,
|
|
||||||
fallbackAccountId: account.accountId ?? DEFAULT_ACCOUNT_ID,
|
|
||||||
policy: account.config.dmPolicy,
|
|
||||||
allowFrom: account.config.allowFrom ?? [],
|
|
||||||
policyPathSuffix: "dmPolicy",
|
|
||||||
approveHint: "openclaw pairing approve line <code>",
|
|
||||||
normalizeEntry: (raw) => raw.replace(/^line:(?:user:)?/i, ""),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
collectWarnings: ({ account, cfg }) => {
|
collectWarnings: ({ account, cfg }) => {
|
||||||
return collectAllowlistProviderRestrictSendersWarnings({
|
return collectAllowlistProviderRestrictSendersWarnings({
|
||||||
cfg,
|
cfg,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
buildAccountScopedDmSecurityPolicy,
|
|
||||||
buildOpenGroupPolicyWarning,
|
buildOpenGroupPolicyWarning,
|
||||||
collectAllowlistProviderGroupPolicyWarnings,
|
collectAllowlistProviderGroupPolicyWarnings,
|
||||||
createScopedAccountConfigAccessors,
|
createScopedAccountConfigAccessors,
|
||||||
|
createScopedChannelConfigBase,
|
||||||
|
createScopedDmSecurityResolver,
|
||||||
} from "openclaw/plugin-sdk/compat";
|
} from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
applyAccountNameToChannelSection,
|
applyAccountNameToChannelSection,
|
||||||
@@ -10,10 +11,8 @@ import {
|
|||||||
buildProbeChannelStatusSummary,
|
buildProbeChannelStatusSummary,
|
||||||
collectStatusIssuesFromLastError,
|
collectStatusIssuesFromLastError,
|
||||||
DEFAULT_ACCOUNT_ID,
|
DEFAULT_ACCOUNT_ID,
|
||||||
deleteAccountFromConfigSection,
|
|
||||||
normalizeAccountId,
|
normalizeAccountId,
|
||||||
PAIRING_APPROVED_MESSAGE,
|
PAIRING_APPROVED_MESSAGE,
|
||||||
setAccountEnabledInConfigSection,
|
|
||||||
type ChannelPlugin,
|
type ChannelPlugin,
|
||||||
} from "openclaw/plugin-sdk/matrix";
|
} from "openclaw/plugin-sdk/matrix";
|
||||||
import { matrixMessageActions } from "./actions.js";
|
import { matrixMessageActions } from "./actions.js";
|
||||||
@@ -106,6 +105,30 @@ const matrixConfigAccessors = createScopedAccountConfigAccessors({
|
|||||||
formatAllowFrom: (allowFrom) => normalizeMatrixAllowList(allowFrom),
|
formatAllowFrom: (allowFrom) => normalizeMatrixAllowList(allowFrom),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const matrixConfigBase = createScopedChannelConfigBase<ResolvedMatrixAccount, CoreConfig>({
|
||||||
|
sectionKey: "matrix",
|
||||||
|
listAccountIds: listMatrixAccountIds,
|
||||||
|
resolveAccount: (cfg, accountId) => resolveMatrixAccount({ cfg, accountId }),
|
||||||
|
defaultAccountId: resolveDefaultMatrixAccountId,
|
||||||
|
clearBaseFields: [
|
||||||
|
"name",
|
||||||
|
"homeserver",
|
||||||
|
"userId",
|
||||||
|
"accessToken",
|
||||||
|
"password",
|
||||||
|
"deviceName",
|
||||||
|
"initialSyncLimit",
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const resolveMatrixDmPolicy = createScopedDmSecurityResolver<ResolvedMatrixAccount>({
|
||||||
|
channelKey: "matrix",
|
||||||
|
resolvePolicy: (account) => account.config.dm?.policy,
|
||||||
|
resolveAllowFrom: (account) => account.config.dm?.allowFrom,
|
||||||
|
allowFromPathSuffix: "dm.",
|
||||||
|
normalizeEntry: (raw) => normalizeMatrixUserId(raw),
|
||||||
|
});
|
||||||
|
|
||||||
export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
||||||
id: "matrix",
|
id: "matrix",
|
||||||
meta,
|
meta,
|
||||||
@@ -127,32 +150,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|||||||
reload: { configPrefixes: ["channels.matrix"] },
|
reload: { configPrefixes: ["channels.matrix"] },
|
||||||
configSchema: buildChannelConfigSchema(MatrixConfigSchema),
|
configSchema: buildChannelConfigSchema(MatrixConfigSchema),
|
||||||
config: {
|
config: {
|
||||||
listAccountIds: (cfg) => listMatrixAccountIds(cfg as CoreConfig),
|
...matrixConfigBase,
|
||||||
resolveAccount: (cfg, accountId) => resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId }),
|
|
||||||
defaultAccountId: (cfg) => resolveDefaultMatrixAccountId(cfg as CoreConfig),
|
|
||||||
setAccountEnabled: ({ cfg, accountId, enabled }) =>
|
|
||||||
setAccountEnabledInConfigSection({
|
|
||||||
cfg: cfg as CoreConfig,
|
|
||||||
sectionKey: "matrix",
|
|
||||||
accountId,
|
|
||||||
enabled,
|
|
||||||
allowTopLevel: true,
|
|
||||||
}),
|
|
||||||
deleteAccount: ({ cfg, accountId }) =>
|
|
||||||
deleteAccountFromConfigSection({
|
|
||||||
cfg: cfg as CoreConfig,
|
|
||||||
sectionKey: "matrix",
|
|
||||||
accountId,
|
|
||||||
clearBaseFields: [
|
|
||||||
"name",
|
|
||||||
"homeserver",
|
|
||||||
"userId",
|
|
||||||
"accessToken",
|
|
||||||
"password",
|
|
||||||
"deviceName",
|
|
||||||
"initialSyncLimit",
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
isConfigured: (account) => account.configured,
|
isConfigured: (account) => account.configured,
|
||||||
describeAccount: (account) => ({
|
describeAccount: (account) => ({
|
||||||
accountId: account.accountId,
|
accountId: account.accountId,
|
||||||
@@ -164,18 +162,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|||||||
...matrixConfigAccessors,
|
...matrixConfigAccessors,
|
||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
resolveDmPolicy: resolveMatrixDmPolicy,
|
||||||
return buildAccountScopedDmSecurityPolicy({
|
|
||||||
cfg: cfg as CoreConfig,
|
|
||||||
channelKey: "matrix",
|
|
||||||
accountId,
|
|
||||||
fallbackAccountId: account.accountId ?? DEFAULT_ACCOUNT_ID,
|
|
||||||
policy: account.config.dm?.policy,
|
|
||||||
allowFrom: account.config.dm?.allowFrom ?? [],
|
|
||||||
allowFromPathSuffix: "dm.",
|
|
||||||
normalizeEntry: (raw) => normalizeMatrixUserId(raw),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
collectWarnings: ({ account, cfg }) => {
|
collectWarnings: ({ account, cfg }) => {
|
||||||
return collectAllowlistProviderGroupPolicyWarnings({
|
return collectAllowlistProviderGroupPolicyWarnings({
|
||||||
cfg: cfg as CoreConfig,
|
cfg: cfg as CoreConfig,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
collectAllowlistProviderGroupPolicyWarnings,
|
collectAllowlistProviderGroupPolicyWarnings,
|
||||||
buildAccountScopedDmSecurityPolicy,
|
|
||||||
collectOpenGroupPolicyRouteAllowlistWarnings,
|
collectOpenGroupPolicyRouteAllowlistWarnings,
|
||||||
createScopedAccountConfigAccessors,
|
createScopedAccountConfigAccessors,
|
||||||
|
createScopedDmSecurityResolver,
|
||||||
formatAllowFromLowercase,
|
formatAllowFromLowercase,
|
||||||
} from "openclaw/plugin-sdk/compat";
|
} from "openclaw/plugin-sdk/compat";
|
||||||
import {
|
import {
|
||||||
@@ -112,6 +112,14 @@ const telegramConfigBase = createScopedChannelConfigBase<ResolvedTelegramAccount
|
|||||||
clearBaseFields: ["botToken", "tokenFile", "name"],
|
clearBaseFields: ["botToken", "tokenFile", "name"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resolveTelegramDmPolicy = createScopedDmSecurityResolver<ResolvedTelegramAccount>({
|
||||||
|
channelKey: "telegram",
|
||||||
|
resolvePolicy: (account) => account.config.dmPolicy,
|
||||||
|
resolveAllowFrom: (account) => account.config.allowFrom,
|
||||||
|
policyPathSuffix: "dmPolicy",
|
||||||
|
normalizeEntry: (raw) => raw.replace(/^(telegram|tg):/i, ""),
|
||||||
|
});
|
||||||
|
|
||||||
export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProbe> = {
|
export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProbe> = {
|
||||||
id: "telegram",
|
id: "telegram",
|
||||||
meta: {
|
meta: {
|
||||||
@@ -180,18 +188,7 @@ export const telegramPlugin: ChannelPlugin<ResolvedTelegramAccount, TelegramProb
|
|||||||
...telegramConfigAccessors,
|
...telegramConfigAccessors,
|
||||||
},
|
},
|
||||||
security: {
|
security: {
|
||||||
resolveDmPolicy: ({ cfg, accountId, account }) => {
|
resolveDmPolicy: resolveTelegramDmPolicy,
|
||||||
return buildAccountScopedDmSecurityPolicy({
|
|
||||||
cfg,
|
|
||||||
channelKey: "telegram",
|
|
||||||
accountId,
|
|
||||||
fallbackAccountId: account.accountId ?? DEFAULT_ACCOUNT_ID,
|
|
||||||
policy: account.config.dmPolicy,
|
|
||||||
allowFrom: account.config.allowFrom ?? [],
|
|
||||||
policyPathSuffix: "dmPolicy",
|
|
||||||
normalizeEntry: (raw) => raw.replace(/^(telegram|tg):/i, ""),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
collectWarnings: ({ account, cfg }) => {
|
collectWarnings: ({ account, cfg }) => {
|
||||||
const groupAllowlistConfigured =
|
const groupAllowlistConfigured =
|
||||||
account.config.groups && Object.keys(account.config.groups).length > 0;
|
account.config.groups && Object.keys(account.config.groups).length > 0;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
deleteAccountFromConfigSection,
|
deleteAccountFromConfigSection,
|
||||||
setAccountEnabledInConfigSection,
|
setAccountEnabledInConfigSection,
|
||||||
} from "../channels/plugins/config-helpers.js";
|
} from "../channels/plugins/config-helpers.js";
|
||||||
|
import { buildAccountScopedDmSecurityPolicy } from "../channels/plugins/helpers.js";
|
||||||
import { normalizeWhatsAppAllowFromEntries } from "../channels/plugins/normalize/whatsapp.js";
|
import { normalizeWhatsAppAllowFromEntries } from "../channels/plugins/normalize/whatsapp.js";
|
||||||
import type { ChannelConfigAdapter } from "../channels/plugins/types.adapters.js";
|
import type { ChannelConfigAdapter } from "../channels/plugins/types.adapters.js";
|
||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
@@ -104,6 +105,45 @@ export function createScopedChannelConfigBase<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createScopedDmSecurityResolver<
|
||||||
|
ResolvedAccount extends { accountId?: string | null },
|
||||||
|
>(params: {
|
||||||
|
channelKey: string;
|
||||||
|
resolvePolicy: (account: ResolvedAccount) => string | null | undefined;
|
||||||
|
resolveAllowFrom: (account: ResolvedAccount) => Array<string | number> | null | undefined;
|
||||||
|
resolveFallbackAccountId?: (account: ResolvedAccount) => string | null | undefined;
|
||||||
|
defaultPolicy?: string;
|
||||||
|
allowFromPathSuffix?: string;
|
||||||
|
policyPathSuffix?: string;
|
||||||
|
approveChannelId?: string;
|
||||||
|
approveHint?: string;
|
||||||
|
normalizeEntry?: (raw: string) => string;
|
||||||
|
}) {
|
||||||
|
return ({
|
||||||
|
cfg,
|
||||||
|
accountId,
|
||||||
|
account,
|
||||||
|
}: {
|
||||||
|
cfg: OpenClawConfig;
|
||||||
|
accountId?: string | null;
|
||||||
|
account: ResolvedAccount;
|
||||||
|
}) =>
|
||||||
|
buildAccountScopedDmSecurityPolicy({
|
||||||
|
cfg,
|
||||||
|
channelKey: params.channelKey,
|
||||||
|
accountId,
|
||||||
|
fallbackAccountId: params.resolveFallbackAccountId?.(account) ?? account.accountId,
|
||||||
|
policy: params.resolvePolicy(account),
|
||||||
|
allowFrom: params.resolveAllowFrom(account) ?? [],
|
||||||
|
defaultPolicy: params.defaultPolicy,
|
||||||
|
allowFromPathSuffix: params.allowFromPathSuffix,
|
||||||
|
policyPathSuffix: params.policyPathSuffix,
|
||||||
|
approveChannelId: params.approveChannelId,
|
||||||
|
approveHint: params.approveHint,
|
||||||
|
normalizeEntry: params.normalizeEntry,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveWhatsAppConfigAllowFrom(params: {
|
export function resolveWhatsAppConfigAllowFrom(params: {
|
||||||
cfg: OpenClawConfig;
|
cfg: OpenClawConfig;
|
||||||
accountId?: string | null;
|
accountId?: string | null;
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ export {
|
|||||||
formatTrimmedAllowFromEntries,
|
formatTrimmedAllowFromEntries,
|
||||||
mapAllowFromEntries,
|
mapAllowFromEntries,
|
||||||
resolveOptionalConfigString,
|
resolveOptionalConfigString,
|
||||||
|
createScopedDmSecurityResolver,
|
||||||
formatWhatsAppConfigAllowFromEntries,
|
formatWhatsAppConfigAllowFromEntries,
|
||||||
resolveIMessageConfigAllowFrom,
|
resolveIMessageConfigAllowFrom,
|
||||||
resolveIMessageConfigDefaultTo,
|
resolveIMessageConfigDefaultTo,
|
||||||
|
|||||||
Reference in New Issue
Block a user