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:
|
- Activation modes:
|
||||||
- `mention` (default): requires @mention or regex match.
|
- `mention` (default): requires @mention or regex match.
|
||||||
- `always`: always triggers.
|
- `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).
|
- Owner = `channels.whatsapp.allowFrom` (or self E.164 if unset).
|
||||||
- **History injection** (pending-only):
|
- **History injection** (pending-only):
|
||||||
- Recent *unprocessed* messages (default 50) inserted under:
|
- 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-telegram", description: "Route replies to Telegram." },
|
||||||
{ name: "dock-discord", description: "Route replies to Discord." },
|
{ name: "dock-discord", description: "Route replies to Discord." },
|
||||||
{ name: "dock-slack", description: "Route replies to Slack." },
|
{ 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: "send", description: "Set send mode (on|off|inherit)." },
|
||||||
{ name: "reset", description: "Reset the session (/new)." },
|
{ name: "reset", description: "Reset the session (/new)." },
|
||||||
{ name: "new", description: "Reset the session (/reset)." },
|
{ name: "new", description: "Reset the session (/reset)." },
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
import { normalizeCommandBody } from "./commands-registry.js";
|
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 {
|
export function normalizeGroupActivation(raw?: string | null): GroupActivationMode | undefined {
|
||||||
const value = raw?.trim().toLowerCase();
|
const value = raw?.trim().toLowerCase();
|
||||||
if (value === "mention") return "mention";
|
if (value === "mention") return "mention";
|
||||||
if (value === "always") return "always";
|
if (value === "always") return "always";
|
||||||
|
if (value === "replies") return "replies";
|
||||||
|
if (value === "mention+replies") return "mention+replies";
|
||||||
|
if (value === "never") return "never";
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export const handleActivationCommand: CommandHandler = async (params, allowTextC
|
|||||||
if (!activationCommand.mode) {
|
if (!activationCommand.mode) {
|
||||||
return {
|
return {
|
||||||
shouldContinue: false,
|
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) {
|
if (params.sessionEntry && params.sessionStore && params.sessionKey) {
|
||||||
|
|||||||
@ -59,7 +59,7 @@ type StatusArgs = {
|
|||||||
sessionEntry?: SessionEntry;
|
sessionEntry?: SessionEntry;
|
||||||
sessionKey?: string;
|
sessionKey?: string;
|
||||||
sessionScope?: SessionScope;
|
sessionScope?: SessionScope;
|
||||||
groupActivation?: "mention" | "always";
|
groupActivation?: "mention" | "always" | "replies" | "mention+replies" | "never";
|
||||||
resolvedThink?: ThinkLevel;
|
resolvedThink?: ThinkLevel;
|
||||||
resolvedVerbose?: VerboseLevel;
|
resolvedVerbose?: VerboseLevel;
|
||||||
resolvedReasoning?: ReasoningLevel;
|
resolvedReasoning?: ReasoningLevel;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export type SessionEntry = {
|
|||||||
authProfileOverride?: string;
|
authProfileOverride?: string;
|
||||||
authProfileOverrideSource?: "auto" | "user";
|
authProfileOverrideSource?: "auto" | "user";
|
||||||
authProfileOverrideCompactionCount?: number;
|
authProfileOverrideCompactionCount?: number;
|
||||||
groupActivation?: "mention" | "always";
|
groupActivation?: "mention" | "always" | "replies" | "mention+replies" | "never";
|
||||||
groupActivationNeedsSystemIntro?: boolean;
|
groupActivationNeedsSystemIntro?: boolean;
|
||||||
sendPolicy?: "allow" | "deny";
|
sendPolicy?: "allow" | "deny";
|
||||||
queueMode?:
|
queueMode?:
|
||||||
|
|||||||
@ -303,7 +303,9 @@ export async function applySessionsPatchToStore(params: {
|
|||||||
} else if (raw !== undefined) {
|
} else if (raw !== undefined) {
|
||||||
const normalized = normalizeGroupActivation(String(raw));
|
const normalized = normalizeGroupActivation(String(raw));
|
||||||
if (!normalized) {
|
if (!normalized) {
|
||||||
return invalid('invalid groupActivation (use "mention"|"always")');
|
return invalid(
|
||||||
|
'invalid groupActivation (use "mention"|"always"|"replies"|"mention+replies"|"never")',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
next.groupActivation = normalized;
|
next.groupActivation = normalized;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,7 +150,7 @@ export function helpText(options: SlashCommandOptions = {}): string {
|
|||||||
"/usage <off|tokens|full>",
|
"/usage <off|tokens|full>",
|
||||||
"/elevated <on|off|ask|full>",
|
"/elevated <on|off|ask|full>",
|
||||||
"/elev <on|off|ask|full>",
|
"/elev <on|off|ask|full>",
|
||||||
"/activation <mention|always>",
|
"/activation <mention|always|replies|mention+replies|never>",
|
||||||
"/new or /reset",
|
"/new or /reset",
|
||||||
"/abort",
|
"/abort",
|
||||||
"/settings",
|
"/settings",
|
||||||
|
|||||||
@ -391,7 +391,7 @@ export function createCommandHandlers(context: CommandHandlerContext) {
|
|||||||
break;
|
break;
|
||||||
case "activation":
|
case "activation":
|
||||||
if (!args) {
|
if (!args) {
|
||||||
chatLog.addSystem("usage: /activation <mention|always>");
|
chatLog.addSystem("usage: /activation <mention|always|replies|mention+replies|never>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -101,28 +101,47 @@ export function applyGroupGating(params: {
|
|||||||
sessionKey: params.sessionKey,
|
sessionKey: params.sessionKey,
|
||||||
conversationId: params.conversationId,
|
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 selfJid = params.msg.selfJid?.replace(/:\\d+/, "");
|
||||||
const replySenderJid = params.msg.replyToSenderJid?.replace(/:\\d+/, "");
|
const replySenderJid = params.msg.replyToSenderJid?.replace(/:\\d+/, "");
|
||||||
const selfE164 = params.msg.selfE164 ? normalizeE164(params.msg.selfE164) : null;
|
const selfE164 = params.msg.selfE164 ? normalizeE164(params.msg.selfE164) : null;
|
||||||
const replySenderE164 = params.msg.replyToSenderE164
|
const replySenderE164 = params.msg.replyToSenderE164
|
||||||
? normalizeE164(params.msg.replyToSenderE164)
|
? normalizeE164(params.msg.replyToSenderE164)
|
||||||
: null;
|
: null;
|
||||||
const implicitMention = Boolean(
|
const isReplyToBot = Boolean(
|
||||||
(selfJid && replySenderJid && selfJid === replySenderJid) ||
|
(selfJid && replySenderJid && selfJid === replySenderJid) ||
|
||||||
(selfE164 && replySenderE164 && selfE164 === replySenderE164),
|
(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({
|
const mentionGate = resolveMentionGating({
|
||||||
requireMention,
|
requireMention,
|
||||||
canDetectMention: true,
|
canDetectMention: true,
|
||||||
wasMentioned,
|
wasMentioned,
|
||||||
implicitMention,
|
implicitMention: isReplyToBot, // treat reply-to-bot as an implicit mention
|
||||||
shouldBypassMention,
|
shouldBypassMention: safeShouldBypassMention,
|
||||||
});
|
});
|
||||||
params.msg.wasMentioned = mentionGate.effectiveWasMentioned;
|
params.msg.wasMentioned = mentionGate.effectiveWasMentioned;
|
||||||
if (!shouldBypassMention && requireMention && mentionGate.shouldSkip) {
|
|
||||||
|
if (!shouldProcess) {
|
||||||
params.logVerbose(
|
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 =
|
const sender =
|
||||||
params.msg.senderName && params.msg.senderE164
|
params.msg.senderName && params.msg.senderE164
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user