mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
perf(renderer): gate WorktreeCardAgentsBody's send-target subscriptions (#7545)
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -2,12 +2,14 @@
|
||||
agent rendering and lineage disclosure behavior together; splitting during
|
||||
this bug fix would risk divergent parent-child row behavior. */
|
||||
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { useAppStore } from '@/store'
|
||||
import { activateAndRevealWorktree } from '@/lib/worktree-activation'
|
||||
import { activateTabAndFocusPane } from '@/lib/activate-tab-and-focus-pane'
|
||||
import DashboardAgentRow from '@/components/dashboard/DashboardAgentRow'
|
||||
import { useNow } from '@/components/dashboard/useNow'
|
||||
import { deriveRunningAgentSendTargets } from '@/lib/running-agent-targets'
|
||||
import { selectSendTargetInputs } from './worktree-card-send-target-inputs'
|
||||
import { useWorktreeAgentRows } from './useWorktreeAgentRows'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { DashboardAgentRow as DashboardAgentRowData } from '@/components/dashboard/useDashboardData'
|
||||
@@ -89,12 +91,15 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
|
||||
const dropAgentStatus = useAppStore((s) => s.dropAgentStatus)
|
||||
const dismissRetainedAgent = useAppStore((s) => s.dismissRetainedAgent)
|
||||
const agentSendPopoverTargetMode = useAppStore((s) => s.agentSendPopoverTargetMode)
|
||||
const agentStatusByPaneKey = useAppStore((s) => s.agentStatusByPaneKey)
|
||||
const agentStatusEpoch = useAppStore((s) => s.agentStatusEpoch)
|
||||
const tabsByWorktree = useAppStore((s) => s.tabsByWorktree)
|
||||
const terminalLayoutsByTabId = useAppStore((s) => s.terminalLayoutsByTabId)
|
||||
const ptyIdsByTabId = useAppStore((s) => s.ptyIdsByTabId)
|
||||
const runtimePaneTitlesByTabId = useAppStore((s) => s.runtimePaneTitlesByTabId)
|
||||
// Why: these five maps are read only to derive send-target eligibility, which
|
||||
// matters only while the send-target popover targets THIS card. Two of them
|
||||
// (runtimePaneTitlesByTabId, agentStatusByPaneKey) churn on every pane-title
|
||||
// and agent-status write app-wide, so subscribing to them unconditionally made
|
||||
// every mounted agent body re-render on unrelated terminals. Gate the
|
||||
// subscription: return a stable empty constant when the popover isn't ours, so
|
||||
// useShallow keeps the same result and idle bodies stop reacting to the churn.
|
||||
const sendTargetInputs = useAppStore(useShallow((s) => selectSendTargetInputs(s, worktreeId)))
|
||||
const sendPromptToSidebarAgentTarget = useAppStore((s) => s.sendPromptToSidebarAgentTarget)
|
||||
const focusedAgentPaneKey = useFocusedAgentPaneKey(worktreeId)
|
||||
const compactAgentListRootRef = useRef<HTMLDivElement | null>(null)
|
||||
@@ -134,16 +139,7 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
|
||||
}
|
||||
|
||||
return new Map(
|
||||
deriveRunningAgentSendTargets(
|
||||
{
|
||||
agentStatusByPaneKey,
|
||||
tabsByWorktree,
|
||||
terminalLayoutsByTabId,
|
||||
ptyIdsByTabId,
|
||||
runtimePaneTitlesByTabId
|
||||
},
|
||||
worktreeId
|
||||
).map((target) => [
|
||||
deriveRunningAgentSendTargets(sendTargetInputs, worktreeId).map((target) => [
|
||||
target.paneKey,
|
||||
agentSendPopoverTargetMode?.status === 'sending' &&
|
||||
agentSendPopoverTargetMode.sendingPaneKey === target.paneKey
|
||||
@@ -159,12 +155,11 @@ const WorktreeCardAgentsBody = React.memo(function WorktreeCardAgentsBody({
|
||||
agentStatusEpoch,
|
||||
agentSendPopoverTargetMode?.sendingPaneKey,
|
||||
agentSendPopoverTargetMode?.status,
|
||||
agentStatusByPaneKey,
|
||||
isAgentSendTargetModeActive,
|
||||
ptyIdsByTabId,
|
||||
runtimePaneTitlesByTabId,
|
||||
tabsByWorktree,
|
||||
terminalLayoutsByTabId,
|
||||
// sendTargetInputs is a stable empty constant while inactive and a
|
||||
// shallow-compared bundle of the five maps while active, so it covers all
|
||||
// five former deps in one reference.
|
||||
sendTargetInputs,
|
||||
worktreeId
|
||||
])
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { shallow } from 'zustand/shallow'
|
||||
import type { AgentSendPopoverTargetMode } from '@/store/slices/ui'
|
||||
import {
|
||||
EMPTY_SEND_TARGET_INPUTS,
|
||||
selectSendTargetInputs,
|
||||
type SendTargetInputsState
|
||||
} from './worktree-card-send-target-inputs'
|
||||
|
||||
const BASE: SendTargetInputsState = {
|
||||
agentSendPopoverTargetMode: null,
|
||||
agentStatusByPaneKey: {},
|
||||
tabsByWorktree: {},
|
||||
terminalLayoutsByTabId: {},
|
||||
ptyIdsByTabId: {},
|
||||
runtimePaneTitlesByTabId: {}
|
||||
}
|
||||
|
||||
function makeMode(worktreeId: string): AgentSendPopoverTargetMode {
|
||||
return {
|
||||
id: 'mode-1',
|
||||
instanceId: 'inst-1',
|
||||
worktreeId,
|
||||
source: 'diff-notes',
|
||||
prompt: 'do it',
|
||||
label: 'Send',
|
||||
launchSource: 'sidebar',
|
||||
eligiblePaneKeys: [],
|
||||
disabledPaneKeys: {},
|
||||
status: 'open'
|
||||
}
|
||||
}
|
||||
|
||||
describe('selectSendTargetInputs', () => {
|
||||
it('returns the shared empty constant when the popover does not target this worktree', () => {
|
||||
// Inactive (popover closed): stable empty reference.
|
||||
const inactive = selectSendTargetInputs(BASE, 'wt-A')
|
||||
expect(inactive).toBe(EMPTY_SEND_TARGET_INPUTS)
|
||||
|
||||
// Churning the hottest maps while inactive must NOT change the selected
|
||||
// reference, so a useShallow subscription skips the re-render.
|
||||
const churned: SendTargetInputsState = {
|
||||
...BASE,
|
||||
runtimePaneTitlesByTabId: { 'tab-1': 'claude' },
|
||||
agentStatusByPaneKey: { 'tab-1:leaf-1': {} as never }
|
||||
}
|
||||
const afterChurn = selectSendTargetInputs(churned, 'wt-A')
|
||||
expect(afterChurn).toBe(EMPTY_SEND_TARGET_INPUTS)
|
||||
expect(shallow(inactive, afterChurn)).toBe(true)
|
||||
})
|
||||
|
||||
it('stays the stable empty constant when the popover targets a different worktree', () => {
|
||||
const s: SendTargetInputsState = { ...BASE, agentSendPopoverTargetMode: makeMode('wt-OTHER') }
|
||||
expect(selectSendTargetInputs(s, 'wt-A')).toBe(EMPTY_SEND_TARGET_INPUTS)
|
||||
})
|
||||
|
||||
it('exposes the live maps when the popover targets this worktree', () => {
|
||||
const titles = { 'tab-1': 'claude' }
|
||||
const s: SendTargetInputsState = {
|
||||
...BASE,
|
||||
agentSendPopoverTargetMode: makeMode('wt-A'),
|
||||
runtimePaneTitlesByTabId: titles
|
||||
}
|
||||
const active = selectSendTargetInputs(s, 'wt-A')
|
||||
// Live map references pass straight through so eligibility derives correctly.
|
||||
expect(active.runtimePaneTitlesByTabId).toBe(titles)
|
||||
expect(active).not.toBe(EMPTY_SEND_TARGET_INPUTS)
|
||||
})
|
||||
|
||||
it('shallow-changes only when a subscribed map reference actually changes while active', () => {
|
||||
const titles = { 'tab-1': 'claude' }
|
||||
const s1: SendTargetInputsState = {
|
||||
...BASE,
|
||||
agentSendPopoverTargetMode: makeMode('wt-A'),
|
||||
runtimePaneTitlesByTabId: titles
|
||||
}
|
||||
const r1 = selectSendTargetInputs(s1, 'wt-A')
|
||||
|
||||
// Same underlying map refs -> shallow-equal -> no re-render.
|
||||
expect(shallow(r1, selectSendTargetInputs(s1, 'wt-A'))).toBe(true)
|
||||
|
||||
// A real pane-title write replaces the map ref -> shallow-unequal -> the
|
||||
// open popover re-derives eligibility, exactly as before this change.
|
||||
const s2: SendTargetInputsState = { ...s1, runtimePaneTitlesByTabId: { 'tab-1': 'codex' } }
|
||||
expect(shallow(r1, selectSendTargetInputs(s2, 'wt-A'))).toBe(false)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { RunningAgentTargetState } from '@/lib/running-agent-targets'
|
||||
|
||||
export type SendTargetInputsState = Pick<
|
||||
AppState,
|
||||
| 'agentSendPopoverTargetMode'
|
||||
| 'agentStatusByPaneKey'
|
||||
| 'tabsByWorktree'
|
||||
| 'terminalLayoutsByTabId'
|
||||
| 'ptyIdsByTabId'
|
||||
| 'runtimePaneTitlesByTabId'
|
||||
>
|
||||
|
||||
// Why: shared stable reference returned whenever the send-target popover isn't
|
||||
// targeting this card. useShallow keeps the same result across unrelated
|
||||
// pane-title / agent-status churn, so idle agent bodies stop re-rendering.
|
||||
// Frozen so this shared singleton can never be mutated by a consumer.
|
||||
export const EMPTY_SEND_TARGET_INPUTS: RunningAgentTargetState = Object.freeze({
|
||||
agentStatusByPaneKey: {},
|
||||
tabsByWorktree: {},
|
||||
terminalLayoutsByTabId: {},
|
||||
ptyIdsByTabId: {},
|
||||
runtimePaneTitlesByTabId: {}
|
||||
})
|
||||
|
||||
/**
|
||||
* Select the five maps `deriveRunningAgentSendTargets` needs — but only while
|
||||
* the send-target popover targets this worktree. When it doesn't, return a
|
||||
* stable empty constant so a useShallow-wrapped subscription stays referentially
|
||||
* equal across the (very hot) pane-title / agent-status writes and skips the
|
||||
* re-render that would otherwise fire on every mounted agent body app-wide.
|
||||
*/
|
||||
export function selectSendTargetInputs(
|
||||
s: SendTargetInputsState,
|
||||
worktreeId: string
|
||||
): RunningAgentTargetState {
|
||||
if (s.agentSendPopoverTargetMode?.worktreeId !== worktreeId) {
|
||||
return EMPTY_SEND_TARGET_INPUTS
|
||||
}
|
||||
return {
|
||||
agentStatusByPaneKey: s.agentStatusByPaneKey,
|
||||
tabsByWorktree: s.tabsByWorktree,
|
||||
terminalLayoutsByTabId: s.terminalLayoutsByTabId,
|
||||
ptyIdsByTabId: s.ptyIdsByTabId,
|
||||
runtimePaneTitlesByTabId: s.runtimePaneTitlesByTabId
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user