diff --git a/lib/openclaw-chat/media-attachments.ts b/lib/openclaw-chat/media-attachments.ts index a2b13c3dc..fa17b41f8 100644 --- a/lib/openclaw-chat/media-attachments.ts +++ b/lib/openclaw-chat/media-attachments.ts @@ -27,6 +27,27 @@ const VIDEO_CONTENT_TYPE_BY_EXTENSION: Record = { const VIDEO_EXTENSION_PATTERN = /\.(mp4|mov|webm|m4v|mkv)(?:$|[?#])/i; const ARCHIVE_EXTENSION_PATTERN = /\.zip(?:$|[?#])/i; +const FILE_EXTENSION_PATTERN = + /\.(zip|rar|7z|tar|gz|tgz|pdf|txt|md|docx?|pptx?|xlsx?|csv|tsv|json|xml|mp3|wav|m4a|aac|flac|ogg|psd|ai|dxf|dwg|step|stp)(?:$|[?#])/i; +const FILE_CONTENT_TYPES = new Set([ + "application/gzip", + "application/msword", + "application/pdf", + "application/vnd.ms-excel", + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.rar", + "application/x-7z-compressed", + "application/x-rar-compressed", + "application/x-tar", + "application/x-zip-compressed", + "application/zip", + "text/csv", + "text/plain", + "text/tab-separated-values", +]); export type OpenClawChatMediaAttachment = { type: "image" | "video" | "file"; @@ -105,6 +126,18 @@ export function isOpenClawChatArchiveAttachment( ); } +export function isOpenClawChatFileAttachment( + url: string, + contentType?: string | null +) { + const normalizedContentType = normalizeContentType(contentType); + return ( + FILE_CONTENT_TYPES.has(normalizedContentType) || + normalizedContentType.startsWith("audio/") || + FILE_EXTENSION_PATTERN.test(String(url || "")) + ); +} + export function normalizeOpenClawChatMediaAttachments( value: unknown ): OpenClawChatMediaAttachment[] {