import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import { createActionGate, jsonResult, readReactionParams, readStringParam, type OpenClawConfig, } from "openclaw/plugin-sdk/whatsapp-core"; import { resolveAuthorizedWhatsAppOutboundTarget } from "./action-runtime-target-auth.js"; import { sendReactionWhatsApp } from "./send.js"; export const whatsAppActionRuntime = { resolveAuthorizedWhatsAppOutboundTarget, sendReactionWhatsApp, }; export async function handleWhatsAppAction( params: Record, cfg: OpenClawConfig, ): Promise> { const action = readStringParam(params, "action", { required: true }); const isActionEnabled = createActionGate(cfg.channels?.whatsapp?.actions); if (action === "react") { if (!isActionEnabled("reactions")) { throw new Error("WhatsApp reactions are disabled."); } const chatJid = readStringParam(params, "chatJid", { required: true }); const messageId = readStringParam(params, "messageId", { required: true }); const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a WhatsApp reaction.", }); const participant = readStringParam(params, "participant"); const accountId = readStringParam(params, "accountId"); const fromMeRaw = params.fromMe; const fromMe = typeof fromMeRaw === "boolean" ? fromMeRaw : undefined; // Resolve account + allowFrom via shared account logic so auth and routing stay aligned. const resolved = whatsAppActionRuntime.resolveAuthorizedWhatsAppOutboundTarget({ cfg, chatJid, accountId, actionLabel: "reaction", }); const resolvedEmoji = remove ? "" : emoji; await whatsAppActionRuntime.sendReactionWhatsApp(resolved.to, messageId, resolvedEmoji, { verbose: false, fromMe, participant: participant ?? undefined, accountId: resolved.accountId, }); if (!remove && !isEmpty) { return jsonResult({ ok: true, added: emoji }); } return jsonResult({ ok: true, removed: true }); } throw new Error(`Unsupported WhatsApp action: ${action}`); }