fix(native-chat): drop local terminal topology from structured sync

This commit is contained in:
Brennan Benson
2026-08-12 19:36:51 -07:00
parent 1377932db3
commit e444d4bedd
2 changed files with 68 additions and 9 deletions
@@ -0,0 +1,61 @@
import { describe, expect, it } from 'vitest'
import type { RuntimeMobileSessionTabsResult } from '../../../shared/runtime-types'
import { projectLocalStructuredSessionTabs } from './local-structured-session-tabs-sync'
describe('local structured session tab projection', () => {
it('drops terminal topology while retaining structured tabs', () => {
const snapshot = {
worktree: 'workspace-1',
publicationEpoch: 'epoch-1',
snapshotVersion: 1,
activeGroupId: 'structured-group',
activeTabId: 'agent-session:codex-1',
activeTabType: 'agent-session',
tabGroups: [
{
id: 'terminal-group',
activeTabId: 'terminal-1',
tabOrder: ['terminal-1']
},
{
id: 'structured-group',
activeTabId: 'agent-session:codex-1',
tabOrder: ['agent-session:codex-1']
}
],
tabGroupLayout: {
type: 'split',
direction: 'horizontal',
first: { type: 'leaf', groupId: 'terminal-group' },
second: { type: 'leaf', groupId: 'structured-group' }
},
tabs: [
{
type: 'terminal',
id: 'terminal-1',
parentTabId: 'terminal-1',
leafId: 'leaf-1',
title: 'Terminal',
status: 'ready',
terminal: 'term-1',
ptyId: 'pty-1',
isActive: false
},
{
type: 'agent-session',
id: 'agent-session:codex-1',
title: 'Codex Chat',
sessionId: 'codex-1',
agent: 'codex',
isActive: true
}
]
} satisfies RuntimeMobileSessionTabsResult
expect(projectLocalStructuredSessionTabs(snapshot)).toMatchObject({
tabGroups: undefined,
tabGroupLayout: undefined,
tabs: [expect.objectContaining({ type: 'agent-session', agent: 'codex' })]
})
})
})
@@ -11,20 +11,18 @@ type SessionTabsEvent =
| { type: 'snapshots'; snapshots: RuntimeMobileSessionTabsResult[] }
| { type: 'end' }
function structuredOnly(snapshot: RuntimeMobileSessionTabsResult): RuntimeMobileSessionTabsResult {
export function projectLocalStructuredSessionTabs(
snapshot: RuntimeMobileSessionTabsResult
): RuntimeMobileSessionTabsResult {
const structuredIds = new Set(
snapshot.tabs.filter((tab) => tab.type === 'agent-session').map((tab) => tab.id)
)
return {
...snapshot,
tabs: snapshot.tabs.filter((tab) => structuredIds.has(tab.id)),
tabGroups: snapshot.tabGroups?.map((group) => ({
...group,
tabOrder: group.tabOrder.filter((id) => structuredIds.has(id)),
activeTabId:
group.activeTabId && structuredIds.has(group.activeTabId) ? group.activeTabId : null,
recentTabIds: group.recentTabIds?.filter((id) => structuredIds.has(id))
}))
// Why: replaying local terminal topology under the structured owner clones the workspace layout.
tabGroups: undefined,
tabGroupLayout: undefined
}
}
@@ -34,7 +32,7 @@ function applySnapshots(snapshots: readonly RuntimeMobileSessionTabsResult[]): v
for (const snapshot of snapshots) {
const patch = applyWebSessionTabsSnapshot(
next,
structuredOnly(snapshot),
projectLocalStructuredSessionTabs(snapshot),
LOCAL_STRUCTURED_SESSION_OWNER
)
next = patch === next ? next : ({ ...next, ...patch } as typeof state)