From 65fa529e032d35c1e18313e99367b80980ce9a3d Mon Sep 17 00:00:00 2001 From: Sebastian <19554889+sebslight@users.noreply.github.com> Date: Mon, 16 Feb 2026 22:59:37 -0500 Subject: [PATCH] Revert "fix(whatsapp): allow per-message link preview override\n\nWhatsApp messages default to enabling link previews for URLs. This adds\nsupport for overriding this behavior per-message via the \nparameter (e.g. from tool options), consistent with Telegram.\n\nFix: Updated internal WhatsApp Web API layers to pass option\ndown to Baileys ." This reverts commit 1bef2fc68bc512c886c25ef1dfba67f58c90e811. --- .../whatsapp/src/channel.send-options.test.ts | 61 ------------------- extensions/whatsapp/src/channel.ts | 5 +- src/web/active-listener.ts | 3 +- src/web/inbound/monitor.ts | 7 +-- src/web/inbound/send-api.ts | 23 ++----- src/web/outbound.ts | 7 +-- 6 files changed, 9 insertions(+), 97 deletions(-) delete mode 100644 extensions/whatsapp/src/channel.send-options.test.ts diff --git a/extensions/whatsapp/src/channel.send-options.test.ts b/extensions/whatsapp/src/channel.send-options.test.ts deleted file mode 100644 index abdc071129..0000000000 --- a/extensions/whatsapp/src/channel.send-options.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk"; -import { describe, it, expect, vi, beforeEach } from "vitest"; -import { whatsappPlugin } from "./channel.js"; - -// Mock runtime -const mockSendMessageWhatsApp = vi - .fn() - .mockResolvedValue({ messageId: "123", toJid: "123@s.whatsapp.net" }); - -vi.mock("./runtime.js", () => ({ - getWhatsAppRuntime: () => ({ - channel: { - text: { chunkText: (t: string) => [t] }, - whatsapp: { - sendMessageWhatsApp: mockSendMessageWhatsApp, - createLoginTool: vi.fn(), - }, - }, - logging: { shouldLogVerbose: () => false }, - }), -})); - -describe("whatsappPlugin.outbound.sendText", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it("passes linkPreview option to sendMessageWhatsApp", async () => { - await whatsappPlugin.outbound!.sendText!({ - cfg: {} as OpenClawConfig, - to: "1234567890", - text: "http://example.com", - // @ts-expect-error - injecting extra param as per runtime behavior - linkPreview: false, - }); - - expect(mockSendMessageWhatsApp).toHaveBeenCalledWith( - "1234567890", - "http://example.com", - expect.objectContaining({ - linkPreview: false, - }), - ); - }); - - it("passes linkPreview=undefined when omitted", async () => { - await whatsappPlugin.outbound!.sendText!({ - cfg: {} as OpenClawConfig, - to: "1234567890", - text: "hello", - }); - - expect(mockSendMessageWhatsApp).toHaveBeenCalledWith( - "1234567890", - "hello", - expect.objectContaining({ - linkPreview: undefined, - }), - ); - }); -}); diff --git a/extensions/whatsapp/src/channel.ts b/extensions/whatsapp/src/channel.ts index 900ce0cde8..f0248823ca 100644 --- a/extensions/whatsapp/src/channel.ts +++ b/extensions/whatsapp/src/channel.ts @@ -290,15 +290,12 @@ export const whatsappPlugin: ChannelPlugin = { pollMaxOptions: 12, resolveTarget: ({ to, allowFrom, mode }) => resolveWhatsAppOutboundTarget({ to, allowFrom, mode }), - sendText: async (params) => { - const { to, text, accountId, deps, gifPlayback } = params; - const linkPreview = (params as { linkPreview?: boolean }).linkPreview; + sendText: async ({ to, text, accountId, deps, gifPlayback }) => { const send = deps?.sendWhatsApp ?? getWhatsAppRuntime().channel.whatsapp.sendMessageWhatsApp; const result = await send(to, text, { verbose: false, accountId: accountId ?? undefined, gifPlayback, - linkPreview, }); return { channel: "whatsapp", ...result }; }, diff --git a/src/web/active-listener.ts b/src/web/active-listener.ts index 40aabbfe3d..0cb48ab405 100644 --- a/src/web/active-listener.ts +++ b/src/web/active-listener.ts @@ -1,12 +1,11 @@ -import { formatCliCommand } from "../cli/command-format.js"; import type { PollInput } from "../polls.js"; +import { formatCliCommand } from "../cli/command-format.js"; import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; export type ActiveWebSendOptions = { gifPlayback?: boolean; accountId?: string; fileName?: string; - linkPreview?: boolean; }; export type ActiveWebListener = { diff --git a/src/web/inbound/monitor.ts b/src/web/inbound/monitor.ts index 33c6d2bba5..b21813e6f0 100644 --- a/src/web/inbound/monitor.ts +++ b/src/web/inbound/monitor.ts @@ -1,5 +1,6 @@ import type { AnyMessageContent, proto, WAMessage } from "@whiskeysockets/baileys"; import { DisconnectReason, isJidGroup } from "@whiskeysockets/baileys"; +import type { WebInboundMessage, WebListenerCloseReason } from "./types.js"; import { createInboundDebouncer } from "../../auto-reply/inbound-debounce.js"; import { formatLocationText } from "../../channels/location.js"; import { logVerbose, shouldLogVerbose } from "../../globals.js"; @@ -20,7 +21,6 @@ import { } from "./extract.js"; import { downloadInboundMedia } from "./media.js"; import { createWebSendApi } from "./send-api.js"; -import type { WebInboundMessage, WebListenerCloseReason } from "./types.js"; export async function monitorWebInbox(options: { verbose: boolean; @@ -366,10 +366,7 @@ export async function monitorWebInbox(options: { const sendApi = createWebSendApi({ sock: { - sendMessage: (jid, content, options) => - options === undefined - ? sock.sendMessage(jid, content) - : sock.sendMessage(jid, content, options), + sendMessage: (jid: string, content: AnyMessageContent) => sock.sendMessage(jid, content), sendPresenceUpdate: (presence, jid?: string) => sock.sendPresenceUpdate(presence, jid), }, defaultAccountId: options.accountId, diff --git a/src/web/inbound/send-api.ts b/src/web/inbound/send-api.ts index ecedcda509..05824536c1 100644 --- a/src/web/inbound/send-api.ts +++ b/src/web/inbound/send-api.ts @@ -1,11 +1,7 @@ -import type { - AnyMessageContent, - MiscMessageGenerationOptions, - WAPresence, -} from "@whiskeysockets/baileys"; +import type { AnyMessageContent, WAPresence } from "@whiskeysockets/baileys"; +import type { ActiveWebSendOptions } from "../active-listener.js"; import { recordChannelActivity } from "../../infra/channel-activity.js"; import { toWhatsappJid } from "../../utils.js"; -import type { ActiveWebSendOptions } from "../active-listener.js"; function recordWhatsAppOutbound(accountId: string) { recordChannelActivity({ @@ -23,11 +19,7 @@ function resolveOutboundMessageId(result: unknown): string { export function createWebSendApi(params: { sock: { - sendMessage: ( - jid: string, - content: AnyMessageContent, - options?: MiscMessageGenerationOptions, - ) => Promise; + sendMessage: (jid: string, content: AnyMessageContent) => Promise; sendPresenceUpdate: (presence: WAPresence, jid?: string) => Promise; }; defaultAccountId: string; @@ -71,14 +63,7 @@ export function createWebSendApi(params: { } else { payload = { text }; } - let result; - if (sendOptions?.linkPreview === false) { - // Baileys types have changed across releases; keep backward-compatible runtime behavior. - const miscOptions = { linkPreview: null } as unknown as MiscMessageGenerationOptions; - result = await params.sock.sendMessage(jid, payload, miscOptions); - } else { - result = await params.sock.sendMessage(jid, payload); - } + const result = await params.sock.sendMessage(jid, payload); const accountId = sendOptions?.accountId ?? params.defaultAccountId; recordWhatsAppOutbound(accountId); const messageId = resolveOutboundMessageId(result); diff --git a/src/web/outbound.ts b/src/web/outbound.ts index 23022a784e..5d3e84ba40 100644 --- a/src/web/outbound.ts +++ b/src/web/outbound.ts @@ -21,7 +21,6 @@ export async function sendMessageWhatsApp( mediaLocalRoots?: readonly string[]; gifPlayback?: boolean; accountId?: string; - linkPreview?: boolean; }, ): Promise<{ messageId: string; toJid: string }> { let text = body; @@ -76,14 +75,10 @@ export async function sendMessageWhatsApp( const hasExplicitAccountId = Boolean(options.accountId?.trim()); const accountId = hasExplicitAccountId ? resolvedAccountId : undefined; const sendOptions: ActiveWebSendOptions | undefined = - options.gifPlayback || - options.accountId || - options.linkPreview !== undefined || - documentFileName + options.gifPlayback || accountId || documentFileName ? { ...(options.gifPlayback ? { gifPlayback: true } : {}), ...(documentFileName ? { fileName: documentFileName } : {}), - ...(options.linkPreview !== undefined ? { linkPreview: options.linkPreview } : {}), accountId, } : undefined;