Handle possible token expired errors

Signed-off-by: Tao He <sighingnow@gmail.com>
pull/431/head
Tao He 2023-03-04 21:27:37 +08:00
rodzic f27568b65b
commit 452a61eb1b
2 zmienionych plików z 36 dodań i 5 usunięć

Wyświetl plik

@ -219,8 +219,11 @@ export class ChatGPTUnofficialProxyAPI {
}
} catch (err) {
// ignore for now; there seem to be some non-json messages
// console.warn('fetchSSE onMessage unexpected error', err)
reject(err)
}
},
onError: (err) => {
reject(err)
}
},
this._fetch

Wyświetl plik

@ -6,10 +6,13 @@ import { streamAsyncIterable } from './stream-async-iterable'
export async function fetchSSE(
url: string,
options: Parameters<typeof fetch>[1] & { onMessage: (data: string) => void },
options: Parameters<typeof fetch>[1] & {
onMessage: (data: string) => void
onError?: (error: any) => void
},
fetch: types.FetchFn = globalFetch
) {
const { onMessage, ...fetchOptions } = options
const { onMessage, onError, ...fetchOptions } = options
const res = await fetch(url, fetchOptions)
if (!res.ok) {
let reason: string
@ -33,6 +36,31 @@ export async function fetchSSE(
}
})
// check if the response is an error, if so, throw it
const feed = (chunk: string) => {
let response = null
try {
response = JSON.parse(chunk)
} catch {
/// ignore
}
if (response?.detail) {
if (response.detail.type === 'invalid_request_error') {
const msg = `ChatGPT error ${response.detail.message}: ${response.detail.code} (${response.detail.type})`
const error = new types.ChatGPTError(msg, { cause: response })
error.statusCode = response.detail.code
error.statusText = response.detail.message
if (onError) {
onError(error)
} else {
console.error(error)
}
return // don't feed to event parser
}
}
parser.feed(chunk)
}
if (!res.body.getReader) {
// Vercel polyfills `fetch` with `node-fetch`, which doesn't conform to
// web standards, so this is a workaround...
@ -45,13 +73,13 @@ export async function fetchSSE(
body.on('readable', () => {
let chunk: string | Buffer
while (null !== (chunk = body.read())) {
parser.feed(chunk.toString())
feed(chunk.toString())
}
})
} else {
for await (const chunk of streamAsyncIterable(res.body)) {
const str = new TextDecoder().decode(chunk)
parser.feed(str)
feed(str)
}
}
}