(
request: () => Promise<T>,
opts?: { also403Revoked?: boolean },
)
| 113 | * revoked" body (some endpoints signal revocation this way instead of 401). |
| 114 | */ |
| 115 | export async function withOAuth401Retry<T>( |
| 116 | request: () => Promise<T>, |
| 117 | opts?: { also403Revoked?: boolean }, |
| 118 | ): Promise<T> { |
| 119 | try { |
| 120 | return await request() |
| 121 | } catch (err) { |
| 122 | if (!axios.isAxiosError(err)) throw err |
| 123 | const status = err.response?.status |
| 124 | const isAuthError = |
| 125 | status === 401 || |
| 126 | (opts?.also403Revoked && |
| 127 | status === 403 && |
| 128 | typeof err.response?.data === 'string' && |
| 129 | err.response.data.includes('OAuth token has been revoked')) |
| 130 | if (!isAuthError) throw err |
| 131 | const failedAccessToken = getClaudeAIOAuthTokens()?.accessToken |
| 132 | if (!failedAccessToken) throw err |
| 133 | await handleOAuth401Error(failedAccessToken) |
| 134 | return await request() |
| 135 | } |
| 136 | } |
| 137 |
no test coverage detected