import type { IssueAttachment } from "@paperclipai/shared"; import { isMarkdownAttachmentContent } from "@paperclipai/shared"; import { isImageLikeOutput, isVideoLikeOutput } from "./issue-output"; import { isHtmlPreview } from "./html-preview"; type AttachmentPathLike = { contentPath: string; openPath?: string; downloadPath?: string; }; function normalizedContentType(attachment: Pick) { return attachment.contentType.toLowerCase().split(";")[0]?.trim() ?? ""; } export function attachmentFilename(attachment: Pick) { return attachment.originalFilename ?? attachment.id; } export function attachmentOpenPath(attachment: AttachmentPathLike) { return attachment.openPath ?? attachment.contentPath; } export function attachmentDownloadPath(attachment: AttachmentPathLike) { return attachment.downloadPath ?? `${attachment.contentPath}?download=1`; } export function isImageAttachment(attachment: Pick & Partial>) { const type = normalizedContentType(attachment); return isImageLikeOutput(type, attachment.originalFilename) && !/^image\/hei[cf](?:-sequence)?$/.test(type); } export function isVideoAttachment( attachment: Pick, ) { return isVideoLikeOutput(attachment.contentType, attachment.originalFilename); } export function isMarkdownAttachment( attachment: Pick, ) { return isMarkdownAttachmentContent(attachment); } export function isTextAttachment(attachment: { contentType: string; originalFilename?: string | null; }) { const type = attachment.contentType.toLowerCase().split(";")[0].trim(); return isMarkdownAttachmentContent(attachment) || isHtmlPreview(type, attachment.originalFilename) || type.startsWith("text/") || /^(application\/(json|xml|javascript|x-yaml|yaml)|application\/[\w.-]+\+json)$/.test(type) || (["", "application/octet-stream"].includes(type) && /\.(txt|log|csv|json|yaml|yml|toml|ini|sh|ts|tsx|js|jsx|py|css|html)$/i.test(attachment.originalFilename ?? "")); }