feat: add ChatGPTError with more info on HTTP errors

pull/89/head
Travis Fischer 2022-12-10 16:19:35 -06:00
rodzic 8cc642e9bb
commit 90c6e3500f
4 zmienionych plików z 54 dodań i 12 usunięć

Wyświetl plik

@ -1,6 +1,7 @@
import test from 'ava'
import dotenv from 'dotenv-safe'
import * as types from './types'
import { ChatGPTAPI } from './chatgpt-api'
dotenv.config()
@ -20,6 +21,7 @@ test('ChatGPTAPI invalid session token', async (t) => {
await chatgpt.ensureAuth()
},
{
instanceOf: types.ChatGPTError,
message: 'ChatGPT failed to refresh auth token. Error: Unauthorized'
}
)
@ -64,6 +66,7 @@ if (!isCI) {
await chatgpt.ensureAuth()
},
{
instanceOf: types.ChatGPTError,
message:
'ChatGPT failed to refresh auth token. Error: session token may have expired'
}

Wyświetl plik

@ -1,5 +1,5 @@
import ExpiryMap from 'expiry-map'
import pTimeout, { TimeoutError } from 'p-timeout'
import pTimeout from 'p-timeout'
import { v4 as uuidv4 } from 'uuid'
import * as types from './types'
@ -68,7 +68,7 @@ export class ChatGPTAPI {
this._accessTokenCache = new ExpiryMap<string, string>(accessTokenTTL)
if (!this._sessionToken) {
throw new Error('ChatGPT invalid session token')
throw new types.ChatGPTError('ChatGPT invalid session token')
}
}
@ -238,6 +238,7 @@ export class ChatGPTAPI {
return cachedAccessToken
}
let response: Response
try {
const res = await fetch('https://chat.openai.com/api/auth/session', {
headers: {
@ -245,8 +246,14 @@ export class ChatGPTAPI {
'user-agent': this._userAgent
}
}).then((r) => {
response = r
if (!r.ok) {
throw new Error(`${r.status} ${r.statusText}`)
const error = new types.ChatGPTError(`${r.status} ${r.statusText}`)
error.response = r
error.statusCode = r.status
error.statusText = r.statusText
throw error
}
return r.json() as any as types.SessionResult
@ -255,22 +262,41 @@ export class ChatGPTAPI {
const accessToken = res?.accessToken
if (!accessToken) {
throw new Error('Unauthorized')
const error = new types.ChatGPTError('Unauthorized')
error.response = response
error.statusCode = response?.status
error.statusText = response?.statusText
throw error
}
const error = res?.error
if (error) {
if (error === 'RefreshAccessTokenError') {
throw new Error('session token may have expired')
const appError = res?.error
if (appError) {
if (appError === 'RefreshAccessTokenError') {
const error = new types.ChatGPTError('session token may have expired')
error.response = response
error.statusCode = response?.status
error.statusText = response?.statusText
throw error
} else {
throw new Error(error)
const error = new types.ChatGPTError(appError)
error.response = response
error.statusCode = response?.status
error.statusText = response?.statusText
throw error
}
}
this._accessTokenCache.set(KEY_ACCESS_TOKEN, accessToken)
return accessToken
} catch (err: any) {
throw new Error(`ChatGPT failed to refresh auth token. ${err.toString()}`)
const error = new types.ChatGPTError(
`ChatGPT failed to refresh auth token. ${err.toString()}`
)
error.response = response
error.statusCode = response?.status
error.statusText = response?.statusText
error.originalError = err
throw error
}
}

Wyświetl plik

@ -1,5 +1,6 @@
import { createParser } from 'eventsource-parser'
import * as types from './types'
import { fetch } from './fetch'
import { streamAsyncIterable } from './stream-async-iterable'
@ -10,7 +11,12 @@ export async function fetchSSE(
const { onMessage, ...fetchOptions } = options
const res = await fetch(url, fetchOptions)
if (!res.ok) {
throw new Error(`ChatGPTAPI error ${res.status || res.statusText}`)
const msg = `ChatGPTAPI error ${res.status || res.statusText}`
const error = new types.ChatGPTError(msg)
error.statusCode = res.status
error.statusText = res.statusText
error.response = res
throw error
}
const parser = createParser((event) => {
@ -25,7 +31,7 @@ export async function fetchSSE(
const body: NodeJS.ReadableStream = res.body as any
if (!body.on || !body.read) {
throw new Error('unsupported "fetch" implementation')
throw new types.ChatGPTError('unsupported "fetch" implementation')
}
body.on('readable', () => {

Wyświetl plik

@ -287,3 +287,10 @@ export type SendConversationMessageOptions = Omit<
SendMessageOptions,
'conversationId' | 'parentMessageId'
>
export class ChatGPTError extends Error {
statusCode?: number
statusText?: string
response?: Response
originalError?: Error
}