From 8f12e8a114546326ee5b39d6aae859da6d906d0b Mon Sep 17 00:00:00 2001 From: Gaurav <39389231+gsquared94@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:57:35 -0700 Subject: fix: clearcut logging (retry #3744) (#3751) --- packages/core/src/utils/user_account.ts | 115 ++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 packages/core/src/utils/user_account.ts (limited to 'packages/core/src/utils/user_account.ts') diff --git a/packages/core/src/utils/user_account.ts b/packages/core/src/utils/user_account.ts new file mode 100644 index 00000000..6701dfe3 --- /dev/null +++ b/packages/core/src/utils/user_account.ts @@ -0,0 +1,115 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import path from 'node:path'; +import { promises as fsp, existsSync, readFileSync } from 'node:fs'; +import * as os from 'os'; +import { GEMINI_DIR, GOOGLE_ACCOUNTS_FILENAME } from './paths.js'; + +interface UserAccounts { + active: string | null; + old: string[]; +} + +function getGoogleAccountsCachePath(): string { + return path.join(os.homedir(), GEMINI_DIR, GOOGLE_ACCOUNTS_FILENAME); +} + +async function readAccounts(filePath: string): Promise { + try { + const content = await fsp.readFile(filePath, 'utf-8'); + if (!content.trim()) { + return { active: null, old: [] }; + } + return JSON.parse(content) as UserAccounts; + } catch (error) { + if (error instanceof Error && 'code' in error && error.code === 'ENOENT') { + // File doesn't exist, which is fine. + return { active: null, old: [] }; + } + // File is corrupted or not valid JSON, start with a fresh object. + console.debug('Could not parse accounts file, starting fresh.', error); + return { active: null, old: [] }; + } +} + +export async function cacheGoogleAccount(email: string): Promise { + const filePath = getGoogleAccountsCachePath(); + await fsp.mkdir(path.dirname(filePath), { recursive: true }); + + const accounts = await readAccounts(filePath); + + if (accounts.active && accounts.active !== email) { + if (!accounts.old.includes(accounts.active)) { + accounts.old.push(accounts.active); + } + } + + // If the new email was in the old list, remove it + accounts.old = accounts.old.filter((oldEmail) => oldEmail !== email); + + accounts.active = email; + await fsp.writeFile(filePath, JSON.stringify(accounts, null, 2), 'utf-8'); +} + +export function getCachedGoogleAccount(): string | null { + try { + const filePath = getGoogleAccountsCachePath(); + if (existsSync(filePath)) { + const content = readFileSync(filePath, 'utf-8').trim(); + if (!content) { + return null; + } + const accounts: UserAccounts = JSON.parse(content); + return accounts.active; + } + return null; + } catch (error) { + console.debug('Error reading cached Google Account:', error); + return null; + } +} + +export function getLifetimeGoogleAccounts(): number { + try { + const filePath = getGoogleAccountsCachePath(); + if (!existsSync(filePath)) { + return 0; + } + + const content = readFileSync(filePath, 'utf-8').trim(); + if (!content) { + return 0; + } + const accounts: UserAccounts = JSON.parse(content); + let count = accounts.old.length; + if (accounts.active) { + count++; + } + return count; + } catch (error) { + console.debug('Error reading lifetime Google Accounts:', error); + return 0; + } +} + +export async function clearCachedGoogleAccount(): Promise { + const filePath = getGoogleAccountsCachePath(); + if (!existsSync(filePath)) { + return; + } + + const accounts = await readAccounts(filePath); + + if (accounts.active) { + if (!accounts.old.includes(accounts.active)) { + accounts.old.push(accounts.active); + } + accounts.active = null; + } + + await fsp.writeFile(filePath, JSON.stringify(accounts, null, 2), 'utf-8'); +} -- cgit v1.2.3