116 lines
5.0 KiB
TypeScript
116 lines
5.0 KiB
TypeScript
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
import { onNewMessage, setMentionOverride, getTurnDebugInfo } from "../turn-manager.js";
|
|
import { extractDiscordChannelId } from "../channel-resolver.js";
|
|
import type { DirigentConfig } from "../rules.js";
|
|
|
|
type DebugConfig = {
|
|
enableDebugLogs?: boolean;
|
|
debugLogChannelIds?: string[];
|
|
};
|
|
|
|
type MessageReceivedDeps = {
|
|
api: OpenClawPluginApi;
|
|
baseConfig: DirigentConfig;
|
|
getLivePluginConfig: (api: OpenClawPluginApi, fallback: DirigentConfig) => DirigentConfig;
|
|
shouldDebugLog: (config: DirigentConfig & DebugConfig, channelId?: string) => boolean;
|
|
debugCtxSummary: (ctx: Record<string, unknown>, event: Record<string, unknown>) => Record<string, unknown>;
|
|
ensureTurnOrder: (api: OpenClawPluginApi, channelId: string) => void;
|
|
getModeratorUserId: (cfg: DirigentConfig) => string | undefined;
|
|
recordChannelAccount: (channelId: string, accountId: string) => boolean;
|
|
extractMentionedUserIds: (content: string) => string[];
|
|
buildUserIdToAccountIdMap: (api: OpenClawPluginApi) => Map<string, string>;
|
|
};
|
|
|
|
export function registerMessageReceivedHook(deps: MessageReceivedDeps): void {
|
|
const {
|
|
api,
|
|
baseConfig,
|
|
getLivePluginConfig,
|
|
shouldDebugLog,
|
|
debugCtxSummary,
|
|
ensureTurnOrder,
|
|
getModeratorUserId,
|
|
recordChannelAccount,
|
|
extractMentionedUserIds,
|
|
buildUserIdToAccountIdMap,
|
|
} = deps;
|
|
|
|
api.on("message_received", async (event, ctx) => {
|
|
try {
|
|
const c = (ctx || {}) as Record<string, unknown>;
|
|
const e = (event || {}) as Record<string, unknown>;
|
|
const preChannelId = extractDiscordChannelId(c, e);
|
|
const livePre = getLivePluginConfig(api, baseConfig as DirigentConfig) as DirigentConfig & DebugConfig;
|
|
if (shouldDebugLog(livePre, preChannelId)) {
|
|
api.logger.info(`dirigent: debug message_received preflight ctx=${JSON.stringify(debugCtxSummary(c, e))}`);
|
|
}
|
|
|
|
if (preChannelId) {
|
|
ensureTurnOrder(api, preChannelId);
|
|
const metadata = (e as Record<string, unknown>).metadata as Record<string, unknown> | undefined;
|
|
const from =
|
|
(typeof metadata?.senderId === "string" && metadata.senderId) ||
|
|
(typeof (e as Record<string, unknown>).from === "string" ? ((e as Record<string, unknown>).from as string) : "");
|
|
|
|
const moderatorUserId = getModeratorUserId(livePre);
|
|
if (moderatorUserId && from === moderatorUserId) {
|
|
if (shouldDebugLog(livePre, preChannelId)) {
|
|
api.logger.info(`dirigent: ignoring moderator message in channel=${preChannelId}`);
|
|
}
|
|
} else {
|
|
const humanList = livePre.humanList || livePre.bypassUserIds || [];
|
|
const isHuman = humanList.includes(from);
|
|
const senderAccountId = typeof c.accountId === "string" ? c.accountId : undefined;
|
|
|
|
if (senderAccountId && senderAccountId !== "default") {
|
|
const isNew = recordChannelAccount(preChannelId, senderAccountId);
|
|
if (isNew) {
|
|
ensureTurnOrder(api, preChannelId);
|
|
api.logger.info(`dirigent: new account ${senderAccountId} seen in channel=${preChannelId}, turn order updated`);
|
|
}
|
|
}
|
|
|
|
if (isHuman) {
|
|
const messageContent = ((e as Record<string, unknown>).content as string) || ((e as Record<string, unknown>).text as string) || "";
|
|
const mentionedUserIds = extractMentionedUserIds(messageContent);
|
|
|
|
if (mentionedUserIds.length > 0) {
|
|
const userIdMap = buildUserIdToAccountIdMap(api);
|
|
const mentionedAccountIds = mentionedUserIds.map((uid) => userIdMap.get(uid)).filter((aid): aid is string => !!aid);
|
|
|
|
if (mentionedAccountIds.length > 0) {
|
|
ensureTurnOrder(api, preChannelId);
|
|
const overrideSet = setMentionOverride(preChannelId, mentionedAccountIds);
|
|
if (overrideSet) {
|
|
api.logger.info(
|
|
`dirigent: mention override set channel=${preChannelId} mentionedAgents=${JSON.stringify(mentionedAccountIds)}`,
|
|
);
|
|
if (shouldDebugLog(livePre, preChannelId)) {
|
|
api.logger.info(`dirigent: turn state after override: ${JSON.stringify(getTurnDebugInfo(preChannelId))}`);
|
|
}
|
|
} else {
|
|
onNewMessage(preChannelId, senderAccountId, isHuman);
|
|
}
|
|
} else {
|
|
onNewMessage(preChannelId, senderAccountId, isHuman);
|
|
}
|
|
} else {
|
|
onNewMessage(preChannelId, senderAccountId, isHuman);
|
|
}
|
|
} else {
|
|
onNewMessage(preChannelId, senderAccountId, isHuman);
|
|
}
|
|
|
|
if (shouldDebugLog(livePre, preChannelId)) {
|
|
api.logger.info(
|
|
`dirigent: turn onNewMessage channel=${preChannelId} from=${from} isHuman=${isHuman} accountId=${senderAccountId ?? "unknown"}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
api.logger.warn(`dirigent: message hook failed: ${String(err)}`);
|
|
}
|
|
});
|
|
}
|