mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
refactor(terminal): keep mobile content-fact caches in their producers (#27537)
The agent-status projection and mobile terminal theme kept their caches on the shared graph state object. Each producer now owns its cache, so neither imports the graph state or graph types; the graph still calls them as before.
This commit is contained in:
@@ -19,14 +19,19 @@ import { performance } from 'node:perf_hooks'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const GRAPH_SOURCE = readFileSync(
|
||||
fileURLToPath(new URL('../../src/renderer/src/runtime/sync-runtime-graph.ts', import.meta.url)),
|
||||
fileURLToPath(
|
||||
new URL(
|
||||
'../../src/renderer/src/runtime/sync-runtime-graph/agent-status-projection.ts',
|
||||
import.meta.url
|
||||
)
|
||||
),
|
||||
'utf8'
|
||||
)
|
||||
|
||||
const bucketMatch = GRAPH_SOURCE.match(/AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS = ([0-9_]+)/)
|
||||
if (!bucketMatch) {
|
||||
throw new Error(
|
||||
'sync-runtime-graph.ts no longer defines the updatedAt bucket; re-sync this benchmark.'
|
||||
'agent-status-projection.ts no longer defines the updatedAt bucket; re-sync this benchmark.'
|
||||
)
|
||||
}
|
||||
const BUCKET_MS = Number(bucketMatch[1].replaceAll('_', ''))
|
||||
|
||||
@@ -20,6 +20,7 @@ vi.mock('./sync-runtime-graph/editor-draft-hash', async (importOriginal) => {
|
||||
|
||||
const { stableHashString } = await import('./sync-runtime-graph/editor-draft-hash')
|
||||
const {
|
||||
AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS_FOR_TESTS: AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS,
|
||||
buildRuntimeMobileAgentStatusProjectionForTests,
|
||||
getRuntimeMobileSessionSyncKey,
|
||||
resetRuntimeMobileAgentStatusProjectionCacheForTests,
|
||||
@@ -31,7 +32,6 @@ const {
|
||||
buildRuntimeMobileEditorDraftsProjection,
|
||||
buildRuntimeMobileOpenFilesProjection
|
||||
} = await import('./sync-runtime-graph/sync-projections')
|
||||
const { AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS } = await import('./sync-runtime-graph/graph-state')
|
||||
|
||||
// ── Reference implementations: the pre-change bodies, kept verbatim ────────────────────
|
||||
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { AgentMainAgentStatus } from '../../../../shared/main-agent-status'
|
||||
import { AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS, graphState } from './graph-state'
|
||||
import type { AgentStatusProjectionCacheEntry } from './types'
|
||||
|
||||
const AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS = 30_000
|
||||
|
||||
type AgentStatusProjectionCacheEntry = {
|
||||
entry: AppState['agentStatusByPaneKey'][string]
|
||||
projection: string
|
||||
}
|
||||
type AgentStatusProjectionCache = {
|
||||
source: AppState['agentStatusByPaneKey']
|
||||
entries: Map<string, AgentStatusProjectionCacheEntry>
|
||||
projection: string
|
||||
}
|
||||
|
||||
let cachedAgentStatusProjection: AgentStatusProjectionCache | null = null
|
||||
|
||||
function mainAgentKey(mainAgent: AgentMainAgentStatus | undefined) {
|
||||
return mainAgent ? [mainAgent.state, mainAgent.outcome ?? null, mainAgent.stateStartedAt] : null
|
||||
@@ -44,7 +56,7 @@ function serializeAgentStatusEntry(
|
||||
export function buildRuntimeMobileAgentStatusProjection(
|
||||
agentStatusByPaneKey: AppState['agentStatusByPaneKey']
|
||||
): string {
|
||||
const cached = graphState.cachedAgentStatusProjection
|
||||
const cached = cachedAgentStatusProjection
|
||||
if (cached?.source === agentStatusByPaneKey) {
|
||||
return cached.projection
|
||||
}
|
||||
@@ -59,7 +71,7 @@ export function buildRuntimeMobileAgentStatusProjection(
|
||||
nextEntries.length === cached.entries.size &&
|
||||
nextEntries.every(([paneKey, entry]) => cached.entries.get(paneKey)?.entry === entry)
|
||||
) {
|
||||
graphState.cachedAgentStatusProjection = {
|
||||
cachedAgentStatusProjection = {
|
||||
...cached,
|
||||
source: agentStatusByPaneKey
|
||||
}
|
||||
@@ -85,7 +97,7 @@ export function buildRuntimeMobileAgentStatusProjection(
|
||||
}
|
||||
// Same-bucket heartbeats must not rejoin every pane's accumulated preview text.
|
||||
const projection = projectionUnchanged && cached ? cached.projection : `[${parts.join(',')}]`
|
||||
graphState.cachedAgentStatusProjection = {
|
||||
cachedAgentStatusProjection = {
|
||||
source: agentStatusByPaneKey,
|
||||
entries,
|
||||
projection
|
||||
@@ -103,5 +115,5 @@ export const AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS_FOR_TESTS =
|
||||
AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS
|
||||
|
||||
export function resetRuntimeMobileAgentStatusProjectionCacheForTests(): void {
|
||||
graphState.cachedAgentStatusProjection = null
|
||||
cachedAgentStatusProjection = null
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ import { createBrowserUuid } from '@/lib/browser-uuid'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type {
|
||||
RuntimeMobileSessionSnapshotTab,
|
||||
RuntimeMobileSessionTabsSnapshot,
|
||||
RuntimeMobileTerminalTheme
|
||||
RuntimeMobileSessionTabsSnapshot
|
||||
} from '../../../../shared/runtime-types'
|
||||
import type {
|
||||
AgentStatusProjectionCache,
|
||||
BrowserPagesProjectionCache,
|
||||
BrowserWorkspacesProjectionCache,
|
||||
EditorDraftHashCache,
|
||||
@@ -17,7 +15,6 @@ import type {
|
||||
} from './types'
|
||||
|
||||
export const NO_TRANSPORT_GRACE_MS = 10_000
|
||||
export const AGENT_STATUS_SYNC_UPDATED_AT_BUCKET_MS = 30_000
|
||||
export const RUNTIME_GRAPH_SYNC_COALESCE_MS = 16
|
||||
|
||||
export const EMPTY_ACTIVE_BROWSER_TAB_ID_BY_WORKTREE: AppState['activeBrowserTabIdByWorktree'] = {}
|
||||
@@ -41,7 +38,6 @@ export const graphState = {
|
||||
syncEnabled: false,
|
||||
syncTimer: null as ReturnType<typeof setTimeout> | null,
|
||||
getStoreState: null as (() => AppState) | null,
|
||||
mobileSessionSnapshotVersion: 0,
|
||||
mobileSessionSnapshotCacheByWorktree: new Map<
|
||||
string,
|
||||
{
|
||||
@@ -52,17 +48,13 @@ export const graphState = {
|
||||
>(),
|
||||
publishedMobileSessionSnapshotByWorktree: new Map<string, RuntimeMobileSessionTabsSnapshot>(),
|
||||
cachedTabsProjection: null as TabsProjectionCache | null,
|
||||
cachedAgentStatusProjection: null as AgentStatusProjectionCache | null,
|
||||
cachedOpenFilesProjection: null as OpenFilesProjectionCache | null,
|
||||
cachedBrowserWorkspacesProjection: null as BrowserWorkspacesProjectionCache | null,
|
||||
cachedBrowserPagesProjection: null as BrowserPagesProjectionCache | null,
|
||||
cachedOpenFileIndexesSource: null as AppState['openFiles'] | null,
|
||||
cachedOpenFileIndexes: null as OpenFileIndexes | null,
|
||||
cachedEditorDraftHashes: null as EditorDraftHashCache | null,
|
||||
cachedMobileTerminalThemeSettings: null as AppState['settings'] | null,
|
||||
cachedMobileTerminalThemeSystemPrefersDark: null as boolean | null,
|
||||
cachedMobileTerminalTheme: undefined as RuntimeMobileTerminalTheme | undefined,
|
||||
hasCachedMobileTerminalTheme: false
|
||||
mobileSessionSnapshotVersion: 0
|
||||
}
|
||||
|
||||
/** IDs occurring more than once cannot address the legacy tab-keyed runtime maps safely. */
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { getSystemPrefersDark, resolveEffectiveTerminalAppearance } from '@/lib/terminal-theme'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { RuntimeMobileTerminalTheme } from '../../../../shared/runtime-types'
|
||||
import { graphState } from './graph-state'
|
||||
import { normalizeTerminalMinimumContrastRatio } from '@/lib/terminal-contrast-correction'
|
||||
|
||||
function hexToRgba(hex: string, alpha: number): string {
|
||||
@@ -64,20 +63,25 @@ export function resolveMobileTerminalTheme(
|
||||
}
|
||||
}
|
||||
|
||||
let cachedMobileTerminalThemeSettings: AppState['settings'] | null = null
|
||||
let cachedMobileTerminalThemeSystemPrefersDark: boolean | null = null
|
||||
let cachedMobileTerminalTheme: RuntimeMobileTerminalTheme | undefined
|
||||
let hasCachedMobileTerminalTheme = false
|
||||
|
||||
export function getMobileTerminalTheme(
|
||||
state: AppState,
|
||||
systemPrefersDark = getSystemPrefersDark()
|
||||
): RuntimeMobileTerminalTheme | undefined {
|
||||
if (
|
||||
graphState.hasCachedMobileTerminalTheme &&
|
||||
graphState.cachedMobileTerminalThemeSettings === state.settings &&
|
||||
graphState.cachedMobileTerminalThemeSystemPrefersDark === systemPrefersDark
|
||||
hasCachedMobileTerminalTheme &&
|
||||
cachedMobileTerminalThemeSettings === state.settings &&
|
||||
cachedMobileTerminalThemeSystemPrefersDark === systemPrefersDark
|
||||
) {
|
||||
return graphState.cachedMobileTerminalTheme
|
||||
return cachedMobileTerminalTheme
|
||||
}
|
||||
graphState.cachedMobileTerminalTheme = resolveMobileTerminalTheme(state, systemPrefersDark)
|
||||
graphState.cachedMobileTerminalThemeSettings = state.settings
|
||||
graphState.cachedMobileTerminalThemeSystemPrefersDark = systemPrefersDark
|
||||
graphState.hasCachedMobileTerminalTheme = true
|
||||
return graphState.cachedMobileTerminalTheme
|
||||
cachedMobileTerminalTheme = resolveMobileTerminalTheme(state, systemPrefersDark)
|
||||
cachedMobileTerminalThemeSettings = state.settings
|
||||
cachedMobileTerminalThemeSystemPrefersDark = systemPrefersDark
|
||||
hasCachedMobileTerminalTheme = true
|
||||
return cachedMobileTerminalTheme
|
||||
}
|
||||
|
||||
@@ -92,15 +92,6 @@ export type EditorDraftHashCache = {
|
||||
hashByFileId: Map<string, string>
|
||||
projection: string
|
||||
}
|
||||
export type AgentStatusProjectionCacheEntry = {
|
||||
entry: AppState['agentStatusByPaneKey'][string]
|
||||
projection: string
|
||||
}
|
||||
export type AgentStatusProjectionCache = {
|
||||
source: AppState['agentStatusByPaneKey']
|
||||
entries: Map<string, AgentStatusProjectionCacheEntry>
|
||||
projection: string
|
||||
}
|
||||
export type MobileSessionAgentStatusByWorktree = ReadonlyMap<
|
||||
string,
|
||||
ReadonlyMap<string, AppState['agentStatusByPaneKey'][string]>
|
||||
|
||||
Reference in New Issue
Block a user