/** * Per-session concurrency primitives. * * The locking model is deliberately fine-grained: one owner-level mutex guards * id issuance and live-slot reservation, one mutation mutex per session guards * state/input/resize decisions, and output ingestion never takes either lock so * a chatty child cannot block Close. */ /** Monotonic time source. Wall time is only used for receipts, never deadlines. */ export interface Clock { now(): number; setTimeout(handler: () => void, ms: number): TimerHandle; clearTimeout(handle: TimerHandle): void; } export type TimerHandle = { readonly id: unknown; }; export declare const systemClock: Clock; export declare class AsyncMutex { private tail; /** Serialize `fn`; rejections do not poison the queue. */ run(fn: () => Promise | T): Promise; } /** * Single-winner terminal work. Every later caller joins the first promise, so * cleanup executes exactly once no matter how many triggers race. */ export declare class FinalizeOnce { private promise; private winnerReason; get started(): boolean; /** The reason that won the race, useful for choosing a terminal state. */ get reason(): string | undefined; run(reason: string, fn: () => Promise): Promise; join(): Promise | undefined; } export type Unsubscribe = () => void; /** Version-counter subscription used by blocking reads and send gathering. */ export declare class Notifier { private version; private readonly listeners; get current(): number; bump(): void; subscribe(listener: (version: number) => void): Unsubscribe; clear(): void; } export interface SessionTimers { idle?: TimerHandle | undefined; lifetime?: TimerHandle | undefined; } /** Idle resets on activity; lifetime is fixed from confirmed launch. */ export declare class TimerSet { private readonly clock; private readonly onExpire; private readonly timers; constructor(clock: Clock, onExpire: (reason: "idle-timeout" | "lifetime-timeout") => void); armIdle(ms: number | undefined): void; armLifetime(ms: number | undefined): void; clearAll(): void; } /** Resolve/reject handle for one in-flight wait, removable on cancel. */ export interface Waiter { cancel(): void; } export declare class WaiterSet { private readonly waiters; add(waiter: Waiter): Unsubscribe; cancelAll(): void; get size(): number; } /** * One accepted input action. Immutable once queued: the payload is never * rewritten, and delivery is attempted exactly once. */ export interface QueuedInputAction { readonly sequence: number; readonly queuedBytes: number; /** Cursor captured when the action was accepted, used as the default page start. */ readonly cursorAtAcceptance: number; readonly deliver: () => Promise; readonly settle: (outcome: InputDeliveryOutcome) => void; } export interface InputDeliveryOutcome { readonly status: "delivered" | "not-delivered" | "unknown"; readonly deliveredBytes: number; readonly cause?: unknown; } /** * FIFO writer lane. Accepted actions are written strictly in ascending sequence * order by a single drain loop, so concurrent sends can never interleave bytes * or reorder commands. */ export declare class OrderedInputQueue { private readonly queue; private draining; private nextSequence; private queuedBytes; get depth(): number; get pendingBytes(): number; peekSequence(): number; /** Reserve a sequence number and queued-byte budget for one action. */ reserve(bytes: number): number; enqueue(action: QueuedInputAction): void; private drain; /** Reject every undelivered entry, e.g. after process exit or close. */ rejectAll(outcome: InputDeliveryOutcome): void; }