mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 00:03:15 +00:00
fix(chat): localize monitoring status without render churn
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { AgentStateDot, agentStateLabel } from '@/components/AgentStateDot'
|
||||
|
||||
const MONITORING_LABEL = agentStateLabel('monitoring')
|
||||
import { AgentStateDot } from '@/components/AgentStateDot'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
|
||||
export function NativeChatMonitoringStatus({
|
||||
monitoring
|
||||
@@ -20,7 +19,9 @@ export function NativeChatMonitoringStatus({
|
||||
<span aria-hidden="true">
|
||||
<AgentStateDot state="monitoring" title={null} />
|
||||
</span>
|
||||
<span>{MONITORING_LABEL}</span>
|
||||
<span>
|
||||
{translate('components.native-chat.monitoringStatus.label', 'Monitoring background tasks')}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,12 +44,11 @@ function resolveNativeChatHookStatus(
|
||||
}
|
||||
|
||||
export function useNativeChatMonitoringStatus(paneKey: string): boolean {
|
||||
// Why: monitoring stays out of foreground lifecycle while remaining visible from the tab glyph's pane-status source.
|
||||
const agentStatusEpoch = useAppStore((store) => store.agentStatusEpoch)
|
||||
void agentStatusEpoch
|
||||
return useAppStore((store) =>
|
||||
resolveNativeChatMonitoringStatus(store.agentStatusByPaneKey[paneKey])
|
||||
)
|
||||
return useAppStore((store) => {
|
||||
// Why: epoch invalidates freshness; the primitive result avoids unrelated-pane rerenders.
|
||||
void store.agentStatusEpoch
|
||||
return resolveNativeChatMonitoringStatus(store.agentStatusByPaneKey[paneKey])
|
||||
})
|
||||
}
|
||||
|
||||
export function useNativeChatHookStatus(
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import '@testing-library/jest-dom/vitest'
|
||||
|
||||
import { act, cleanup, render, screen } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
|
||||
import { AGENT_STATUS_STALE_AFTER_MS } from '../../../../shared/agent-status-types'
|
||||
import { useAppStore } from '@/store'
|
||||
import { useNativeChatMonitoringStatus } from './use-native-chat-hook-status'
|
||||
|
||||
const PANE_KEY = 'tab-1:11111111-1111-4111-8111-111111111111'
|
||||
|
||||
function monitoringEntry(updatedAt: number): AgentStatusEntry {
|
||||
return {
|
||||
paneKey: PANE_KEY,
|
||||
state: 'working',
|
||||
workingMode: 'monitoring',
|
||||
prompt: 'Monitor background tasks',
|
||||
updatedAt,
|
||||
stateStartedAt: updatedAt,
|
||||
stateHistory: []
|
||||
}
|
||||
}
|
||||
|
||||
describe('useNativeChatMonitoringStatus', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
vi.setSystemTime(new Date('2026-09-04T12:00:00.000Z'))
|
||||
useAppStore.setState({
|
||||
agentStatusByPaneKey: { [PANE_KEY]: monitoringEntry(Date.now()) },
|
||||
agentStatusEpoch: 0
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
cleanup()
|
||||
useAppStore.setState({ agentStatusByPaneKey: {}, agentStatusEpoch: 0 })
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('rerenders at expiry without rerendering for an unrelated epoch', () => {
|
||||
let renders = 0
|
||||
function Probe(): React.JSX.Element {
|
||||
renders += 1
|
||||
const monitoring = useNativeChatMonitoringStatus(PANE_KEY)
|
||||
return <span>{monitoring ? 'monitoring' : 'idle'}</span>
|
||||
}
|
||||
|
||||
render(<Probe />)
|
||||
expect(screen.getByText('monitoring')).toBeInTheDocument()
|
||||
expect(renders).toBe(1)
|
||||
|
||||
act(() => {
|
||||
useAppStore.setState((state) => ({ agentStatusEpoch: state.agentStatusEpoch + 1 }))
|
||||
})
|
||||
expect(renders).toBe(1)
|
||||
|
||||
vi.setSystemTime(Date.now() + AGENT_STATUS_STALE_AFTER_MS + 1)
|
||||
act(() => {
|
||||
useAppStore.setState((state) => ({ agentStatusEpoch: state.agentStatusEpoch + 1 }))
|
||||
})
|
||||
expect(screen.getByText('idle')).toBeInTheDocument()
|
||||
expect(renders).toBe(2)
|
||||
})
|
||||
})
|
||||
@@ -17009,7 +17009,10 @@
|
||||
},
|
||||
"structuredSessionCloseFailed": "Could not close this Codex chat",
|
||||
"structuredSessionLaunchFailed": "Could not open Codex chat",
|
||||
"structuredSessionCloseFailedDescription": "The terminal stayed open so the provider remains recoverable."
|
||||
"structuredSessionCloseFailedDescription": "The terminal stayed open so the provider remains recoverable.",
|
||||
"monitoringStatus": {
|
||||
"label": "Monitoring background tasks"
|
||||
}
|
||||
},
|
||||
"tab": {
|
||||
"bar": {
|
||||
|
||||
Reference in New Issue
Block a user