import { WindowFrameProvider } from '@renderer/components/chat/shell/WindowFrameContext'
import { useCommandHandler } from '@renderer/hooks/command'
import { AGENT_WORKSPACE_TYPE } from '@shared/data/api/schemas/agentWorkspaces'
import { MIN_WINDOW_HEIGHT, SECOND_MIN_WINDOW_WIDTH } from '@shared/utils/window'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import type { ReactNode } from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'

const agentPageMocks = vi.hoisted(() => ({
  workspace: {
    id: 'workspace-a',
    name: 'Workspace A',
    path: '/workspace/a',
    type: 'user',
    orderKey: 'a0',
    createdAt: '2026-01-01T00:00:00.000Z',
    updatedAt: '2026-01-01T00:00:00.000Z'
  },
  workspaceNext: {
    id: 'workspace-next',
    name: 'Workspace Next',
    path: '/workspace/next',
    type: 'user',
    orderKey: 'a1',
    createdAt: '2026-01-02T00:00:00.000Z',
    updatedAt: '2026-01-02T00:00:00.000Z'
  },
  persistedSession: {
    id: 'session-created',
    agentId: 'agent-a',
    name: 'hello',
    description: '',
    workspaceId: 'workspace-a',
    workspace: {
      id: 'workspace-a',
      name: 'Workspace A',
      path: '/workspace/a',
      type: 'user',
      orderKey: 'a0',
      createdAt: '2026-01-01T00:00:00.000Z',
      updatedAt: '2026-01-01T00:00:00.000Z'
    },
    orderKey: 'p0',
    createdAt: '2026-01-03T00:00:00.000Z',
    updatedAt: '2026-01-03T00:00:00.000Z'
  },
  agents: [{ id: 'agent-a', model: 'model-a', name: 'Agent A' }],
  currentTab: undefined as { metadata?: Record<string, unknown> } | undefined,
  lastUsedAgentId: null as string | null,
  lastUsedSessionId: null as string | null,
  lastUsedWorkspaceId: null as string | null,
  classicLayoutRightPaneOpen: true,
  focusExistingTab: vi.fn(() => false),
  activeSessionOptions: null as {
    activeSessionId: string | null
    setActiveSessionId: (id: string | null) => void
  } | null,
  setLastUsedAgentId: vi.fn(),
  setLastUsedSessionId: vi.fn(),
  setLastUsedWorkspaceId: vi.fn(),
  setClassicLayoutRightPaneOpen: vi.fn(),
  setShowSidebar: vi.fn(),
  sessionLayout: 'modern' as 'modern' | 'classic',
  isActiveTab: false,
  showSidebar: false,
  routeSearch: { sessionId: 'session-initial' } as Record<string, unknown>,
  dataApiGet: vi.fn(),
  dataApiPost: vi.fn(),
  updateSession: vi.fn(),
  setSessionWorkspace: vi.fn(),
  invalidateCache: vi.fn(),
  classicLayoutSessions: [] as Array<{
    id: string
    agentId?: string
    name: string
    createdAt?: string
    updatedAt: string
    workspaceId?: string
    workspace?: { type?: string }
  }>
}))

const activeSessionMocks = vi.hoisted(() => ({
  session: null as any,
  isLoading: false,
  sessionSource: 'none' as 'query' | 'pending' | 'none'
}))

vi.mock('@data/DataApiService', () => ({
  dataApiService: {
    get: agentPageMocks.dataApiGet,
    post: agentPageMocks.dataApiPost
  }
}))

vi.mock('@renderer/hooks/resourceViewSources', () => ({
  useAgentSessionsSource: () => ({ sessions: agentPageMocks.classicLayoutSessions })
}))

vi.mock('@renderer/hooks/command', () => ({
  useCommandHandler: vi.fn()
}))

vi.mock('@data/hooks/usePreference', async () => {
  const React = await import('react')

  return {
    usePreference: (key: string) => {
      const [value, setValue] = React.useState<unknown>(
        key === 'topic.tab.show'
          ? agentPageMocks.showSidebar
          : key === 'agent.layout'
            ? agentPageMocks.sessionLayout
            : undefined
      )
      const setPreference = vi.fn(async (nextValue: unknown) => {
        if (key === 'topic.tab.show') {
          agentPageMocks.showSidebar = Boolean(nextValue)
          agentPageMocks.setShowSidebar(nextValue)
        }
        setValue(nextValue)
      })

      return [value, setPreference]
    }
  }
})

vi.mock('@renderer/data/hooks/useCache', async () => {
  const React = await import('react')

  return {
    useSharedCache: () => [null, vi.fn()],
    usePersistCache: (key: string) => {
      const initialValue = (() => {
        switch (key) {
          case 'ui.agent.last_used_agent_id':
            return agentPageMocks.lastUsedAgentId
          case 'ui.agent.last_used_session_id':
            return agentPageMocks.lastUsedSessionId
          case 'ui.agent.last_used_workspace_id':
            return agentPageMocks.lastUsedWorkspaceId
          case 'ui.agent.right_pane_open':
            return agentPageMocks.classicLayoutRightPaneOpen
          default:
            return undefined
        }
      })()
      const [value, setValue] = React.useState(initialValue)
      if (
        key !== 'ui.agent.last_used_agent_id' &&
        key !== 'ui.agent.last_used_session_id' &&
        key !== 'ui.agent.last_used_workspace_id' &&
        key !== 'ui.agent.right_pane_open'
      ) {
        return [undefined, vi.fn()]
      }

      const setCache = vi.fn((nextValue: string | boolean | null) => {
        if (key === 'ui.agent.last_used_agent_id') {
          agentPageMocks.lastUsedAgentId = nextValue as string | null
          agentPageMocks.setLastUsedAgentId(nextValue)
        } else if (key === 'ui.agent.last_used_session_id') {
          agentPageMocks.lastUsedSessionId = nextValue as string | null
          agentPageMocks.setLastUsedSessionId(nextValue)
        } else if (key === 'ui.agent.right_pane_open') {
          agentPageMocks.classicLayoutRightPaneOpen = nextValue as boolean
          agentPageMocks.setClassicLayoutRightPaneOpen(nextValue)
        } else {
          agentPageMocks.lastUsedWorkspaceId = nextValue as string | null
          agentPageMocks.setLastUsedWorkspaceId(nextValue)
        }
        setValue(nextValue)
      })

      return [value, setCache]
    }
  }
})

