From db4fddb2dcb02a800287479f4c914bd096dfd2a6 Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 20 Sep 2026 04:29:04 -0700 Subject: [PATCH] feat(antigravity): expose native accounts to desktop IPC --- .../register-core-handlers.ts | 16 ++++++++++++++-- .../startup/main-process-account-services.ts | 17 +++++++++++++++++ src/main/startup/main-process-state.ts | 2 ++ src/main/startup/main-window-core-services.ts | 3 ++- src/preload/api-types.ts | 2 ++ src/preload/api/agent-account-api.ts | 19 +++++++++++++++++++ .../api/antigravity-accounts-bridge.ts | 9 +++++++++ src/preload/index.ts | 2 ++ .../web/preload-api/web-agent-accounts-api.ts | 12 ++++++++++++ src/renderer/src/web/web-preload-api.ts | 2 ++ 10 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/preload/api/antigravity-accounts-bridge.ts diff --git a/src/main/ipc/register-core-handlers/register-core-handlers.ts b/src/main/ipc/register-core-handlers/register-core-handlers.ts index cb08d7a511f..b05d1d505f6 100644 --- a/src/main/ipc/register-core-handlers/register-core-handlers.ts +++ b/src/main/ipc/register-core-handlers/register-core-handlers.ts @@ -1,4 +1,4 @@ -import { app } from 'electron' +import { app, ipcMain } from 'electron' import { registerAppHandlers } from '../app' import { registerCliHandlers } from '../cli' import { registerPreflightHandlers } from '../preflight' @@ -76,6 +76,7 @@ import type { OpenCodeUsageStore } from '../../opencode-usage/store' import type { RateLimitService } from '../../rate-limits/service' import type { CodexAccountService } from '../../codex-accounts/service' import type { ClaudeAccountService } from '../../claude-accounts/service' +import type { AntigravityAccountService } from '../../antigravity/native-account-service' import type { AutomationService } from '../../automations/service' import type { AgentAwakeService } from '../../agent-awake-service' import type { CrashReportStore } from '../../crash-reporting/crash-report-store' @@ -124,7 +125,8 @@ export function registerCoreHandlers( keybindings?: KeybindingService, lifecycleOptions: CoreHandlerLifecycleOptions = {}, pluginService?: PluginService, - marketplaceServices?: PluginMarketplaceHandlerServices + marketplaceServices?: PluginMarketplaceHandlerServices, + antigravityAccounts?: AntigravityAccountService ): void { // Why: on macOS the app can stay alive after all windows close, then // openMainWindow() is called again on 'activate'. ipcMain.handle() throws @@ -148,6 +150,16 @@ export function registerCoreHandlers( registerCodexConfigSyncHandlers(codexAccounts.runtimeHomeService) registerAgentTrustHandlers() registerClaudeAccountHandlers(claudeAccounts) + if (antigravityAccounts) { + ipcMain.handle('antigravityAccounts:list', () => antigravityAccounts.listAccounts()) + ipcMain.handle('antigravityAccounts:add', () => antigravityAccounts.addCurrentAccount()) + ipcMain.handle('antigravityAccounts:select', (_event, args: { accountId: string }) => + antigravityAccounts.selectAccount(args.accountId) + ) + ipcMain.handle('antigravityAccounts:remove', (_event, args: { accountId: string }) => + antigravityAccounts.removeAccount(args.accountId) + ) + } registerMiniMaxCredentialsHandlers(rateLimits) registerGrokAccountHandlers() registerRateLimitHandlers(rateLimits, codexAccounts) diff --git a/src/main/startup/main-process-account-services.ts b/src/main/startup/main-process-account-services.ts index 2d3c8be1b1e..a1a1c4b8410 100644 --- a/src/main/startup/main-process-account-services.ts +++ b/src/main/startup/main-process-account-services.ts @@ -1,4 +1,5 @@ import { app } from 'electron' +import { join } from 'node:path' import { RateLimitService } from '../rate-limits/service' import { CodexRuntimeHomeService } from '../codex-accounts/runtime-home-service' import { CodexAccountService } from '../codex-accounts/service' @@ -24,6 +25,14 @@ import { setSystemCodexHomeHookSweepSuppressed } from '../codex/hook-service' import { isRealHomeCodexHookLaneUsable } from '../codex/codex-real-home-hook-install' import { resolveHostCodexSessionSourceHome } from '../codex/codex-session-source-home' import { browserManager } from '../browser/browser-manager' +import { + AntigravityAccountService, + createEncryptedAntigravityAccountStore +} from '../antigravity/native-account-service' +import { + readAntigravityMacOSCredential, + writeAntigravityMacOSCredential +} from '../antigravity/native-macos-credentials' import { mainProcessState as state } from './main-process-state' export function initializeMainProcessAccountServices(): void { @@ -67,6 +76,14 @@ export function initializeMainProcessAccountServices(): void { state.codexSessionMigration.scheduleInitialRun() state.claudeRuntimeAuth = new ClaudeRuntimeAuthService(store) state.claudeAccounts = new ClaudeAccountService(store, state.rateLimits, state.claudeRuntimeAuth) + if (process.platform === 'darwin') { + state.antigravityAccounts = new AntigravityAccountService( + createEncryptedAntigravityAccountStore( + join(app.getPath('userData'), 'antigravity-accounts.bin') + ), + { read: readAntigravityMacOSCredential, write: writeAntigravityMacOSCredential } + ) + } state.rateLimits.setCodexHomePathResolver((target) => state.codexRuntimeHome!.prepareForRateLimitFetch(target) ) diff --git a/src/main/startup/main-process-state.ts b/src/main/startup/main-process-state.ts index 2b9361a6d51..7d5d0394fa1 100644 --- a/src/main/startup/main-process-state.ts +++ b/src/main/startup/main-process-state.ts @@ -8,6 +8,7 @@ import type { OpenCodeUsageStore } from '../opencode-usage/store' import type { CodexAccountService } from '../codex-accounts/service' import type { CodexRuntimeHomeService } from '../codex-accounts/runtime-home-service' import type { ClaudeAccountService } from '../claude-accounts/service' +import type { AntigravityAccountService } from '../antigravity/native-account-service' import type { ClaudeRuntimeAuthService } from '../claude-accounts/runtime-auth-service' import type { OrcaRuntimeService } from '../runtime/orca-runtime' import type { RateLimitService } from '../rate-limits/service' @@ -59,6 +60,7 @@ export const mainProcessState = { codexRuntimeHome: null as CodexRuntimeHomeService | null, codexSessionMigration: null as ReturnType | null, claudeAccounts: null as ClaudeAccountService | null, + antigravityAccounts: null as AntigravityAccountService | null, claudeRuntimeAuth: null as ClaudeRuntimeAuthService | null, runtime: null as OrcaRuntimeService | null, rateLimits: null as RateLimitService | null, diff --git a/src/main/startup/main-window-core-services.ts b/src/main/startup/main-window-core-services.ts index d3ece383ee3..03d92db32c2 100644 --- a/src/main/startup/main-window-core-services.ts +++ b/src/main/startup/main-window-core-services.ts @@ -99,7 +99,8 @@ export function attachMainWindowCoreServices( state.pluginService ?? undefined, state.pluginMarketplaceService && state.pluginMarketplaceInstaller ? { marketplace: state.pluginMarketplaceService, installer: state.pluginMarketplaceInstaller } - : undefined + : undefined, + state.antigravityAccounts ?? undefined ) automations.setWebContents(window.webContents) automations.start() diff --git a/src/preload/api-types.ts b/src/preload/api-types.ts index 9a592ff264c..f6c276ad493 100644 --- a/src/preload/api-types.ts +++ b/src/preload/api-types.ts @@ -1,5 +1,6 @@ import type { ClaudeAccountsApi, + AntigravityAccountsApi, CodexAccountsApi, CodexConfigSyncApi, GrokAccountsApi, @@ -102,6 +103,7 @@ export type PreloadApi = { keybindings: KeybindingsApi codexAccounts: CodexAccountsApi claudeAccounts: ClaudeAccountsApi + antigravityAccounts: AntigravityAccountsApi cli: CliApi codexConfigSync: CodexConfigSyncApi agentTrust: AgentTrustApi diff --git a/src/preload/api/agent-account-api.ts b/src/preload/api/agent-account-api.ts index f041e41f8b7..b8c5a9e1421 100644 --- a/src/preload/api/agent-account-api.ts +++ b/src/preload/api/agent-account-api.ts @@ -58,6 +58,25 @@ export type ClaudeAccountsApi = { }) => Promise } +export type AntigravityAccountState = { + accounts: { + id: string + email: string | null + subject: string | null + authMethod: string + createdAt: number + updatedAt: number + }[] + activeAccountId: string | null +} + +export type AntigravityAccountsApi = { + list: () => Promise + add: () => Promise + select: (args: { accountId: string }) => Promise + remove: (args: { accountId: string }) => Promise +} + export type GrokAccountsApi = { getStatus: () => Promise } diff --git a/src/preload/api/antigravity-accounts-bridge.ts b/src/preload/api/antigravity-accounts-bridge.ts new file mode 100644 index 00000000000..ef705a93feb --- /dev/null +++ b/src/preload/api/antigravity-accounts-bridge.ts @@ -0,0 +1,9 @@ +import { ipcRenderer } from 'electron' +import type { PreloadApi } from '../api-types' + +export const antigravityAccountsApi: PreloadApi['antigravityAccounts'] = { + list: () => ipcRenderer.invoke('antigravityAccounts:list'), + add: () => ipcRenderer.invoke('antigravityAccounts:add'), + select: (args) => ipcRenderer.invoke('antigravityAccounts:select', args), + remove: (args) => ipcRenderer.invoke('antigravityAccounts:remove', args) +} diff --git a/src/preload/index.ts b/src/preload/index.ts index f7bb5a30bcc..e03b3a035c4 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -38,6 +38,7 @@ import { localhostWorktreeLabelsApi } from './api/localhost-worktree-labels-brid import { keybindingsApi } from './api/keybindings-bridge' import { codexAccountsApi } from './api/codex-accounts-bridge' import { claudeAccountsApi } from './api/claude-accounts-bridge' +import { antigravityAccountsApi } from './api/antigravity-accounts-bridge' import { cliApi } from './api/cli-bridge' import { codexConfigSyncApi } from './api/codex-config-sync-bridge' import { agentTrustApi } from './api/agent-trust-bridge' @@ -136,6 +137,7 @@ const api = { keybindings: keybindingsApi, codexAccounts: codexAccountsApi, claudeAccounts: claudeAccountsApi, + antigravityAccounts: antigravityAccountsApi, cli: cliApi, codexConfigSync: codexConfigSyncApi, agentTrust: agentTrustApi, diff --git a/src/renderer/src/web/preload-api/web-agent-accounts-api.ts b/src/renderer/src/web/preload-api/web-agent-accounts-api.ts index 8738039de61..e49ce92bb09 100644 --- a/src/renderer/src/web/preload-api/web-agent-accounts-api.ts +++ b/src/renderer/src/web/preload-api/web-agent-accounts-api.ts @@ -51,6 +51,18 @@ export function createClaudeAccountsApi(): PreloadApi['claudeAccounts'] { } } +export function createAntigravityAccountsApi(): PreloadApi['antigravityAccounts'] { + const empty = { accounts: [], activeAccountId: null } + const unsupported = () => + Promise.reject(new Error('Antigravity account storage is only available in the desktop app.')) + return { + list: () => Promise.resolve(empty), + add: unsupported, + select: unsupported, + remove: unsupported + } +} + export function createCodexAccountsApi(): PreloadApi['codexAccounts'] { const empty = createEmptyManagedAccountsState() return { diff --git a/src/renderer/src/web/web-preload-api.ts b/src/renderer/src/web/web-preload-api.ts index 0f6848a1827..0b951986f11 100644 --- a/src/renderer/src/web/web-preload-api.ts +++ b/src/renderer/src/web/web-preload-api.ts @@ -3,6 +3,7 @@ import type { StatsSummary } from '../../../shared/process-stats-types' import { createWebE2EApi } from './preload-api/web-e2e-api' import { createClaudeAccountsApi, + createAntigravityAccountsApi, createCodexAccountsApi, createGrokAccountsApi, createMiniMaxCredentialsApi @@ -109,6 +110,7 @@ function createWebPreloadApi(): Partial { grokAccounts: createGrokAccountsApi(), codexAccounts: createCodexAccountsApi(), claudeAccounts: createClaudeAccountsApi(), + antigravityAccounts: createAntigravityAccountsApi(), cli: createCliApi(), macosTccPrompts: createMacosTccPromptsApi(), codexConfigSync: {