refactor: share inbound media detection

This commit is contained in:
Peter Steinberger
2026-04-20 14:27:16 +01:00
parent 80ab02d8be
commit b722273acb
3 changed files with 31 additions and 26 deletions

View File

@@ -28,6 +28,7 @@ import {
createAcpDispatchDeliveryCoordinator,
type AcpDispatchDeliveryCoordinator,
} from "./dispatch-acp-delivery.js";
import { hasInboundMedia } from "./inbound-media.js";
import type { ReplyDispatchKind, ReplyDispatcher } from "./reply-dispatcher.types.js";
let dispatchAcpManagerRuntimePromise: Promise<
@@ -85,18 +86,6 @@ function resolveAcpPromptText(ctx: FinalizedMsgContext): string {
]).trim();
}
function hasInboundMediaForAcp(ctx: FinalizedMsgContext): boolean {
return Boolean(
ctx.StickerMediaIncluded ||
ctx.Sticker ||
normalizeOptionalString(ctx.MediaPath) ||
normalizeOptionalString(ctx.MediaUrl) ||
ctx.MediaPaths?.some((value) => normalizeOptionalString(value)) ||
ctx.MediaUrls?.some((value) => normalizeOptionalString(value)) ||
ctx.MediaTypes?.length,
);
}
function resolveAcpRequestId(ctx: FinalizedMsgContext): string {
const id = ctx.MessageSidFull ?? ctx.MessageSid ?? ctx.MessageSidFirst ?? ctx.MessageSidLast;
if (typeof id === "string") {
@@ -396,7 +385,7 @@ export async function tryDispatchAcpReply(params: {
if (agentPolicyError) {
throw agentPolicyError;
}
if (hasInboundMediaForAcp(params.ctx) && !params.ctx.MediaUnderstanding?.length) {
if (hasInboundMedia(params.ctx) && !params.ctx.MediaUnderstanding?.length) {
try {
const { applyMediaUnderstanding } = await loadDispatchAcpMediaRuntime();
await applyMediaUnderstanding({
@@ -411,7 +400,7 @@ export async function tryDispatchAcpReply(params: {
}
const promptText = resolveAcpPromptText(params.ctx);
const attachments = hasInboundMediaForAcp(params.ctx)
const attachments = hasInboundMedia(params.ctx)
? await resolveAcpAttachments({ ctx: params.ctx, cfg: params.cfg })
: [];
if (!promptText && attachments.length === 0) {

View File

@@ -33,6 +33,7 @@ import {
import { handleInlineActions } from "./get-reply-inline-actions.js";
import { runPreparedReply } from "./get-reply-run.js";
import { finalizeInboundContext } from "./inbound-context.js";
import { hasInboundMedia } from "./inbound-media.js";
import { emitPreAgentMessageHooks } from "./message-preprocess-hooks.js";
import { createFastTestModelSelectionState } from "./model-selection.js";
import { initSessionState } from "./session.js";
@@ -119,18 +120,6 @@ function mergeSkillFilters(channelFilter?: string[], agentFilter?: string[]): st
return channel.filter((name) => agentSet.has(name));
}
function hasInboundMedia(ctx: MsgContext): boolean {
return Boolean(
ctx.StickerMediaIncluded ||
ctx.Sticker ||
normalizeOptionalString(ctx.MediaPath) ||
normalizeOptionalString(ctx.MediaUrl) ||
ctx.MediaPaths?.some((value) => normalizeOptionalString(value)) ||
ctx.MediaUrls?.some((value) => normalizeOptionalString(value)) ||
ctx.MediaTypes?.length,
);
}
function hasLinkCandidate(ctx: MsgContext): boolean {
const message = ctx.BodyForCommands ?? ctx.CommandBody ?? ctx.RawBody ?? ctx.Body;
if (!message) {

View File

@@ -0,0 +1,27 @@
import { normalizeOptionalString } from "../../shared/string-coerce.js";
export type InboundMediaContext = {
StickerMediaIncluded?: unknown;
Sticker?: unknown;
MediaPath?: unknown;
MediaUrl?: unknown;
MediaPaths?: readonly unknown[];
MediaUrls?: readonly unknown[];
MediaTypes?: readonly unknown[];
};
function hasNormalizedStringEntry(values: readonly unknown[] | undefined): boolean {
return Array.isArray(values) && values.some((value) => normalizeOptionalString(value));
}
export function hasInboundMedia(ctx: InboundMediaContext): boolean {
return Boolean(
ctx.StickerMediaIncluded ||
ctx.Sticker ||
normalizeOptionalString(ctx.MediaPath) ||
normalizeOptionalString(ctx.MediaUrl) ||
hasNormalizedStringEntry(ctx.MediaPaths) ||
hasNormalizedStringEntry(ctx.MediaUrls) ||
(Array.isArray(ctx.MediaTypes) && ctx.MediaTypes.length > 0),
);
}