type PWBrowser = import("playwright").Browser; type PWBrowserContext = import("playwright").BrowserContext; type PWPage = import("playwright").Page; export declare function getRunnerDeviceId(): string; export type SessionOwnership = "owned" | "attached"; export type SessionState = "connecting" | "ready" | "running" | "paused" | "crashed" | "closed"; export type SpaceKind = "ephemeral" | "persistent"; export interface SpaceSpec { kind: SpaceKind; /** Stable opaque id, required for persistent Spaces. */ id?: string; } /** A single @eN binding. Refs are valid only while EVERY generation * component still matches the live lease (plan Section 8). */ export interface BoundRef { ref: string; targetRef: string; frameKey: string; backendNodeId: number; snapshotGeneration: number; documentGeneration: number; role: string; name: string; } export interface TargetLease { /** Opaque target ref (matches grant.target.ref for the leased target). */ ref: string; page: PWPage; snapshotGeneration: number; documentGeneration: number; refs: Map; lastActivity: number; /** Serialize writes per target (plan Section 7 concurrency rule). */ opChain: Promise; } export interface BrowserSessionRecord { id: string; runId: string; ownership: SessionOwnership; engine: string; state: SessionState; space: SpaceSpec; browser: PWBrowser | null; /** launchPersistentContext returns a context without a Browser handle; * owned sessions therefore key teardown on context, not browser. */ context: PWBrowserContext | null; targets: Map; createdAt: number; lastActivity: number; idleTtlMs: number; maxLifetimeMs: number; /** Set for owned EPHEMERAL sessions: deleted at teardown. */ ephemeralUserDataDir: string | null; cancelled: boolean; } export declare class SessionError extends Error { readonly code: "session_not_found" | "session_crashed" | "session_closed" | "target_not_found" | "stale_ref" | "lease_conflict"; constructor(code: SessionError["code"], message: string); } export declare function spaceUserDataDir(space: SpaceSpec, runId: string): { dir: string; ephemeral: boolean; }; export declare class SessionManager { private sessions; private sweeper; private log; constructor(opts?: { log?: (m: string) => void; }); /** Create the session record; the caller (bridge) supplies the live * Playwright handles once launch/attach succeeds. */ createSession(opts: { runId: string; ownership: SessionOwnership; engine: string; space: SpaceSpec; idleTtlMs?: number; maxLifetimeMs?: number; }): BrowserSessionRecord; attachHandles(rec: BrowserSessionRecord, handles: { browser?: PWBrowser | null; context: PWBrowserContext; ephemeralUserDataDir?: string | null; }): void; getSession(runId: string): BrowserSessionRecord; peekSession(runId: string): BrowserSessionRecord | undefined; touch(rec: BrowserSessionRecord): void; leaseTarget(rec: BrowserSessionRecord, ref: string, page: PWPage): TargetLease; getLease(rec: BrowserSessionRecord, ref: string): TargetLease; /** New snapshot -> new generation; every previously issued @eN ref * becomes stale by construction. */ beginSnapshot(lease: TargetLease): number; bindRef(lease: TargetLease, binding: BoundRef): void; /** Resolve an @eN ref, failing closed on ANY generation mismatch. */ resolveRef(lease: TargetLease, ref: string): BoundRef; /** Serialize an operation on a target (one write at a time per lease). */ runOnTarget(lease: TargetLease, op: () => Promise): Promise; /** Tear down a run's session. Closes ONLY owned contexts/browsers; an * attached (user-owned) browser is disconnected from, never closed. * Idempotent; safe on every terminal path. */ teardownRun(runId: string, reason: string): Promise; teardownAll(reason: string): Promise; /** TTL sweep: idle timeout + hard max lifetime. */ private sweep; dispose(): void; } export {};