import type { Base64ContentBlock } from "@langchain/core/messages"; import { toast } from "sonner"; // Returns a Promise of a typed multimodal block for images or PDFs export async function fileToContentBlock( file: File, ): Promise { const supportedImageTypes = [ "image/jpeg", "image/png", "image/gif", "image/webp", ]; const supportedFileTypes = [...supportedImageTypes, "application/pdf"]; if (!supportedFileTypes.includes(file.type)) { toast.error( `Unsupported file type: ${file.type}. Supported types are: ${supportedFileTypes.join(", ")}`, ); return Promise.reject(new Error(`Unsupported file type: ${file.type}`)); } const data = await fileToBase64(file); if (supportedImageTypes.includes(file.type)) { return { type: "image", source_type: "base64", mime_type: file.type, data, metadata: { name: file.name }, }; } // PDF return { type: "file", source_type: "base64", mime_type: "application/pdf", data, metadata: { filename: file.name }, }; } // Helper to convert File to base64 string export async function fileToBase64(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { const result = reader.result as string; // Remove the data:...;base64, prefix resolve(result.split(",")[1]); }; reader.onerror = reject; reader.readAsDataURL(file); }); } // Type guard for Base64ContentBlock export function isBase64ContentBlock( block: unknown, ): block is Base64ContentBlock { if (typeof block !== "object" || block === null || !("type" in block)) return false; // file type (legacy) if ( (block as { type: unknown }).type === "file" && "source_type" in block && (block as { source_type: unknown }).source_type === "base64" && "mime_type" in block && typeof (block as { mime_type?: unknown }).mime_type === "string" && ((block as { mime_type: string }).mime_type.startsWith("image/") || (block as { mime_type: string }).mime_type === "application/pdf") ) { return true; } // image type (new) if ( (block as { type: unknown }).type === "image" && "source_type" in block && (block as { source_type: unknown }).source_type === "base64" && "mime_type" in block && typeof (block as { mime_type?: unknown }).mime_type === "string" && (block as { mime_type: string }).mime_type.startsWith("image/") ) { return true; } return false; }