Files
orca/src/main/runtime/run-terminal-client-use.ts
T
OrcaWinandm4air 8e4716aa65 refactor(pty): PTY controller inventory and startup waits take a host id (#26998)
The runtime PTY controller's listProcesses / supportsForegroundProcessEvidence
and the local daemon-startup waits took a connectionId where null meant
this machine and undefined meant every host. They now take an
ExecutionHostId (omitted = every host for inventory, this machine for
startup waits); id-routed callers pass the PTY's resolved host instead
of re-deriving a raw SSH connection id.

Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
2026-10-09 16:48:14 -07:00

58 lines
2.0 KiB
TypeScript

/**
* What the headless automation sweep asks a runtime about a run's terminal before closing it:
* whether a client used it, and whether only its shell still runs.
*/
import type { RuntimePtyController } from './runtime-pty-controller-contract'
import type { TerminalRunFactsRegister } from './terminal-run-facts'
import {
confirmRootShellAloneFromProcessTable,
inspectionShowsShellAlone
} from './run-terminal-shell-alone'
import { LOCAL_EXECUTION_HOST_ID } from '../../shared/execution-host'
/**
* Whether a client drove or is viewing a PTY's current process, for closing finished run
* terminals: `unknown` when this process cannot tell (it adopted the PTY rather than spawned it).
*/
export function readRunTerminalClientUse(
host: {
hasRawTerminalViewSubscriber: (ptyId: string) => boolean
terminalRunFacts: Pick<TerminalRunFactsRegister, 'read'>
},
ptyId: string
): 'used' | 'unused' | 'unknown' {
if (host.hasRawTerminalViewSubscriber(ptyId)) {
return 'used'
}
const facts = host.terminalRunFacts.read(ptyId, undefined)
if (facts.firstUserInputAt !== null) {
return 'used'
}
return facts.freshSpawn ? 'unused' : 'unknown'
}
/**
* Fresh execution-host proof that only the spawned shell runs in a PTY, at its prompt, on POSIX
* and Windows alike; false whenever that cannot be proven.
*/
export async function confirmRunTerminalShellAlone(
controller: RuntimePtyController | null | undefined,
ptyId: string
): Promise<boolean> {
try {
if (await controller?.confirmShellForeground?.(ptyId)) {
return true
}
if (process.platform === 'win32') {
return inspectionShowsShellAlone(
(await controller?.inspectProcess?.(ptyId, { scanChildProcesses: true })) ?? null
)
}
const processes = (await controller?.listProcesses?.(LOCAL_EXECUTION_HOST_ID)) ?? []
const rootPid = processes.find((entry) => entry.id === ptyId)?.rootProcessId
return rootPid ? await confirmRootShellAloneFromProcessTable(rootPid) : false
} catch {
return false
}
}