refactor(bots): share the stale Bot Chat tile probe between the roster click and tip open
isStaleBotChatTile(canonicalIds) replaces the copy in openStoredBotChat, whose try/catch duplicated the optional call; the stale-tiles test no longer contradicts its own comment.
This commit is contained in:
@@ -18,9 +18,10 @@ const { openBotCanonicalChat, prepareBotSource } = vi.hoisted(() => ({
|
||||
prepareBotSource: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('./canonical-chat', () => ({
|
||||
vi.mock('./canonical-chat', async () => ({
|
||||
CANONICAL_CHAT_TITLE: 'Bot Chat',
|
||||
ensureBotMetadata: vi.fn(async () => ({})),
|
||||
isStaleBotChatTile: (await vi.importActual<typeof import('./canonical-chat')>('./canonical-chat')).isStaleBotChatTile,
|
||||
notifyBotOpenFailure: vi.fn(),
|
||||
openBotCanonicalChat,
|
||||
prepareBotSource,
|
||||
|
||||
@@ -74,8 +74,7 @@ describe('120810: compressed Bot Chat discards the stale tile', () => {
|
||||
// Live tip and registry row are never stale.
|
||||
expect(probe({ storedSessionId: 'tip-9', workspaceTabTitle: 'Bot Chat' })).toBe(false)
|
||||
expect(probe({ storedSessionId: 'root-1', workspaceTabTitle: 'Bot Chat' })).toBe(false)
|
||||
// User + threads are never stale.
|
||||
expect(probe({ storedSessionId: 'side-1', workspaceTabTitle: 'Bot Chat' })).toBe(true)
|
||||
// A user + thread carries its own title, so it is never stale.
|
||||
expect(probe({ storedSessionId: 'side-1', workspaceTabTitle: 'my thread' })).toBe(false)
|
||||
// Tip opens after the probe.
|
||||
expect(hostMock.openSession.mock.calls[0][0]).toBe('tip-9')
|
||||
|
||||
@@ -60,6 +60,12 @@ interface CanonicalChatRow extends CanonicalSession {
|
||||
readonly live_message_count?: SessionListRow['live_message_count']
|
||||
}
|
||||
|
||||
/** A Bot Chat tile left on an old compression segment: titled as the canonical
|
||||
* chat but keyed to none of the lineage ids the owner currently resolves to. */
|
||||
export const isStaleBotChatTile =
|
||||
(canonicalIds: readonly string[]) => (tile: { storedSessionId: string; workspaceTabTitle?: string }) =>
|
||||
tile.workspaceTabTitle === CANONICAL_CHAT_TITLE && !canonicalIds.includes(String(tile.storedSessionId))
|
||||
|
||||
/** Should the open wait for a painted transcript? The paintable row count
|
||||
* decides when the gateway reports it; the denormalized total is the only
|
||||
* fallback older gateways offer, and no count at all means the row is
|
||||
@@ -153,16 +159,7 @@ async function openStoredBotChat(
|
||||
// old-segment tile is discarded here or it survives beside the tip
|
||||
// (hermes-agent#120810). Same owner-scoped probe the roster click runs.
|
||||
const canonicalIds = [...new Set([summary?.id, storedId].filter(Boolean).map(String))]
|
||||
|
||||
try {
|
||||
host.focusOpenWorkspaceSession?.(
|
||||
ownerKey,
|
||||
tile => tile.workspaceTabTitle === CANONICAL_CHAT_TITLE && !canonicalIds.includes(String(tile.storedSessionId)),
|
||||
canonicalIds
|
||||
)
|
||||
} catch {
|
||||
// Older shells: the tip open below still lands.
|
||||
}
|
||||
host.focusOpenWorkspaceSession?.(ownerKey, isStaleBotChatTile(canonicalIds), canonicalIds)
|
||||
|
||||
await host.openSession(storedId, {
|
||||
...(route
|
||||
|
||||
@@ -16,9 +16,10 @@ const { openBotCanonicalChat, prepareBotSource } = vi.hoisted(() => ({
|
||||
prepareBotSource: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('./canonical-chat', () => ({
|
||||
vi.mock('./canonical-chat', async () => ({
|
||||
CANONICAL_CHAT_TITLE: 'Bot Chat',
|
||||
ensureBotMetadata: vi.fn(async () => ({})),
|
||||
isStaleBotChatTile: (await vi.importActual<typeof import('./canonical-chat')>('./canonical-chat')).isStaleBotChatTile,
|
||||
notifyBotOpenFailure: vi.fn(),
|
||||
openBotCanonicalChat,
|
||||
prepareBotSource,
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
rosterWatermarks,
|
||||
saveSelectedRosterBot
|
||||
} from './bot-state'
|
||||
import { CANONICAL_CHAT_TITLE, notifyBotOpenFailure, openBotCanonicalChat, prepareBotSource } from './canonical-chat'
|
||||
import { isStaleBotChatTile, notifyBotOpenFailure, openBotCanonicalChat, prepareBotSource } from './canonical-chat'
|
||||
import { $botMeta, botActivitySession, botRosterKey, botSelectionKey, newBotChat } from './data'
|
||||
import { $groupChats, $groupChatWorkspace } from './group-chat'
|
||||
import { openGroupChat } from './group-chat-view'
|
||||
@@ -197,13 +197,8 @@ function focusExistingBotTab(bot: RosterRow): null | { registryId: string; store
|
||||
return null
|
||||
}
|
||||
|
||||
const isStaleTile = (tile: { storedSessionId: string; workspaceTabTitle?: string }) =>
|
||||
typeof tile.workspaceTabTitle === 'string' &&
|
||||
tile.workspaceTabTitle === CANONICAL_CHAT_TITLE &&
|
||||
!canonicalIds.includes(String(tile.storedSessionId))
|
||||
|
||||
try {
|
||||
const focused = host.focusOpenWorkspaceSession(botWorkspaceOwnerKey(bot), isStaleTile, canonicalIds)
|
||||
const focused = host.focusOpenWorkspaceSession(botWorkspaceOwnerKey(bot), isStaleBotChatTile(canonicalIds), canonicalIds)
|
||||
|
||||
return typeof focused === 'string' && focused
|
||||
? { registryId: String(canonical!.id), storedSessionId: focused }
|
||||
|
||||
Reference in New Issue
Block a user