char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
094e53db1
char/aliceai-t5-moe
1/** 2* File upload lifecycle for the ChatScreen form. 3* 4* Owns the queue of processed `ChatUploadedFile`, the rejection-by-capability 5* dialog state, and the dual-layer validation pipeline (general format + 6* model modality). The caller provides the active model's capabilities and ID 7* as reactive getters so validation tracks the model in real time. 8*/ 9 10import { filterFilesByModalities , isFileTypeSupported } from '$lib/utils' ; 11import { processFilesToChatUploaded } from '$lib/utils/browser-only' ; 12 13interface UseChatScreenFileUploadOptions { 14capabilities :() => { hasVision :boolean ; hasAudio :boolean ; hasVideo :boolean }; 15activeModelId :() => string | null | undefined ; 16} 17 18export interface FileErrorData { 19generallyUnsupported :File []; 20modalityUnsupported :File []; 21modalityReasons :Record < string , string >; 22supportedTypes :string []; 23} 24 25export function useChatScreenFileUpload ( options :UseChatScreenFileUploadOptions ) { 26let uploadedFiles = $state < ChatUploadedFile []>([]); 27let showFileErrorDialog = $state ( false ); 28let fileErrorData = $state < FileErrorData >({ 29generallyUnsupported :[], 30modalityReasons :{}, 31modalityUnsupported :[], 32supportedTypes :[] 33}); 34 35async function processFiles ( files :File []) { 36const generallySupported :File [] = []; 37const generallyUnsupported :File [] = []; 38 39for ( const file of files ) { 40if ( isFileTypeSupported ( file . name , file . type )) { 41generallySupported . push ( file ); 42} else { 43generallyUnsupported . push ( file ); 44} 45} 46 47const { modalityReasons, supportedFiles, unsupportedFiles} = filterFilesByModalities ( 48generallySupported , 49options . capabilities () 50); 51const allUnsupportedFiles = [ ...generallyUnsupported , ...unsupportedFiles ]; 52 53if ( allUnsupportedFiles . length > 0 ) { 54const supportedTypes :string [] = [ 'text files' , 'PDFs' ]; 55const caps = options . capabilities (); 56 57if ( caps . hasVision ) supportedTypes . push ( 'images' ); 58 59if ( caps . hasAudio ) supportedTypes . push ( 'audio files' ); 60 61if ( caps . hasVideo ) supportedTypes . push ( 'video files' ); 62 63fileErrorData = { 64 generallyUnsupported, 65 modalityReasons, 66modalityUnsupported :unsupportedFiles , 67 supportedTypes 68}; 69showFileErrorDialog = true ; 70} 71 72if ( supportedFiles . length > 0 ) { 73const processed = await processFilesToChatUploaded ( 74supportedFiles , 75options . activeModelId () ?? undefined 76); 77 78uploadedFiles = [ ...uploadedFiles , ...processed ]; 79} 80} 81 82function handleFileUpload ( files :File []) { 83return processFiles ( files ); 84} 85 86function handleFileRemove ( fileId :string ) { 87uploadedFiles = uploadedFiles . filter (( f ) => f . id !== fileId ); 88} 89 90return { 91get fileErrorData () { 92return fileErrorData ; 93}, 94 handleFileRemove, 95 handleFileUpload, 96get showFileErrorDialog () { 97return showFileErrorDialog ; 98}, 99set showFileErrorDialog ( value ) { 100showFileErrorDialog = value ; 101}, 102get uploadedFiles () { 103return uploadedFiles ; 104}, 105set uploadedFiles ( value ) { 106uploadedFiles = value ; 107} 108}; 109}