UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

99 lines (98 loc) • 4.2 kB
import { l as kindFromMime, u as mimeTypeFromFilePath } from "./mime-CGDYrRzL.mjs"; import { l as normalizeMediaFacts, u as projectMediaFacts } from "./media-facts-CJdQ4R61.mjs"; import { t as probeMediaFilesWithinBudget } from "./media-probe-COHtJCIk.mjs"; import { t as resolveLocalMediaPath } from "./local-media-path-DneQarct.mjs"; //#region src/channels/inbound-event/media.ts const MAX_INBOUND_MEDIA_PROBES = 8; const INBOUND_MEDIA_PROBE_CONCURRENCY = 2; const INBOUND_MEDIA_PROBE_BUDGET_MS = 3e3; function resolveMediaPlaceholderKind(media) { if (media.kind && media.kind !== "unknown") return media.kind; const inferredKind = kindFromMime(media.contentType) ?? kindFromMime(mimeTypeFromFilePath(media.url)) ?? kindFromMime(mimeTypeFromFilePath(media.path)); return inferredKind && inferredKind !== "unknown" ? inferredKind : "attachment"; } const PLURAL_MEDIA_PLACEHOLDER_LABELS = { image: "images", video: "videos", audio: "audio attachments", document: "files", sticker: "stickers", attachment: "attachments" }; /** Renders structured media facts for channel surfaces that can carry text only. */ function formatMediaPlaceholderText(media) { if (media.length === 0) return ""; const kinds = media.map(resolveMediaPlaceholderKind); const firstKind = kinds[0] ?? "attachment"; const kind = kinds.every((candidate) => candidate === firstKind) ? firstKind : kinds.includes("attachment") ? "attachment" : "document"; const tag = `<media:${kind}>`; return media.length === 1 ? tag : `${tag} (${media.length} ${PLURAL_MEDIA_PLACEHOLDER_LABELS[kind]})`; } /** Appends an unavailable-media notice to real caption text, or returns the notice alone. */ function formatInboundMediaUnavailableText(params) { const body = params.body?.trim() ?? ""; const notice = params.notice.trim(); if (!body) return notice; return `${body}\n\n${notice}`; } /** Normalizes plugin-provided attachments into ordered runtime facts. */ function toInboundMediaFacts(media, defaults = {}) { return normalizeMediaFacts(media, defaults); } function resolveProbeKind(media) { const kind = media.kind ?? kindFromMime(media.contentType) ?? kindFromMime(mimeTypeFromFilePath(media.path)); return kind === "audio" || kind === "video" ? kind : void 0; } /** Adds best-effort audio/video metadata without probing URL-only media. */ async function toInboundMediaFactsWithMetadata(media, defaults = {}) { const facts = toInboundMediaFacts(media, defaults); const candidates = []; for (const [index, fact] of facts.entries()) { const kind = resolveProbeKind(fact); const localPath = fact.path ? resolveLocalMediaPath(fact.path) : void 0; if (kind && localPath) candidates.push({ fact, index, kind, localPath }); } const metadata = await probeMediaFilesWithinBudget(candidates.map((candidate) => ({ filePath: candidate.localPath, kind: candidate.kind })), { budgetMs: INBOUND_MEDIA_PROBE_BUDGET_MS, concurrency: INBOUND_MEDIA_PROBE_CONCURRENCY, maxProbes: MAX_INBOUND_MEDIA_PROBES }); for (const [candidateIndex, candidate] of candidates.entries()) facts[candidate.index] = { ...candidate.fact, ...metadata[candidateIndex] }; return facts; } /** Projects facts into history without transient turn-only fields. */ function toHistoryMediaEntries(media, defaults = {}) { return toInboundMediaFacts(media, defaults).map((entry) => { const historyEntry = { path: entry.path, url: entry.url, contentType: entry.contentType, kind: entry.kind, messageId: entry.messageId }; if (entry.durationMs) historyEntry.durationMs = entry.durationMs; if (entry.width) historyEntry.width = entry.width; if (entry.height) historyEntry.height = entry.height; return historyEntry; }); } /** * Builds the legacy singular/plural environment projection. * @deprecated Pass ordered facts as `media`; use `toInboundMediaFacts` to normalize inputs. */ function buildChannelInboundMediaPayload(media) { return projectMediaFacts(media); } //#endregion export { toInboundMediaFacts as a, toHistoryMediaEntries as i, formatInboundMediaUnavailableText as n, toInboundMediaFactsWithMetadata as o, formatMediaPlaceholderText as r, buildChannelInboundMediaPayload as t };