vi.mock('@renderer/hooks/agent/useAgent', () => ({
  useAgents: () => ({
    agents: agentPageMocks.agents,
    isLoading: false
  }),
  useAgent: (id: string | null) => ({
    agent: id ? agentPageMocks.agents.find((a) => a.id === id) : undefined
  })
}))

vi.mock('@renderer/hooks/agent/useSession', () => ({
  useSession: () => ({
    session: undefined,
    isLoading: false
  }),
  useUpdateSession: () => ({
    updateSession: agentPageMocks.updateSession,
    setSessionWorkspace: agentPageMocks.setSessionWorkspace
  }),
  useActiveSession: (options: {
    activeSessionId: string | null
    setActiveSessionId: (id: string | null) => void
    pendingSession?: any
  }) => {
    agentPageMocks.activeSessionOptions = {
      activeSessionId: options.activeSessionId,
      setActiveSessionId: options.setActiveSessionId
    }
    const pendingSession =
      options.pendingSession && options.pendingSession.id === options.activeSessionId ? options.pendingSession : null
    return {
      session: pendingSession ?? activeSessionMocks.session ?? undefined,
      isLoading: activeSessionMocks.isLoading,
      sessionSource: pendingSession
        ? 'pending'
        : activeSessionMocks.session
          ? activeSessionMocks.sessionSource
          : 'none',
      activeSessionId: options.activeSessionId,
      setActiveSessionId: options.setActiveSessionId
    }
  }
}))

vi.mock('@renderer/data/hooks/useDataApi', () => ({
  useInvalidateCache: () => agentPageMocks.invalidateCache
}))

vi.mock('@tanstack/react-router', () => ({
  useSearch: () => agentPageMocks.routeSearch
}))

vi.mock('@renderer/hooks/useConversationNavigation', () => ({
  useConversationNavigation: () => ({
    focusExistingTab: agentPageMocks.focusExistingTab,
    openConversationTab: vi.fn()
  })
}))

vi.mock('@renderer/hooks/tab', () => ({
  useCurrentTab: () => agentPageMocks.currentTab,
  useCurrentTabId: () => 'agent-tab',
  useIsActiveTab: () => agentPageMocks.isActiveTab,
  useTabSelfMetadata: vi.fn()
}))

vi.mock('@renderer/services/EventService', () => ({
  EVENT_NAMES: {
    GLOBAL_SEARCH_SELECT_AGENT_SESSION: 'GLOBAL_SEARCH_SELECT_AGENT_SESSION',
    GLOBAL_SEARCH_SELECT_AGENT_SESSION_MESSAGE: 'GLOBAL_SEARCH_SELECT_AGENT_SESSION_MESSAGE',
    SHOW_ASSISTANTS: 'SHOW_ASSISTANTS',
    REVEAL_ACTIVE_RESOURCE_LIST: 'REVEAL_ACTIVE_RESOURCE_LIST'
  },
  EventEmitter: {
    emit: vi.fn(),
    on: vi.fn(() => vi.fn())
  }
}))

vi.mock('react-i18next', () => ({
  initReactI18next: {
    init: vi.fn(),
    type: '3rdParty'
  },
  useTranslation: () => ({
    t: (key: string) =>
      ({
        'agent.session.list.title': '任务'
      })[key] ?? key
  })
}))

