mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 08:03:20 +00:00
fix(chat): retain clear pane identity with reopened history
This commit is contained in:
@@ -14,9 +14,13 @@ import {
|
||||
beforeEach(resetWebSessionTabsSyncTestState)
|
||||
|
||||
describe('clear pane identity', () => {
|
||||
it.each(['agent-session', 'terminal'] as const)(
|
||||
'replaces a %s pane in its existing local position',
|
||||
(contentType) => {
|
||||
it.each(
|
||||
(['agent-session', 'terminal'] as const).flatMap((contentType) =>
|
||||
(['absent', 'before', 'after'] as const).map((history) => ({ contentType, history }))
|
||||
)
|
||||
)(
|
||||
'replaces a $contentType pane with reopened history $history the replacement',
|
||||
({ contentType, history }) => {
|
||||
const state = makeState({
|
||||
unifiedTabsByWorktree: {
|
||||
[WT]: [
|
||||
@@ -83,13 +87,30 @@ describe('clear pane identity', () => {
|
||||
],
|
||||
{ activeTabId: 'agent-session:new-session', activeTabType: 'agent-session' }
|
||||
)
|
||||
if (history !== 'absent') {
|
||||
const oldTab = {
|
||||
type: 'agent-session' as const,
|
||||
id: 'agent-session:old-session',
|
||||
sessionId: 'old-session',
|
||||
agent: 'codex' as const,
|
||||
title: 'History',
|
||||
isActive: false
|
||||
}
|
||||
if (history === 'before') {
|
||||
snapshot.tabs.unshift(oldTab)
|
||||
} else {
|
||||
snapshot.tabs.push(oldTab)
|
||||
}
|
||||
}
|
||||
const next = applyWebSessionTabsSnapshot(state, snapshot, ENV, NOW, {
|
||||
contentScope: 'agent-session',
|
||||
preserveLocalLayout: true,
|
||||
terminalPtyMode: 'local'
|
||||
})
|
||||
expect(next.unifiedTabsByWorktree?.[WT]).toHaveLength(1)
|
||||
expect(next.unifiedTabsByWorktree?.[WT]?.[0]).toMatchObject({
|
||||
expect(next.unifiedTabsByWorktree?.[WT]).toHaveLength(history === 'absent' ? 1 : 2)
|
||||
expect(
|
||||
next.unifiedTabsByWorktree?.[WT]?.find((tab) => tab.entityId === 'new-session')
|
||||
).toMatchObject({
|
||||
id: 'local-pane',
|
||||
entityId: 'new-session',
|
||||
contentType: 'agent-session',
|
||||
@@ -97,10 +118,19 @@ describe('clear pane identity', () => {
|
||||
isPinned: true
|
||||
})
|
||||
expect(next.groupsByWorktree?.[WT]?.[0]).toMatchObject({
|
||||
tabOrder: ['local-pane'],
|
||||
activeTabId: 'local-pane'
|
||||
})
|
||||
expect(next.groupsByWorktree?.[WT]?.[0]?.tabOrder[0]).toBe('local-pane')
|
||||
expect(next.activeTabIdByWorktree?.[WT] ?? state.activeTabIdByWorktree[WT]).toBe('local-pane')
|
||||
expect(next.tabsByWorktree?.[WT] ?? []).toEqual([])
|
||||
const repeated = applyWebSessionTabsSnapshot({ ...state, ...next }, snapshot, ENV, NOW + 1, {
|
||||
contentScope: 'agent-session',
|
||||
preserveLocalLayout: true,
|
||||
terminalPtyMode: 'local'
|
||||
})
|
||||
expect(repeated.unifiedTabsByWorktree?.[WT] ?? next.unifiedTabsByWorktree?.[WT]).toEqual(
|
||||
next.unifiedTabsByWorktree?.[WT]
|
||||
)
|
||||
}
|
||||
)
|
||||
it('gives reopened history its own tab when clear retained its former local ID', () => {
|
||||
|
||||
@@ -60,23 +60,40 @@ export function buildMirroredAgentTabs(
|
||||
now: number
|
||||
): MirroredAgentTab[] {
|
||||
const agentTabs = snapshot.tabs.filter(isAgentSessionTab)
|
||||
const publishedSessions = new Set(agentTabs.map((tab) => tab.sessionId))
|
||||
const occupiedIds = new Set(currentUnifiedTabs.map((tab) => tab.id))
|
||||
const assignedIds = new Set<string>()
|
||||
return agentTabs.map((tab, index) => {
|
||||
const replacementTabs = new Map<string, Tab>()
|
||||
const replacementIds = new Set<string>()
|
||||
for (const tab of agentTabs) {
|
||||
if (!tab.replacesSessionId) {
|
||||
continue
|
||||
}
|
||||
const existing =
|
||||
currentUnifiedTabs.find(
|
||||
(candidate) =>
|
||||
candidate.contentType === 'agent-session' && candidate.entityId === tab.sessionId
|
||||
) ??
|
||||
(tab.replacesSessionId && !publishedSessions.has(tab.replacesSessionId)
|
||||
? currentUnifiedTabs.find(
|
||||
(candidate) =>
|
||||
candidate.structuredSessionId === tab.replacesSessionId ||
|
||||
(candidate.contentType === 'agent-session' &&
|
||||
candidate.entityId === tab.replacesSessionId)
|
||||
)
|
||||
: undefined)
|
||||
currentUnifiedTabs.find(
|
||||
(candidate) =>
|
||||
!replacementIds.has(candidate.id) &&
|
||||
(candidate.structuredSessionId === tab.replacesSessionId ||
|
||||
(candidate.contentType === 'agent-session' &&
|
||||
candidate.entityId === tab.replacesSessionId))
|
||||
)
|
||||
if (existing) {
|
||||
replacementTabs.set(tab.sessionId, existing)
|
||||
replacementIds.add(existing.id)
|
||||
}
|
||||
}
|
||||
return agentTabs.map((tab, index) => {
|
||||
const existing =
|
||||
replacementTabs.get(tab.sessionId) ??
|
||||
currentUnifiedTabs.find(
|
||||
(candidate) =>
|
||||
!replacementIds.has(candidate.id) &&
|
||||
candidate.contentType === 'agent-session' &&
|
||||
candidate.entityId === tab.sessionId
|
||||
)
|
||||
const baseId = structuredAgentSessionTabId(tab.sessionId)
|
||||
let localId = existing?.id ?? baseId
|
||||
if (!existing || assignedIds.has(localId)) {
|
||||
|
||||
Reference in New Issue
Block a user