Files
orca/src/main/runtime/agent-session-tab-layout.test.ts
T
Jinwoo Hong fa962dd1cd Record chat tab opens and closes in main (dark, layout-owner build only) (#30019)
* Record chat tab opens, closes and host-listed chats in main (dark, layout-owner build only)

A chat tab the window opens, closes, or adds and removes from a host
listing of this machine's chats now reaches main as openAgentSessionTab,
closeTabs or setTabProps under the window's ids, so the window's save no
longer teaches main a chat tab. openAgentSessionTab takes the window's
place, creation time and new split group, and the same open again
changes nothing. Switch-off builds are unchanged.

* test(layout): a paired server's chat tabs send nothing to main (dark)

* fix(layout): keep a windowless host's chat-tab saves as they were; send synced chat opens in tab order (dark)

Only a window's openAgentSessionTab (main marks it drawn on layout.apply)
takes the new rules: a repeat changes nothing, a taken id is refused, and
a workspace with no group takes the window's. A windowless host's own
saves mint a fresh group and keep a chat whose id another tab holds, as
before. A host listing's new chats are recorded in tab order, so each
open's anchor already reached main.

* refactor(layout): one rule set for a chat tab open; the windowless caller names only a group it holds (dark)

Drops the per-sender drawn flag. The windowless save passes its
remembered active group only when the workspace still holds it, so it
mints a fresh group as before. Refusing a taken chat tab id is gated on
the build switch: shipped builds still save the duplicate id.
2026-10-17 00:57:12 -07:00

57 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest'
import type { WorkspaceSessionState } from '../../shared/workspace-session-state-types'
import { withChatTabChanges, type ChatTabChange } from './agent-session-tab-layout'
const WT = 'repo-1::/tmp/worktree-a'
const EMPTY: WorkspaceSessionState = {
activeRepoId: 'repo-1',
activeWorktreeId: WT,
activeTabId: null,
tabsByWorktree: {},
terminalLayoutsByTabId: {}
}
function open(sessionId: string, tabId = `structured-agent-session-${sessionId}`): ChatTabChange {
return { open: { sessionId, agent: 'codex', tabId } }
}
function change(session: WorkspaceSessionState, changes: ChatTabChange[]): WorkspaceSessionState {
const next = withChatTabChanges('local', session, WT, changes)
if (!next) {
throw new Error('nothing changed')
}
return next
}
describe('a windowless host’s chat tab saves', () => {
it('open a chat in a freshly minted group once the last one closed', () => {
const first = change(EMPTY, [open('chat-a')])
const firstGroup = first.tabGroups?.[WT]?.[0]?.id
const closed = change(first, [{ close: 'chat-a' }])
// The workspace keeps no group, but its saved view still names the closed chat's group.
const remembering = {
...closed,
activeGroupIdByWorktree: { ...closed.activeGroupIdByWorktree, [WT]: firstGroup! }
}
expect(remembering.tabGroups?.[WT] ?? []).toEqual([])
const reopened = change(remembering, [open('chat-b')])
const groups = reopened.tabGroups?.[WT] ?? []
expect(firstGroup).toBeTruthy()
expect(groups).toHaveLength(1)
expect(groups[0]?.id).not.toBe(firstGroup)
})
// Preserved legacy behaviour: with the build switch off a duplicate chat tab id is still saved.
it('save a chat whose tab id another tab already holds, as they always have', () => {
const saved = change(EMPTY, [open('chat-a', 'structured-agent-session-shared')])
const both = change(saved, [open('chat-b', 'structured-agent-session-shared')])
expect(
(both.unifiedTabs?.[WT] ?? [])
.filter((tab) => tab.contentType === 'agent-session')
.map((tab) => tab.entityId)
.sort()
).toEqual(['chat-a', 'chat-b'])
})
})