({
accessToken,
refreshToken,
idToken = null,
accountId = null,
email = null,
authMode = 'chatgpt',
now = Date.now(),
authPath = resolveCodexAuthPath(),
}: WriteCodexAuthOptions)
| 153 | } |
| 154 | |
| 155 | export async function writeCodexAuthFile({ |
| 156 | accessToken, |
| 157 | refreshToken, |
| 158 | idToken = null, |
| 159 | accountId = null, |
| 160 | email = null, |
| 161 | authMode = 'chatgpt', |
| 162 | now = Date.now(), |
| 163 | authPath = resolveCodexAuthPath(), |
| 164 | }: WriteCodexAuthOptions): Promise<string> { |
| 165 | const existing = readJsonObject(authPath) ?? {}; |
| 166 | const existingTokens = isRecord(existing.tokens) ? existing.tokens : {}; |
| 167 | const normalizedAccountId = firstString( |
| 168 | accountId, |
| 169 | existingTokens.account_id, |
| 170 | existing.account_id, |
| 171 | ); |
| 172 | const normalizedEmail = firstString(email, existing.email); |
| 173 | const next = { |
| 174 | ...existing, |
| 175 | auth_mode: firstString(authMode, existing.auth_mode) ?? 'chatgpt', |
| 176 | account_id: normalizedAccountId, |
| 177 | email: normalizedEmail, |
| 178 | OPENAI_API_KEY: Object.prototype.hasOwnProperty.call(existing, 'OPENAI_API_KEY') |
| 179 | ? existing.OPENAI_API_KEY |
| 180 | : null, |
| 181 | last_refresh: new Date(now).toISOString(), |
| 182 | tokens: { |
| 183 | ...existingTokens, |
| 184 | id_token: firstString(idToken, accessToken), |
| 185 | access_token: accessToken, |
| 186 | refresh_token: refreshToken, |
| 187 | account_id: normalizedAccountId, |
| 188 | }, |
| 189 | }; |
| 190 | await writeJsonAtomic(authPath, next); |
| 191 | return authPath; |
| 192 | } |
| 193 | |
| 194 | export function decodeJwtPayload(token: string | null | undefined): Record<string, any> | null { |
| 195 | if (!token) { |
no test coverage detected