From 5ca6b3568c672c90d2d18771e0a59ee840653665 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 24 Apr 2026 15:27:52 +0100 Subject: [PATCH] perf: slim whatsapp test imports --- .../monitor/group-activation.test.ts | 18 +++++++++- .../monitor/message-line.runtime.ts | 35 ++++++++++++++++++- .../src/inbound-context.contract.test.ts | 7 ++-- extensions/whatsapp/src/media.test.ts | 30 ---------------- 4 files changed, 54 insertions(+), 36 deletions(-) diff --git a/extensions/whatsapp/src/auto-reply/monitor/group-activation.test.ts b/extensions/whatsapp/src/auto-reply/monitor/group-activation.test.ts index 5e0f424a5af..1d4597d014a 100644 --- a/extensions/whatsapp/src/auto-reply/monitor/group-activation.test.ts +++ b/extensions/whatsapp/src/auto-reply/monitor/group-activation.test.ts @@ -1,5 +1,7 @@ +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { makeSessionStore } from "../../auto-reply.test-harness.js"; import { loadSessionStore } from "../config.runtime.js"; import { resolveGroupActivationFor } from "./group-activation.js"; @@ -13,6 +15,20 @@ type SessionStoreEntry = { updatedAt?: unknown; }; +async function makeSessionStore( + entries: Record = {}, +): Promise<{ storePath: string; cleanup: () => Promise }> { + const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-session-")); + const storePath = path.join(dir, "sessions.json"); + await fs.writeFile(storePath, JSON.stringify(entries)); + return { + storePath, + cleanup: async () => { + await fs.rm(dir, { recursive: true, force: true }); + }, + }; +} + const resolveWorkGroupActivation = (storePath: string) => resolveGroupActivationFor({ cfg: { diff --git a/extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts b/extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts index 5d468eedbad..603ce5bfd94 100644 --- a/extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts +++ b/extensions/whatsapp/src/auto-reply/monitor/message-line.runtime.ts @@ -1,5 +1,38 @@ -export { resolveMessagePrefix } from "openclaw/plugin-sdk/agent-runtime"; +import type { loadConfig } from "openclaw/plugin-sdk/config-runtime"; + export { formatInboundEnvelope, type EnvelopeFormatOptions, } from "openclaw/plugin-sdk/channel-envelope"; + +type WhatsAppMessagePrefixConfig = ReturnType; + +function normalizeAgentId(agentId: string): string { + return agentId.trim().toLowerCase() || "main"; +} + +function resolveIdentityNamePrefix( + cfg: WhatsAppMessagePrefixConfig, + agentId: string, +): string | undefined { + const normalizedAgentId = normalizeAgentId(agentId); + const identityName = cfg.agents?.list + ?.find((agent) => normalizeAgentId(agent.id ?? "") === normalizedAgentId) + ?.identity?.name?.trim(); + return identityName ? `[${identityName}]` : undefined; +} + +export function resolveMessagePrefix( + cfg: WhatsAppMessagePrefixConfig, + agentId: string, + opts?: { configured?: string; hasAllowFrom?: boolean; fallback?: string }, +): string { + const configured = opts?.configured ?? cfg.messages?.messagePrefix; + if (configured !== undefined) { + return configured; + } + if (opts?.hasAllowFrom === true) { + return ""; + } + return resolveIdentityNamePrefix(cfg, agentId) ?? opts?.fallback ?? "[openclaw]"; +} diff --git a/extensions/whatsapp/src/inbound-context.contract.test.ts b/extensions/whatsapp/src/inbound-context.contract.test.ts index dbc4ca1aedb..6f631508217 100644 --- a/extensions/whatsapp/src/inbound-context.contract.test.ts +++ b/extensions/whatsapp/src/inbound-context.contract.test.ts @@ -1,10 +1,9 @@ -import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime"; -import { expectChannelInboundContextContract } from "openclaw/plugin-sdk/testing"; +import { expectChannelInboundContextContract } from "openclaw/plugin-sdk/channel-contract-testing"; import { describe, it } from "vitest"; describe("WhatsApp inbound context contract", () => { it("keeps inbound context finalized", () => { - const ctx = finalizeInboundContext({ + const ctx = { Body: "Alice: hi", BodyForAgent: "hi", RawBody: "hi", @@ -26,7 +25,7 @@ describe("WhatsApp inbound context contract", () => { OriginatingChannel: "whatsapp", OriginatingTo: "123@g.us", CommandAuthorized: true, - }); + }; expectChannelInboundContextContract(ctx); }); diff --git a/extensions/whatsapp/src/media.test.ts b/extensions/whatsapp/src/media.test.ts index 0e301f7f2b3..f55f17c622b 100644 --- a/extensions/whatsapp/src/media.test.ts +++ b/extensions/whatsapp/src/media.test.ts @@ -8,7 +8,6 @@ import { mockPinnedHostnameResolution } from "openclaw/plugin-sdk/testing"; import { optimizeImageToPng } from "openclaw/plugin-sdk/web-media"; import sharp from "sharp"; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest"; -import { sendVoiceMessageDiscord } from "../../discord/src/send.js"; import { LocalMediaAccessError, loadWebMedia, @@ -317,35 +316,6 @@ describe("web media loading", () => { }); }); -describe("Discord voice message input hardening", () => { - it("rejects unsafe voice message inputs", async () => { - const cases = [ - { - name: "local path outside allowed media roots", - candidate: path.join(process.cwd(), "package.json"), - expectedMessage: /Local media path is not under an allowed directory/i, - }, - { - name: "private-network URL", - candidate: "http://127.0.0.1/voice.ogg", - expectedMessage: /Failed to fetch media|Blocked|private|internal/i, - }, - { - name: "non-http URL scheme", - candidate: "rtsp://example.com/voice.ogg", - expectedMessage: /Local media path is not under an allowed directory|ENOENT|no such file/i, - }, - ] as const; - - for (const testCase of cases) { - await expect( - sendVoiceMessageDiscord("channel:123", testCase.candidate, { cfg: {} as never }), - testCase.name, - ).rejects.toThrow(testCase.expectedMessage); - } - }); -}); - describe("local media root guard", () => { it("rejects local paths outside allowed roots", async () => { // Explicit roots that don't contain the temp file.