/** * Session transport contracts plus the single centralized table that maps text * submission and named controls onto transport/platform byte sequences. * * A launch is confirmed only after the OS acknowledges spawn. Host stdin is * never inherited: agent-controlled sessions must not be able to take the * user's controlling terminal. */ import type { TreeSignalOutcome } from "../os/process-tree.js"; import type { Unsubscribe } from "./runtime.js"; import type { ControlInput, OutputStream, ProcessOutcome, SessionTransportKind, SubmitBehavior, TerminalDimensions } from "./types.js"; export interface TransportOutput { readonly stream: OutputStream; readonly bytes: Uint8Array; readonly observedAt: number; } export type DeliveryResult = { readonly status: "delivered"; readonly deliveredBytes: number; } | { readonly status: "not-delivered"; readonly deliveredBytes: 0; readonly cause?: unknown; } | { readonly status: "unknown"; readonly deliveredBytes: number; readonly cause?: unknown; }; export interface SessionTransport { readonly kind: SessionTransportKind; readonly pid: number; readonly processGroupId?: number | undefined; /** Hashed start-time evidence captured at launch confirmation. */ readonly identity: string | undefined; write(bytes: Uint8Array): Promise; control(action: ControlInput): Promise; closeInput(): Promise; resize?(dimensions: TerminalDimensions): Promise; pauseOutput(): void; resumeOutput(): void; requestTreeTermination(kind: "graceful" | "forceful"): Promise; onOutput(listener: (event: TransportOutput) => void): Unsubscribe; onExit(listener: (outcome: ProcessOutcome) => void): Unsubscribe; /** Settles after transport output sources can emit no additional bytes. */ waitForOutputDrain?(): Promise; dispose(): Promise; } export interface LaunchIdentity { readonly pid: number; readonly processGroupId?: number | undefined; readonly identity: string | undefined; } export interface LaunchRequest { readonly command: string; readonly cwd: string; readonly env?: NodeJS.ProcessEnv | undefined; readonly onLaunchIdentity?: ((identity: LaunchIdentity) => void) | undefined; } export interface LaunchResult { readonly transport: SessionTransport; } export interface PtyCapability { readonly available: boolean; readonly platform: NodeJS.Platform; /** Non-secret diagnostic for why PTY is unavailable on this target. */ readonly reason?: string | undefined; } export interface SessionTransportFactory { capability(platform?: NodeJS.Platform): Promise; startPipe(request: LaunchRequest): Promise; startPty(request: LaunchRequest & { dimensions: TerminalDimensions; }): Promise; } /** * A transient pre-spawn failure proves no process side effect occurred, so the * manager may retry the launch exactly once. */ export declare class LaunchFailure extends Error { readonly code: string; readonly spawnConfirmed: boolean; readonly transient: boolean; constructor(code: string, message: string, spawnConfirmed: boolean, transient: boolean); } /** PTY line discipline expects CR; a pipe expects LF. */ export declare function enterSequence(kind: SessionTransportKind): Uint8Array; export declare function encodeTextInput(text: string, submit: SubmitBehavior, kind: SessionTransportKind): Uint8Array; /** * Byte payload for a named control on a PTY. `undefined` means the control has * no byte form on that platform and must be reported as unsupported or handled * out of band (signals on a pipe). */ export declare function ptyControlBytes(action: ControlInput, platform?: NodeJS.Platform): Uint8Array | undefined; /** * Pipe controls: `interrupt`/`suspend` are process signals because there is no * line discipline, `eof` half-closes stdin, and the rest are the same bytes a * terminal would have delivered. */ export type PipeControlAction = { readonly kind: "signal"; readonly signal: NodeJS.Signals; } | { readonly kind: "bytes"; readonly bytes: Uint8Array; } | { readonly kind: "close-input"; } | { readonly kind: "unsupported"; }; export declare function pipeControlAction(action: ControlInput, platform?: NodeJS.Platform): PipeControlAction;