mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:01:01 +00:00
fix: isolate external direct-message runtime policy
This commit is contained in:
@@ -76,12 +76,10 @@ describe("buildTelegramMessageContext dm thread sessions", () => {
|
||||
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.ctxPayload?.MessageThreadId).toBe(42);
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe(
|
||||
"agent:main:telegram:default:direct:42:thread:1234:42",
|
||||
);
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:main:thread:1234:42");
|
||||
});
|
||||
|
||||
it("uses the Telegram direct session key when no thread id", async () => {
|
||||
it("uses the main session key when no thread id", async () => {
|
||||
const ctx = await buildContext({
|
||||
message_id: 2,
|
||||
chat: { id: 1234, type: "private" },
|
||||
@@ -92,7 +90,7 @@ describe("buildTelegramMessageContext dm thread sessions", () => {
|
||||
|
||||
expect(ctx).not.toBeNull();
|
||||
expect(ctx?.ctxPayload?.MessageThreadId).toBeUndefined();
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:telegram:default:direct:42");
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:main");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ describe("buildTelegramMessageContext named-account DM fallback", () => {
|
||||
expect(ctx).toBeNull();
|
||||
});
|
||||
|
||||
it("uses a per-account session key for default-account DMs", async () => {
|
||||
it("uses the main session key for default-account DMs", async () => {
|
||||
setRuntimeConfigSnapshot(baseCfg);
|
||||
|
||||
const ctx = await buildTelegramMessageContextForTest({
|
||||
@@ -154,7 +154,7 @@ describe("buildTelegramMessageContext named-account DM fallback", () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:telegram:default:direct:42");
|
||||
expect(getLastUpdateLastRoute()?.sessionKey).toBe("agent:main:telegram:default:direct:42");
|
||||
expect(ctx?.ctxPayload?.SessionKey).toBe("agent:main:main");
|
||||
expect(getLastUpdateLastRoute()?.sessionKey).toBe("agent:main:main");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,8 +6,9 @@ import {
|
||||
import { logInboundDrop } from "openclaw/plugin-sdk/channel-inbound";
|
||||
import type { TelegramDirectConfig, TelegramGroupConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { deriveLastRoutePolicy } from "openclaw/plugin-sdk/routing";
|
||||
import { DEFAULT_ACCOUNT_ID, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
||||
import { normalizeAccountId, resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { resolveDefaultTelegramAccountId } from "./accounts.js";
|
||||
import { withTelegramApiErrorLogging } from "./api-logging.js";
|
||||
import { firstDefined, normalizeAllowFrom, normalizeDmAllowFromWithStore } from "./bot-access.js";
|
||||
import { resolveTelegramInboundBody } from "./bot-message-context.body.js";
|
||||
@@ -234,7 +235,10 @@ export const buildTelegramMessageContext = async ({
|
||||
});
|
||||
const requiresExplicitAccountBinding = (
|
||||
candidate: ReturnType<typeof resolveTelegramConversationRoute>["route"],
|
||||
): boolean => candidate.accountId !== DEFAULT_ACCOUNT_ID && candidate.matchedBy === "default";
|
||||
): boolean =>
|
||||
normalizeAccountId(candidate.accountId) !==
|
||||
normalizeAccountId(resolveDefaultTelegramAccountId(freshCfg)) &&
|
||||
candidate.matchedBy === "default";
|
||||
const isNamedAccountFallback = requiresExplicitAccountBinding(route);
|
||||
// Named-account groups still require an explicit binding; DMs get a
|
||||
// per-account fallback session key below to preserve isolation.
|
||||
|
||||
@@ -1697,7 +1697,7 @@ describe("createTelegramBot", () => {
|
||||
expect(replySpy).toHaveBeenCalledTimes(1);
|
||||
const payload = replySpy.mock.calls[0][0];
|
||||
expect(payload.AccountId).toBe("opie");
|
||||
expect(payload.SessionKey).toBe("agent:opie:telegram:opie:direct:999");
|
||||
expect(payload.SessionKey).toBe("agent:opie:main");
|
||||
});
|
||||
|
||||
it("reloads DM routing bindings between messages without recreating the bot", async () => {
|
||||
@@ -1705,7 +1705,12 @@ describe("createTelegramBot", () => {
|
||||
const configForAgent = (agentId: string) => ({
|
||||
channels: {
|
||||
telegram: {
|
||||
defaultAccount: "work",
|
||||
accounts: {
|
||||
work: {
|
||||
botToken: "tok-work",
|
||||
dmPolicy: "open",
|
||||
},
|
||||
opie: {
|
||||
botToken: "tok-opie",
|
||||
dmPolicy: "open",
|
||||
@@ -1809,7 +1814,12 @@ describe("createTelegramBot", () => {
|
||||
loadConfig.mockReturnValue({
|
||||
channels: {
|
||||
telegram: {
|
||||
defaultAccount: "work",
|
||||
accounts: {
|
||||
work: {
|
||||
botToken: "tok-work",
|
||||
dmPolicy: "open",
|
||||
},
|
||||
opie: {
|
||||
botToken: "tok-opie",
|
||||
dmPolicy: "open",
|
||||
|
||||
@@ -2190,9 +2190,7 @@ describe("createTelegramBot", () => {
|
||||
|
||||
expect(replySpy).toHaveBeenCalledTimes(1);
|
||||
const payload = replySpy.mock.calls[0][0];
|
||||
expect(payload.CommandTargetSessionKey).toBe(
|
||||
"agent:main:telegram:default:direct:12345:thread:12345:99",
|
||||
);
|
||||
expect(payload.CommandTargetSessionKey).toBe("agent:main:main:thread:12345:99");
|
||||
});
|
||||
|
||||
it("allows native DM commands for paired users", async () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { resolveTelegramConversationBaseSessionKey } from "./conversation-route.
|
||||
describe("resolveTelegramConversationBaseSessionKey", () => {
|
||||
const cfg: OpenClawConfig = {};
|
||||
|
||||
it("uses a per-account key for default-account DMs", () => {
|
||||
it("keeps default-account DMs on the route session key", () => {
|
||||
expect(
|
||||
resolveTelegramConversationBaseSessionKey({
|
||||
cfg,
|
||||
@@ -20,7 +20,34 @@ describe("resolveTelegramConversationBaseSessionKey", () => {
|
||||
isGroup: false,
|
||||
senderId: 12345,
|
||||
}),
|
||||
).toBe("agent:main:telegram:default:direct:12345");
|
||||
).toBe("agent:main:main");
|
||||
});
|
||||
|
||||
it("keeps configured default-account DMs on the route session key", () => {
|
||||
expect(
|
||||
resolveTelegramConversationBaseSessionKey({
|
||||
cfg: {
|
||||
channels: {
|
||||
telegram: {
|
||||
defaultAccount: "work",
|
||||
accounts: {
|
||||
work: {},
|
||||
personal: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
route: {
|
||||
agentId: "main",
|
||||
accountId: "work",
|
||||
matchedBy: "default",
|
||||
sessionKey: "agent:main:main",
|
||||
},
|
||||
chatId: 12345,
|
||||
isGroup: false,
|
||||
senderId: 12345,
|
||||
}),
|
||||
).toBe("agent:main:main");
|
||||
});
|
||||
|
||||
it("uses the per-account fallback key for named-account DMs without an explicit binding", () => {
|
||||
|
||||
@@ -7,11 +7,13 @@ import {
|
||||
import {
|
||||
buildAgentSessionKey,
|
||||
deriveLastRoutePolicy,
|
||||
normalizeAccountId,
|
||||
resolveAgentRoute,
|
||||
} from "openclaw/plugin-sdk/routing";
|
||||
import { buildAgentMainSessionKey, sanitizeAgentId } from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveDefaultTelegramAccountId } from "./accounts.js";
|
||||
import {
|
||||
buildTelegramGroupPeerId,
|
||||
buildTelegramParentPeer,
|
||||
@@ -147,10 +149,13 @@ export function resolveTelegramConversationBaseSessionKey(params: {
|
||||
isGroup: boolean;
|
||||
senderId?: string | number | null;
|
||||
}): string {
|
||||
if (params.isGroup || params.route.matchedBy === "binding.channel") {
|
||||
const routeAccountId = normalizeAccountId(params.route.accountId);
|
||||
const defaultAccountId = normalizeAccountId(resolveDefaultTelegramAccountId(params.cfg));
|
||||
const isNamedAccountFallback =
|
||||
routeAccountId !== defaultAccountId && params.route.matchedBy === "default";
|
||||
if (!isNamedAccountFallback || params.isGroup) {
|
||||
return params.route.sessionKey;
|
||||
}
|
||||
const configuredDmScope = params.cfg.session?.dmScope;
|
||||
return normalizeLowercaseStringOrEmpty(
|
||||
buildAgentSessionKey({
|
||||
agentId: params.route.agentId,
|
||||
@@ -163,10 +168,7 @@ export function resolveTelegramConversationBaseSessionKey(params: {
|
||||
senderId: params.senderId,
|
||||
}),
|
||||
},
|
||||
dmScope:
|
||||
configuredDmScope && configuredDmScope !== "main"
|
||||
? configuredDmScope
|
||||
: "per-account-channel-peer",
|
||||
dmScope: "per-account-channel-peer",
|
||||
identityLinks: params.cfg.session?.identityLinks,
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user