feat(antigravity): expose native accounts to desktop IPC

This commit is contained in:
Neil
2026-09-20 04:29:04 -07:00
parent fdc1ddd849
commit db4fddb2dc
10 changed files with 81 additions and 3 deletions
@@ -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)
@@ -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)
)
+2
View File
@@ -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<typeof createCodexSessionMigrationScheduler> | 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,
@@ -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()
+2
View File
@@ -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
+19
View File
@@ -58,6 +58,25 @@ export type ClaudeAccountsApi = {
}) => Promise<ClaudeRateLimitAccountsState>
}
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<AntigravityAccountState>
add: () => Promise<AntigravityAccountState>
select: (args: { accountId: string }) => Promise<AntigravityAccountState>
remove: (args: { accountId: string }) => Promise<AntigravityAccountState>
}
export type GrokAccountsApi = {
getStatus: () => Promise<GrokAccountStatus>
}
@@ -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)
}
+2
View File
@@ -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,
@@ -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 {
+2
View File
@@ -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<PreloadApi> {
grokAccounts: createGrokAccountsApi(),
codexAccounts: createCodexAccountsApi(),
claudeAccounts: createClaudeAccountsApi(),
antigravityAccounts: createAntigravityAccountsApi(),
cli: createCliApi(),
macosTccPrompts: createMacosTccPromptsApi(),
codexConfigSync: {