(
request: () => Promise<T>,
opts?: { also403Revoked?: boolean },
)
| 141 | * revoked" body (some endpoints signal revocation this way instead of 401). |
| 142 | */ |
| 143 | export async function withOAuth401Retry<T>( |
| 144 | request: () => Promise<T>, |
| 145 | opts?: { also403Revoked?: boolean }, |
| 146 | ): Promise<T> { |
| 147 | try { |
| 148 | return await request() |
| 149 | } catch (err) { |
| 150 | if (!axios.isAxiosError(err)) throw err |
| 151 | const status = err.response?.status |
| 152 | const isAuthError = |
| 153 | status === 401 || |
| 154 | (opts?.also403Revoked && |
| 155 | status === 403 && |
| 156 | typeof err.response?.data === 'string' && |
| 157 | err.response.data.includes('OAuth token has been revoked')) |
| 158 | if (!isAuthError) throw err |
| 159 | const failedAccessToken = getClaudeAIOAuthTokens()?.accessToken |
| 160 | if (!failedAccessToken) throw err |
| 161 | await handleOAuth401Error(failedAccessToken) |
| 162 | return await request() |
| 163 | } |
| 164 | } |
no test coverage detected