| 123 | } |
| 124 | |
| 125 | async function refreshAccessToken(refreshToken: string, issuer = ISSUER): Promise<TokenResponse> { |
| 126 | const response = await fetch(`${issuer}/oauth/token`, { |
| 127 | method: "POST", |
| 128 | headers: { "Content-Type": "application/x-www-form-urlencoded" }, |
| 129 | body: new URLSearchParams({ |
| 130 | grant_type: "refresh_token", |
| 131 | refresh_token: refreshToken, |
| 132 | client_id: CLIENT_ID, |
| 133 | }).toString(), |
| 134 | }) |
| 135 | if (!response.ok) { |
| 136 | throw new Error(`Token refresh failed: ${response.status}`) |
| 137 | } |
| 138 | return response.json() |
| 139 | } |
| 140 | |
| 141 | // Kept as a named export for plugin.codex tests; delegates to the shared branded page. |
| 142 | export const renderOAuthError = (error: string) => OauthCallbackPage.error(error, { provider: "ChatGPT" }) |