@@ -10,6 +10,7 @@ import {
10
10
useContext ,
11
11
} from "react" ;
12
12
import { toast } from "sonner" ;
13
+ import { getErrorMessage } from "@/lib/error-utils" ;
13
14
14
15
interface Message {
15
16
id : number ;
@@ -34,6 +35,22 @@ interface StatusChangeEvent {
34
35
status : string ;
35
36
}
36
37
38
+ interface APIErrorDetail {
39
+ location : string ;
40
+ message : string ;
41
+ value : null | string | number | boolean | object ;
42
+ }
43
+
44
+ interface APIErrorModel {
45
+ $schema : string ;
46
+ detail : string ;
47
+ errors : APIErrorDetail [ ] ;
48
+ instance : string ;
49
+ status : number ;
50
+ title : string ;
51
+ type : string ;
52
+ }
53
+
37
54
function isDraftMessage ( message : Message | DraftMessage ) : boolean {
38
55
return message . id === undefined ;
39
56
}
@@ -42,11 +59,17 @@ type MessageType = "user" | "raw";
42
59
43
60
export type ServerStatus = "stable" | "running" | "offline" | "unknown" ;
44
61
62
+ export interface FileUploadResponse {
63
+ ok : boolean ;
64
+ filePath ?: string ;
65
+ }
66
+
45
67
interface ChatContextValue {
46
68
messages : ( Message | DraftMessage ) [ ] ;
47
69
loading : boolean ;
48
70
serverStatus : ServerStatus ;
49
71
sendMessage : ( message : string , type ?: MessageType ) => void ;
72
+ uploadFiles : ( formData : FormData ) => Promise < FileUploadResponse > ;
50
73
}
51
74
52
75
const ChatContext = createContext < ChatContextValue | undefined > ( undefined ) ;
@@ -229,34 +252,27 @@ export function ChatProvider({ children }: PropsWithChildren) {
229
252
} ) ;
230
253
231
254
if ( ! response . ok ) {
232
- const errorData = await response . json ( ) ;
255
+ const errorData = await response . json ( ) as APIErrorModel ;
233
256
console . error ( "Failed to send message:" , errorData ) ;
234
257
const detail = errorData . detail ;
235
258
const messages =
236
259
"errors" in errorData
237
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
- errorData . errors . map ( ( e : any ) => e . message ) . join ( ", " )
260
+ ?
261
+ errorData . errors . map ( ( e : APIErrorDetail ) => e . message ) . join ( ", " )
239
262
: "" ;
240
263
241
264
const fullDetail = `${ detail } : ${ messages } ` ;
242
265
toast . error ( `Failed to send message` , {
243
266
description : fullDetail ,
244
267
} ) ;
245
268
}
246
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
247
- } catch ( error : any ) {
248
- console . error ( "Error sending message:" , error ) ;
249
- const detail = error . detail ;
250
- const messages =
251
- "errors" in error
252
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
253
- error . errors . map ( ( e : any ) => e . message ) . join ( "\n" )
254
- : "" ;
255
269
256
- const fullDetail = `${ detail } : ${ messages } ` ;
270
+ } catch ( error ) {
271
+ console . error ( "Error sending message:" , error ) ;
272
+ const message = getErrorMessage ( error )
257
273
258
274
toast . error ( `Error sending message` , {
259
- description : fullDetail ,
275
+ description : message ,
260
276
} ) ;
261
277
} finally {
262
278
if ( type === "user" ) {
@@ -268,13 +284,54 @@ export function ChatProvider({ children }: PropsWithChildren) {
268
284
}
269
285
} ;
270
286
287
+ // Upload files to workspace
288
+ const uploadFiles = async ( formData : FormData ) : Promise < FileUploadResponse > => {
289
+ let result : FileUploadResponse = { ok : true } ;
290
+ try {
291
+ const response = await fetch ( `${ agentAPIUrl } /upload` , {
292
+ method : 'POST' ,
293
+ body : formData ,
294
+ } ) ;
295
+
296
+ if ( ! response . ok ) {
297
+ result . ok = false ;
298
+ const errorData = await response . json ( ) as APIErrorModel ;
299
+ console . error ( "Failed to send message:" , errorData ) ;
300
+ const detail = errorData . detail ;
301
+ const messages =
302
+ "errors" in errorData
303
+ ?
304
+ errorData . errors . map ( ( e : APIErrorDetail ) => e . message ) . join ( ", " )
305
+ : "" ;
306
+
307
+ const fullDetail = `${ detail } : ${ messages } ` ;
308
+ toast . error ( `Failed to upload files` , {
309
+ description : fullDetail ,
310
+ } ) ;
311
+ } else {
312
+ result = ( await response . json ( ) ) as FileUploadResponse ;
313
+ }
314
+
315
+ } catch ( error ) {
316
+ result . ok = false ;
317
+ console . error ( "Error uploading files:" , error ) ;
318
+ const message = getErrorMessage ( error )
319
+
320
+ toast . error ( `Error uploading files` , {
321
+ description : message ,
322
+ } ) ;
323
+ }
324
+ return result ;
325
+ }
326
+
271
327
return (
272
328
< ChatContext . Provider
273
329
value = { {
274
330
messages,
275
331
loading,
276
332
sendMessage,
277
333
serverStatus,
334
+ uploadFiles,
278
335
} }
279
336
>
280
337
{ children }
0 commit comments