mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
fix(codex): suppress false restart notices after reauth
This commit is contained in:
@@ -668,16 +668,90 @@ describe('markLiveCodexSessionsForRestart lane scoping', () => {
|
||||
vi.mocked(window.api.codexAccounts.listRecordedPaneLanes).mockResolvedValue({
|
||||
'pty-1': 'host'
|
||||
})
|
||||
vi.mocked(window.api.codexAccounts.listStalePanes).mockResolvedValue([
|
||||
{
|
||||
ptyId: 'pty-1',
|
||||
launchAccountId: 'account-a',
|
||||
activeAccountId: 'account-b',
|
||||
reason: 'account-change'
|
||||
}
|
||||
])
|
||||
|
||||
await markLiveCodexSessionsForRestart({
|
||||
previousAccountLabel: ACCOUNT_A,
|
||||
nextAccountLabel: ACCOUNT_B,
|
||||
previousAccountId: 'account-a',
|
||||
nextAccountId: 'account-b',
|
||||
target: { runtime: 'host' }
|
||||
})
|
||||
|
||||
expect(useAppStore.getState().codexRestartNoticeByPtyId['pty-1']).toEqual({
|
||||
previousAccountLabel: ACCOUNT_A,
|
||||
nextAccountLabel: ACCOUNT_B
|
||||
nextAccountLabel: ACCOUNT_B,
|
||||
previousAccountId: 'account-a',
|
||||
nextAccountId: 'account-b'
|
||||
})
|
||||
})
|
||||
|
||||
it('suppresses a null-to-account reauth notice when the recorded pane is already current', async () => {
|
||||
seedPanes([{ ptyId: 'pty-1' }])
|
||||
vi.mocked(window.api.codexAccounts.listRecordedPaneLanes).mockResolvedValue({
|
||||
'pty-1': 'host'
|
||||
})
|
||||
|
||||
await markLiveCodexSessionsForRestart({
|
||||
previousAccountLabel: 'System default',
|
||||
nextAccountLabel: ACCOUNT_A,
|
||||
previousAccountId: null,
|
||||
nextAccountId: 'account-a',
|
||||
target: { runtime: 'host' }
|
||||
})
|
||||
|
||||
expect(window.api.codexAccounts.listStalePanes).toHaveBeenCalledWith({
|
||||
ptyIds: ['pty-1']
|
||||
})
|
||||
expect(useAppStore.getState().codexRestartNoticeByPtyId).toEqual({})
|
||||
})
|
||||
|
||||
it('classifies current, stale, and unrecorded panes independently', async () => {
|
||||
seedPanes([{ ptyId: 'pty-current' }, { ptyId: 'pty-stale' }, { ptyId: 'pty-unknown' }])
|
||||
vi.mocked(window.api.codexAccounts.listRecordedPaneLanes).mockResolvedValue({
|
||||
'pty-current': 'host',
|
||||
'pty-stale': 'host'
|
||||
})
|
||||
vi.mocked(window.api.codexAccounts.listStalePanes).mockResolvedValue([
|
||||
{
|
||||
ptyId: 'pty-stale',
|
||||
launchAccountId: 'account-a',
|
||||
activeAccountId: 'account-b',
|
||||
reason: 'account-change'
|
||||
}
|
||||
])
|
||||
|
||||
await markLiveCodexSessionsForRestart({
|
||||
previousAccountLabel: ACCOUNT_A,
|
||||
nextAccountLabel: ACCOUNT_B,
|
||||
previousAccountId: 'account-a',
|
||||
nextAccountId: 'account-b',
|
||||
target: { runtime: 'host' }
|
||||
})
|
||||
|
||||
expect(window.api.codexAccounts.listStalePanes).toHaveBeenCalledWith({
|
||||
ptyIds: ['pty-current', 'pty-stale']
|
||||
})
|
||||
expect(useAppStore.getState().codexRestartNoticeByPtyId).toEqual({
|
||||
'pty-stale': {
|
||||
previousAccountLabel: ACCOUNT_A,
|
||||
nextAccountLabel: ACCOUNT_B,
|
||||
previousAccountId: 'account-a',
|
||||
nextAccountId: 'account-b'
|
||||
},
|
||||
'pty-unknown': {
|
||||
previousAccountLabel: ACCOUNT_A,
|
||||
nextAccountLabel: ACCOUNT_B,
|
||||
previousAccountId: 'account-a',
|
||||
nextAccountId: 'account-b'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -214,38 +214,39 @@ export async function markLiveCodexSessionsForRestart(args: {
|
||||
return
|
||||
}
|
||||
|
||||
const currentState = useAppStore.getState()
|
||||
const restoredRouteNoticePtyIds = liveCodexSessionPtyIds.filter(
|
||||
(ptyId) => currentState.codexRestartNoticeByPtyId[ptyId]?.homeRouteChanged === true
|
||||
)
|
||||
const restoredRouteNoticePtyIdSet = new Set(restoredRouteNoticePtyIds)
|
||||
const recordedLiveScans = scans.filter((scan) => scan.eligible && scan.laneSource === 'recorded')
|
||||
// Why: a reauth can report null -> A even though a pane's immutable launch
|
||||
// route was already A; main's per-PTY record is the restart authority.
|
||||
const authoritativeStalePanes =
|
||||
restoredRouteNoticePtyIds.length === 0
|
||||
recordedLiveScans.length === 0
|
||||
? null
|
||||
: await window.api.codexAccounts
|
||||
.listStalePanes({ ptyIds: restoredRouteNoticePtyIds })
|
||||
.listStalePanes({ ptyIds: recordedLiveScans.map((scan) => scan.ptyId) })
|
||||
.catch(() => null)
|
||||
const authoritativeStaleByPtyId = authoritativeStalePanes
|
||||
? new Map(authoritativeStalePanes.map((pane) => [pane.ptyId, pane]))
|
||||
: null
|
||||
if (authoritativeStaleByPtyId) {
|
||||
for (const ptyId of restoredRouteNoticePtyIds) {
|
||||
if (!authoritativeStaleByPtyId.has(ptyId)) {
|
||||
useAppStore.getState().clearCodexRestartNotice(ptyId)
|
||||
for (const scan of recordedLiveScans) {
|
||||
if (!authoritativeStaleByPtyId.has(scan.ptyId)) {
|
||||
useAppStore.getState().clearCodexRestartNotice(scan.ptyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useAppStore.getState().markCodexRestartNotices(
|
||||
liveCodexSessionPtyIds.flatMap((ptyId) => {
|
||||
if (authoritativeStaleByPtyId && restoredRouteNoticePtyIdSet.has(ptyId)) {
|
||||
const stalePane = authoritativeStaleByPtyId.get(ptyId)
|
||||
scans.flatMap((scan) => {
|
||||
if (!scan.eligible) {
|
||||
return []
|
||||
}
|
||||
if (authoritativeStaleByPtyId && scan.laneSource === 'recorded') {
|
||||
const stalePane = authoritativeStaleByPtyId.get(scan.ptyId)
|
||||
if (!stalePane) {
|
||||
return []
|
||||
}
|
||||
return [
|
||||
{
|
||||
ptyId,
|
||||
ptyId: scan.ptyId,
|
||||
previousAccountLabel: args.previousAccountLabel,
|
||||
nextAccountLabel: args.nextAccountLabel,
|
||||
previousAccountId: stalePane.launchAccountId,
|
||||
@@ -256,7 +257,7 @@ export async function markLiveCodexSessionsForRestart(args: {
|
||||
}
|
||||
return [
|
||||
{
|
||||
ptyId,
|
||||
ptyId: scan.ptyId,
|
||||
previousAccountLabel: args.previousAccountLabel,
|
||||
nextAccountLabel: args.nextAccountLabel,
|
||||
...(args.previousAccountId === undefined
|
||||
|
||||
Reference in New Issue
Block a user