diff --git a/config/scripts/pr-e2e-gate-contract.test.mjs b/config/scripts/pr-e2e-gate-contract.test.mjs index 7daa7522548..6bbc4510980 100644 --- a/config/scripts/pr-e2e-gate-contract.test.mjs +++ b/config/scripts/pr-e2e-gate-contract.test.mjs @@ -36,7 +36,7 @@ describe('restart-survival E2E routing', () => { 'src/main/runtime/rpc/methods/browser-client-host.ts', 'src/main/browser/browser-client-host-authority-replacement-wait.ts', 'src/main/browser/paired-runtime-browser-client-host-composition.ts', - 'src/renderer/src/runtime/web-session-tabs-sync.ts', + 'src/renderer/src/runtime/web-session-tabs-sync/snapshot-api.ts', 'src/renderer/src/runtime/host-session-snapshot-authority.ts', 'src/renderer/src/runtime/restored-client-hosted-browser-host-attach.ts', 'src/renderer/src/store/slices/runtime-status.ts', @@ -131,7 +131,7 @@ describe('PR E2E gate contract', () => { 'src/renderer/src/components/terminal-pane/terminal-error-accumulation.ts', 'src/renderer/src/runtime/web-runtime-terminal-creation.ts', 'src/renderer/src/runtime/web-runtime-session-tab-lifecycle.ts', - 'src/renderer/src/runtime/web-session-tabs-sync.ts', + 'src/renderer/src/runtime/web-session-tabs-sync/use-web-session-tabs-sync.ts', 'src/renderer/src/runtime/web-session-terminal-orphan-recovery.ts', 'src/renderer/src/runtime/web-session-terminal-orphan-recovery-adoption.ts', 'src/renderer/src/runtime/web-session-terminal-orphan-recovery-surface.ts', diff --git a/config/scripts/pr-e2e-layout-oracle-routing.test.mjs b/config/scripts/pr-e2e-layout-oracle-routing.test.mjs index b4afd8e5c4a..f98629bac20 100644 --- a/config/scripts/pr-e2e-layout-oracle-routing.test.mjs +++ b/config/scripts/pr-e2e-layout-oracle-routing.test.mjs @@ -35,7 +35,7 @@ const STACK_WRITERS = [ 'src/renderer/src/store/slices/terminals.ts', 'src/renderer/src/components/terminal-pane/TerminalPane.tsx', 'src/renderer/src/runtime/sync-runtime-graph.ts', - 'src/renderer/src/runtime/web-session-tabs-sync.ts', + 'src/renderer/src/runtime/web-session-tabs-sync/store-patch.ts', 'src/main/runtime/orca-runtime-split-terminal.ts', 'src/main/runtime/orca-runtime-sync-window-graph.ts', 'src/main/runtime/mobile-session-layout-projection.ts', diff --git a/config/scripts/pr-e2e-source-routing.mjs b/config/scripts/pr-e2e-source-routing.mjs index 1b29e5ff45c..05b76b35341 100644 --- a/config/scripts/pr-e2e-source-routing.mjs +++ b/config/scripts/pr-e2e-source-routing.mjs @@ -337,7 +337,7 @@ export const PR_E2E_SOURCE_ROUTES = [ specs: ['tests/e2e/paired-remote-terminal-serve-restart-binding.spec.ts'], matches: (file) => isProductSource(file) && - /^(?:src\/main\/daemon\/(?:daemon-attach-only-retirement|daemon-pty-applied-size|daemon-pty-session-control|daemon-pty-spawn-result)\.ts|src\/renderer\/src\/components\/terminal-pane\/(?:remote-runtime-pty-transport|terminal-error-accumulation)\.ts|src\/renderer\/src\/runtime\/(?:web-runtime-terminal-creation|web-runtime-session-tab-lifecycle|web-session-tabs-sync|web-session-terminal-orphan-(?:topology|recovery(?:-(?:adoption|surface|inventory|inventory-validation|cache|queue|rpc-lane|pane))?))\.ts)$/.test( + /^(?:src\/main\/daemon\/(?:daemon-attach-only-retirement|daemon-pty-applied-size|daemon-pty-session-control|daemon-pty-spawn-result)\.ts|src\/renderer\/src\/components\/terminal-pane\/(?:remote-runtime-pty-transport|terminal-error-accumulation)\.ts|src\/renderer\/src\/runtime\/(?:web-runtime-terminal-creation|web-runtime-session-tab-lifecycle|web-session-tabs-sync\/use-web-session-tabs-sync|web-session-terminal-orphan-(?:topology|recovery(?:-(?:adoption|surface|inventory|inventory-validation|cache|queue|rpc-lane|pane))?))\.ts)$/.test( file ) }, @@ -367,7 +367,7 @@ export const PR_E2E_SOURCE_ROUTES = [ specs: ['tests/e2e/paired-remote-pane-layout-retry.spec.ts'], matches: (file) => isProductSource(file) && - /^(?:src\/renderer\/src\/components\/terminal-pane\/(?:remote-pane-layout-push|TerminalPane)\.tsx?|src\/renderer\/src\/lib\/terminal-layout-equality\.ts|src\/renderer\/src\/runtime\/web-session-tabs-sync\.ts|src\/renderer\/src\/store\/slices\/terminals\.ts)$/.test( + /^(?:src\/renderer\/src\/components\/terminal-pane\/(?:remote-pane-layout-push|TerminalPane)\.tsx?|src\/renderer\/src\/lib\/terminal-layout-equality\.ts|src\/renderer\/src\/runtime\/web-session-tabs-sync\/use-web-session-tabs-sync\.ts|src\/renderer\/src\/store\/slices\/terminals\.ts)$/.test( file ) }, diff --git a/config/scripts/pr-unit-support-routing.test.mjs b/config/scripts/pr-unit-support-routing.test.mjs index 21fbdfd452c..fc849c2b0c1 100644 --- a/config/scripts/pr-unit-support-routing.test.mjs +++ b/config/scripts/pr-unit-support-routing.test.mjs @@ -25,7 +25,7 @@ describe('unit support routing', () => { (unitHarness) => { for (const file of [ 'src/renderer/src/runtime/web-session-tabs-sync-next-test-harness.ts', - 'src/renderer/src/runtime/web-session-tabs-sync.ts', + 'src/renderer/src/runtime/web-session-tabs-sync/snapshot-api.ts', 'src/renderer/src/components/native-chat/NativeChatStructuredSession.next-test-harness.tsx', 'src/renderer/src/components/native-chat/NativeChatStructuredSession.tsx', 'src/main/providers/windows-conpty-wide-char-duplication.node-pty.test.ts', @@ -50,7 +50,7 @@ describe('unit support routing', () => { const spec = 'tests/e2e/paired-client-hosted-browser-restart-survival.spec.ts' for (const file of [ 'src/renderer/src/runtime/web-session-tabs-sync-next-test-harness.ts', - 'src/renderer/src/runtime/web-session-tabs-sync.ts', + 'src/renderer/src/runtime/web-session-tabs-sync/snapshot-api.ts', spec ]) { expect(selectPrE2eSpecs([harness, file]), file).toContain(spec) diff --git a/src/renderer/src/app-shell/use-app-shell-services.ts b/src/renderer/src/app-shell/use-app-shell-services.ts index ebe65572811..9cd6fed0245 100644 --- a/src/renderer/src/app-shell/use-app-shell-services.ts +++ b/src/renderer/src/app-shell/use-app-shell-services.ts @@ -14,7 +14,7 @@ import { import { useRadixBodyPointerEventsRecovery } from '../hooks/useRadixBodyPointerEventsRecovery' import { useGitStatusPolling } from '../components/right-sidebar/useGitStatusPolling' import { useOsc52ClipboardDefaultOnNotice } from '../components/terminal-pane/osc52-clipboard-default-on-notice' -import { useWebSessionTabsSync } from '../runtime/web-session-tabs-sync' +import { useWebSessionTabsSync } from '../runtime/web-session-tabs-sync/use-web-session-tabs-sync' import { useLocalStructuredSessionTabsSync } from '../runtime/local-structured-session-tabs-sync' import { useHostStructuredAgentsSync } from '../runtime/host-structured-agents-sync' import { useHostModelCatalogSnapshotsSync } from '../runtime/host-model-catalog-snapshots-sync' diff --git a/src/renderer/src/components/terminal/terminal-close-confirm-keyboard-vs-mouse.test.ts b/src/renderer/src/components/terminal/terminal-close-confirm-keyboard-vs-mouse.test.ts index 16e7e42e18d..5c6bc77e255 100644 --- a/src/renderer/src/components/terminal/terminal-close-confirm-keyboard-vs-mouse.test.ts +++ b/src/renderer/src/components/terminal/terminal-close-confirm-keyboard-vs-mouse.test.ts @@ -43,8 +43,10 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: vi.fn((tabId: string) => tabId) })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ - getLatestWebSessionTabsPublicationEpoch: vi.fn(() => 'epoch-1'), +vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ + getLatestWebSessionTabsPublicationEpoch: vi.fn(() => 'epoch-1') +})) +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: resolveHostSessionTabIdForWebSessionTabMock })) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions-kill-all.test.ts b/src/renderer/src/components/terminal/terminal-tab-actions-kill-all.test.ts index 5afaa29977c..e9d01e71eca 100644 --- a/src/renderer/src/components/terminal/terminal-tab-actions-kill-all.test.ts +++ b/src/renderer/src/components/terminal/terminal-tab-actions-kill-all.test.ts @@ -26,7 +26,7 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: vi.fn((tabId: string) => tabId) })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: vi.fn(() => null) })) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts b/src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts index db49761fa48..ce1d48d3bfb 100644 --- a/src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts +++ b/src/renderer/src/components/terminal/terminal-tab-actions-unified-close.test.ts @@ -23,8 +23,10 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: vi.fn((tabId: string) => tabId) })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ - getLatestWebSessionTabsPublicationEpoch: vi.fn(() => null), +vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ + getLatestWebSessionTabsPublicationEpoch: vi.fn(() => null) +})) +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: vi.fn(() => null) })) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts b/src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts index 5efef986723..5f8bbc489dd 100644 --- a/src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts +++ b/src/renderer/src/components/terminal/terminal-tab-actions-unrouted-close.test.ts @@ -21,8 +21,10 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: (tabId: string) => tabId })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ - getLatestWebSessionTabsPublicationEpoch: () => null, +vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ + getLatestWebSessionTabsPublicationEpoch: () => null +})) +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: () => null })) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions.test.ts b/src/renderer/src/components/terminal/terminal-tab-actions.test.ts index bb49769f7f1..8af23f055c8 100644 --- a/src/renderer/src/components/terminal/terminal-tab-actions.test.ts +++ b/src/renderer/src/components/terminal/terminal-tab-actions.test.ts @@ -43,8 +43,10 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: toHostSessionTabIdMock })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ - getLatestWebSessionTabsPublicationEpoch: getLatestWebSessionTabsPublicationEpochMock, +vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ + getLatestWebSessionTabsPublicationEpoch: getLatestWebSessionTabsPublicationEpochMock +})) +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: resolveHostSessionTabIdForWebSessionTabMock })) diff --git a/src/renderer/src/components/terminal/terminal-tab-actions.ts b/src/renderer/src/components/terminal/terminal-tab-actions.ts index 03187001a63..37b002cdb3e 100644 --- a/src/renderer/src/components/terminal/terminal-tab-actions.ts +++ b/src/renderer/src/components/terminal/terminal-tab-actions.ts @@ -2,10 +2,8 @@ import { useAppStore } from '@/store' import { closeWebRuntimeSessionTab } from '@/runtime/web-runtime-session-tab-lifecycle' import { isWebRuntimeSessionActive } from '@/runtime/web-runtime-session-environment' import { toHostSessionTabId } from '@/runtime/web-terminal-surface-id' -import { - getLatestWebSessionTabsPublicationEpoch, - resolveHostSessionTabIdForWebSessionTab -} from '@/runtime/web-session-tabs-sync' +import { getLatestWebSessionTabsPublicationEpoch } from '@/runtime/web-session-tabs-sync/tracking-lifecycle' +import { resolveHostSessionTabIdForWebSessionTab } from '@/runtime/web-session-tabs-sync/tracking-mappings' import { resolveTerminalCloseRoute } from '@/lib/terminal-close-route' import { guardPinnedTabClose, diff --git a/src/renderer/src/components/terminal/terminal-tab-close-running-confirm.test.ts b/src/renderer/src/components/terminal/terminal-tab-close-running-confirm.test.ts index 1a30871181c..548cb1f792e 100644 --- a/src/renderer/src/components/terminal/terminal-tab-close-running-confirm.test.ts +++ b/src/renderer/src/components/terminal/terminal-tab-close-running-confirm.test.ts @@ -39,8 +39,10 @@ vi.mock('@/runtime/web-terminal-surface-id', () => ({ toHostSessionTabId: vi.fn((tabId: string) => tabId) })) -vi.mock('@/runtime/web-session-tabs-sync', () => ({ - getLatestWebSessionTabsPublicationEpoch: vi.fn(() => 'epoch-1'), +vi.mock('@/runtime/web-session-tabs-sync/tracking-lifecycle', () => ({ + getLatestWebSessionTabsPublicationEpoch: vi.fn(() => 'epoch-1') +})) +vi.mock('@/runtime/web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: resolveHostSessionTabIdForWebSessionTabMock })) diff --git a/src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts b/src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts index ce246d00327..ad98e476904 100644 --- a/src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts +++ b/src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts @@ -3,7 +3,7 @@ import { tabHasLivePty } from '@/lib/tab-has-live-pty' import { createWebRuntimeSessionTerminal } from '@/runtime/web-runtime-terminal-creation' import { isWebRuntimeSessionActive } from '@/runtime/web-runtime-session-environment' import { isWebTerminalSurfaceTabId } from '@/runtime/web-terminal-surface-id' -import { getLastKnownHostTerminalTabCount } from '@/runtime/web-session-tabs-sync' +import { getLastKnownHostTerminalTabCount } from '@/runtime/web-session-tabs-sync/tracking-lifecycle' import { beginWebRuntimeWakeTerminalRespawn, endWebRuntimeWakeTerminalRespawn diff --git a/src/renderer/src/lib/worktree-activation-created-agent.test.ts b/src/renderer/src/lib/worktree-activation-created-agent.test.ts index 91ff86c43a2..6619eb32214 100644 --- a/src/renderer/src/lib/worktree-activation-created-agent.test.ts +++ b/src/renderer/src/lib/worktree-activation-created-agent.test.ts @@ -3,7 +3,7 @@ import { getDefaultSettings } from '../../../shared/constants' import { useAppStore } from '@/store' import { activateAndRevealWorktree } from './worktree-activation' import { ensureWebRuntimeWorktreeTerminalAfterWake } from './web-runtime-worktree-terminal-after-wake' -import { resetWebSessionTabsSnapshotFreshnessForTests } from '@/runtime/web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from '@/runtime/web-session-tabs-sync/tracking-lifecycle' import { resetWebRuntimeWakeTerminalRespawnForTests } from '@/runtime/web-runtime-wake-terminal-respawn' import { makeCreatedAgentWorktree as makeWorktree, @@ -494,7 +494,8 @@ describe('activateAndRevealWorktree', () => { })) }) - const { shouldApplyWebSessionTabsSnapshot } = await import('@/runtime/web-session-tabs-sync') + const { shouldApplyWebSessionTabsSnapshot } = + await import('@/runtime/web-session-tabs-sync/tracking-decisions') shouldApplyWebSessionTabsSnapshot( { worktree: worktree.id, diff --git a/src/renderer/src/lib/worktree-activation-empty-remote.test.ts b/src/renderer/src/lib/worktree-activation-empty-remote.test.ts index 9dea28f2e0c..2d350a82207 100644 --- a/src/renderer/src/lib/worktree-activation-empty-remote.test.ts +++ b/src/renderer/src/lib/worktree-activation-empty-remote.test.ts @@ -3,7 +3,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { getDefaultSettings } from '../../../shared/constants' import type { Worktree } from '../../../shared/worktree/types' import { resetWebRuntimeWakeTerminalRespawnForTests } from '@/runtime/web-runtime-wake-terminal-respawn' -import { resetWebSessionTabsSnapshotFreshnessForTests } from '@/runtime/web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from '@/runtime/web-session-tabs-sync/tracking-lifecycle' import { useAppStore } from '@/store' import { ensureWebRuntimeWorktreeTerminalAfterWake } from './web-runtime-worktree-terminal-after-wake' import { toast } from 'sonner' @@ -117,6 +117,12 @@ describe('empty remote worktree activation', () => { }) ) expect(toast.error).not.toHaveBeenCalled() + // Why: drain the post-create snapshot refresh so it cannot land on the next test's bridge. + await vi.waitFor(() => + expect(callRuntimeEnvironment).toHaveBeenCalledWith( + expect.objectContaining({ method: 'session.tabs.list' }) + ) + ) }) it('surfaces a failed host terminal request without retrying ambiguously', async () => { diff --git a/src/renderer/src/runtime/host-session-mirror-frame-ordering-harness.ts b/src/renderer/src/runtime/host-session-mirror-frame-ordering-harness.ts index 98c1e93d34d..472761778b0 100644 --- a/src/renderer/src/runtime/host-session-mirror-frame-ordering-harness.ts +++ b/src/renderer/src/runtime/host-session-mirror-frame-ordering-harness.ts @@ -24,7 +24,7 @@ import { } from './host-session-mirror-frame-fixtures' import { resetHostSessionMirrorHydrationForTests } from './host-session-mirror-hydration' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' -import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' const initialState = useAppStore.getInitialState() diff --git a/src/renderer/src/runtime/host-session-mirror-hydration-frame-ordering.test.tsx b/src/renderer/src/runtime/host-session-mirror-hydration-frame-ordering.test.tsx index bcbbef03350..4fc867c6c37 100644 --- a/src/renderer/src/runtime/host-session-mirror-hydration-frame-ordering.test.tsx +++ b/src/renderer/src/runtime/host-session-mirror-hydration-frame-ordering.test.tsx @@ -70,11 +70,9 @@ import { setDocumentVisibility, tabIds } from './host-session-mirror-frame-ordering-harness' -import { - clearWebSessionTabsTrackingForEnvironment, - useWebSessionTabsSync, - WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS -} from './web-session-tabs-sync' +import { clearWebSessionTabsTrackingForEnvironment } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' +import { WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS } from './web-session-tabs-sync/state' import { hasHostSessionMirrorHydrated } from './host-session-mirror-hydration' import { WINDOW_VISIBILITY_SUBSCRIPTION_PARK_DELAY_MS } from './window-visibility-subscription-parking' diff --git a/src/renderer/src/runtime/host-session-mirror-settle-receipt-frames.test.tsx b/src/renderer/src/runtime/host-session-mirror-settle-receipt-frames.test.tsx index 33861ccfadd..ea9aa7e7e43 100644 --- a/src/renderer/src/runtime/host-session-mirror-settle-receipt-frames.test.tsx +++ b/src/renderer/src/runtime/host-session-mirror-settle-receipt-frames.test.tsx @@ -72,11 +72,9 @@ import { hasHostSessionMirrorHydrated } from './host-session-mirror-hydration' import { refreshWebRuntimeSessionTabsSnapshot } from './web-runtime-session-snapshot' -import { - clearWebSessionTabsTrackingForEnvironment, - useWebSessionTabsSync, - WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS -} from './web-session-tabs-sync' +import { clearWebSessionTabsTrackingForEnvironment } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' +import { WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS } from './web-session-tabs-sync/state' import { WINDOW_VISIBILITY_SUBSCRIPTION_PARK_DELAY_MS } from './window-visibility-subscription-parking' /** diff --git a/src/renderer/src/runtime/local-structured-session-empty-worktree-visibility.test.ts b/src/renderer/src/runtime/local-structured-session-empty-worktree-visibility.test.ts index 22af26b6544..f3fca9cb707 100644 --- a/src/renderer/src/runtime/local-structured-session-empty-worktree-visibility.test.ts +++ b/src/renderer/src/runtime/local-structured-session-empty-worktree-visibility.test.ts @@ -2,7 +2,8 @@ import { afterEach, describe, expect, it } from 'vitest' import type { RuntimeMobileSessionTabsResult } from '../../../shared/runtime-types' import type { Tab } from '../../../shared/tab-types' import { projectLocalStructuredSessionTabs } from './local-structured-session-tabs-sync' -import { applyWebSessionTabsSnapshot, type WebSessionTabsSyncState } from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' import { collectClientLayoutGroupIds } from './web-session-client-owned-tab-placement' import { resetWebSessionFocusIntentForTests } from './web-session-focus-intent' diff --git a/src/renderer/src/runtime/local-structured-session-retired-epoch-repair.test.ts b/src/renderer/src/runtime/local-structured-session-retired-epoch-repair.test.ts index 95edbadbf58..88974375907 100644 --- a/src/renderer/src/runtime/local-structured-session-retired-epoch-repair.test.ts +++ b/src/renderer/src/runtime/local-structured-session-retired-epoch-repair.test.ts @@ -17,7 +17,7 @@ import { resetLocalStructuredSessionVersionForTests } from './local-structured-session-tabs-sync' import { localStructuredSessionEpochHistoryByWorktree } from './local-structured-session-tabs-sync/inventory-generation-fence' -import type { WebSessionTabsSyncState } from './web-session-tabs-sync' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' import { resetWebSessionFocusIntentForTests } from './web-session-focus-intent' const WORKTREE = 'folder:ws-1' diff --git a/src/renderer/src/runtime/local-structured-session-reveal-visibility.test.ts b/src/renderer/src/runtime/local-structured-session-reveal-visibility.test.ts index 181ec3ebe27..6df5e16a869 100644 --- a/src/renderer/src/runtime/local-structured-session-reveal-visibility.test.ts +++ b/src/renderer/src/runtime/local-structured-session-reveal-visibility.test.ts @@ -18,8 +18,8 @@ import { applyLocalStructuredSessionTabSnapshots, resetLocalStructuredSessionVersionForTests } from './local-structured-session-tabs-sync' -import type { WebSessionTabsSyncState } from './web-session-tabs-sync' -import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' const WORKTREE = 'repo-1::/tmp/wt-reveal' const HOST_TAB_ID = 'agent-session:codex-reveal-1' diff --git a/src/renderer/src/runtime/local-structured-session-tab-retirement.ts b/src/renderer/src/runtime/local-structured-session-tab-retirement.ts index db560849044..1a51a220c65 100644 --- a/src/renderer/src/runtime/local-structured-session-tab-retirement.ts +++ b/src/renderer/src/runtime/local-structured-session-tab-retirement.ts @@ -1,6 +1,6 @@ import type { WorktreeRuntimeOwnerState } from '../lib/worktree-runtime-owner' import { folderWorkspaceKey } from '../../../shared/workspace-scope' -import type { WebSessionTabsSyncState } from './web-session-tabs-sync' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' export type StructuredSessionTabPublicationVersion = { publicationEpoch: string diff --git a/src/renderer/src/runtime/local-structured-session-tabs-host-isolation.test.ts b/src/renderer/src/runtime/local-structured-session-tabs-host-isolation.test.ts index 1329ae4b6ef..61407540060 100644 --- a/src/renderer/src/runtime/local-structured-session-tabs-host-isolation.test.ts +++ b/src/renderer/src/runtime/local-structured-session-tabs-host-isolation.test.ts @@ -6,7 +6,8 @@ import { applyLocalStructuredSessionTabSnapshots, projectLocalStructuredSessionTabs } from './local-structured-session-tabs-sync' -import { applyWebSessionTabsSnapshot, type WebSessionTabsSyncState } from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' import { ENV, HOST_SURFACE_ID, diff --git a/src/renderer/src/runtime/local-structured-session-tabs-sync.test.ts b/src/renderer/src/runtime/local-structured-session-tabs-sync.test.ts index 7c1c0cf7ae1..c9a01f3acc7 100644 --- a/src/renderer/src/runtime/local-structured-session-tabs-sync.test.ts +++ b/src/renderer/src/runtime/local-structured-session-tabs-sync.test.ts @@ -14,11 +14,9 @@ import { resetLocalStructuredSessionVersionForTests, startLocalStructuredSessionTabsSync } from './local-structured-session-tabs-sync' -import { - applyWebSessionTabsSnapshot, - resetWebSessionTabsSnapshotFreshnessForTests, - type WebSessionTabsSyncState -} from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' import { recordWebSessionFocusIntent, resetWebSessionFocusIntentForTests diff --git a/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts b/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts index 156eb6c6df4..34b9f8a70af 100644 --- a/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts +++ b/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts @@ -5,11 +5,9 @@ import type { import { markStructuredAgentSessionLaunchesPublished } from '../../lib/structured-agent-session-launch-publication' import type { WorktreeRuntimeOwnerState } from '../../lib/worktree-runtime-owner' import { getExecutionHostIdForWorktree } from '../../lib/worktree-runtime-owner' -import { - applyWebSessionTabsSnapshot, - applyWebSessionTabsStorePatch -} from '../web-session-tabs-sync' -import type { WebSessionTabsSyncState } from '../web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from '../web-session-tabs-sync/snapshot-api' +import { applyWebSessionTabsStorePatch } from '../web-session-tabs-sync/store-patch' +import type { WebSessionTabsSyncState } from '../web-session-tabs-sync/state' import { admitRetiredValueUnderAuthority, noteRetiredValue, diff --git a/src/renderer/src/runtime/local-structured-session-unverifiable-inventory.test.ts b/src/renderer/src/runtime/local-structured-session-unverifiable-inventory.test.ts index ad2e7380b8b..4817e9d3379 100644 --- a/src/renderer/src/runtime/local-structured-session-unverifiable-inventory.test.ts +++ b/src/renderer/src/runtime/local-structured-session-unverifiable-inventory.test.ts @@ -13,11 +13,9 @@ import { applyLocalStructuredSessionTabSnapshots, resetLocalStructuredSessionVersionForTests } from './local-structured-session-tabs-sync' -import { - applyWebSessionTabsSnapshot, - resetWebSessionTabsSnapshotFreshnessForTests, - type WebSessionTabsSyncState -} from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' const WORKTREE_ID = 'repo-1::worktree-1' const TERMINAL_ID = 'terminal-1' diff --git a/src/renderer/src/runtime/use-runtime-session-mirror-environment-key.test.ts b/src/renderer/src/runtime/use-runtime-session-mirror-environment-key.test.ts index 2069bb85bdc..4e777f746d2 100644 --- a/src/renderer/src/runtime/use-runtime-session-mirror-environment-key.test.ts +++ b/src/renderer/src/runtime/use-runtime-session-mirror-environment-key.test.ts @@ -24,7 +24,7 @@ import { selectRuntimeSessionMirrorTargetInputs, useRuntimeSessionMirrorEnvironmentKeys } from './use-runtime-session-mirror-environment-key' -import { useWebSessionTabsSync } from './web-session-tabs-sync' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' const initialState = useAppStore.getInitialState() diff --git a/src/renderer/src/runtime/web-runtime-browser-capability-cleanup.test.ts b/src/renderer/src/runtime/web-runtime-browser-capability-cleanup.test.ts index f6ae6c5c52b..a4b11ce53e9 100644 --- a/src/renderer/src/runtime/web-runtime-browser-capability-cleanup.test.ts +++ b/src/renderer/src/runtime/web-runtime-browser-capability-cleanup.test.ts @@ -21,12 +21,18 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: vi.fn(), - applyWebSessionTabsSnapshot: vi.fn(), - decideWebSessionTabsSnapshot: vi.fn(() => ({ apply: true, settlesHostMirror: true })), - getWebSessionTabsTrackingGeneration: vi.fn(() => 0), - applyWebSessionTabsStorePatch: vi.fn(() => () => {}), + getWebSessionTabsTrackingGeneration: vi.fn(() => 0) +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ applyWebSessionTabsSnapshot: vi.fn() })) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: vi.fn(() => ({ apply: true, settlesHostMirror: true })) +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ + applyWebSessionTabsStorePatch: vi.fn(() => () => {}) +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: vi.fn() })) diff --git a/src/renderer/src/runtime/web-runtime-browser-creation-placement-test-rig.ts b/src/renderer/src/runtime/web-runtime-browser-creation-placement-test-rig.ts index 6eacef429e3..db9d6279159 100644 --- a/src/renderer/src/runtime/web-runtime-browser-creation-placement-test-rig.ts +++ b/src/renderer/src/runtime/web-runtime-browser-creation-placement-test-rig.ts @@ -5,7 +5,7 @@ import type { Tab, TabGroup } from '../../../shared/tab-types' import type { ExecutionHostId } from '../../../shared/execution-host' import { useAppStore } from '../store' import type { AppState } from '../store/types' -import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' import { ENV, NOW, WT, makeSnapshot } from './web-session-tabs-sync-test-harness' export const HOST: ExecutionHostId = `runtime:${ENV}` diff --git a/src/renderer/src/runtime/web-runtime-session-browser-client-placement.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-client-placement.test.ts index 99b4e8747f0..e93f664fa39 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-client-placement.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-client-placement.test.ts @@ -47,16 +47,24 @@ vi.mock('../store', () => ({ subscribe: mocks.subscribe } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) vi.mock('@/lib/feature-education-telemetry', () => ({ diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-failure.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-failure.test.ts index 0384a4875f9..251aaf60f6d 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-failure.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-failure.test.ts @@ -41,16 +41,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-focus.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-focus.test.ts index 0e94dea229f..9f8b2eb05b1 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-focus.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-focus.test.ts @@ -43,16 +43,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-split-placement.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-split-placement.test.ts index 3c9fa9c217f..56a741bc07f 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-split-placement.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-split-placement.test.ts @@ -44,16 +44,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-staged-focus.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-staged-focus.test.ts index 4116efaf43d..625a3a46826 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-staged-focus.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-staged-focus.test.ts @@ -48,16 +48,24 @@ vi.mock('../store', () => ({ subscribe: mocks.subscribe } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) vi.mock('@/lib/feature-education-telemetry', () => ({ diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-staged-hosting-intent.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-staged-hosting-intent.test.ts index 9d249832fd6..f5a55c6adde 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-staged-hosting-intent.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-staged-hosting-intent.test.ts @@ -48,16 +48,24 @@ vi.mock('../store', () => ({ subscribe: mocks.subscribe } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) vi.mock('@/lib/feature-education-telemetry', () => ({ diff --git a/src/renderer/src/runtime/web-runtime-session-browser-create-staging.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-create-staging.test.ts index dbc39a31d02..d519d51ab78 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-create-staging.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-create-staging.test.ts @@ -44,16 +44,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-browser-placement-staleness.test.ts b/src/renderer/src/runtime/web-runtime-session-browser-placement-staleness.test.ts index 5b2352f78b0..add36d9a4dc 100644 --- a/src/renderer/src/runtime/web-runtime-session-browser-placement-staleness.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-browser-placement-staleness.test.ts @@ -47,15 +47,23 @@ vi.mock('../store', () => ({ subscribe: mocks.subscribe } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) vi.mock('@/lib/feature-education-telemetry', () => ({ diff --git a/src/renderer/src/runtime/web-runtime-session-snapshot.ts b/src/renderer/src/runtime/web-runtime-session-snapshot.ts index 86b5399abab..e2805054be2 100644 --- a/src/renderer/src/runtime/web-runtime-session-snapshot.ts +++ b/src/renderer/src/runtime/web-runtime-session-snapshot.ts @@ -13,8 +13,8 @@ import { captureRuntimeEnvironmentCall } from './web-runtime-session-environment import { throwIfE2eWebRuntimeBrowserReconciliationFails } from './web-runtime-browser-creation-e2e-fault' import { getSessionTabsRuntimeIdFromResponse } from './web-session-tabs-sync/publisher-identity-fences' import { WEB_SESSION_TABS_FRAME_OUTRANKED } from './web-session-tabs-sync/tracking-decisions' -// Not through the barrel: receipt ordering is this path's gate, not an optional collaborator a -// caller's module mock may leave out — doing so is what left this path unordered to begin with. +// Imported statically, not lazily: receipt ordering is this path's gate, not an optional +// collaborator a caller's module mock may leave out — doing so is what left this path unordered. import { recordReceivedWebSessionTabsSnapshot, shouldApplyRecoveredWebSessionTabsSnapshot @@ -39,20 +39,31 @@ export async function refreshWebRuntimeSessionTabsSnapshot( errorMode?: 'warn' | 'throw' } = {} ): Promise { - const webSessionTabsSync = await import('./web-session-tabs-sync') + // Why one await up front: the apply below must not yield between the list and its receipt. + const [ + { applyWebSessionTabsSnapshot }, + { applyWebSessionTabsStorePatch }, + { decideWebSessionTabsSnapshot }, + { getWebSessionTabsTrackingGeneration } + ] = await Promise.all([ + import('./web-session-tabs-sync/snapshot-api'), + import('./web-session-tabs-sync/store-patch'), + import('./web-session-tabs-sync/tracking-decisions'), + import('./web-session-tabs-sync/tracking-lifecycle') + ]) const expectedEnvironmentPairingRevision = options.expectedEnvironmentPairingRevision ?? getRuntimeEnvironmentRevision(environmentId) const expectedEnvironmentConnectionGeneration = getRuntimeEnvironmentConnectionGeneration(environmentId) - const expectedTrackingGeneration = - webSessionTabsSync.getWebSessionTabsTrackingGeneration(environmentId) + const expectedTrackingGeneration = getWebSessionTabsTrackingGeneration(environmentId) const callEnvironment = captureRuntimeEnvironmentCall( environmentId, expectedEnvironmentPairingRevision ) try { if (options.acceptCurrentSnapshot) { - const { acceptReplayedWebSessionTabsSnapshot } = await import('./web-session-tabs-sync') + const { acceptReplayedWebSessionTabsSnapshot } = + await import('./web-session-tabs-sync/tracking-lifecycle') // Why: the host snapshot may have arrived before structured create returned; // re-accept its current version after the exact provisional handoff is known. acceptReplayedWebSessionTabsSnapshot(environmentId, worktreeId) @@ -93,11 +104,6 @@ export async function refreshWebRuntimeSessionTabsSnapshot( ...options.confirmAgentSessionHandoff }) } - const { - applyWebSessionTabsSnapshot, - applyWebSessionTabsStorePatch, - decideWebSessionTabsSnapshot - } = webSessionTabsSync // A list is evidence about a moment, not about now. Record its place in receipt order before // ranking it, or a snapshot the host answered before a close lands after the retraction did. recordReceivedWebSessionTabsSnapshot( diff --git a/src/renderer/src/runtime/web-runtime-session-tab-activate-close.test.ts b/src/renderer/src/runtime/web-runtime-session-tab-activate-close.test.ts index 12839e5ccea..c3cbf2cb7f5 100644 --- a/src/renderer/src/runtime/web-runtime-session-tab-activate-close.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-tab-activate-close.test.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type * as TrackingDecisions from './web-session-tabs-sync/tracking-decisions' import { activateWebRuntimeSessionTab, closeWebRuntimeSessionTab @@ -47,16 +48,25 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', async (importOriginal) => ({ + ...(await importOriginal()), + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-tab-lifecycle.ts b/src/renderer/src/runtime/web-runtime-session-tab-lifecycle.ts index baea7869400..0143417d970 100644 --- a/src/renderer/src/runtime/web-runtime-session-tab-lifecycle.ts +++ b/src/renderer/src/runtime/web-runtime-session-tab-lifecycle.ts @@ -113,7 +113,8 @@ async function callWebRuntimeSessionTabMethod( if (isLifecycleClose && (!args.publicationEpoch || !args.terminalHandle)) { // Why: missing host-generation or terminal-incarnation evidence means keep; // a tab id alone can be stale or reused after reconnect. - const { acceptReplayedWebSessionTabsSnapshot } = await import('./web-session-tabs-sync') + const { acceptReplayedWebSessionTabsSnapshot } = + await import('./web-session-tabs-sync/tracking-lifecycle') acceptReplayedWebSessionTabsSnapshot(environmentId, args.worktreeId) await refreshWebRuntimeSessionTabsSnapshot(environmentId, args.worktreeId) console.warn('[web-runtime-session] suppressed lifecycle close without incarnation evidence', { @@ -130,7 +131,8 @@ async function callWebRuntimeSessionTabMethod( } try { - const { resolveHostSessionTabIdForWebSessionTab } = await import('./web-session-tabs-sync') + const { resolveHostSessionTabIdForWebSessionTab } = + await import('./web-session-tabs-sync/tracking-mappings') const state = useAppStore.getState() const hostTabId = resolveHostSessionTabIdForWebSessionTab(state, { @@ -191,7 +193,8 @@ async function callWebRuntimeSessionTabMethod( // only when it republished; dead-leaf refusals must stay suppressed. clearWebSessionCloseIntent(intentOwner, args.worktreeId, immediateHostTabId) clearWebSessionCloseIntent(intentOwner, args.worktreeId, hostTabId) - const { acceptReplayedWebSessionTabsSnapshot } = await import('./web-session-tabs-sync') + const { acceptReplayedWebSessionTabsSnapshot } = + await import('./web-session-tabs-sync/tracking-lifecycle') acceptReplayedWebSessionTabsSnapshot(environmentId, args.worktreeId) } await refreshWebRuntimeSessionTabsSnapshot(environmentId, args.worktreeId, { @@ -220,7 +223,8 @@ async function callWebRuntimeSessionTabMethod( } } if (isLifecycleClose) { - const { acceptReplayedWebSessionTabsSnapshot } = await import('./web-session-tabs-sync') + const { acceptReplayedWebSessionTabsSnapshot } = + await import('./web-session-tabs-sync/tracking-lifecycle') acceptReplayedWebSessionTabsSnapshot(environmentId, args.worktreeId) await refreshWebRuntimeSessionTabsSnapshot(environmentId, args.worktreeId, { expectedEnvironmentPairingRevision: intentOwner.pairingRevision diff --git a/src/renderer/src/runtime/web-runtime-session-tab-move.test.ts b/src/renderer/src/runtime/web-runtime-session-tab-move.test.ts index cc169aed2a9..4ea4ae504e2 100644 --- a/src/renderer/src/runtime/web-runtime-session-tab-move.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-tab-move.test.ts @@ -38,16 +38,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab, resolveHostSessionGroupIdForWebSessionTab: mocks.resolveHostSessionGroupIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-tab-move.ts b/src/renderer/src/runtime/web-runtime-session-tab-move.ts index d80271e2827..69640e94bf7 100644 --- a/src/renderer/src/runtime/web-runtime-session-tab-move.ts +++ b/src/renderer/src/runtime/web-runtime-session-tab-move.ts @@ -46,7 +46,7 @@ export async function moveWebRuntimeSessionTab( try { const { resolveHostSessionGroupIdForWebSessionTab, resolveHostSessionTabIdForWebSessionTab } = - await import('./web-session-tabs-sync') + await import('./web-session-tabs-sync/tracking-mappings') const state = useAppStore.getState() const groups = state.groupsByWorktree?.[args.worktreeId] ?? [] const targetGroup = groups.find((group) => group.id === args.targetGroupId) diff --git a/src/renderer/src/runtime/web-runtime-session-tab-props.test.ts b/src/renderer/src/runtime/web-runtime-session-tab-props.test.ts index cdc831536cc..d1617e65770 100644 --- a/src/renderer/src/runtime/web-runtime-session-tab-props.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-tab-props.test.ts @@ -34,16 +34,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-terminal-host-authority.test.ts b/src/renderer/src/runtime/web-runtime-session-terminal-host-authority.test.ts index 353ed60a62e..5e148cdeda8 100644 --- a/src/renderer/src/runtime/web-runtime-session-terminal-host-authority.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-terminal-host-authority.test.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type * as TrackingDecisions from './web-session-tabs-sync/tracking-decisions' import { createWebRuntimeAgentSessionTerminal, createWebRuntimeAgentSessionTerminalWithLaunchDraft, @@ -47,16 +48,25 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', async (importOriginal) => ({ + ...(await importOriginal()), + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-terminal-legacy-create.test.ts b/src/renderer/src/runtime/web-runtime-session-terminal-legacy-create.test.ts index 9e039195267..3f0d8808ded 100644 --- a/src/renderer/src/runtime/web-runtime-session-terminal-legacy-create.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-terminal-legacy-create.test.ts @@ -40,16 +40,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-terminal-pane-delegation.test.ts b/src/renderer/src/runtime/web-runtime-session-terminal-pane-delegation.test.ts index edd0d09a05b..f4b4ae42f57 100644 --- a/src/renderer/src/runtime/web-runtime-session-terminal-pane-delegation.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-terminal-pane-delegation.test.ts @@ -48,16 +48,24 @@ vi.mock('../lib/activate-tab-and-focus-pane', () => ({ activateTabAndFocusPane: mocks.activateTabAndFocusPane })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session-terminal-workspace-routing.test.ts b/src/renderer/src/runtime/web-runtime-session-terminal-workspace-routing.test.ts index 459c3f24ba2..c1908ab2786 100644 --- a/src/renderer/src/runtime/web-runtime-session-terminal-workspace-routing.test.ts +++ b/src/renderer/src/runtime/web-runtime-session-terminal-workspace-routing.test.ts @@ -41,14 +41,22 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ - acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ + acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-session.test.ts b/src/renderer/src/runtime/web-runtime-session.test.ts index 7a428ef2880..7fa11e4de27 100644 --- a/src/renderer/src/runtime/web-runtime-session.test.ts +++ b/src/renderer/src/runtime/web-runtime-session.test.ts @@ -46,16 +46,24 @@ vi.mock('../store', () => ({ } })) -vi.mock('./web-session-tabs-sync', () => ({ +vi.mock('./web-session-tabs-sync/tracking-lifecycle', () => ({ acceptReplayedWebSessionTabsSnapshot: mocks.acceptReplayedWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot, - decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot, - getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration, + getWebSessionTabsTrackingGeneration: mocks.getWebSessionTabsTrackingGeneration +})) +vi.mock('./web-session-tabs-sync/snapshot-api', () => ({ + applyWebSessionTabsSnapshot: mocks.applyWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/tracking-decisions', () => ({ + decideWebSessionTabsSnapshot: mocks.decideWebSessionTabsSnapshot +})) +vi.mock('./web-session-tabs-sync/store-patch', () => ({ applyWebSessionTabsStorePatch: (buildPatch: (state: unknown) => unknown) => { mocks.setState(buildPatch) // The production caller invokes the returned settle receipt. return () => {} - }, + } +})) +vi.mock('./web-session-tabs-sync/tracking-mappings', () => ({ resolveHostSessionTabIdForWebSessionTab: mocks.resolveHostSessionTabIdForWebSessionTab })) diff --git a/src/renderer/src/runtime/web-runtime-terminal-actions.ts b/src/renderer/src/runtime/web-runtime-terminal-actions.ts index 9219330882b..9ea1db698aa 100644 --- a/src/renderer/src/runtime/web-runtime-terminal-actions.ts +++ b/src/renderer/src/runtime/web-runtime-terminal-actions.ts @@ -251,7 +251,7 @@ export function setWebRuntimeTabProps(args: { } const callEnvironment = captureRuntimeEnvironmentCall(environmentId) const state = useAppStore.getState() - void import('./web-session-tabs-sync') + void import('./web-session-tabs-sync/tracking-mappings') .then(({ resolveHostSessionTabIdForWebSessionTab }) => { const hostTabId = resolveHostSessionTabIdForWebSessionTab(state, { diff --git a/src/renderer/src/runtime/web-session-tabs-retired-epoch-census-repair.test.tsx b/src/renderer/src/runtime/web-session-tabs-retired-epoch-census-repair.test.tsx index b69b76b12d7..35aacc8065d 100644 --- a/src/renderer/src/runtime/web-session-tabs-retired-epoch-census-repair.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-retired-epoch-census-repair.test.tsx @@ -32,10 +32,8 @@ vi.mock('./web-session-terminal-orphan-recovery', () => ({ import { useAppStore } from '@/store' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' -import { - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync -} from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' /** * #21928: a paired host mints `headless:` epochs for one worktree between renderer frames, so the diff --git a/src/renderer/src/runtime/web-session-tabs-stream-end-resubscribe.test.tsx b/src/renderer/src/runtime/web-session-tabs-stream-end-resubscribe.test.tsx index 14e0e7514f0..2c156c30a64 100644 --- a/src/renderer/src/runtime/web-session-tabs-stream-end-resubscribe.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-stream-end-resubscribe.test.tsx @@ -32,10 +32,8 @@ vi.mock('./web-session-terminal-orphan-recovery', () => ({ import { useAppStore } from '@/store' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' -import { - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync -} from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' import { WINDOW_VISIBILITY_SUBSCRIPTION_RETRY_INITIAL_MS } from './window-visibility-subscription-parking' /** diff --git a/src/renderer/src/runtime/web-session-tabs-sync-editor-ownership.test.ts b/src/renderer/src/runtime/web-session-tabs-sync-editor-ownership.test.ts index bcb911aa9f8..e7b00e7c34a 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-editor-ownership.test.ts +++ b/src/renderer/src/runtime/web-session-tabs-sync-editor-ownership.test.ts @@ -5,7 +5,7 @@ import type { } from '../../../shared/runtime-types' import type { OpenFile } from '../store/slices/editor' import { buildOwnedEditorFileId } from '../store/slices/editor/file-ids/editor-file-ids' -import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' import { ENV, NOW, diff --git a/src/renderer/src/runtime/web-session-tabs-sync-host-group-mapping.test.ts b/src/renderer/src/runtime/web-session-tabs-sync-host-group-mapping.test.ts index 6aeb397662b..dc80baaa0f4 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-host-group-mapping.test.ts +++ b/src/renderer/src/runtime/web-session-tabs-sync-host-group-mapping.test.ts @@ -1,9 +1,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { toWebTerminalSurfaceTabId } from '../../../shared/terminal-surface-id' -import { - applyWebSessionTabsSnapshot, - resolveHostSessionGroupIdForWebSessionTab -} from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' +import { resolveHostSessionGroupIdForWebSessionTab } from './web-session-tabs-sync/tracking-mappings' import { ENV, LEAF_ID, diff --git a/src/renderer/src/runtime/web-session-tabs-sync-initial-terminal-relaunch.test.tsx b/src/renderer/src/runtime/web-session-tabs-sync-initial-terminal-relaunch.test.tsx index 4e9ba65e439..11c5ace6ac3 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-initial-terminal-relaunch.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-sync-initial-terminal-relaunch.test.tsx @@ -44,10 +44,8 @@ import { useAppStore } from '@/store' import type { PublicKnownRuntimeEnvironment } from '../../../shared/runtime-environments' import type { AppState } from '@/store/types' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' -import { - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync -} from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' import { clearRuntimeEnvironmentConnectionGenerationsForTests } from '@/store/slices/runtime-status' import { resetWebRuntimeInitialTerminalBootstrapForTests } from './web-runtime-initial-terminal-bootstrap' diff --git a/src/renderer/src/runtime/web-session-tabs-sync-mirrored-draft-close.test.ts b/src/renderer/src/runtime/web-session-tabs-sync-mirrored-draft-close.test.ts index 041a932594e..745582fd313 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-mirrored-draft-close.test.ts +++ b/src/renderer/src/runtime/web-session-tabs-sync-mirrored-draft-close.test.ts @@ -13,7 +13,7 @@ vi.mock('./web-runtime-session-tab-lifecycle', () => ({ import { useAppStore } from '../store' import { createWorkspaceTabCloseCommands } from '@/components/tab-group/workspace-tab-close-commands' import { ORCA_EDITOR_REQUEST_FILE_CLOSE_EVENT } from '@/components/editor/editor-autosave' -import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from './web-session-tabs-sync/snapshot-api' import { ENV, NOW, diff --git a/src/renderer/src/runtime/web-session-tabs-sync-reconnect-resubscribe.test.tsx b/src/renderer/src/runtime/web-session-tabs-sync-reconnect-resubscribe.test.tsx index fd13e945bf3..c001f258a5f 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-reconnect-resubscribe.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-sync-reconnect-resubscribe.test.tsx @@ -30,10 +30,8 @@ vi.mock('@/lib/worktree-runtime-owner', async (importOriginal) => { import { useAppStore } from '@/store' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' import { clearHostLiveTerminalProbesForTests } from './host-live-terminal-probe' -import { - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync -} from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' import { clearRuntimeEnvironmentConnectionGenerationsForTests } from '@/store/slices/runtime-status' import { buildRuntimeSessionMirrorEnvironmentKeys } from './use-runtime-session-mirror-environment-key' diff --git a/src/renderer/src/runtime/web-session-tabs-sync-unverifiable-host.test.tsx b/src/renderer/src/runtime/web-session-tabs-sync-unverifiable-host.test.tsx index 06623338eae..b5989ef16f0 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-unverifiable-host.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-sync-unverifiable-host.test.tsx @@ -31,10 +31,8 @@ import { useAppStore } from '@/store' import type { RuntimeEnvironmentStatus } from '@/store/slices/runtime-status-types' import { replaceRuntimeEnvironmentRevisions } from './runtime-environment-revision' import { clearHostLiveTerminalProbesForTests } from './host-live-terminal-probe' -import { - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync -} from './web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' import { clearRuntimeEnvironmentConnectionGenerationsForTests } from '@/store/slices/runtime-status' const ENV_A = 'env-a' diff --git a/src/renderer/src/runtime/web-session-tabs-sync-visibility-collision.test.tsx b/src/renderer/src/runtime/web-session-tabs-sync-visibility-collision.test.tsx index 1c7715e99b5..b42fd0f9b0a 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-visibility-collision.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-sync-visibility-collision.test.tsx @@ -49,10 +49,10 @@ import { subscribeAcceptedWebSessionTerminalHandle } from './web-session-termina import { _getWebSessionTabsReceiptTrackingCountsForTest, _getWebSessionTabsTrackingCountsForTest, - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync, - WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS -} from './web-session-tabs-sync' + resetWebSessionTabsSnapshotFreshnessForTests +} from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' +import { WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS } from './web-session-tabs-sync/state' import { WINDOW_VISIBILITY_SUBSCRIPTION_PARK_DELAY_MS } from './window-visibility-subscription-parking' const ENV_A = 'env-a' diff --git a/src/renderer/src/runtime/web-session-tabs-sync-window-visibility.test.tsx b/src/renderer/src/runtime/web-session-tabs-sync-window-visibility.test.tsx index 1cfdf4508c3..493e2f2e014 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync-window-visibility.test.tsx +++ b/src/renderer/src/runtime/web-session-tabs-sync-window-visibility.test.tsx @@ -47,10 +47,10 @@ import { clearHostLiveTerminalProbesForTests } from './host-live-terminal-probe' import { acceptReplayedWebSessionTabsSnapshot, _getWebSessionTabsTrackingCountsForTest, - resetWebSessionTabsSnapshotFreshnessForTests, - useWebSessionTabsSync, - WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS -} from './web-session-tabs-sync' + resetWebSessionTabsSnapshotFreshnessForTests +} from './web-session-tabs-sync/tracking-lifecycle' +import { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' +import { WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS } from './web-session-tabs-sync/state' import { clearRuntimeEnvironmentConnectionGenerationsForTests } from '@/store/slices/runtime-status' import { WINDOW_VISIBILITY_SUBSCRIPTION_PARK_DELAY_BACKOFF_LIMIT, diff --git a/src/renderer/src/runtime/web-session-tabs-sync.test.ts b/src/renderer/src/runtime/web-session-tabs-sync.test.ts index 22c996d83b5..2d9fa99edcf 100644 --- a/src/renderer/src/runtime/web-session-tabs-sync.test.ts +++ b/src/renderer/src/runtime/web-session-tabs-sync.test.ts @@ -13,13 +13,15 @@ import type { Tab } from '../../../shared/tab-types' import type { TerminalTab } from '../../../shared/terminal-tab-types' import { acceptReplayedWebSessionTabsSnapshot, + clearWebSessionTabsTrackingForEnvironment +} from './web-session-tabs-sync/tracking-lifecycle' +import { applyFreshWebSessionTabsSnapshot, - applyWebSessionTabsSnapshot, - clearWebSessionTabsTrackingForEnvironment, - resolveHostSessionTabIdForWebSessionTab, - shouldApplyWebSessionTabsSnapshot, - type WebSessionTabsSyncState -} from './web-session-tabs-sync' + applyWebSessionTabsSnapshot +} from './web-session-tabs-sync/snapshot-api' +import { resolveHostSessionTabIdForWebSessionTab } from './web-session-tabs-sync/tracking-mappings' +import { shouldApplyWebSessionTabsSnapshot } from './web-session-tabs-sync/tracking-decisions' +import type { WebSessionTabsSyncState } from './web-session-tabs-sync/state' import { recordReceivedWebSessionTabsSnapshot, shouldApplyRecoveredWebSessionTabsSnapshot diff --git a/src/renderer/src/runtime/web-session-tabs-sync.ts b/src/renderer/src/runtime/web-session-tabs-sync.ts deleted file mode 100644 index ac9ac6d240e..00000000000 --- a/src/renderer/src/runtime/web-session-tabs-sync.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** Public boundary for the web runtime session-tab mirror. */ -export { - applyFreshWebSessionTabsSnapshot, - applyFreshWebSessionTabsSnapshots, - applyWebSessionTabsSnapshot, - applyWebSessionTabsSnapshots, - applyWebSessionTabsSnapshotOperations, - decideWebSessionTabsSnapshotOperations -} from './web-session-tabs-sync/snapshot-api' -export type { - DecidedWebSessionTabsSnapshotOperation, - WebSessionTabsSnapshotOperation -} from './web-session-tabs-sync/snapshot-api' - -export { - acceptReplayedWebSessionTabsSnapshot, - clearWebSessionTabsTrackingForEnvironment, - getLastKnownHostTerminalTabCount, - getLatestWebSessionTabsPublicationEpoch, - getWebSessionTabsTrackingGeneration, - resetWebSessionTabsSnapshotFreshnessForTests, - _getWebSessionTabsReceiptTrackingCountsForTest, - _getWebSessionTabsTrackingCountsForTest -} from './web-session-tabs-sync/tracking-lifecycle' -export { - resolveHostSessionGroupIdForWebSessionTab, - resolveHostSessionTabIdForWebSessionTab -} from './web-session-tabs-sync/tracking-mappings' -export { - decideWebSessionTabsSnapshot, - shouldApplyWebSessionTabsSnapshot, - shouldBootstrapInitialWebRuntimeTerminal, - shouldRespawnWebRuntimeTerminalAfterWake, - shouldSyncAllRuntimeSessionTabs, - shouldSyncRuntimeSessionTabs, - WEB_SESSION_TABS_FRAME_OUTRANKED -} from './web-session-tabs-sync/tracking-decisions' -export type { WebSessionTabsSnapshotDecision } from './web-session-tabs-sync/tracking-decisions' - -export { applyWebSessionTabsStorePatch } from './web-session-tabs-sync/store-patch' -export type { - HostSessionMirrorPatchFrame, - HostSessionMirrorPatchVerdict, - HostSessionMirrorSettle -} from './web-session-tabs-sync/mirror-settle' -export { - hostSessionMirrorSettleForPatchlessFrame, - createHostSessionMirrorSettle -} from './web-session-tabs-sync/mirror-settle' - -export { WEB_SESSION_TABS_VISIBILITY_RESUME_STAGGER_MS } from './web-session-tabs-sync/state' -export type { - WebSessionTabsSnapshotApplyOptions, - WebSessionTabsSyncState, - SessionTabsStreamEvent -} from './web-session-tabs-sync/state' - -export { useWebSessionTabsSync } from './web-session-tabs-sync/use-web-session-tabs-sync' diff --git a/tests/e2e/structured-session-reopened-tab-close.unit.test.ts b/tests/e2e/structured-session-reopened-tab-close.unit.test.ts index 8adffbf260e..79e63d5df25 100644 --- a/tests/e2e/structured-session-reopened-tab-close.unit.test.ts +++ b/tests/e2e/structured-session-reopened-tab-close.unit.test.ts @@ -15,7 +15,7 @@ import { setStructuredAgentSessionHost } from '../../src/main/native-chat/agent- import { useAppStore } from '../../src/renderer/src/store' import { applyStructuredSessionTabSnapshots } from '../../src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply' import { resetLocalStructuredSessionVersionForTests } from '../../src/renderer/src/runtime/local-structured-session-tabs-sync' -import { resetWebSessionTabsSnapshotFreshnessForTests } from '../../src/renderer/src/runtime/web-session-tabs-sync' +import { resetWebSessionTabsSnapshotFreshnessForTests } from '../../src/renderer/src/runtime/web-session-tabs-sync/tracking-lifecycle' import { registerSessionTabIpcBridge } from '../../src/renderer/src/hooks/ipc-events/session-tab-ipc-bridge' import { registerTerminalUiRoutingIpcBridge } from '../../src/renderer/src/hooks/ipc-events/terminal-ui-routing-ipc-bridge' import { resetWebSessionCloseIntentForTests } from '../../src/renderer/src/runtime/web-session-close-intent' diff --git a/tests/e2e/structured-session-tab-close-stale-frame.unit.test.ts b/tests/e2e/structured-session-tab-close-stale-frame.unit.test.ts index 3ee86a6e047..478ba69e302 100644 --- a/tests/e2e/structured-session-tab-close-stale-frame.unit.test.ts +++ b/tests/e2e/structured-session-tab-close-stale-frame.unit.test.ts @@ -16,10 +16,8 @@ import { setStructuredAgentSessionHost } from '../../src/main/native-chat/agent- import { useAppStore } from '../../src/renderer/src/store' import { applyStructuredSessionTabSnapshots } from '../../src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply' import { resetLocalStructuredSessionVersionForTests } from '../../src/renderer/src/runtime/local-structured-session-tabs-sync' -import { - applyWebSessionTabsSnapshot, - resetWebSessionTabsSnapshotFreshnessForTests -} from '../../src/renderer/src/runtime/web-session-tabs-sync' +import { applyWebSessionTabsSnapshot } from '../../src/renderer/src/runtime/web-session-tabs-sync/snapshot-api' +import { resetWebSessionTabsSnapshotFreshnessForTests } from '../../src/renderer/src/runtime/web-session-tabs-sync/tracking-lifecycle' import { acceptPairedHostStructuredSessions } from '../../src/renderer/src/runtime/structured-agent-session-tab-retirement' import { LOCAL_STRUCTURED_SESSION_OWNER } from '../../src/renderer/src/runtime/local-structured-session-owner' import { registerSessionTabIpcBridge } from '../../src/renderer/src/hooks/ipc-events/session-tab-ipc-bridge'