Merge ee4b49c88b into 09be5d45d5
This commit is contained in:
commit
960c321094
@ -200,7 +200,10 @@ The wizard uses it to set your **allowlist/owner** so your own DMs are permitted
|
||||
- Activation modes:
|
||||
- `mention` (default): requires @mention or regex match.
|
||||
- `always`: always triggers.
|
||||
- `/activation mention|always` is owner-only and must be sent as a standalone message.
|
||||
- `replies`: only triggers when someone replies to a bot message.
|
||||
- `mention+replies`: triggers on @mention/regex match OR replies to bot messages.
|
||||
- `never`: never triggers (except for control commands from owners).
|
||||
- `/activation mention|always|replies|mention+replies|never` is owner-only and must be sent as a standalone message.
|
||||
- Owner = `channels.whatsapp.allowFrom` (or self E.164 if unset).
|
||||
- **History injection** (pending-only):
|
||||
- Recent *unprocessed* messages (default 50) inserted under:
|
||||
|
||||
@ -21,7 +21,10 @@ export function getAvailableCommands(): AvailableCommand[] {
|
||||
{ name: "dock-telegram", description: "Route replies to Telegram." },
|
||||
{ name: "dock-discord", description: "Route replies to Discord." },
|
||||
{ name: "dock-slack", description: "Route replies to Slack." },
|
||||
{ name: "activation", description: "Set group activation (mention|always)." },
|
||||
{
|
||||
name: "activation",
|
||||
description: "Set group activation (mention|always|replies|mention+replies|never).",
|
||||
},
|
||||
{ name: "send", description: "Set send mode (on|off|inherit)." },
|
||||
{ name: "reset", description: "Reset the session (/new)." },
|
||||
{ name: "new", description: "Reset the session (/reset)." },
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
import { normalizeCommandBody } from "./commands-registry.js";
|
||||
|
||||
export type GroupActivationMode = "mention" | "always";
|
||||
export type GroupActivationMode = "mention" | "always" | "replies" | "mention+replies" | "never";
|
||||
|
||||
export function normalizeGroupActivation(raw?: string | null): GroupActivationMode | undefined {
|
||||
const value = raw?.trim().toLowerCase();
|
||||
if (value === "mention") return "mention";
|
||||
if (value === "always") return "always";
|
||||
if (value === "replies") return "replies";
|
||||
if (value === "mention+replies") return "mention+replies";
|
||||
if (value === "never") return "never";
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ export const handleActivationCommand: CommandHandler = async (params, allowTextC
|
||||
if (!activationCommand.mode) {
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: { text: "⚙️ Usage: /activation mention|always" },
|
||||
reply: { text: "⚙️ Usage: /activation mention|always|replies|mention+replies|never" },
|
||||
};
|
||||
}
|
||||
if (params.sessionEntry && params.sessionStore && params.sessionKey) {
|
||||
|
||||
@ -59,7 +59,7 @@ type StatusArgs = {
|
||||
sessionEntry?: SessionEntry;
|
||||
sessionKey?: string;
|
||||
sessionScope?: SessionScope;
|
||||
groupActivation?: "mention" | "always";
|
||||
groupActivation?: "mention" | "always" | "replies" | "mention+replies" | "never";
|
||||
resolvedThink?: ThinkLevel;
|
||||
resolvedVerbose?: VerboseLevel;
|
||||
resolvedReasoning?: ReasoningLevel;
|
||||
|
||||
@ -54,7 +54,7 @@ export type SessionEntry = {
|
||||
authProfileOverride?: string;
|
||||
authProfileOverrideSource?: "auto" | "user";
|
||||
authProfileOverrideCompactionCount?: number;
|
||||
groupActivation?: "mention" | "always";
|
||||
groupActivation?: "mention" | "always" | "replies" | "mention+replies" | "never";
|
||||
groupActivationNeedsSystemIntro?: boolean;
|
||||
sendPolicy?: "allow" | "deny";
|
||||
queueMode?:
|
||||
|
||||
@ -303,7 +303,9 @@ export async function applySessionsPatchToStore(params: {
|
||||
} else if (raw !== undefined) {
|
||||
const normalized = normalizeGroupActivation(String(raw));
|
||||
if (!normalized) {
|
||||
return invalid('invalid groupActivation (use "mention"|"always")');
|
||||
return invalid(
|
||||
'invalid groupActivation (use "mention"|"always"|"replies"|"mention+replies"|"never")',
|
||||
);
|
||||
}
|
||||
next.groupActivation = normalized;
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ export function helpText(options: SlashCommandOptions = {}): string {
|
||||
"/usage <off|tokens|full>",
|
||||
"/elevated <on|off|ask|full>",
|
||||
"/elev <on|off|ask|full>",
|
||||
"/activation <mention|always>",
|
||||
"/activation <mention|always|replies|mention+replies|never>",
|
||||
"/new or /reset",
|
||||
"/abort",
|
||||
"/settings",
|
||||
|
||||
@ -391,7 +391,7 @@ export function createCommandHandlers(context: CommandHandlerContext) {
|
||||
break;
|
||||
case "activation":
|
||||
if (!args) {
|
||||
chatLog.addSystem("usage: /activation <mention|always>");
|
||||
chatLog.addSystem("usage: /activation <mention|always|replies|mention+replies|never>");
|
||||
break;
|
||||
}
|
||||
try {
|
||||
|
||||
@ -101,28 +101,47 @@ export function applyGroupGating(params: {
|
||||
sessionKey: params.sessionKey,
|
||||
conversationId: params.conversationId,
|
||||
});
|
||||
const requireMention = activation !== "always";
|
||||
|
||||
// Check if this message is a reply to the bot
|
||||
const selfJid = params.msg.selfJid?.replace(/:\\d+/, "");
|
||||
const replySenderJid = params.msg.replyToSenderJid?.replace(/:\\d+/, "");
|
||||
const selfE164 = params.msg.selfE164 ? normalizeE164(params.msg.selfE164) : null;
|
||||
const replySenderE164 = params.msg.replyToSenderE164
|
||||
? normalizeE164(params.msg.replyToSenderE164)
|
||||
: null;
|
||||
const implicitMention = Boolean(
|
||||
const isReplyToBot = Boolean(
|
||||
(selfJid && replySenderJid && selfJid === replySenderJid) ||
|
||||
(selfE164 && replySenderE164 && selfE164 === replySenderE164),
|
||||
);
|
||||
|
||||
// Ensure safe default for shouldBypassMention in case it's undefined in some contexts
|
||||
const safeShouldBypassMention = typeof shouldBypassMention !== "undefined" ? shouldBypassMention : false;
|
||||
|
||||
// Determine if we should process based on activation mode
|
||||
const shouldProcess = (() => {
|
||||
if (activation === "always") return true;
|
||||
if (activation === "never") return safeShouldBypassMention;
|
||||
if (activation === "replies") return isReplyToBot || safeShouldBypassMention;
|
||||
if (activation === "mention+replies")
|
||||
return wasMentioned || isReplyToBot || safeShouldBypassMention;
|
||||
// Default to "mention" mode
|
||||
return wasMentioned || safeShouldBypassMention;
|
||||
})();
|
||||
|
||||
// require mention only in strict 'mention' mode
|
||||
const requireMention = activation === "mention";
|
||||
const mentionGate = resolveMentionGating({
|
||||
requireMention,
|
||||
canDetectMention: true,
|
||||
wasMentioned,
|
||||
implicitMention,
|
||||
shouldBypassMention,
|
||||
implicitMention: isReplyToBot, // treat reply-to-bot as an implicit mention
|
||||
shouldBypassMention: safeShouldBypassMention,
|
||||
});
|
||||
params.msg.wasMentioned = mentionGate.effectiveWasMentioned;
|
||||
if (!shouldBypassMention && requireMention && mentionGate.shouldSkip) {
|
||||
|
||||
if (!shouldProcess) {
|
||||
params.logVerbose(
|
||||
`Group message stored for context (no mention detected) in ${params.conversationId}: ${params.msg.body}`,
|
||||
`Group message stored for context (no activation pass) in ${params.conversationId}: ${params.msg.body}`,
|
||||
);
|
||||
const sender =
|
||||
params.msg.senderName && params.msg.senderE164
|
||||
|
||||
Loading…
Reference in New Issue
Block a user