Files
orca/src/renderer/src/runtime/web-session-tabs-sync/active-session-subscription.ts
T
OrcaWinandm4air cce31b4b4d refactor(renderer-terminal-runtime): clean up Phase 3-3.8 code (#26900)
- One helper plans and runs a paste into a terminal pane (five copies before)
- Reuse getShortcutPlatform instead of three private copies
- runtime-git-client becomes plain re-exports
- TerminalErrorToast builds each token's test/replace regex from one helper
- Reuse PreconnectInputWriter for the recovery input hold
- Name the session-tabs snapshot callback type once
- Narrow isTerminalDriverState with 'in' instead of a cast
- Inline the single-use terminal-pane-client-host wrapper

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-09 12:09:56 -07:00

279 lines
11 KiB
TypeScript

import type { RuntimeRpcResponse } from '../../../../shared/runtime-rpc-envelope'
import type { RuntimeMobileSessionTabsResult } from '../../../../shared/runtime-types'
import { isRuntimeSubscriptionReplayResponse } from '../../../../shared/runtime-subscription-replay'
import { useAppStore } from '../../store'
import { getRuntimeEnvironmentRevision } from '../runtime-environment-revision'
import { recoverWebSessionTerminalOrphansBeforeApply } from '../web-session-terminal-orphan-recovery'
import { installWindowVisibilitySubscriptionParking } from '../window-visibility-subscription-parking'
import {
recordReceivedWebSessionTabsSnapshot,
shouldApplyRecoveredWebSessionTabsSnapshot
} from './tracking'
import {
decideWebSessionTabsSnapshot,
shouldBootstrapInitialWebRuntimeTerminal,
shouldRespawnWebRuntimeTerminalAfterWake,
shouldSyncRuntimeSessionTabs
} from './tracking-decisions'
import {
acceptReplayedWebSessionTabsSnapshot,
getWebSessionTabsTrackingGeneration
} from './tracking-lifecycle'
import {
acceptSessionTabsRuntimeId,
getSessionTabsRuntimeIdFromResponse
} from './publisher-identity-fences'
import { applyWebSessionTabsSnapshot } from './snapshot-api'
import { applyWebSessionTabsStorePatch } from './store-patch'
import {
hostSessionMirrorSettleForPatchlessFrame,
type HostSessionMirrorSettle
} from './mirror-settle'
import {
beginWebRuntimeWakeTerminalRespawn,
endWebRuntimeWakeTerminalRespawn,
shouldSkipWebRuntimeWakeTerminalRespawn
} from '../web-runtime-wake-terminal-respawn'
import { createWebRuntimeSessionTerminal } from '../web-runtime-session'
import {
isWebRuntimeInitialTerminalBootstrapInFlight,
releaseWebRuntimeInitialTerminalBootstrapOnMirrorFrame
} from '../web-runtime-initial-terminal-bootstrap'
import { dispatchWebRuntimeInitialTerminalBootstrap } from '../web-runtime-initial-terminal-bootstrap-dispatch'
import { toRuntimeWorktreeSelector } from '../runtime-worktree-selector'
import type { SessionTabsStreamEvent } from './state'
import type { SessionTabsSnapshotHandler } from './visibility-resume-types'
import { subscribeRuntimeEnvironment } from '../runtime-environment-pairing-refresh'
type Ref<T> = { current: T }
export type ActiveSubscriptionArgs = {
activeWorktreeId: string | null
activeWorktreeRuntimeEnvironmentId: string | null | undefined
activeWorktreeRuntimeConnectionGeneration: number
activeWorktreeRuntimePairingRevision: number | undefined
workspaceSessionReady: boolean
visibilitySnapshotReceipt: Ref<SessionTabsSnapshotHandler<void>>
visibilitySnapshotApply: Ref<SessionTabsSnapshotHandler<boolean>>
visibilitySnapshotAccepted: Ref<SessionTabsSnapshotHandler<void>>
}
/** Install the selected-worktree stream, which resumes immediately on visibility changes. */
export function installActiveSessionTabsSubscription({
activeWorktreeId,
activeWorktreeRuntimeEnvironmentId,
activeWorktreeRuntimeConnectionGeneration,
activeWorktreeRuntimePairingRevision,
workspaceSessionReady,
visibilitySnapshotReceipt,
visibilitySnapshotApply,
visibilitySnapshotAccepted
}: ActiveSubscriptionArgs): (() => void) | undefined {
const environmentId = activeWorktreeRuntimeEnvironmentId?.trim()
if (
!shouldSyncRuntimeSessionTabs({
activeWorktreeId,
activeWorktreeRuntimeEnvironmentId,
workspaceSessionReady
}) ||
!environmentId ||
!activeWorktreeId
) {
return undefined
}
const expectedTrackingGeneration = getWebSessionTabsTrackingGeneration(environmentId)
let requestedInitialTerminal = false
let requestedRespawnAfterWake = false
const applyActiveSnapshot = async (
event: RuntimeMobileSessionTabsResult & { type: 'snapshot' | 'updated' },
response: RuntimeRpcResponse<unknown>,
isCurrent: () => boolean,
receivedFrame: number,
runtimeId?: string
): Promise<HostSessionMirrorSettle | null> => {
const recovered = await recoverWebSessionTerminalOrphansBeforeApply(
useAppStore.getState(),
event,
environmentId,
{
expectedEnvironmentPairingRevision: activeWorktreeRuntimePairingRevision,
getCurrentState: () => useAppStore.getState()
}
)
if (
!isCurrent() ||
!recovered ||
!shouldApplyRecoveredWebSessionTabsSnapshot(
environmentId,
recovered,
receivedFrame,
runtimeId
) ||
!visibilitySnapshotApply.current(environmentId, recovered, receivedFrame, runtimeId)
) {
return null
}
if (event.type === 'snapshot' || isRuntimeSubscriptionReplayResponse(response)) {
acceptReplayedWebSessionTabsSnapshot(environmentId, recovered.worktree)
}
const recoveredEvent: SessionTabsStreamEvent = { ...recovered, type: event.type }
const decision = decideWebSessionTabsSnapshot(recovered, environmentId, runtimeId)
const syncState = useAppStore.getState()
const localTabs = syncState.tabsByWorktree[activeWorktreeId] ?? []
const localTerminalCount = localTabs.length
const hasLiveLocalPty = localTabs.some(
(tab) => (syncState.ptyIdsByTabId[tab.id] ?? []).length > 0
)
const bootstrap = shouldBootstrapInitialWebRuntimeTerminal({
event: recoveredEvent,
activeWorktreeId,
// Why both: the closure flag records that this subscription already owned a create, so the
// same closure never seeds twice even once the shared latch is released; a create that threw
// never set it, so a later frame may retry. The shared latch is what survives the effect
// re-runs a workspace switch triggers — without it a second closure seeds a second terminal
// while the first create is still in flight (STA-6173).
requestedInitialTerminal:
requestedInitialTerminal ||
isWebRuntimeInitialTerminalBootstrapInFlight(environmentId, activeWorktreeId),
snapshotIsFresh: decision.apply,
localTerminalCount,
hasPersistedTerminalState: Object.hasOwn(syncState.tabsByWorktree, activeWorktreeId)
})
const respawn = shouldRespawnWebRuntimeTerminalAfterWake({
event: recoveredEvent,
activeWorktreeId,
requestedRespawnAfterWake,
snapshotIsFresh: decision.apply,
localTerminalCount,
hasLiveLocalPty,
skipWakeRespawn: shouldSkipWebRuntimeWakeTerminalRespawn(activeWorktreeId)
})
let settle: HostSessionMirrorSettle | null = decision.apply
? null
: hostSessionMirrorSettleForPatchlessFrame(decision, environmentId, recovered.worktree, {
connectionGeneration: activeWorktreeRuntimeConnectionGeneration,
pairingRevision: activeWorktreeRuntimePairingRevision,
trackingGeneration: expectedTrackingGeneration
})
if (decision.apply) {
const replayed = isRuntimeSubscriptionReplayResponse(response)
settle = applyWebSessionTabsStorePatch(
(state) => applyWebSessionTabsSnapshot(state, recovered, environmentId),
{
frames: [
{
environmentId,
worktreeId: recovered.worktree,
decision,
expectedEnvironmentConnectionGeneration: activeWorktreeRuntimeConnectionGeneration,
expectedEnvironmentPairingRevision: activeWorktreeRuntimePairingRevision,
expectedTrackingGeneration
}
]
},
recovered,
event.type === 'updated' && !replayed
)
visibilitySnapshotAccepted.current(environmentId, recovered, receivedFrame, runtimeId)
// Why here and only on an applied frame: this is the mirror's answer about the worktree. A
// bootstrap whose create resolved without a row was parked until that answer arrived; a
// pending create keeps its claim (see the latch module). The predicate above already ran with
// the latch held, so this frame never seeds — the next one decides on real state.
releaseWebRuntimeInitialTerminalBootstrapOnMirrorFrame(environmentId, recovered.worktree)
}
try {
if (isCurrent() && bootstrap) {
// Latch claim, create, and row-conditional release live in the dispatch helper.
if (await dispatchWebRuntimeInitialTerminalBootstrap(environmentId, activeWorktreeId)) {
requestedInitialTerminal = true
}
} else if (isCurrent() && respawn && beginWebRuntimeWakeTerminalRespawn(activeWorktreeId)) {
requestedRespawnAfterWake = true
await createWebRuntimeSessionTerminal({
worktreeId: activeWorktreeId,
environmentId,
activate: true,
selectWorktree: false
}).finally(() => endWebRuntimeWakeTerminalRespawn(activeWorktreeId))
}
} catch (error) {
if (isCurrent()) {
console.warn('[web-session-tabs-sync] snapshot follow-up failed:', error)
}
}
return settle
}
return installWindowVisibilitySubscriptionParking([
{
subscribe: (isCurrent) =>
subscribeRuntimeEnvironment(
{
selector: environmentId,
method: 'session.tabs.subscribe',
params: { worktree: toRuntimeWorktreeSelector(activeWorktreeId) },
timeoutMs: 15_000,
expectedEnvironmentPairingRevision: activeWorktreeRuntimePairingRevision
},
{
onResponse: (response) => {
if (
!isCurrent() ||
getRuntimeEnvironmentRevision(environmentId) !==
activeWorktreeRuntimePairingRevision
) {
return
}
if (response.ok === false) {
console.warn('[web-session-tabs-sync] subscription failed:', response.error.message)
return
}
const event = response.result as SessionTabsStreamEvent
if (event.type !== 'snapshot' && event.type !== 'updated') {
return
}
const runtimeId = getSessionTabsRuntimeIdFromResponse(response)
if (runtimeId && !acceptSessionTabsRuntimeId(environmentId, runtimeId)) {
return
}
const frame = recordReceivedWebSessionTabsSnapshot(
environmentId,
event,
undefined,
runtimeId
)
visibilitySnapshotReceipt.current(environmentId, event, frame, runtimeId)
void applyActiveSnapshot(event, response, isCurrent, frame, runtimeId)
.catch((error) => {
if (isCurrent()) {
console.warn('[web-session-tabs-sync] active snapshot recovery failed:', error)
}
return null
})
.then((settle) => {
if (isCurrent()) {
settle?.()
}
})
},
onError: (error) => {
if (isCurrent()) {
console.warn('[web-session-tabs-sync] subscription error:', error.message)
}
}
}
),
onSubscribeError: (error) => {
console.warn(
'[web-session-tabs-sync] failed to subscribe:',
error instanceof Error ? error.message : String(error)
)
},
onUnsubscribeError: (error) => {
console.warn('[web-session-tabs-sync] failed to unsubscribe:', error)
}
}
])
}