feat(dashboard): add project_id display for Antigravity accounts

Display GCP project_id for Antigravity (agy) accounts in the Dashboard:

- Add projectId field to AccountInfo interface (account-manager.ts)
- Read project_id from auth files when discovering/registering accounts
- Pass projectId through token-manager when registering new accounts
- Add projectId to OAuthAccount type (api-client.ts)
- Add projectId to AccountRow type (auth-monitor/types.ts)
- Display project_id in account-item.tsx with FolderCode icon
- Show N/A warning with amber tooltip if project_id is missing
  suggesting user remove and re-add account to fetch it

Note: project_id is read-only and respects privacy mode blur.
This commit is contained in:
kaitranntt
2026-01-15 10:49:23 -05:00
parent 3de894784f
commit ed2ce138e4
6 changed files with 77 additions and 4 deletions
+20 -3
View File
@@ -47,6 +47,8 @@ export interface AccountInfo {
pausedAt?: string;
/** Account tier: free or paid (Pro/Ultra combined) */
tier?: AccountTier;
/** GCP Project ID (Antigravity only) - read-only, fetched from auth token */
projectId?: string;
}
/** Provider accounts configuration */
@@ -293,7 +295,8 @@ export function registerAccount(
provider: CLIProxyProvider,
tokenFile: string,
email?: string,
nickname?: string
nickname?: string,
projectId?: string
): AccountInfo {
const registry = loadAccountsRegistry();
@@ -350,7 +353,7 @@ export function registerAccount(
const isFirstAccount = Object.keys(providerAccounts.accounts).length === 0;
// Create or update account
providerAccounts.accounts[accountId] = {
const accountMeta: Omit<AccountInfo, 'id' | 'provider' | 'isDefault'> = {
email,
nickname: accountNickname,
tokenFile,
@@ -358,6 +361,13 @@ export function registerAccount(
lastUsedAt: new Date().toISOString(),
};
// Include projectId for Antigravity accounts
if (provider === 'agy' && projectId) {
accountMeta.projectId = projectId;
}
providerAccounts.accounts[accountId] = accountMeta;
// Set as default if first account
if (isFirstAccount) {
providerAccounts.default = accountId;
@@ -671,13 +681,20 @@ export function discoverExistingAccounts(): void {
// Register account with auto-generated nickname
// Use mtime as lastUsedAt (when token was last modified = last auth/refresh)
const lastModified = stats.mtime || stats.birthtime || new Date();
providerAccounts.accounts[accountId] = {
const accountMeta: Omit<AccountInfo, 'id' | 'provider' | 'isDefault'> = {
email,
nickname: generateNickname(email),
tokenFile: file,
createdAt: stats.birthtime?.toISOString() || new Date().toISOString(),
lastUsedAt: lastModified.toISOString(),
};
// Read project_id for Antigravity accounts (read-only field from auth token)
if (provider === 'agy' && data.project_id) {
accountMeta.projectId = data.project_id;
}
providerAccounts.accounts[accountId] = accountMeta;
} catch {
// Skip invalid files
continue;
+8 -1
View File
@@ -229,8 +229,15 @@ export function registerAccountFromToken(
const content = fs.readFileSync(tokenPath, 'utf-8');
const data = JSON.parse(content);
const email = data.email || undefined;
const projectId = data.project_id || undefined;
return registerAccount(provider, newestFile, email, nickname || generateNickname(email));
return registerAccount(
provider,
newestFile,
email,
nickname || generateNickname(email),
projectId
);
} catch {
return null;
}