diff --git a/extensions/matrix/src/onboarding.test.ts b/extensions/matrix/src/onboarding.test.ts index a4ce2e55f1a..d956558c72c 100644 --- a/extensions/matrix/src/onboarding.test.ts +++ b/extensions/matrix/src/onboarding.test.ts @@ -263,4 +263,35 @@ describe("matrix onboarding", () => { expect(result.cfg.channels?.["matrix"]?.dm).toBeUndefined(); expect(result.cfg.channels?.["matrix"]?.groups).toBeUndefined(); }); + + it("reports account-scoped DM config keys for named accounts", () => { + const resolveConfigKeys = matrixOnboardingAdapter.dmPolicy?.resolveConfigKeys; + expect(resolveConfigKeys).toBeDefined(); + if (!resolveConfigKeys) { + return; + } + + expect( + resolveConfigKeys( + { + channels: { + matrix: { + accounts: { + default: { + homeserver: "https://matrix.main.example.org", + }, + ops: { + homeserver: "https://matrix.ops.example.org", + }, + }, + }, + }, + } as CoreConfig, + "ops", + ), + ).toEqual({ + policyKey: "channels.matrix.accounts.ops.dm.policy", + allowFromKey: "channels.matrix.accounts.ops.dm.allowFrom", + }); + }); }); diff --git a/extensions/matrix/src/onboarding.ts b/extensions/matrix/src/onboarding.ts index 9fcdecd29a1..c962095a5ae 100644 --- a/extensions/matrix/src/onboarding.ts +++ b/extensions/matrix/src/onboarding.ts @@ -24,7 +24,7 @@ import { hasReadyMatrixEnvAuth, resolveScopedMatrixEnvConfig, } from "./matrix/client.js"; -import { updateMatrixAccountConfig } from "./matrix/config-update.js"; +import { resolveMatrixConfigPath, updateMatrixAccountConfig } from "./matrix/config-update.js"; import { ensureMatrixSdkInstalled, isMatrixSdkAvailable } from "./matrix/deps.js"; import { resolveMatrixTargets } from "./resolve-targets.js"; import type { CoreConfig } from "./types.js"; @@ -175,6 +175,16 @@ const dmPolicy: ChannelOnboardingDmPolicy = { channel, policyKey: "channels.matrix.dm.policy", allowFromKey: "channels.matrix.dm.allowFrom", + resolveConfigKeys: (cfg, accountId) => { + const basePath = resolveMatrixConfigPath( + cfg as CoreConfig, + resolveMatrixOnboardingAccountId(cfg as CoreConfig, accountId), + ); + return { + policyKey: `${basePath}.dm.policy`, + allowFromKey: `${basePath}.dm.allowFrom`, + }; + }, getCurrent: (cfg, accountId) => resolveMatrixAccountConfig({ cfg: cfg as CoreConfig, diff --git a/src/channels/plugins/onboarding-types.ts b/src/channels/plugins/onboarding-types.ts index faf1006203f..44e2a45a92b 100644 --- a/src/channels/plugins/onboarding-types.ts +++ b/src/channels/plugins/onboarding-types.ts @@ -75,6 +75,10 @@ export type ChannelOnboardingDmPolicy = { channel: ChannelId; policyKey: string; allowFromKey: string; + resolveConfigKeys?: ( + cfg: OpenClawConfig, + accountId?: string, + ) => { policyKey: string; allowFromKey: string }; getCurrent: (cfg: OpenClawConfig, accountId?: string) => DmPolicy; setPolicy: (cfg: OpenClawConfig, policy: DmPolicy, accountId?: string) => OpenClawConfig; promptAllowFrom?: (params: { diff --git a/src/commands/onboard-channels.ts b/src/commands/onboard-channels.ts index 3a154552395..92094f818b1 100644 --- a/src/commands/onboard-channels.ts +++ b/src/commands/onboard-channels.ts @@ -247,12 +247,16 @@ async function maybeConfigureDmPolicies(params: { let cfg = params.cfg; const selectPolicy = async (policy: ChannelOnboardingDmPolicy) => { const accountId = accountIdsByChannel?.get(policy.channel); + const { policyKey, allowFromKey } = policy.resolveConfigKeys?.(cfg, accountId) ?? { + policyKey: policy.policyKey, + allowFromKey: policy.allowFromKey, + }; await prompter.note( [ "Default: pairing (unknown DMs get a pairing code).", `Approve: ${formatCliCommand(`openclaw pairing approve ${policy.channel} `)}`, - `Allowlist DMs: ${policy.policyKey}="allowlist" + ${policy.allowFromKey} entries.`, - `Public DMs: ${policy.policyKey}="open" + ${policy.allowFromKey} includes "*".`, + `Allowlist DMs: ${policyKey}="allowlist" + ${allowFromKey} entries.`, + `Public DMs: ${policyKey}="open" + ${allowFromKey} includes "*".`, "Multi-user DMs: run: " + formatCliCommand('openclaw config set session.dmScope "per-channel-peer"') + ' (or "per-account-channel-peer" for multi-account channels) to isolate sessions.',