mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 00:03:15 +00:00
fix(codex): flag signed-out system default (#9619)
* fix(codex): flag signed-out system default * fix(codex): distinguish missing sign-in warnings * test(codex): preserve system OAuth auth warning
This commit is contained in:
@@ -414,21 +414,20 @@ export function AccountsPane({
|
||||
// WSL falls back to the generic label.
|
||||
const systemCodexIdentity =
|
||||
accountRuntime.runtime === 'host' ? codexAccounts.systemDefault : undefined
|
||||
// Why: the auth warning is derived from the desktop's own rate-limit poll;
|
||||
// with a remote owner it would misattribute local auth state to the server.
|
||||
const activeCodexAuthWarning =
|
||||
codexAccountsLoaded && !isRemoteAccountScope
|
||||
? getCodexAccountAuthWarning({
|
||||
limits: codexRateLimits,
|
||||
target: codexRateLimitTarget,
|
||||
runtime: accountRuntime,
|
||||
activeAccountId: activeCodexAccountId,
|
||||
accountId: activeCodexAccountId,
|
||||
authKind: activeCodexAccountId === null ? systemCodexIdentity?.authKind : undefined
|
||||
})
|
||||
: null
|
||||
const systemCodexNeedsReauthentication =
|
||||
activeCodexAccountId === null && Boolean(activeCodexAuthWarning)
|
||||
// Why: remote snapshots own their system-default identity, but the desktop's
|
||||
// rate-limit poll must not be misattributed to a remote account owner.
|
||||
const activeCodexAuthWarning = codexAccountsLoaded
|
||||
? getCodexAccountAuthWarning({
|
||||
limits: isRemoteAccountScope ? null : codexRateLimits,
|
||||
target: codexRateLimitTarget,
|
||||
runtime: accountRuntime,
|
||||
activeAccountId: activeCodexAccountId,
|
||||
accountId: activeCodexAccountId,
|
||||
authKind: activeCodexAccountId === null ? systemCodexIdentity?.authKind : undefined
|
||||
})
|
||||
: null
|
||||
const systemCodexMissingSignIn = activeCodexAuthWarning === 'missing-sign-in'
|
||||
const systemCodexNeedsSignIn = activeCodexAccountId === null && Boolean(activeCodexAuthWarning)
|
||||
const accountRuntimeUnavailable =
|
||||
accountRuntime.runtime === 'wsl' && !wslAvailable && !wslCapabilitiesLoading
|
||||
|
||||
@@ -1080,16 +1079,22 @@ export function AccountsPane({
|
||||
<div className="flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive">
|
||||
<AlertTriangle className="mt-0.5 size-3.5 shrink-0" />
|
||||
<span>
|
||||
{activeCodexAccountId
|
||||
{systemCodexMissingSignIn
|
||||
? translate(
|
||||
'auto.components.settings.AccountsPane.75ca9b718e',
|
||||
'Codex reported that the active account needs a fresh sign-in. Re-authenticate it before starting new Codex sessions.'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.settings.AccountsPane.e4a28e8894',
|
||||
'Codex reported that the {{value0}} login needs a fresh sign-in. Sign in again before starting new Codex sessions.',
|
||||
'auto.components.settings.AccountsPane.codexSystemDefaultNeedsSignIn',
|
||||
'No Codex sign-in was found for {{value0}}.',
|
||||
{ value0: accountRuntimeSentenceLabel }
|
||||
)}
|
||||
)
|
||||
: activeCodexAccountId
|
||||
? translate(
|
||||
'auto.components.settings.AccountsPane.75ca9b718e',
|
||||
'Codex reported that the active account needs a fresh sign-in. Re-authenticate it before starting new Codex sessions.'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.settings.AccountsPane.e4a28e8894',
|
||||
'Codex reported that the {{value0}} login needs a fresh sign-in. Sign in again before starting new Codex sessions.',
|
||||
{ value0: accountRuntimeSentenceLabel }
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
@@ -1156,7 +1161,7 @@ export function AccountsPane({
|
||||
}
|
||||
disabled={codexAction !== 'idle' || accountRuntimeUnavailable}
|
||||
className={`flex w-full items-center justify-between gap-3 rounded-md border px-3 py-2.5 text-left transition-colors ${
|
||||
systemCodexNeedsReauthentication
|
||||
systemCodexNeedsSignIn
|
||||
? 'border-destructive/50 bg-destructive/5'
|
||||
: systemCodexActive
|
||||
? 'border-foreground/20 bg-accent/15'
|
||||
@@ -1179,7 +1184,7 @@ export function AccountsPane({
|
||||
{translate('auto.components.settings.AccountsPane.e74831fb6b', 'Active')}
|
||||
</Badge>
|
||||
) : null}
|
||||
{systemCodexNeedsReauthentication ? (
|
||||
{systemCodexNeedsSignIn ? (
|
||||
<Badge
|
||||
variant="destructive"
|
||||
className="h-4 shrink-0 rounded px-1.5 text-[10px] font-medium leading-none"
|
||||
@@ -1193,15 +1198,21 @@ export function AccountsPane({
|
||||
</div>
|
||||
<span
|
||||
className={`truncate text-[11px] ${
|
||||
systemCodexNeedsReauthentication ? 'text-destructive' : 'text-muted-foreground'
|
||||
systemCodexNeedsSignIn ? 'text-destructive' : 'text-muted-foreground'
|
||||
}`}
|
||||
>
|
||||
{systemCodexNeedsReauthentication
|
||||
? translate(
|
||||
'auto.components.settings.AccountsPane.fd62f37c24',
|
||||
'Codex reported this {{value0}} login is out of date.',
|
||||
{ value0: accountRuntimeSentenceLabel }
|
||||
)
|
||||
{systemCodexNeedsSignIn
|
||||
? systemCodexMissingSignIn
|
||||
? translate(
|
||||
'auto.components.settings.AccountsPane.codexSystemDefaultNeedsSignIn',
|
||||
'No Codex sign-in was found for {{value0}}.',
|
||||
{ value0: accountRuntimeSentenceLabel }
|
||||
)
|
||||
: translate(
|
||||
'auto.components.settings.AccountsPane.fd62f37c24',
|
||||
'Codex reported this {{value0}} login is out of date.',
|
||||
{ value0: accountRuntimeSentenceLabel }
|
||||
)
|
||||
: getCodexSystemDefaultSubtitle(
|
||||
systemCodexIdentity,
|
||||
accountRuntimeSentenceLabel
|
||||
|
||||
@@ -49,7 +49,22 @@ describe('codex account auth warning', () => {
|
||||
activeAccountId: 'account-1',
|
||||
accountId: 'account-1'
|
||||
})
|
||||
).toContain('access token could not be refreshed')
|
||||
).toBe('stale-sign-in')
|
||||
})
|
||||
|
||||
it('preserves stale-sign-in warnings for an OAuth system default', () => {
|
||||
expect(
|
||||
getCodexAccountAuthWarning({
|
||||
limits: codexLimits(
|
||||
'Your access token could not be refreshed. Please log out and sign in again.'
|
||||
),
|
||||
target: { runtime: 'host', wslDistro: null },
|
||||
runtime: { runtime: 'host' },
|
||||
activeAccountId: null,
|
||||
accountId: null,
|
||||
authKind: 'oauth'
|
||||
})
|
||||
).toBe('stale-sign-in')
|
||||
})
|
||||
|
||||
it('does not warn for inactive accounts or a different runtime', () => {
|
||||
@@ -90,6 +105,33 @@ describe('codex account auth warning', () => {
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('warns only when the active system default has no usable login', () => {
|
||||
const getWarning = (authKind: 'none' | 'api-key' | 'oauth') =>
|
||||
getCodexAccountAuthWarning({
|
||||
limits: null,
|
||||
target: { runtime: 'host', wslDistro: null },
|
||||
runtime: { runtime: 'host' },
|
||||
activeAccountId: null,
|
||||
accountId: null,
|
||||
authKind
|
||||
})
|
||||
|
||||
expect(getWarning('none')).toBe('missing-sign-in')
|
||||
expect(getWarning('api-key')).toBeNull()
|
||||
expect(getWarning('oauth')).toBeNull()
|
||||
|
||||
expect(
|
||||
getCodexAccountAuthWarning({
|
||||
limits: null,
|
||||
target: { runtime: 'host', wslDistro: null },
|
||||
runtime: { runtime: 'host' },
|
||||
activeAccountId: 'account-1',
|
||||
accountId: null,
|
||||
authKind: 'none'
|
||||
})
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('allows a WSL default account location to receive the active WSL target warning', () => {
|
||||
expect(
|
||||
codexRateLimitTargetMatchesAccountRuntime(
|
||||
|
||||
@@ -10,6 +10,8 @@ type AccountRuntime = {
|
||||
wslDistro?: string | null
|
||||
}
|
||||
|
||||
type CodexAccountAuthWarning = 'missing-sign-in' | 'stale-sign-in'
|
||||
|
||||
export function codexRateLimitTargetMatchesAccountRuntime(
|
||||
target: RateLimitRuntimeTarget,
|
||||
runtime: AccountRuntime
|
||||
@@ -30,14 +32,17 @@ export function getCodexAccountAuthWarning(args: {
|
||||
activeAccountId: string | null
|
||||
accountId: string | null
|
||||
authKind?: CodexSystemDefaultIdentity['authKind']
|
||||
}): string | null {
|
||||
}): CodexAccountAuthWarning | null {
|
||||
if (args.accountId !== args.activeAccountId) {
|
||||
return null
|
||||
}
|
||||
// Why: app-server reports API-key homes as a ChatGPT-auth error because
|
||||
// usage is unsupported; that is not a stale sign-in the user can re-auth.
|
||||
if (args.accountId === null && args.authKind === 'api-key') {
|
||||
return null
|
||||
}
|
||||
if (args.accountId !== args.activeAccountId) {
|
||||
return null
|
||||
if (args.accountId === null && args.authKind === 'none') {
|
||||
return 'missing-sign-in'
|
||||
}
|
||||
if (!codexRateLimitTargetMatchesAccountRuntime(args.target, args.runtime)) {
|
||||
return null
|
||||
@@ -45,5 +50,5 @@ export function getCodexAccountAuthWarning(args: {
|
||||
if (args.limits?.status !== 'error' || !isCodexAuthError(args.limits.error)) {
|
||||
return null
|
||||
}
|
||||
return args.limits.error?.trim() || 'Codex reported that this sign-in needs re-authentication.'
|
||||
return 'stale-sign-in'
|
||||
}
|
||||
|
||||
@@ -4989,7 +4989,8 @@
|
||||
"remoteScopeAuthContext": "Each account keeps its own sign-in context on {{value0}}.",
|
||||
"remoteEmptyClaudeAccounts": "No managed Claude accounts on {{value0}}. It uses its system default Claude login; add accounts on that server.",
|
||||
"remoteEmptyCodexAccounts": "No managed Codex accounts on {{value0}}. It uses its system default Codex login; add accounts on that server.",
|
||||
"codexSystemDefaultCustomProvider": "Custom provider — no usage tracked."
|
||||
"codexSystemDefaultCustomProvider": "Custom provider — no usage tracked.",
|
||||
"codexSystemDefaultNeedsSignIn": "No Codex sign-in was found for {{value0}}."
|
||||
},
|
||||
"AdvancedPane": {
|
||||
"40b29e0bf3": "Restart",
|
||||
|
||||
@@ -4966,7 +4966,8 @@
|
||||
"remoteScopeAuthContext": "Cada cuenta mantiene su propio contexto de inicio de sesión en {{value0}}.",
|
||||
"remoteEmptyClaudeAccounts": "No hay cuentas de Claude administradas en {{value0}}. Usa su inicio de sesión de Claude predeterminado del sistema; agrega cuentas en ese servidor.",
|
||||
"remoteEmptyCodexAccounts": "No hay cuentas de Codex administradas en {{value0}}. Usa su inicio de sesión de Codex predeterminado del sistema; agrega cuentas en ese servidor.",
|
||||
"codexSystemDefaultCustomProvider": "Proveedor personalizado — no se registra el uso."
|
||||
"codexSystemDefaultCustomProvider": "Proveedor personalizado — no se registra el uso.",
|
||||
"codexSystemDefaultNeedsSignIn": "No se encontró ningún inicio de sesión de Codex para {{value0}}."
|
||||
},
|
||||
"AdvancedPane": {
|
||||
"40b29e0bf3": "Reiniciar",
|
||||
|
||||
@@ -4951,7 +4951,8 @@
|
||||
"remoteScopeAuthContext": "各アカウントは {{value0}} 上に独自のサインインコンテキストを保持します。",
|
||||
"remoteEmptyClaudeAccounts": "{{value0}} に管理対象の Claude アカウントはありません。システム既定の Claude ログインを使用します。アカウントの追加はそのサーバー上で行ってください。",
|
||||
"remoteEmptyCodexAccounts": "{{value0}} に管理対象の Codex アカウントはありません。システム既定の Codex ログインを使用します。アカウントの追加はそのサーバー上で行ってください。",
|
||||
"codexSystemDefaultCustomProvider": "カスタムプロバイダー — 使用量は追跡されません。"
|
||||
"codexSystemDefaultCustomProvider": "カスタムプロバイダー — 使用量は追跡されません。",
|
||||
"codexSystemDefaultNeedsSignIn": "{{value0}} の Codex サインインが見つかりません。"
|
||||
},
|
||||
"AdvancedPane": {
|
||||
"40b29e0bf3": "再起動",
|
||||
|
||||
@@ -4951,7 +4951,8 @@
|
||||
"remoteScopeAuthContext": "각 계정은 {{value0}}에 자체 로그인 컨텍스트를 유지합니다.",
|
||||
"remoteEmptyClaudeAccounts": "{{value0}}에 관리되는 Claude 계정이 없습니다. 해당 서버의 시스템 기본 Claude 로그인을 사용하며, 계정 추가는 그 서버에서 진행하세요.",
|
||||
"remoteEmptyCodexAccounts": "{{value0}}에 관리되는 Codex 계정이 없습니다. 해당 서버의 시스템 기본 Codex 로그인을 사용하며, 계정 추가는 그 서버에서 진행하세요.",
|
||||
"codexSystemDefaultCustomProvider": "사용자 지정 제공업체 — 사용량을 추적하지 않습니다."
|
||||
"codexSystemDefaultCustomProvider": "사용자 지정 제공업체 — 사용량을 추적하지 않습니다.",
|
||||
"codexSystemDefaultNeedsSignIn": "{{value0}}에 대한 Codex 로그인을 찾을 수 없습니다."
|
||||
},
|
||||
"AdvancedPane": {
|
||||
"40b29e0bf3": "다시 시작",
|
||||
|
||||
@@ -4951,7 +4951,8 @@
|
||||
"remoteScopeAuthContext": "每个账户在 {{value0}} 上保留自己的登录上下文。",
|
||||
"remoteEmptyClaudeAccounts": "{{value0}} 上没有受管理的 Claude 账户。它使用其系统默认的 Claude 登录;请在该服务器上添加账户。",
|
||||
"remoteEmptyCodexAccounts": "{{value0}} 上没有受管理的 Codex 账户。它使用其系统默认的 Codex 登录;请在该服务器上添加账户。",
|
||||
"codexSystemDefaultCustomProvider": "自定义提供商 — 不跟踪使用情况。"
|
||||
"codexSystemDefaultCustomProvider": "自定义提供商 — 不跟踪使用情况。",
|
||||
"codexSystemDefaultNeedsSignIn": "未找到 {{value0}} 的 Codex 登录信息。"
|
||||
},
|
||||
"AdvancedPane": {
|
||||
"40b29e0bf3": "重新启动",
|
||||
|
||||
Reference in New Issue
Block a user