Skip to content

Commit 1d94cf4

Browse files
committed
fix(whatsapp): route group activation through session accessor
1 parent d716900 commit 1d94cf4

3 files changed

Lines changed: 30 additions & 14 deletions

File tree

extensions/whatsapp/src/auto-reply/monitor/group-activation.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
// Whatsapp plugin module implements group activation behavior.
22
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
33
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
4-
import { updateSessionStore } from "openclaw/plugin-sdk/session-store-runtime";
4+
import {
5+
getSessionEntry,
6+
patchSessionEntry,
7+
resolveStorePath,
8+
type SessionEntry,
9+
} from "openclaw/plugin-sdk/session-store-runtime";
510
import { resolveWhatsAppLegacyGroupSessionKey } from "../../group-session-key.js";
611
import { resolveWhatsAppInboundPolicy } from "../../inbound-policy.js";
7-
import { loadSessionStore, resolveStorePath } from "../config.runtime.js";
812
import { normalizeGroupActivation } from "./group-activation.runtime.js";
913

1014
function hasNamedWhatsAppAccounts(cfg: OpenClawConfig) {
@@ -28,6 +32,7 @@ function isActivationOnlyEntry(
2832
);
2933
}
3034

35+
/** Resolves group activation for a WhatsApp conversation and backfills scoped session metadata. */
3136
export async function resolveGroupActivationFor(params: {
3237
cfg: OpenClawConfig;
3338
accountId?: string | null;
@@ -38,13 +43,15 @@ export async function resolveGroupActivationFor(params: {
3843
const storePath = resolveStorePath(params.cfg.session?.store, {
3944
agentId: params.agentId,
4045
});
41-
const store = loadSessionStore(storePath);
46+
const sessionScope = { storePath, agentId: params.agentId };
4247
const legacySessionKey = resolveWhatsAppLegacyGroupSessionKey({
4348
sessionKey: params.sessionKey,
4449
accountId: params.accountId,
4550
});
46-
const legacyEntry = legacySessionKey ? store[legacySessionKey] : undefined;
47-
const scopedEntry = store[params.sessionKey];
51+
const legacyEntry = legacySessionKey
52+
? getSessionEntry({ ...sessionScope, sessionKey: legacySessionKey })
53+
: undefined;
54+
const scopedEntry = getSessionEntry({ ...sessionScope, sessionKey: params.sessionKey });
4855
const normalizedAccountId = normalizeAccountId(params.accountId);
4956
const ignoreScopedActivation =
5057
normalizedAccountId === DEFAULT_ACCOUNT_ID &&
@@ -54,15 +61,22 @@ export async function resolveGroupActivationFor(params: {
5461
(ignoreScopedActivation ? undefined : scopedEntry?.groupActivation) ??
5562
legacyEntry?.groupActivation;
5663
if (activation !== undefined && scopedEntry?.groupActivation === undefined) {
57-
await updateSessionStore(storePath, (nextStore) => {
58-
const nextScopedEntry = nextStore[params.sessionKey];
59-
if (nextScopedEntry?.groupActivation !== undefined) {
60-
return;
61-
}
62-
nextStore[params.sessionKey] = {
63-
...nextScopedEntry,
64-
groupActivation: activation,
65-
};
64+
// Activation-only backfills must not synthesize session ids or activity.
65+
// replaceEntry preserves existing scoped metadata while keeping fallback writes sparse.
66+
await patchSessionEntry({
67+
...sessionScope,
68+
sessionKey: params.sessionKey,
69+
fallbackEntry: {} as SessionEntry,
70+
replaceEntry: true,
71+
update: (entry) => {
72+
if (entry.groupActivation !== undefined) {
73+
return null;
74+
}
75+
return {
76+
...entry,
77+
groupActivation: activation,
78+
};
79+
},
6680
});
6781
}
6882
const requireMention = resolveWhatsAppInboundPolicy({

scripts/check-session-accessor-boundary.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export const migratedBundledPluginSessionAccessorFiles = new Set([
143143
"extensions/telegram/src/bot-message-dispatch.ts",
144144
"extensions/telegram/src/bot-native-commands.ts",
145145
"extensions/voice-call/src/response-generator.ts",
146+
"extensions/whatsapp/src/auto-reply/monitor/group-activation.ts",
146147
]);
147148

148149
export const migratedEmbeddedAgentSessionTargetFiles = new Set([

test/scripts/check-session-accessor-boundary.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ describe("session accessor boundary guard", () => {
9898
"extensions/telegram/src/bot-message-dispatch.ts",
9999
"extensions/telegram/src/bot-native-commands.ts",
100100
"extensions/voice-call/src/response-generator.ts",
101+
"extensions/whatsapp/src/auto-reply/monitor/group-activation.ts",
101102
]),
102103
);
103104
});

0 commit comments

Comments
 (0)