1- import type { AttachmentModality } from "./props" ;
2-
3- const DEFAULT_MAX_SIZE = 20 * 1024 * 1024 ; // 20MB
4-
5- // ---------------------------------------------------------------------------
6- // Deprecation warning helpers
7- // ---------------------------------------------------------------------------
8-
1+ // Re-export utilities from shared
2+ export {
3+ getModalityFromMimeType ,
4+ formatFileSize ,
5+ exceedsMaxSize ,
6+ readFileAsBase64 ,
7+ generateVideoThumbnail ,
8+ matchesAcceptFilter ,
9+ } from "@copilotkit/shared" ;
10+
11+ // Deprecation warning helpers — react-ui specific
912const suppressedWarnings = new Set < string > ( ) ;
1013let globalSuppress = false ;
1114
@@ -26,133 +29,3 @@ export function deprecationWarning(key: string, message: string) {
2629export function suppressDeprecationWarnings ( ) {
2730 globalSuppress = true ;
2831}
29-
30- /**
31- * Derive the attachment modality from a MIME type string.
32- */
33- export function getModalityFromMimeType ( mimeType : string ) : AttachmentModality {
34- if ( mimeType . startsWith ( "image/" ) ) return "image" ;
35- if ( mimeType . startsWith ( "audio/" ) ) return "audio" ;
36- if ( mimeType . startsWith ( "video/" ) ) return "video" ;
37- return "document" ;
38- }
39-
40- /**
41- * Format a byte count as a human-readable file size string.
42- */
43- export function formatFileSize ( bytes : number ) : string {
44- if ( bytes < 1024 ) return `${ bytes } B` ;
45- if ( bytes < 1024 * 1024 ) return `${ ( bytes / 1024 ) . toFixed ( 1 ) } KB` ;
46- return `${ ( bytes / ( 1024 * 1024 ) ) . toFixed ( 1 ) } MB` ;
47- }
48-
49- /**
50- * Check if a file exceeds the maximum allowed size.
51- */
52- export function exceedsMaxSize (
53- file : File ,
54- maxSize : number = DEFAULT_MAX_SIZE ,
55- ) : boolean {
56- return file . size > maxSize ;
57- }
58-
59- /**
60- * Read a File as a base64 string (without the data URL prefix).
61- */
62- export function readFileAsBase64 ( file : File ) : Promise < string > {
63- return new Promise ( ( resolve , reject ) => {
64- const reader = new FileReader ( ) ;
65- reader . onload = ( e ) => {
66- const result = e . target ?. result as string ;
67- const base64 = result ?. split ( "," ) [ 1 ] ;
68- if ( base64 ) {
69- resolve ( base64 ) ;
70- } else {
71- reject ( new Error ( "Failed to read file as base64" ) ) ;
72- }
73- } ;
74- reader . onerror = reject ;
75- reader . readAsDataURL ( file ) ;
76- } ) ;
77- }
78-
79- /**
80- * Generate a thumbnail data URL from a video file by capturing the first frame.
81- * Returns undefined if thumbnail generation fails.
82- */
83- export function generateVideoThumbnail (
84- file : File ,
85- ) : Promise < string | undefined > {
86- return new Promise ( ( resolve ) => {
87- let resolved = false ;
88- const video = document . createElement ( "video" ) ;
89- const canvas = document . createElement ( "canvas" ) ;
90- const url = URL . createObjectURL ( file ) ;
91-
92- const cleanup = ( result : string | undefined ) => {
93- if ( resolved ) return ;
94- resolved = true ;
95- URL . revokeObjectURL ( url ) ;
96- resolve ( result ) ;
97- } ;
98-
99- const timeout = setTimeout ( ( ) => {
100- console . warn (
101- `[CopilotKit] generateVideoThumbnail: timed out for file "${ file . name } "` ,
102- ) ;
103- cleanup ( undefined ) ;
104- } , 10000 ) ;
105-
106- video . preload = "metadata" ;
107- video . muted = true ;
108- video . playsInline = true ;
109-
110- video . onloadeddata = ( ) => {
111- video . currentTime = 0.1 ;
112- } ;
113-
114- video . onseeked = ( ) => {
115- clearTimeout ( timeout ) ;
116- canvas . width = video . videoWidth ;
117- canvas . height = video . videoHeight ;
118- const ctx = canvas . getContext ( "2d" ) ;
119- if ( ctx ) {
120- ctx . drawImage ( video , 0 , 0 ) ;
121- const thumbnail = canvas . toDataURL ( "image/jpeg" , 0.7 ) ;
122- cleanup ( thumbnail ) ;
123- } else {
124- console . warn (
125- "[CopilotKit] generateVideoThumbnail: could not get 2d canvas context" ,
126- ) ;
127- cleanup ( undefined ) ;
128- }
129- } ;
130-
131- video . onerror = ( ) => {
132- clearTimeout ( timeout ) ;
133- console . warn (
134- `[CopilotKit] generateVideoThumbnail: video element error for file "${ file . name } "` ,
135- ) ;
136- cleanup ( undefined ) ;
137- } ;
138-
139- video . src = url ;
140- } ) ;
141- }
142-
143- /**
144- * Check if a file's MIME type matches an accept filter string.
145- * Handles wildcards like "image/*" and comma-separated lists.
146- */
147- export function matchesAcceptFilter ( file : File , accept : string ) : boolean {
148- if ( ! accept || accept === "*/*" ) return true ;
149-
150- const filters = accept . split ( "," ) . map ( ( f ) => f . trim ( ) ) ;
151- return filters . some ( ( filter ) => {
152- if ( filter . endsWith ( "/*" ) ) {
153- const prefix = filter . slice ( 0 , - 2 ) ;
154- return file . type . startsWith ( prefix + "/" ) ;
155- }
156- return file . type === filter ;
157- } ) ;
158- }
0 commit comments