mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 19:44:30 +00:00
refactor(src): split oversized modules
This commit is contained in:
153
src/web/auto-reply/monitor/on-message.ts
Normal file
153
src/web/auto-reply/monitor/on-message.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import type { getReplyFromConfig } from "../../../auto-reply/reply.js";
|
||||
import type { loadConfig } from "../../../config/config.js";
|
||||
import { logVerbose } from "../../../globals.js";
|
||||
import { resolveAgentRoute } from "../../../routing/resolve-route.js";
|
||||
import { buildGroupHistoryKey } from "../../../routing/session-key.js";
|
||||
import { normalizeE164 } from "../../../utils.js";
|
||||
import type { MentionConfig } from "../mentions.js";
|
||||
import type { WebInboundMsg } from "../types.js";
|
||||
import { maybeBroadcastMessage } from "./broadcast.js";
|
||||
import type { EchoTracker } from "./echo.js";
|
||||
import type { GroupHistoryEntry } from "./group-gating.js";
|
||||
import { applyGroupGating } from "./group-gating.js";
|
||||
import { updateLastRouteInBackground } from "./last-route.js";
|
||||
import { resolvePeerId } from "./peer.js";
|
||||
import { processMessage } from "./process-message.js";
|
||||
|
||||
export function createWebOnMessageHandler(params: {
|
||||
cfg: ReturnType<typeof loadConfig>;
|
||||
verbose: boolean;
|
||||
connectionId: string;
|
||||
maxMediaBytes: number;
|
||||
groupHistoryLimit: number;
|
||||
groupHistories: Map<string, GroupHistoryEntry[]>;
|
||||
groupMemberNames: Map<string, Map<string, string>>;
|
||||
echoTracker: EchoTracker;
|
||||
backgroundTasks: Set<Promise<unknown>>;
|
||||
replyResolver: typeof getReplyFromConfig;
|
||||
replyLogger: ReturnType<
|
||||
typeof import("../../../logging.js")["getChildLogger"]
|
||||
>;
|
||||
baseMentionConfig: MentionConfig;
|
||||
account: { authDir?: string; accountId?: string };
|
||||
}) {
|
||||
const processForRoute = async (
|
||||
msg: WebInboundMsg,
|
||||
route: ReturnType<typeof resolveAgentRoute>,
|
||||
groupHistoryKey: string,
|
||||
opts?: {
|
||||
groupHistory?: GroupHistoryEntry[];
|
||||
suppressGroupHistoryClear?: boolean;
|
||||
},
|
||||
) =>
|
||||
processMessage({
|
||||
cfg: params.cfg,
|
||||
msg,
|
||||
route,
|
||||
groupHistoryKey,
|
||||
groupHistories: params.groupHistories,
|
||||
groupMemberNames: params.groupMemberNames,
|
||||
connectionId: params.connectionId,
|
||||
verbose: params.verbose,
|
||||
maxMediaBytes: params.maxMediaBytes,
|
||||
replyResolver: params.replyResolver,
|
||||
replyLogger: params.replyLogger,
|
||||
backgroundTasks: params.backgroundTasks,
|
||||
rememberSentText: params.echoTracker.rememberText,
|
||||
echoHas: params.echoTracker.has,
|
||||
echoForget: params.echoTracker.forget,
|
||||
buildCombinedEchoKey: params.echoTracker.buildCombinedKey,
|
||||
groupHistory: opts?.groupHistory,
|
||||
suppressGroupHistoryClear: opts?.suppressGroupHistoryClear,
|
||||
});
|
||||
|
||||
return async (msg: WebInboundMsg) => {
|
||||
const conversationId = msg.conversationId ?? msg.from;
|
||||
const peerId = resolvePeerId(msg);
|
||||
const route = resolveAgentRoute({
|
||||
cfg: params.cfg,
|
||||
channel: "whatsapp",
|
||||
accountId: msg.accountId,
|
||||
peer: {
|
||||
kind: msg.chatType === "group" ? "group" : "dm",
|
||||
id: peerId,
|
||||
},
|
||||
});
|
||||
const groupHistoryKey =
|
||||
msg.chatType === "group"
|
||||
? buildGroupHistoryKey({
|
||||
channel: "whatsapp",
|
||||
accountId: route.accountId,
|
||||
peerKind: "group",
|
||||
peerId,
|
||||
})
|
||||
: route.sessionKey;
|
||||
|
||||
// Same-phone mode logging retained
|
||||
if (msg.from === msg.to) {
|
||||
logVerbose(`📱 Same-phone mode detected (from === to: ${msg.from})`);
|
||||
}
|
||||
|
||||
// Skip if this is a message we just sent (echo detection)
|
||||
if (params.echoTracker.has(msg.body)) {
|
||||
logVerbose(
|
||||
"Skipping auto-reply: detected echo (message matches recently sent text)",
|
||||
);
|
||||
params.echoTracker.forget(msg.body);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.chatType === "group") {
|
||||
updateLastRouteInBackground({
|
||||
cfg: params.cfg,
|
||||
backgroundTasks: params.backgroundTasks,
|
||||
storeAgentId: route.agentId,
|
||||
sessionKey: route.sessionKey,
|
||||
channel: "whatsapp",
|
||||
to: conversationId,
|
||||
accountId: route.accountId,
|
||||
warn: params.replyLogger.warn.bind(params.replyLogger),
|
||||
});
|
||||
|
||||
const gating = applyGroupGating({
|
||||
cfg: params.cfg,
|
||||
msg,
|
||||
conversationId,
|
||||
groupHistoryKey,
|
||||
agentId: route.agentId,
|
||||
sessionKey: route.sessionKey,
|
||||
baseMentionConfig: params.baseMentionConfig,
|
||||
authDir: params.account.authDir,
|
||||
groupHistories: params.groupHistories,
|
||||
groupHistoryLimit: params.groupHistoryLimit,
|
||||
groupMemberNames: params.groupMemberNames,
|
||||
logVerbose,
|
||||
replyLogger: params.replyLogger,
|
||||
});
|
||||
if (!gating.shouldProcess) return;
|
||||
} else {
|
||||
// Ensure `peerId` for DMs is stable and stored as E.164 when possible.
|
||||
if (!msg.senderE164 && peerId && peerId.startsWith("+")) {
|
||||
msg.senderE164 = normalizeE164(peerId) ?? msg.senderE164;
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast groups: when we'd reply anyway, run multiple agents.
|
||||
// Does not bypass group mention/activation gating above.
|
||||
if (
|
||||
await maybeBroadcastMessage({
|
||||
cfg: params.cfg,
|
||||
msg,
|
||||
peerId,
|
||||
route,
|
||||
groupHistoryKey,
|
||||
groupHistories: params.groupHistories,
|
||||
processMessage: processForRoute,
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await processForRoute(msg, route, groupHistoryKey);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user