feat(web): prime group sessions with member roster

This commit is contained in:
Peter Steinberger
2025-12-03 13:33:32 +00:00
parent 3a8d6b80e0
commit b55ac994ea
6 changed files with 72 additions and 0 deletions

View File

@@ -413,6 +413,25 @@ export async function getReplyFromConfig(
isFirstTurnInSession && sessionCfg?.sessionIntro
? applyTemplate(sessionCfg.sessionIntro, sessionCtx)
: "";
const groupIntro =
isFirstTurnInSession && sessionCtx.ChatType === "group"
? (() => {
const subject = sessionCtx.GroupSubject?.trim();
const members = sessionCtx.GroupMembers?.trim();
const subjectLine = subject
? `You are replying inside the WhatsApp group "${subject}".`
: "You are replying inside a WhatsApp group chat.";
const membersLine = members
? `Group members: ${members}.`
: undefined;
return [subjectLine, membersLine]
.filter(Boolean)
.join(" ")
.concat(
" Address the specific sender noted in the message context.",
);
})()
: "";
const bodyPrefix = reply?.bodyPrefix
? applyTemplate(reply.bodyPrefix, sessionCtx)
: "";
@@ -430,6 +449,9 @@ export async function getReplyFromConfig(
if (sessionIntro) {
prefixedBodyBase = `${sessionIntro}\n\n${prefixedBodyBase}`;
}
if (groupIntro) {
prefixedBodyBase = `${groupIntro}\n\n${prefixedBodyBase}`;
}
if (abortedHint) {
prefixedBodyBase = `${abortedHint}\n\n${prefixedBodyBase}`;
if (sessionEntry && sessionStore && sessionKey) {

View File

@@ -7,6 +7,11 @@ export type MsgContext = {
MediaUrl?: string;
MediaType?: string;
Transcript?: string;
ChatType?: string;
GroupSubject?: string;
GroupMembers?: string;
SenderName?: string;
SenderE164?: string;
};
export type TemplateContext = MsgContext & {

View File

@@ -766,6 +766,11 @@ export async function monitorWebProvider(
MediaPath: latest.mediaPath,
MediaUrl: latest.mediaUrl,
MediaType: latest.mediaType,
ChatType: latest.chatType,
GroupSubject: latest.groupSubject,
GroupMembers: latest.groupParticipants?.join(", "),
SenderName: latest.senderName,
SenderE164: latest.senderE164,
},
{
onReplyStart: latest.sendComposing,

View File

@@ -39,6 +39,8 @@ export type WebInboundMessage = {
senderJid?: string;
senderE164?: string;
senderName?: string;
groupSubject?: string;
groupParticipants?: string[];
mentionedJids?: string[];
selfJid?: string | null;
selfE164?: string | null;
@@ -73,6 +75,33 @@ export async function monitorWebInbox(options: {
const selfJid = sock.user?.id;
const selfE164 = selfJid ? jidToE164(selfJid) : null;
const seen = new Set<string>();
const groupMetaCache = new Map<
string,
{ subject?: string; participants?: string[]; expires: number }
>();
const GROUP_META_TTL_MS = 5 * 60 * 1000; // 5 minutes
const getGroupMeta = async (jid: string) => {
const cached = groupMetaCache.get(jid);
if (cached && cached.expires > Date.now()) return cached;
try {
const meta = await sock.groupMetadata(jid);
const participants =
meta.participants
?.map((p) => jidToE164(p.id) ?? p.id)
.filter(Boolean) ?? [];
const entry = {
subject: meta.subject,
participants,
expires: Date.now() + GROUP_META_TTL_MS,
};
groupMetaCache.set(jid, entry);
return entry;
} catch (err) {
logVerbose(`Failed to fetch group metadata for ${jid}: ${String(err)}`);
return { expires: Date.now() + GROUP_META_TTL_MS };
}
};
sock.ev.on("messages.upsert", async (upsert) => {
if (upsert.type !== "notify") return;
@@ -109,6 +138,13 @@ export async function monitorWebInbox(options: {
const from = group ? remoteJid : jidToE164(remoteJid);
// Skip if we still can't resolve an id to key conversation
if (!from) continue;
let groupSubject: string | undefined;
let groupParticipants: string[] | undefined;
if (group) {
const meta = await getGroupMeta(remoteJid);
groupSubject = meta.subject;
groupParticipants = meta.participants;
}
// Filter unauthorized senders early to prevent wasted processing
// and potential session corruption from Bad MAC errors
@@ -197,6 +233,8 @@ export async function monitorWebInbox(options: {
senderJid: participantJid,
senderE164: senderE164 ?? undefined,
senderName,
groupSubject,
groupParticipants,
mentionedJids: mentionedJids ?? undefined,
selfJid,
selfE164,