vi.mock('../AgentChat', () => ({
  default: ({
    activeSession,
    activeSessionLoading,
    draftConversation,
    missingAgentDraft,
    onCreateEmptySession,
    onEnsurePersistentSession,
    onMissingAgentDraftAgentChange,
    onStartDraftSession,
    onVisibleAgentChange,
    onVisibleWorkspaceChange,
    onDraftAgentChange,
    onDraftWorkspaceChange,
    onSessionWorkspaceChange,
    locateMessageId,
    pane,
    paneOpen,
    resourcePaneCount,
    resourcePane,
    showResourceListControls,
    sessionPaneOpen,
    onSessionPaneOpenChange,
    onPaneCollapse
  }: {
    activeSession?: { id: string } | null
    activeSessionLoading?: boolean
    draftConversation?: {
      agentId: string
      workspaceSource: { type: string; workspaceId?: string }
      workspace?: { id?: string; type: string }
    } | null
    missingAgentDraft?: boolean
    onCreateEmptySession?: () => void | Promise<void>
    onEnsurePersistentSession?: (initialName?: string) => Promise<unknown>
    onMissingAgentDraftAgentChange?: (agentId: string | null) => void | Promise<void>
    onStartDraftSession?: (defaults: {
      agentId: string
      workspaceId?: string
      workspaceMode?: 'user' | 'system'
    }) => void | Promise<void>
    onVisibleAgentChange?: (agentId: string) => void
    onVisibleWorkspaceChange?: (workspaceId: string) => void
    onDraftAgentChange?: (agentId: string | null) => void | Promise<void>
    onDraftWorkspaceChange?: (workspaceId: string | null) => void | Promise<void>
    onSessionWorkspaceChange?: (workspaceId: string | null) => void | Promise<void>
    locateMessageId?: string
    pane?: ReactNode
    paneOpen?: boolean
    resourcePaneCount?: { label: string; count: number }
    resourcePane?: { node?: ReactNode; label?: string } | null
    showResourceListControls?: boolean
    sessionPaneOpen?: boolean
    onSessionPaneOpenChange?: (open: boolean) => void
    onPaneCollapse?: () => void
  }) => (
    <section>
      <output data-testid="active-session">{activeSession?.id ?? ''}</output>
      <output data-testid="active-session-loading">{String(Boolean(activeSessionLoading))}</output>
      <output data-testid="draft-session">{draftConversation?.agentId ?? ''}</output>
      <output data-testid="draft-workspace">
        {draftConversation?.workspaceSource.type === 'user' ? draftConversation.workspaceSource.workspaceId : ''}
      </output>
      <output data-testid="missing-agent-draft">{String(Boolean(missingAgentDraft))}</output>
      <output data-testid="locate-message-id">{locateMessageId ?? ''}</output>
      <output data-testid="pane-open">{String(paneOpen)}</output>
      <output data-testid="session-pane-open">{String(sessionPaneOpen)}</output>
      <output data-testid="show-resource-list-controls">{String(showResourceListControls)}</output>
      {resourcePaneCount && (
        <output data-testid="resource-pane-count">
          {resourcePaneCount.label}:{resourcePaneCount.count}
        </output>
      )}
      <button type="button" onClick={() => void onDraftWorkspaceChange?.('workspace-next')}>
        Select workspace
      </button>
      <button type="button" onClick={() => void onDraftWorkspaceChange?.(null)}>
        Select no project
      </button>
      <button type="button" onClick={() => void onSessionWorkspaceChange?.('workspace-next')}>
        Select session workspace
      </button>
      <button type="button" onClick={() => void onStartDraftSession?.({ agentId: 'agent-a' })}>
        Start draft session
      </button>
      {onCreateEmptySession && (
        <button type="button" onClick={() => void onCreateEmptySession()}>
          Create empty session from composer
        </button>
      )}
      <button type="button" onClick={() => void onMissingAgentDraftAgentChange?.('agent-b')}>
        Select missing draft agent
      </button>
      <button type="button" onClick={() => onVisibleAgentChange?.('agent-visible')}>
        Show visible agent
      </button>
      <button type="button" onClick={() => onVisibleWorkspaceChange?.('workspace-visible')}>
        Show visible workspace
      </button>
      <button type="button" onClick={() => void onDraftAgentChange?.('agent-created')}>
        Select newly created draft agent
      </button>
      <button type="button" onClick={() => void onEnsurePersistentSession?.('hello')}>
        Persist draft session
      </button>
      <button
        type="button"
        onClick={() =>
          void onEnsurePersistentSession?.(
            'Please inspect the renderer startup path and suggest fixes for the auto naming regression'
          )
        }>
        Persist long draft session
      </button>
      {onSessionPaneOpenChange && (
        <button type="button" onClick={() => onSessionPaneOpenChange(false)}>
          Close session pane
        </button>
      )}
      {onPaneCollapse && (
        <button type="button" onClick={onPaneCollapse}>
          Collapse pane
        </button>
      )}
      {pane}
      {resourcePane?.node}
    </section>
  )
}))

vi.mock('../AgentSidePanel', () => ({
  default: ({
    activeSessionId,
    onOpenHistoryRecords,
    onStartDraftSession,
    onStartMissingAgentDraft,
    revealRequest,
    setActiveSessionId
  }: any) => {
    return (
      <div
        data-active-session-id={activeSessionId ?? ''}
        data-reveal-request={JSON.stringify(revealRequest ?? null)}
        data-testid="agent-side-panel">
        <button
          type="button"
          onClick={() =>
            setActiveSessionId?.('session-next', {
              id: 'session-next',
              agentId: 'agent-a',
              name: 'Session Next',
              description: '',
              workspaceId: agentPageMocks.workspace.id,
              workspace: agentPageMocks.workspace,
              orderKey: 'next',
              createdAt: '2026-01-02T00:00:00.000Z',
              updatedAt: '2026-01-02T00:00:00.000Z'
            })
          }>
          Select session next
        </button>
        <button type="button" onClick={() => onOpenHistoryRecords?.()}>
          Open history records
        </button>
        <button type="button" onClick={() => onStartMissingAgentDraft?.()}>
          Start missing agent draft
        </button>
        <button
          type="button"
          onClick={() =>
            onStartDraftSession?.({ agentId: 'agent-a', workspace: { type: AGENT_WORKSPACE_TYPE.SYSTEM } })
          }>
          Start panel draft
        </button>
      </div>
    )
  }
}))

vi.mock('@renderer/components/chat/resources/variants/AgentResourceList', () => ({
  AgentResourceList: ({
    activeAgentId,
    onAddAgent,
    onActiveAgentDeleted
  }: {
    activeAgentId?: string | null
    onAddAgent?: () => void | Promise<void>
    onActiveAgentDeleted?: (agentId: string) => void | Promise<void>
  }) => (
    <div data-active-agent-id={activeAgentId ?? ''} data-testid="agent-resource-list">
      <button type="button" onClick={() => void onAddAgent?.()}>
        Open agent picker
      </button>
      <button type="button" onClick={() => void onActiveAgentDeleted?.(activeAgentId ?? '')}>
        Delete active agent
      </button>
    </div>
  )
}))

