( failedAccessToken: string, )
| 1459 | } |
| 1460 | |
| 1461 | async function handleOAuth401ErrorImpl( |
| 1462 | failedAccessToken: string, |
| 1463 | ): Promise<boolean> { |
| 1464 | // Clear caches and re-read from keychain (async — sync read blocks ~100ms/call) |
| 1465 | clearOAuthTokenCache() |
| 1466 | const currentTokens = await getClaudeAIOAuthTokensAsync() |
| 1467 | |
| 1468 | if (!currentTokens?.refreshToken) { |
| 1469 | return false |
| 1470 | } |
| 1471 | |
| 1472 | // If keychain has a different token, another tab already refreshed - use it |
| 1473 | if (currentTokens.accessToken !== failedAccessToken) { |
| 1474 | logEvent('ncode_oauth_401_recovered_from_keychain', {}) |
| 1475 | return true |
| 1476 | } |
| 1477 | |
| 1478 | // Same token that failed - force refresh, bypassing local expiration check |
| 1479 | return checkAndRefreshOAuthTokenIfNeeded(0, true) |
| 1480 | } |
| 1481 | |
| 1482 | /** |
| 1483 | * Reads OAuth tokens asynchronously, avoiding blocking keychain reads. |
no test coverage detected