diff --git a/src/main/runtime/orca-runtime-invalidate-all-handles-for-pty.ts b/src/main/runtime/orca-runtime-invalidate-all-handles-for-pty.ts index 448fb2a00fb..9d6e5d56ca4 100644 --- a/src/main/runtime/orca-runtime-invalidate-all-handles-for-pty.ts +++ b/src/main/runtime/orca-runtime-invalidate-all-handles-for-pty.ts @@ -1,6 +1,12 @@ // @ts-nocheck -- mechanically split from OrcaRuntimeService; behavior is covered by AST equivalence and characterization tests. import { OrcaRuntimeWithResolveKnownWorkspaceFileTarget } from './orca-runtime-resolve-known-workspace-file-target' import type { PtyIncarnationId } from '../../shared/pty-incarnation' +import { getPtyExecutionHost } from '../../shared/terminal-execution-host' +import { + LOCAL_EXECUTION_HOST_ID, + parseExecutionHostId, + toSshExecutionHostId +} from '../../shared/execution-host' export class OrcaRuntimeWithInvalidateAllHandlesForPty extends OrcaRuntimeWithResolveKnownWorkspaceFileTarget { protected invalidateAllHandlesForPty(ptyId: string, preserveHandle?: string): Set { @@ -110,11 +116,30 @@ export class OrcaRuntimeWithInvalidateAllHandlesForPty extends OrcaRuntimeWithRe return false } + protected invalidatePtyControllerInventoryForLifecycle( + ptyId: string, + connectionId?: string | null + ): void { + const generation = ++this.ptyControllerInventorySequence + const hostId = getPtyExecutionHost(ptyId) + if (hostId === 'foreign' || (hostId && parseExecutionHostId(hostId)?.kind === 'runtime')) { + this.ptyControllerAggregateInventoryGeneration = generation + return + } + const connection = + connectionId === undefined ? this.ptysById.get(ptyId)?.connectionId : connectionId + const providerKey = + hostId ?? (connection ? toSshExecutionHostId(connection) : LOCAL_EXECUTION_HOST_ID) + // A pending census predates this admission or exit, including legacy IDs without an incarnation. + this.ptyControllerInventoryGenerationByProvider.set(providerKey, generation) + } + onPtySpawned( ptyId: string, incarnationId?: PtyIncarnationId, options: { awaitsRegistration?: boolean } = {} ): void { + this.invalidatePtyControllerInventoryForLifecycle(ptyId) const existingPty = this.ptysById.get(ptyId) if ( existingPty && diff --git a/src/main/runtime/orca-runtime-on-pty-exit.ts b/src/main/runtime/orca-runtime-on-pty-exit.ts index 6ddf877f87c..ce24ed65d98 100644 --- a/src/main/runtime/orca-runtime-on-pty-exit.ts +++ b/src/main/runtime/orca-runtime-on-pty-exit.ts @@ -30,6 +30,7 @@ export class OrcaRuntimeWithOnPtyExit extends OrcaRuntimeWithOnClientDisconnecte if (exitIncarnationId && pty?.incarnationId && exitIncarnationId !== pty.incarnationId) { return } + this.invalidatePtyControllerInventoryForLifecycle(ptyId, pty?.connectionId) // A bare exit code is not enough to establish why a process ended: older // daemons and SSH relays can report 0 for crashes and wrapper exits. const observedCause = options.cause ?? resolveUnreportedExitCause(exitCode) diff --git a/src/main/runtime/orca-runtime-refresh-pty-worktree-records-with-controller-inventory.ts b/src/main/runtime/orca-runtime-refresh-pty-worktree-records-with-controller-inventory.ts index aca67f67ba2..930907da120 100644 --- a/src/main/runtime/orca-runtime-refresh-pty-worktree-records-with-controller-inventory.ts +++ b/src/main/runtime/orca-runtime-refresh-pty-worktree-records-with-controller-inventory.ts @@ -55,7 +55,10 @@ export class OrcaRuntimeWithRefreshPtyWorktreeRecordsWithControllerInventory ext } const inventoryGeneration = this.ptyControllerInventorySequence + 1 this.ptyControllerInventorySequence = inventoryGeneration - const providerKey = typeof connectionId === 'string' ? `ssh:${connectionId}` : 'local' + const providerKey = + typeof connectionId === 'string' + ? toSshExecutionHostId(connectionId) + : LOCAL_EXECUTION_HOST_ID const livenessObservationAtStart = this.ptyLivenessObservationSequence if (connectionId === undefined) { this.ptyControllerAggregateInventoryGeneration = inventoryGeneration diff --git a/src/main/runtime/orca-runtime-register-pty.ts b/src/main/runtime/orca-runtime-register-pty.ts index dae2519ca9f..2d36a18a1e0 100644 --- a/src/main/runtime/orca-runtime-register-pty.ts +++ b/src/main/runtime/orca-runtime-register-pty.ts @@ -26,6 +26,7 @@ export class OrcaRuntimeWithRegisterPty extends OrcaRuntimeWithInvalidateAllHand isWsl?: boolean ): void { this.assertPtyDidNotExitBeforeRegistration(ptyId, binding?.incarnationId) + this.invalidatePtyControllerInventoryForLifecycle(ptyId, connectionId) const existingPty = this.ptysById.get(ptyId) const replacementHandle = binding?.terminalHandle?.trim() const pendingReplacement = this.pendingPtyHandleReplacementFences.get(ptyId)