import * as plugins from './plugins.js'; export type TContainerEnvironmentContainer = Pick; /** The public Docker client satisfies this boundary; tests can supply a fake engine. */ export interface IContainerEnvironmentDockerHost { info(): Promise; pullImage(descriptorArg: plugins.docker.IImagePullDescriptor): Promise>; listContainers(optionsArg: plugins.docker.IContainerListOptions): Promise; createContainer(descriptorArg: plugins.docker.IContainerCreationDescriptor): Promise; openEventMonitor(optionsArg: plugins.docker.IDockerEventMonitorOptions): Promise; } /** Implemented by AGL's durable SmartData environment record, never by a process-local cache. */ export interface IContainerEnvironmentSetupReadiness { getReadyContainerId(): Promise; markReady(containerIdArg: string): Promise; } export type TContainerEnvironmentLossReason = 'container_lost' | 'environment_oom' | 'unexplained_exit_137'; /** The caller owns and closes the returned host after all environments have stopped. */ export declare const createControllerRootlessDockerHost: () => plugins.docker.DockerHost; export interface IContainerEnvironmentSetupStep { id: string; command: string; timeoutMs: number; } export interface IContainerEnvironmentOptions { docker: IContainerEnvironmentDockerHost; setupReadiness: IContainerEnvironmentSetupReadiness; /** Opaque and unique within this controller. Account layout belongs to the caller. */ id: string; name: string; labels: Record; imageReference: string; expectedRepoDigest: string; projectDirectory: string; stateDirectory: string; assetsDirectory: string; /** Other mounts are caller-owned; the project, state and assets mounts are always added here. */ additionalBindMounts?: plugins.docker.IContainerBindMount[]; networkEndpoints?: plugins.docker.IContainerNetworkEndpoint[]; namedVolumeMounts?: plugins.docker.IContainerNamedVolumeMount[]; memoryBytes?: number; nanoCpus?: number; pidsLimit?: number; shmSize?: number; lifelineTimeoutSeconds?: number; lifelineHeartbeatSeconds?: number; /** Runs after the first heartbeat and before setup or chats. */ onStartProbe?: (containerArg: TContainerEnvironmentContainer, signalArg: AbortSignal) => Promise; /** The caller marks affected chats lost before the environment is started again. */ onLost?: (reasonArg: TContainerEnvironmentLossReason, errorArg: Error) => Promise; onFailure?: (errorArg: Error) => void; } export type TContainerEnvironmentState = 'stopped' | 'starting' | 'running' | 'stopping' | 'failed' | 'closed'; export interface IContainerEnvironmentSnapshot { id: string; state: TContainerEnvironmentState; containerId?: string; /** False until the initial setup list has completed successfully. */ setupComplete: boolean; } /** Object identity fences terminal operations to one exact Docker container start. */ export interface IContainerEnvironmentRunLease { readonly containerId: string; readonly startedAtUnixNano: string; } /** * One installable rootless environment. The caller supplies its identity, durable setup list and * bind paths; this class owns only Docker's running process, attach and timer lifecycle. */ export declare class ControllerContainerEnvironment { private readonly options; private container?; private currentRunLease?; private attachment?; private attachmentToken?; private attachmentHandlers?; private eventMonitor?; private eventMonitorToken?; private heartbeatTimer?; private heartbeatWrite?; private startAbortController?; private operationQueue; private desiredRunning; private lifecycleIntentToken; private closeRequested; private closePromise?; private lossQueued; private setupSteps; private state; private setupComplete; private readonly memoryBytes; private readonly lifelineTimeoutSeconds; private readonly lifelineHeartbeatSeconds; constructor(options: IContainerEnvironmentOptions); snapshot(): IContainerEnvironmentSnapshot; /** Existing runs are always stopped before attach: stdinOnce cannot be adopted after a crash. */ start(setupStepsArg: readonly IContainerEnvironmentSetupStep[]): Promise; stop(): Promise; /** Rebuild discards the writable layer; the caller's setup definition is replayed in order. */ rebuild(setupStepsArg: readonly IContainerEnvironmentSetupStep[]): Promise; /** Removes only Docker's container. Account folders and transcripts belong to the caller. */ delete(): Promise; close(): Promise; /** Read exact Docker state; a missing container never counts as a healthy running environment. */ reconcile(): Promise; /** Bounded administration and setup commands cannot silently become interactive sessions. */ exec(argvArg: plugins.docker.TContainerCommand, optionsArg: plugins.docker.IContainerExecOptions): Promise; /** Caller owns the returned stream and must close it on chat exit. */ execInteractive(argvArg: plugins.docker.TContainerCommand, optionsArg: plugins.docker.IContainerInteractiveExecOptions): Promise; /** Capture the exact physical run together with a new terminal exec inside the lifecycle queue. */ execInteractiveWithRunLease(argvArg: plugins.docker.TContainerCommand, optionsArg: plugins.docker.IContainerInteractiveExecOptions): Promise<{ session: plugins.docker.IContainerInteractiveExec; runLease: IContainerEnvironmentRunLease; }>; /** A stale terminal cannot signal a process in the next run of the same container ID. */ execIfCurrentRun(runLeaseArg: IContainerEnvironmentRunLease, argvArg: plugins.docker.TContainerCommand, optionsArg: plugins.docker.IContainerExecOptions): Promise; resizeExecIfCurrentRun(runLeaseArg: IContainerEnvironmentRunLease, execIdArg: string, rowsArg: number, colsArg: number): Promise; /** The lease comparison and stop occur in one serialized lifecycle operation. */ stopIfCurrentRun(runLeaseArg: IContainerEnvironmentRunLease): Promise; resizeExec(execIdArg: string, rowsArg: number, colsArg: number): Promise; private assertNotClosed; private requestLifecycleIntent; private assertRequestedRun; private enqueue; private prepareAssets; private findOwnedContainer; private resolveContainer; private startOnce; private runSetupSteps; private bindAttachment; private unbindAttachment; private attachmentLost; private queueLoss; private handleLoss; private watchContainerEvents; private writeHeartbeat; private detachLifeline; private stopContainerAfterFailure; private stopOnce; }