vi.mock('../components/AgentConversationPickerDialog', () => ({
  AgentConversationPickerDialog: ({ open, onSelect }: { open?: boolean; onSelect?: (agentId: string) => void }) =>
    open ? (
      <div data-testid="agent-conversation-picker">
        <button type="button" onClick={() => onSelect?.('agent-b')}>
          Select resource agent
        </button>
      </div>
    ) : null
}))

vi.mock('../components/Sessions', () => ({
  default: ({ agentIdFilter, presentation }: { agentIdFilter?: string | null; presentation?: string }) => (
    <div
      data-agent-id={agentIdFilter ?? ''}
      data-presentation={presentation ?? ''}
      data-testid="session-resource-panel"
    />
  )
}))

vi.mock('../../history/HistoryRecordsPage', () => ({
  default: ({ open, onRecordSelect }: { open?: boolean; onRecordSelect?: (sessionId: string | null) => void }) =>
    open ? (
      <button type="button" onClick={() => onRecordSelect?.(null)}>
        Clear history session
      </button>
    ) : null
}))

import { useTabSelfMetadata } from '@renderer/hooks/tab'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'

import AgentPage from '../AgentPage'

describe('AgentPage', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    agentPageMocks.routeSearch = { sessionId: 'session-initial' }
    agentPageMocks.agents = [{ id: 'agent-a', model: 'model-a', name: 'Agent A' }]
    agentPageMocks.classicLayoutSessions = []
    agentPageMocks.currentTab = undefined
    agentPageMocks.lastUsedAgentId = null
    agentPageMocks.lastUsedWorkspaceId = null
    agentPageMocks.classicLayoutRightPaneOpen = true
    agentPageMocks.activeSessionOptions = null
    agentPageMocks.focusExistingTab.mockReturnValue(false)
    agentPageMocks.sessionLayout = 'modern'
    agentPageMocks.showSidebar = false
    agentPageMocks.isActiveTab = false
    agentPageMocks.dataApiGet.mockImplementation(async (path: string) => {
      if (path === '/agent-workspaces/workspace-next') return agentPageMocks.workspaceNext
      if (path === '/agent-workspaces/workspace-remembered') {
        return { ...agentPageMocks.workspaceNext, id: 'workspace-remembered' }
      }
      return agentPageMocks.workspace
    })
    agentPageMocks.dataApiPost.mockResolvedValue(agentPageMocks.persistedSession)
    agentPageMocks.updateSession.mockResolvedValue(agentPageMocks.persistedSession)
    agentPageMocks.setSessionWorkspace.mockResolvedValue(agentPageMocks.persistedSession)
    agentPageMocks.invalidateCache.mockResolvedValue(undefined)
    activeSessionMocks.session = null
    activeSessionMocks.isLoading = false
    activeSessionMocks.sessionSource = 'none'

    Object.defineProperty(window, 'api', {
      configurable: true,
      value: {
        window: {
          resetMinimumSize: vi.fn().mockResolvedValue(undefined),
          setMinimumSize: vi.fn().mockResolvedValue(undefined)
        }
      }
    })
  })

  it('renders the agent resource list in the left pane', () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = { ...agentPageMocks.persistedSession, agentId: 'agent-a' }
    activeSessionMocks.sessionSource = 'query'

    render(<AgentPage />)

    expect(screen.getByTestId('agent-resource-list')).toHaveAttribute('data-active-agent-id', 'agent-a')
    expect(screen.getByTestId('session-resource-panel')).toHaveAttribute('data-agent-id', 'agent-a')
    expect(screen.getByTestId('session-resource-panel')).toHaveAttribute('data-presentation', 'right-panel')
    expect(screen.getByTestId('session-pane-open')).toHaveTextContent('true')
    expect(screen.queryByTestId('agent-side-panel')).not.toBeInTheDocument()
  })

  it('restores and records the classic-layout agent right pane open state from cache', () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.classicLayoutRightPaneOpen = false
    activeSessionMocks.session = { ...agentPageMocks.persistedSession, agentId: 'agent-a' }
    activeSessionMocks.sessionSource = 'query'

    render(<AgentPage />)

    expect(screen.getByTestId('session-pane-open')).toHaveTextContent('false')

    fireEvent.click(screen.getByRole('button', { name: 'Close session pane' }))

    expect(agentPageMocks.setClassicLayoutRightPaneOpen).toHaveBeenCalledWith(false)
  })

  it('passes the current agent task count to the classic-layout top button', () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = { ...agentPageMocks.persistedSession, agentId: 'agent-a' }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.classicLayoutSessions = [
      { ...agentPageMocks.persistedSession, id: 'session-a' },
      { ...agentPageMocks.persistedSession, id: 'session-b' },
      { ...agentPageMocks.persistedSession, id: 'session-other', agentId: 'agent-b' }
    ]

    render(<AgentPage />)

    expect(screen.getByTestId('resource-pane-count')).toHaveTextContent('任务:2')
    expect(screen.getByTestId('session-resource-panel')).toHaveAttribute('data-agent-id', 'agent-a')
    expect(screen.getByTestId('session-resource-panel')).toHaveAttribute('data-presentation', 'right-panel')
  })

  it('selects the latest historical session by default when entering classic layout without a route session', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.classicLayoutSessions = [
      {
        ...agentPageMocks.persistedSession,
        id: 'session-older',
        updatedAt: '2026-01-01T00:00:00.000Z'
      },
      {
        ...agentPageMocks.persistedSession,
        id: 'session-latest',
        updatedAt: '2026-01-03T00:00:00.000Z'
      }
    ]

    render(<AgentPage />)

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-latest'))
    expect(screen.getByTestId('active-session')).toHaveTextContent('session-latest')
    expect(screen.getByTestId('draft-session')).toHaveTextContent('')
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()
  })

  it('selects the latest remaining session after deleting the active agent (classic layout, never draft)', async () => {
    agentPageMocks.sessionLayout = 'classic'
    // Pin the active session via the route so the load-time auto-select effect stays out of the way.
    agentPageMocks.routeSearch = { sessionId: 'session-a' }
    activeSessionMocks.session = { ...agentPageMocks.persistedSession, id: 'session-a', agentId: 'agent-a' }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.classicLayoutSessions = [
      {
        ...agentPageMocks.persistedSession,
        id: 'session-a',
        agentId: 'agent-a',
        updatedAt: '2026-01-02T00:00:00.000Z'
      },
      {
        ...agentPageMocks.persistedSession,
        id: 'session-b-old',
        agentId: 'agent-b',
        updatedAt: '2026-01-01T00:00:00.000Z'
      },
      {
        ...agentPageMocks.persistedSession,
        id: 'session-b-new',
        agentId: 'agent-b',
        updatedAt: '2026-01-03T00:00:00.000Z'
      }
    ]

    render(<AgentPage />)
    fireEvent.click(screen.getByRole('button', { name: 'Delete active agent' }))

    // Classic layout settles on the latest session of a remaining agent, never the draft compose.
    await waitFor(() => expect(screen.getByTestId('active-session')).toHaveTextContent('session-b-new'))
    expect(screen.getByTestId('missing-agent-draft')).toHaveTextContent('false')
    expect(screen.getByTestId('draft-session')).toHaveTextContent('')
  })

  it('creates and activates an empty session after selecting an agent from the classic-layout picker', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.dataApiPost.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-picker',
      agentId: 'agent-b',
      workspaceId: undefined,
      workspace: {
        type: 'system',
        name: 'No project',
        path: ''
      }
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open agent picker' }))
    fireEvent.click(screen.getByRole('button', { name: 'Select resource agent' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
        body: {
          agentId: 'agent-b',
          name: '',
          workspace: { type: AGENT_WORKSPACE_TYPE.SYSTEM }
        }
      })
    )
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-picker')
    expect(screen.getByTestId('active-session')).toHaveTextContent('session-picker')
    expect(screen.getByTestId('draft-session')).toHaveTextContent('')
  })

  it('uses the remembered workspace when creating an empty session from the classic-layout picker', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.lastUsedWorkspaceId = 'workspace-remembered'
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.dataApiPost.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-picker-workspace',
      agentId: 'agent-b',
      workspaceId: 'workspace-remembered',
      workspace: { ...agentPageMocks.workspaceNext, id: 'workspace-remembered' }
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open agent picker' }))
    fireEvent.click(screen.getByRole('button', { name: 'Select resource agent' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiGet).toHaveBeenCalledWith('/agent-workspaces/workspace-remembered')
    )
    expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
      body: {
        agentId: 'agent-b',
        name: '',
        workspace: { type: AGENT_WORKSPACE_TYPE.USER, workspaceId: 'workspace-remembered' }
      }
    })
    expect(agentPageMocks.setLastUsedWorkspaceId).toHaveBeenCalledWith('workspace-remembered')
  })

  it('reuses the agent latest empty session instead of creating another one from the classic-layout picker', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.classicLayoutSessions = [
      {
        id: 'session-empty-latest',
        agentId: 'agent-b',
        name: '',
        createdAt: '2026-01-03T00:00:00.000Z',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspace: { type: 'system' }
      },
      // Touched (updatedAt > createdAt) → not an untouched placeholder, never reused.
      {
        id: 'session-real-older',
        agentId: 'agent-b',
        name: 'Real session',
        createdAt: '2026-01-01T00:00:00.000Z',
        updatedAt: '2026-01-01T01:00:00.000Z',
        workspace: { type: 'system' }
      }
    ]

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open agent picker' }))
    fireEvent.click(screen.getByRole('button', { name: 'Select resource agent' }))

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-empty-latest'))
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()
  })

  it('reuses the latest empty session when an older candidate has an invalid timestamp', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.classicLayoutSessions = [
      {
        id: 'session-empty-invalid',
        agentId: 'agent-b',
        name: '',
        createdAt: 'not-a-date',
        updatedAt: 'not-a-date',
        workspace: { type: 'system' }
      },
      {
        id: 'session-empty-latest',
        agentId: 'agent-b',
        name: '',
        createdAt: '2026-01-03T00:00:00.000Z',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspace: { type: 'system' }
      }
    ]

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open agent picker' }))
    fireEvent.click(screen.getByRole('button', { name: 'Select resource agent' }))

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-empty-latest'))
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()
  })

  it('reuses the current agent empty session from the classic-layout composer button', async () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = {
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      agentId: 'agent-a',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.classicLayoutSessions = [
      {
        id: 'session-empty-latest',
        agentId: 'agent-a',
        name: '',
        createdAt: '2026-01-03T00:00:00.000Z',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspaceId: 'workspace-a',
        workspace: { type: 'user' }
      }
    ]

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Create empty session from composer' }))

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-empty-latest'))
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()
    expect(agentPageMocks.invalidateCache).not.toHaveBeenCalled()
  })

  it('does not reuse an empty session from a different workspace from the classic-layout composer button', async () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = {
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      agentId: 'agent-a',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.classicLayoutSessions = [
      // Untouched placeholder, but a different workspace → blocked by workspace match, not touched-ness.
      {
        id: 'session-empty-other-workspace',
        agentId: 'agent-a',
        name: '',
        createdAt: '2026-01-03T00:00:00.000Z',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspaceId: 'workspace-b',
        workspace: { type: 'user' }
      }
    ]
    agentPageMocks.dataApiPost.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-composer-empty',
      agentId: 'agent-a',
      name: '',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Create empty session from composer' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
        body: {
          agentId: 'agent-a',
          name: '',
          workspace: { type: AGENT_WORKSPACE_TYPE.USER, workspaceId: 'workspace-a' }
        }
      })
    )
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-composer-empty')
  })

  it('creates a fresh session from the classic-layout composer button when the latest is chatted-in with a blank name (auto-naming off)', async () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = {
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      agentId: 'agent-a',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'
    // Auto-naming off keeps the name blank, but updatedAt has moved past createdAt — a real
    // conversation that must NOT be reused as an empty placeholder (#16434).
    agentPageMocks.classicLayoutSessions = [
      {
        id: 'session-chatted-blank',
        agentId: 'agent-a',
        name: '',
        createdAt: '2026-01-01T00:00:00.000Z',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspaceId: 'workspace-a',
        workspace: { type: 'user' }
      }
    ]
    agentPageMocks.dataApiPost.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-composer-empty',
      agentId: 'agent-a',
      name: '',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Create empty session from composer' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
        body: {
          agentId: 'agent-a',
          name: '',
          workspace: { type: AGENT_WORKSPACE_TYPE.USER, workspaceId: 'workspace-a' }
        }
      })
    )
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-composer-empty')
    expect(screen.getByTestId('active-session')).toHaveTextContent('session-composer-empty')
    expect(agentPageMocks.invalidateCache).toHaveBeenCalledWith([
      '/agent-sessions',
      '/agent-workspaces',
      '/agent-sessions/session-composer-empty'
    ])
  })

  it('toasts when the classic-layout composer empty-session creation fails', async () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = {
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      agentId: 'agent-a',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.classicLayoutSessions = []
    agentPageMocks.dataApiPost.mockRejectedValue(new Error('create failed'))
    const toastError = vi.fn()
    Object.assign(window, { toast: { error: toastError } })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Create empty session from composer' }))

    await waitFor(() => expect(agentPageMocks.dataApiPost).toHaveBeenCalled())
    await waitFor(() => expect(toastError).toHaveBeenCalled())
    // The active session is unchanged — no new session was activated.
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).not.toBe('session-composer-empty')
  })

  it('updates the active classic-layout session workspace through the composer control', async () => {
    agentPageMocks.sessionLayout = 'classic'
    activeSessionMocks.session = {
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      agentId: 'agent-a',
      workspaceId: 'workspace-a',
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'
    agentPageMocks.setSessionWorkspace.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-active',
      workspaceId: 'workspace-next',
      workspace: agentPageMocks.workspaceNext
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Select session workspace' }))

    await waitFor(() =>
      expect(agentPageMocks.setSessionWorkspace).toHaveBeenCalledWith('session-active', {
        type: AGENT_WORKSPACE_TYPE.USER,
        workspaceId: 'workspace-next'
      })
    )
    expect(agentPageMocks.setLastUsedWorkspaceId).toHaveBeenCalledWith('workspace-next')
  })

  it('creates a new session when the agent latest session is not empty from the classic-layout picker', async () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.classicLayoutSessions = [
      {
        id: 'session-real-latest',
        agentId: 'agent-b',
        name: 'Real session',
        updatedAt: '2026-01-03T00:00:00.000Z',
        workspace: { type: 'system' }
      }
    ]
    agentPageMocks.dataApiPost.mockResolvedValue({
      ...agentPageMocks.persistedSession,
      id: 'session-created',
      agentId: 'agent-b',
      workspaceId: undefined,
      workspace: { type: 'system', name: 'No project', path: '' }
    })

    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open agent picker' }))
    fireEvent.click(screen.getByRole('button', { name: 'Select resource agent' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith(
        '/agent-sessions',
        expect.objectContaining({ body: expect.objectContaining({ agentId: 'agent-b' }) })
      )
    )
  })

  it('uses tab metadata as the session entry when the URL is the agents route', () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.currentTab = { metadata: { instanceAppId: 'agents', instanceKey: 'session-from-metadata' } }

    render(<AgentPage />)

    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-from-metadata')
  })

  it('keeps the draft when clearing the tab metadata after starting a new task', async () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.currentTab = { metadata: { instanceAppId: 'agents', instanceKey: 'session-from-metadata' } }

    const { rerender } = render(<AgentPage />)

    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-from-metadata')

    fireEvent.click(screen.getByRole('button', { name: 'Start panel draft' }))

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a'))
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBeNull()

    agentPageMocks.currentTab = { metadata: { instanceAppId: 'agents' } }
    rerender(<AgentPage />)
    await act(async () => {
      await Promise.resolve()
    })

    expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a')
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBeNull()
  })

  it('keeps the metadata session key while the entry session is loading', () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.currentTab = { metadata: { instanceAppId: 'agents', instanceKey: 'session-from-metadata' } }
    activeSessionMocks.isLoading = true

    render(<AgentPage />)

    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-from-metadata')
    expect(vi.mocked(useTabSelfMetadata)).toHaveBeenLastCalledWith(
      expect.objectContaining({
        instanceAppId: 'agents',
        instanceKey: 'session-from-metadata'
      })
    )
  })

  it('updates the controlled session selection when the active session changes inside the tab', async () => {
    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Select session next' }))

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-next'))
    expect(screen.getByTestId('agent-side-panel')).toHaveAttribute('data-active-session-id', 'session-next')
  })

  it('starts a default draft session when history clears the active session', async () => {
    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Open history records' }))
    fireEvent.click(screen.getByRole('button', { name: 'Clear history session' }))

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a'))
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBeNull()
  })

  it('does not mutate the current tab before focusing an already-open global-search session', () => {
    agentPageMocks.focusExistingTab.mockReturnValue(true)

    render(<AgentPage />)

    const sessionMessageHandler = vi
      .mocked(EventEmitter.on)
      .mock.calls.find(([eventName]) => eventName === EVENT_NAMES.GLOBAL_SEARCH_SELECT_AGENT_SESSION_MESSAGE)?.[1] as
      | ((payload: unknown) => void)
      | undefined

    act(() => {
      sessionMessageHandler?.({ sessionId: 'session-open', messageId: 'message-open' })
    })

    expect(agentPageMocks.focusExistingTab).toHaveBeenCalledWith('session-open', { excludeTabId: 'agent-tab' })
    expect(agentPageMocks.setShowSidebar).not.toHaveBeenCalled()
    expect(screen.getByTestId('locate-message-id')).toHaveTextContent('')
  })

  it('opens the session pane when a global-search locate targets a session in the current tab', () => {
    agentPageMocks.sessionLayout = 'classic'
    agentPageMocks.classicLayoutRightPaneOpen = false
    agentPageMocks.focusExistingTab.mockReturnValue(false)

    render(<AgentPage />)

    expect(screen.getByTestId('session-pane-open')).toHaveTextContent('false')

    const sessionMessageHandler = vi
      .mocked(EventEmitter.on)
      .mock.calls.find(([eventName]) => eventName === EVENT_NAMES.GLOBAL_SEARCH_SELECT_AGENT_SESSION_MESSAGE)?.[1] as
      | ((payload: unknown) => void)
      | undefined

    act(() => {
      sessionMessageHandler?.({ sessionId: 'session-locate', messageId: 'message-locate' })
    })

    expect(screen.getByTestId('session-pane-open')).toHaveTextContent('true')
  })

  it('forwards a reveal request when navigation asks the current agent tab to reveal its selection', async () => {
    render(<AgentPage />)

    expect(JSON.parse(screen.getByTestId('agent-side-panel').getAttribute('data-reveal-request') ?? 'null')).toBeNull()

    const revealHandler = vi
      .mocked(EventEmitter.on)
      .mock.calls.find(([eventName]) => eventName === EVENT_NAMES.REVEAL_ACTIVE_RESOURCE_LIST)?.[1] as
      | ((payload: unknown) => void)
      | undefined

    act(() => {
      revealHandler?.({ source: 'agents', tabId: 'agent-tab' })
    })

    expect(JSON.parse(screen.getByTestId('agent-side-panel').getAttribute('data-reveal-request') ?? 'null')).toEqual({
      itemId: 'session-initial',
      requestId: 1
    })

    await act(async () => {
      await new Promise<void>((resolve) => window.requestAnimationFrame(() => resolve()))
    })

    expect(JSON.parse(screen.getByTestId('agent-side-panel').getAttribute('data-reveal-request') ?? 'null')).toBeNull()
  })

  it('collapses the agent sidebar when the shared shell requests it', async () => {
    agentPageMocks.showSidebar = true

    render(<AgentPage />)

    expect(screen.getByTestId('pane-open')).toHaveTextContent('true')

    fireEvent.click(screen.getByRole('button', { name: 'Collapse pane' }))

    await waitFor(() => expect(agentPageMocks.setShowSidebar).toHaveBeenCalledWith(false))
    expect(screen.getByTestId('pane-open')).toHaveTextContent('false')
  })

  it('removes the session sidebar entirely in a detached agent window, shortcut included', () => {
    agentPageMocks.showSidebar = true

    render(
      <WindowFrameProvider value={{ mode: 'window' }}>
        <AgentPage />
      </WindowFrameProvider>
    )

    expect(screen.getByTestId('pane-open')).toHaveTextContent('false')
    // Detached windows show no sidebar toggle / new-session button in the navbar.
    expect(screen.getByTestId('show-resource-list-controls')).toHaveTextContent('false')

    const shortcutHandler = vi
      .mocked(useCommandHandler)
      .mock.calls.find(([command]) => command === 'app.sidebar.toggle')?.[1]

    act(() => {
      void shortcutHandler?.()
    })

    // The sidebar-toggle shortcut is inert in a detached window — the pane stays closed.
    expect(screen.getByTestId('pane-open')).toHaveTextContent('false')
    expect(agentPageMocks.setShowSidebar).not.toHaveBeenCalled()
  })

  it('uses the compact minimum window width even while the agent sidebar is open', async () => {
    agentPageMocks.showSidebar = true

    render(<AgentPage />)

    await waitFor(() => {
      expect(window.api.window.setMinimumSize).toHaveBeenCalledWith(SECOND_MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
    })
  })

  it('shows the missing-agent home composer by default when there are no agents', async () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = []

    render(<AgentPage />)

    expect(screen.getByTestId('active-session')).toHaveTextContent('')
    await waitFor(() => expect(screen.getByTestId('missing-agent-draft')).toHaveTextContent('true'))
    expect(screen.getByTestId('agent-side-panel')).toBeInTheDocument()
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()
  })

  it('starts a renderer-only missing-agent draft after selecting an agent', async () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = []

    const { rerender } = render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Start missing agent draft' }))

    expect(screen.getByTestId('missing-agent-draft')).toHaveTextContent('true')
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()

    agentPageMocks.agents = [{ id: 'agent-b', model: 'model-b', name: 'Agent B' }]
    rerender(<AgentPage />)
    fireEvent.click(screen.getByRole('button', { name: 'Select missing draft agent' }))

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-b'))
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBeNull()
  })

  it('keeps the previous visible session metadata while the selected session is loading', async () => {
    agentPageMocks.routeSearch = { sessionId: 'session-1' }
    activeSessionMocks.session = {
      id: 'session-1',
      agentId: 'agent-a',
      name: 'Session 1',
      workspaceId: agentPageMocks.workspace.id,
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.sessionSource = 'query'

    const { rerender } = render(<AgentPage />)

    expect(screen.getByTestId('active-session')).toHaveTextContent('session-1')
    expect(vi.mocked(useTabSelfMetadata)).toHaveBeenLastCalledWith(
      expect.objectContaining({ instanceAppId: 'agents', instanceKey: 'session-1' })
    )

    agentPageMocks.routeSearch = { sessionId: 'session-2' }
    activeSessionMocks.session = null
    activeSessionMocks.isLoading = true
    rerender(<AgentPage />)

    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-2'))
    expect(screen.getByTestId('active-session')).toHaveTextContent('session-1')
    expect(screen.getByTestId('active-session-loading')).toHaveTextContent('true')
    expect(vi.mocked(useTabSelfMetadata)).toHaveBeenLastCalledWith(
      expect.objectContaining({ instanceAppId: 'agents', instanceKey: 'session-1' })
    )

    activeSessionMocks.session = {
      id: 'session-2',
      agentId: 'agent-a',
      name: 'Session 2',
      workspaceId: agentPageMocks.workspace.id,
      workspace: agentPageMocks.workspace
    }
    activeSessionMocks.isLoading = false
    rerender(<AgentPage />)

    expect(screen.getByTestId('active-session')).toHaveTextContent('session-2')
    expect(screen.getByTestId('active-session-loading')).toHaveTextContent('false')
    expect(vi.mocked(useTabSelfMetadata)).toHaveBeenLastCalledWith(
      expect.objectContaining({ instanceAppId: 'agents', instanceKey: 'session-2' })
    )
  })

  it('starts a first-launch draft session with the remembered agent and workspace', async () => {
    agentPageMocks.routeSearch = {}
    agentPageMocks.agents = [
      { id: 'agent-a', model: 'model-a', name: 'Agent A' },
      { id: 'agent-b', model: 'model-b', name: 'Agent B' }
    ]
    agentPageMocks.lastUsedAgentId = 'agent-b'
    agentPageMocks.lastUsedWorkspaceId = 'workspace-remembered'

    render(<AgentPage />)

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-b'))
    expect(agentPageMocks.dataApiGet).toHaveBeenCalledWith('/agent-workspaces/workspace-remembered')
    expect(screen.getByTestId('draft-workspace')).toHaveTextContent('workspace-remembered')
    expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBeNull()
  })

  it('rebuilds the draft session when the draft workspace changes', async () => {
    agentPageMocks.routeSearch = {}

    render(<AgentPage />)

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a'))
    fireEvent.click(screen.getByRole('button', { name: 'Select workspace' }))

    await waitFor(() => expect(agentPageMocks.dataApiGet).toHaveBeenCalledWith('/agent-workspaces/workspace-next'))
    expect(screen.getByTestId('draft-workspace')).toHaveTextContent('workspace-next')
    expect(agentPageMocks.setLastUsedWorkspaceId).toHaveBeenCalledWith('workspace-next')
  })

  it('persists the draft session only when the first message is sent', async () => {
    agentPageMocks.routeSearch = {}

    render(<AgentPage />)

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a'))
    expect(agentPageMocks.dataApiPost).not.toHaveBeenCalled()

    fireEvent.click(screen.getByRole('button', { name: 'Persist draft session' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
        body: {
          agentId: 'agent-a',
          name: 'hello',
          workspace: { type: AGENT_WORKSPACE_TYPE.SYSTEM }
        }
      })
    )
    await waitFor(() => expect(agentPageMocks.activeSessionOptions?.activeSessionId).toBe('session-created'))
    expect(screen.getByTestId('active-session')).toHaveTextContent('session-created')
  })

  it('uses the shared first-message temporary title when persisting a draft session', async () => {
    agentPageMocks.routeSearch = {}

    render(<AgentPage />)

    await waitFor(() => expect(screen.getByTestId('draft-session')).toHaveTextContent('agent-a'))
    fireEvent.click(screen.getByRole('button', { name: 'Persist long draft session' }))

    await waitFor(() =>
      expect(agentPageMocks.dataApiPost).toHaveBeenCalledWith('/agent-sessions', {
        body: {
          agentId: 'agent-a',
          name: 'Please inspect the renderer startup path and sugge',
          workspace: { type: AGENT_WORKSPACE_TYPE.SYSTEM }
        }
      })
    )
  })

  it('records the visible agent reported by the chat body', async () => {
    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Show visible agent' }))

    await waitFor(() => expect(agentPageMocks.setLastUsedAgentId).toHaveBeenCalledWith('agent-visible'))
  })

  it('records the visible workspace reported by the chat body', async () => {
    render(<AgentPage />)

    fireEvent.click(screen.getByRole('button', { name: 'Show visible workspace' }))

    await waitFor(() => expect(agentPageMocks.setLastUsedWorkspaceId).toHaveBeenCalledWith('workspace-visible'))
  })
})
