perf(test): skip text-only media policy setup

This commit is contained in:
Peter Steinberger
2026-04-20 17:31:37 +01:00
parent b225d31179
commit bf18161ea8
3 changed files with 57 additions and 18 deletions

View File

@@ -27,7 +27,11 @@ import {
import { HEARTBEAT_TOKEN } from "../auto-reply/tokens.js";
import type { ReplyPayload } from "../auto-reply/types.js";
import { getChannelPlugin } from "../channels/plugins/index.js";
import type { ChannelHeartbeatDeps } from "../channels/plugins/types.public.js";
import type {
ChannelHeartbeatDeps,
ChannelId,
ChannelPlugin,
} from "../channels/plugins/types.public.js";
import { loadConfig } from "../config/config.js";
import {
canonicalizeMainSessionAlias,
@@ -44,6 +48,7 @@ import type { AgentDefaultsConfig } from "../config/types.agent-defaults.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import { resolveCronSession } from "../cron/isolated-agent/session.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { getActivePluginChannelRegistry } from "../plugins/runtime.js";
import { getQueueSize } from "../process/command-queue.js";
import { CommandLane } from "../process/lanes.js";
import {
@@ -121,6 +126,13 @@ function loadHeartbeatRunnerRuntime() {
return heartbeatRunnerRuntimePromise;
}
function resolveHeartbeatChannelPlugin(channel: string): ChannelPlugin | undefined {
const activePlugin = getActivePluginChannelRegistry()?.channels.find(
(entry) => entry.plugin.id === channel,
)?.plugin;
return activePlugin ?? getChannelPlugin(channel as ChannelId);
}
export { areHeartbeatsEnabled, setHeartbeatsEnabled };
export {
isHeartbeatEnabledForAgent,
@@ -979,7 +991,7 @@ export async function runHeartbeatOnce(opts: {
if (!canAttemptHeartbeatOk || delivery.channel === "none" || !delivery.to) {
return false;
}
const heartbeatPlugin = getChannelPlugin(delivery.channel);
const heartbeatPlugin = resolveHeartbeatChannelPlugin(delivery.channel);
if (heartbeatPlugin?.heartbeat?.checkReady) {
const readiness = await heartbeatPlugin.heartbeat.checkReady({
cfg,
@@ -1167,7 +1179,7 @@ export async function runHeartbeatOnce(opts: {
}
const deliveryAccountId = delivery.accountId;
const heartbeatPlugin = getChannelPlugin(delivery.channel);
const heartbeatPlugin = resolveHeartbeatChannelPlugin(delivery.channel);
if (heartbeatPlugin?.heartbeat?.checkReady) {
const readiness = await heartbeatPlugin.heartbeat.checkReady({
cfg,

View File

@@ -230,7 +230,7 @@ describe("deliverOutboundPayloads", () => {
cfg: {},
channel: "whatsapp",
to: "+1555",
payloads: [{ text: "hello" }],
payloads: [{ text: "hello", mediaUrl: "file:///tmp/policy.png" }],
deps: { whatsapp: sendWhatsApp },
session: {
key: "agent:main:whatsapp:group:ops",
@@ -259,7 +259,7 @@ describe("deliverOutboundPayloads", () => {
cfg: {},
channel: "whatsapp",
to: "+1555",
payloads: [{ text: "hello" }],
payloads: [{ text: "hello", mediaUrl: "file:///tmp/policy.png" }],
deps: { whatsapp: sendWhatsApp },
session: {
key: "agent:main:whatsapp:group:ops",
@@ -293,7 +293,7 @@ describe("deliverOutboundPayloads", () => {
channel: "whatsapp",
to: "+1555",
accountId: "destination-account",
payloads: [{ text: "hello" }],
payloads: [{ text: "hello", mediaUrl: "file:///tmp/policy.png" }],
deps: { whatsapp: sendWhatsApp },
session: {
key: "agent:main:whatsapp:group:ops",
@@ -312,6 +312,29 @@ describe("deliverOutboundPayloads", () => {
resolveMediaAccessSpy.mockRestore();
});
it("skips media access policy for text-only delivery", async () => {
const resolveMediaAccessSpy = vi.spyOn(
mediaCapabilityModule,
"resolveAgentScopedOutboundMediaAccess",
);
const sendWhatsApp = vi.fn().mockResolvedValue({ messageId: "w4", toJid: "jid" });
await deliverOutboundPayloads({
cfg: {},
channel: "whatsapp",
to: "+1555",
payloads: [{ text: "hello" }],
deps: { whatsapp: sendWhatsApp },
session: {
key: "agent:main:whatsapp:group:ops",
requesterSenderId: "attacker",
},
});
expect(resolveMediaAccessSpy).not.toHaveBeenCalled();
resolveMediaAccessSpy.mockRestore();
});
it("chunks direct adapter text and preserves delivery overrides across sends", async () => {
const sendText = vi.fn().mockImplementation(async ({ text }: { text: string }) => ({
channel: "matrix" as const,

View File

@@ -557,18 +557,22 @@ async function deliverOutboundPayloadsCore(
const accountId = params.accountId;
const deps = params.deps;
const abortSignal = params.abortSignal;
const mediaAccess = resolveAgentScopedOutboundMediaAccess({
cfg,
agentId: params.session?.agentId ?? params.mirror?.agentId,
mediaSources: collectPayloadMediaSources(outboundPayloadPlan),
sessionKey: params.session?.key,
messageProvider: params.session?.key ? undefined : channel,
accountId: params.session?.requesterAccountId ?? accountId,
requesterSenderId: params.session?.requesterSenderId,
requesterSenderName: params.session?.requesterSenderName,
requesterSenderUsername: params.session?.requesterSenderUsername,
requesterSenderE164: params.session?.requesterSenderE164,
});
const mediaSources = collectPayloadMediaSources(outboundPayloadPlan);
const mediaAccess =
mediaSources.length > 0
? resolveAgentScopedOutboundMediaAccess({
cfg,
agentId: params.session?.agentId ?? params.mirror?.agentId,
mediaSources,
sessionKey: params.session?.key,
messageProvider: params.session?.key ? undefined : channel,
accountId: params.session?.requesterAccountId ?? accountId,
requesterSenderId: params.session?.requesterSenderId,
requesterSenderName: params.session?.requesterSenderName,
requesterSenderUsername: params.session?.requesterSenderUsername,
requesterSenderE164: params.session?.requesterSenderE164,
})
: {};
const results: OutboundDeliveryResult[] = [];
const handler = await createChannelHandler({
cfg,