import { createLogger } from '@sim/logger' import { processExecutionFiles } from '@/lib/execution/files' import type { UserFile } from '@/executor/types' const logger = createLogger('ChatFileManager') export interface ChatFile { data?: string // Legacy field - base64-encoded file data (data:mime;base64,...) or raw base64 dataUrl?: string // Preferred field - base64-encoded file data (data:mime;base64,...) url?: string // Direct URL to existing file name: string // Original filename type: string // MIME type } export interface ChatExecutionContext { workspaceId: string workflowId: string executionId: string } /** * Process and upload chat files to temporary execution storage * * Handles two input formats: * 1. Base64 dataUrl - File content encoded as data URL (uploaded from client) * 2. Direct URL - Pass-through URL to existing file (already uploaded) * * Files are stored in the execution context with 5-10 minute expiry. * * @param files Array of chat file attachments * @param executionContext Execution context for temporary storage * @param requestId Unique request identifier for logging/tracing * @param userId User ID for file metadata (optional) * @returns Array of UserFile objects with upload results */ export async function processChatFiles( files: ChatFile[], executionContext: ChatExecutionContext, requestId: string, userId?: string ): Promise { logger.info( `Processing ${files.length} chat files for execution ${executionContext.executionId}`, { requestId, executionContext, } ) const transformedFiles = files.map((file) => { const inlineData = file.dataUrl || file.data return { type: inlineData ? ('file' as const) : ('url' as const), data: inlineData || file.url || '', name: file.name, mime: file.type, } }) const userFiles = await processExecutionFiles( transformedFiles, executionContext, requestId, userId ) logger.info(`Successfully processed ${userFiles.length} chat files`, { requestId, executionId: executionContext.executionId, }) return userFiles } /** * Upload a single chat file to temporary execution storage * * This is a convenience function for uploading individual files. * For batch uploads, use processChatFiles() for better performance. * * @param file Chat file to upload * @param executionContext Execution context for temporary storage * @param requestId Unique request identifier * @returns UserFile object with upload result */ async function uploadChatFile( file: ChatFile, executionContext: ChatExecutionContext, requestId: string, userId?: string ): Promise { const [userFile] = await processChatFiles([file], executionContext, requestId, userId) return userFile }