@@ -6,10 +6,13 @@ import { streamAsyncIterable } from './stream-async-iterable'
6
6
7
7
export async function fetchSSE (
8
8
url : string ,
9
- options : Parameters < typeof fetch > [ 1 ] & { onMessage : ( data : string ) => void } ,
9
+ options : Parameters < typeof fetch > [ 1 ] & {
10
+ onMessage : ( data : string ) => void
11
+ onError ?: ( error : any ) => void
12
+ } ,
10
13
fetch : types . FetchFn = globalFetch
11
14
) {
12
- const { onMessage, ...fetchOptions } = options
15
+ const { onMessage, onError , ...fetchOptions } = options
13
16
const res = await fetch ( url , fetchOptions )
14
17
if ( ! res . ok ) {
15
18
let reason : string
@@ -33,6 +36,31 @@ export async function fetchSSE(
33
36
}
34
37
} )
35
38
39
+ // check if the response is an error, if so, throw it
40
+ const feed = ( chunk : string ) => {
41
+ let response = null
42
+ try {
43
+ response = JSON . parse ( chunk )
44
+ } catch {
45
+ /// ignore
46
+ }
47
+ if ( response ?. detail ) {
48
+ if ( response . detail . type === 'invalid_request_error' ) {
49
+ const msg = `ChatGPT error ${ response . detail . message } : ${ response . detail . code } (${ response . detail . type } )`
50
+ const error = new types . ChatGPTError ( msg , { cause : response } )
51
+ error . statusCode = response . detail . code
52
+ error . statusText = response . detail . message
53
+ if ( onError ) {
54
+ onError ( error )
55
+ } else {
56
+ console . error ( error )
57
+ }
58
+ return // don't feed to event parser
59
+ }
60
+ }
61
+ parser . feed ( chunk )
62
+ }
63
+
36
64
if ( ! res . body . getReader ) {
37
65
// Vercel polyfills `fetch` with `node-fetch`, which doesn't conform to
38
66
// web standards, so this is a workaround...
@@ -45,13 +73,13 @@ export async function fetchSSE(
45
73
body . on ( 'readable' , ( ) => {
46
74
let chunk : string | Buffer
47
75
while ( null !== ( chunk = body . read ( ) ) ) {
48
- parser . feed ( chunk . toString ( ) )
76
+ feed ( chunk . toString ( ) )
49
77
}
50
78
} )
51
79
} else {
52
80
for await ( const chunk of streamAsyncIterable ( res . body ) ) {
53
81
const str = new TextDecoder ( ) . decode ( chunk )
54
- parser . feed ( str )
82
+ feed ( str )
55
83
}
56
84
}
57
85
}
0 commit comments