diff --git a/apps/desktop-tauri/src/i18n/keys.ts b/apps/desktop-tauri/src/i18n/keys.ts index 28811f426f..72c6057d57 100644 --- a/apps/desktop-tauri/src/i18n/keys.ts +++ b/apps/desktop-tauri/src/i18n/keys.ts @@ -293,6 +293,19 @@ export const ALL_LOCALE_KEYS = [ "ProviderClaudeDailyRoutinesUsageHelp", "ProviderCodexSparkUsage", "ProviderCodexSparkUsageHelp", + "CodexAccountsTitle", + "CodexAccountsHint", + "CodexAccountsAddButton", + "CodexAccountsSwitchButton", + "CodexAccountsFetchButton", + "CodexAccountsRemoveButton", + "CodexAccountsEmpty", + "CodexAccountsSourceAmbient", + "CodexAccountsSourceManaged", + "CodexAccountsUsageUnavailable", + "CodexSwitchSuccess", + "CodexSwitchRestartPrompt", + "CodexAccountsRestartDesktop", "ProviderCursorCookieSourceHelp", "ProviderCursorCreditsHelp", "AutoFallbackHelp", diff --git a/apps/desktop-tauri/src/lib/tauri.ts b/apps/desktop-tauri/src/lib/tauri.ts index 27051c75e5..b51844fb58 100644 --- a/apps/desktop-tauri/src/lib/tauri.ts +++ b/apps/desktop-tauri/src/lib/tauri.ts @@ -34,6 +34,10 @@ import type { TrayVisibilityStatusDto, UsageSpendSummary, CodexLocalProjectUsageSnapshot, + CodexAccount, + CodexAccountUsageSnapshot, + CodexAccountsStateBridge, + CodexSwitchResult, } from "../types/bridge"; export function getBootstrapState(): Promise { @@ -436,3 +440,51 @@ export function flyoutStoredSize(): Promise<[number, number] | null> { export function quitApp(): Promise { return invoke("quit_app"); } + +// ── Codex multi-account (ADR 0003) ─────────────────────────────────── + +export function codexAccountsList(): Promise { + return invoke("codex_accounts_list"); +} + +export function codexAccountAdd(): Promise { + return invoke("codex_account_add"); +} + +export function codexAccountRemove(id: string): Promise { + return invoke("codex_account_remove", { id }); +} + +export function codexAccountSwitch(id: string): Promise { + return invoke("codex_account_switch", { id }); +} + +export function codexAccountFetch( + id: string, +): Promise { + return invoke("codex_account_fetch", { id }); +} + +export function codexAccountSnapshots(): Promise< + Record +> { + return invoke>( + "codex_account_snapshots", + ); +} + +export function codexAccountRestartDesktop( + sessionRoot?: string | null, + backupDestination?: string | null, + restoreSource?: string | null, +): Promise { + return invoke("codex_account_restart_desktop", { + sessionRoot, + backupDestination, + restoreSource, + }); +} + +export function getCodexAccountsState(): Promise { + return invoke("get_codex_accounts_state"); +} diff --git a/apps/desktop-tauri/src/types/bridge.ts b/apps/desktop-tauri/src/types/bridge.ts index 89e16af7a4..3d91b68cae 100644 --- a/apps/desktop-tauri/src/types/bridge.ts +++ b/apps/desktop-tauri/src/types/bridge.ts @@ -738,3 +738,58 @@ export interface RegionOption { value: string; label: string; } + +// ── Codex multi-account (ADR 0003) ─────────────────────────────────── + +export type CodexAccountSource = "ambient" | "managedByApp"; + +export interface CodexAccount { + id: string; + nickname: string | null; + emailHint: string | null; + authSubject: string | null; + providerAccountId: string | null; + codexHomePath: string; + source: CodexAccountSource; + createdAt: string; + updatedAt: string; + lastAuthenticatedAt: string | null; +} + +export interface CodexUsageWindow { + usedPercent: number; + resetAt: string | null; + limitWindowSeconds: number; +} + +export interface CodexCreditsBalance { + hasCredits: boolean; + unlimited: boolean; + balance: number | null; +} + +export interface CodexAccountUsageSnapshot { + email: string | null; + providerAccountId: string | null; + plan: string | null; + allowed: boolean | null; + limitReached: boolean | null; + primaryWindow: CodexUsageWindow | null; + secondaryWindow: CodexUsageWindow | null; + credits: CodexCreditsBalance | null; + updatedAt: string; +} + +export interface CodexSwitchResult { + materializedAccount: CodexAccount | null; + backupPath: string | null; + ambientAccount: CodexAccount | null; + desktopSessionBackupPath: string | null; + desktopSessionRestorePath: string | null; + desktopSessionRestoreExists: boolean; +} + +export interface CodexAccountsStateBridge { + accounts: CodexAccount[]; + snapshots: Record; +} diff --git a/rust/src/locale.rs b/rust/src/locale.rs index 7bb2b92a07..cf86892e56 100644 --- a/rust/src/locale.rs +++ b/rust/src/locale.rs @@ -509,6 +509,19 @@ locale_keys! { ProviderClaudeDailyRoutinesUsageHelp, ProviderCodexSparkUsage, ProviderCodexSparkUsageHelp, + CodexAccountsTitle, + CodexAccountsHint, + CodexAccountsAddButton, + CodexAccountsSwitchButton, + CodexAccountsFetchButton, + CodexAccountsRemoveButton, + CodexAccountsEmpty, + CodexAccountsSourceAmbient, + CodexAccountsSourceManaged, + CodexAccountsUsageUnavailable, + CodexSwitchSuccess, + CodexSwitchRestartPrompt, + CodexAccountsRestartDesktop, ProviderCursorCookieSourceHelp, ProviderCursorCreditsHelp, AutoFallbackHelp, diff --git a/rust/src/locale/en-US.ftl b/rust/src/locale/en-US.ftl index aa289501e0..42946a7dee 100644 --- a/rust/src/locale/en-US.ftl +++ b/rust/src/locale/en-US.ftl @@ -288,6 +288,19 @@ ProviderClaudeDailyRoutinesUsage = Show Daily Routines usage ProviderClaudeDailyRoutinesUsageHelp = Show the Daily Routines quota row for Claude web and OAuth usage. ProviderCodexSparkUsage = Show Codex Spark usage ProviderCodexSparkUsageHelp = Show Codex Spark quota rows without hiding credits or other extra usage. +CodexAccountsTitle = Codex Accounts +CodexAccountsHint = Manage multiple Codex accounts. Each account lives in its own managed home; switching updates the active identity. +CodexAccountsAddButton = Add account +CodexAccountsSwitchButton = Switch +CodexAccountsFetchButton = Refresh usage +CodexAccountsRemoveButton = Remove +CodexAccountsEmpty = No Codex accounts found. +CodexAccountsSourceAmbient = Ambient +CodexAccountsSourceManaged = Managed +CodexAccountsUsageUnavailable = No usage data +CodexSwitchSuccess = Active account switched. +CodexSwitchRestartPrompt = Restart Codex Desktop to load the restored session? +CodexAccountsRestartDesktop = Restart Codex Desktop ProviderCursorCookieSourceHelp = Automatic imports browser cookies or stored sessions. ProviderCursorCreditsHelp = On-demand usage beyond included plan limits. AutoFallbackHelp = Auto falls back to the next source if the preferred one fails. diff --git a/rust/src/locale/es-MX.ftl b/rust/src/locale/es-MX.ftl index 044c7a9bb6..f52199c132 100644 --- a/rust/src/locale/es-MX.ftl +++ b/rust/src/locale/es-MX.ftl @@ -282,6 +282,19 @@ ProviderClaudeDailyRoutinesUsage = Mostrar uso de Daily Routines ProviderClaudeDailyRoutinesUsageHelp = Muestra la fila de cuota Daily Routines en el uso web/OAuth de Claude. ProviderCodexSparkUsage = Show Codex Spark usage ProviderCodexSparkUsageHelp = Show Codex Spark quota rows without hiding credits or other extra usage. +CodexAccountsTitle = Cuentas de Codex +CodexAccountsHint = Administra varias cuentas de Codex. Cada cuenta vive en su propio hogar administrado; al cambiar se actualiza la identidad activa. +CodexAccountsAddButton = Añadir cuenta +CodexAccountsSwitchButton = Cambiar +CodexAccountsFetchButton = Actualizar uso +CodexAccountsRemoveButton = Quitar +CodexAccountsEmpty = No se encontraron cuentas de Codex. +CodexAccountsSourceAmbient = Ambiental +CodexAccountsSourceManaged = Administrada +CodexAccountsUsageUnavailable = Sin datos de uso +CodexSwitchSuccess = Cuenta activa cambiada. +CodexSwitchRestartPrompt = ¿Reiniciar Codex Desktop para cargar la sesión restaurada? +CodexAccountsRestartDesktop = Reiniciar Codex Desktop ProviderCursorCookieSourceHelp = Importa automáticamente cookies del navegador o sesiones almacenadas. ProviderCursorCreditsHelp = Uso bajo demanda más allá de los límites del plan incluido. AutoFallbackHelp = Auto recurre a la siguiente fuente si la preferida falla.