/** * Host-side facade builder — `createIsolatedService(spec, transport, options?)` drives an * {@link IsolationTransport} (spawn/terminate/crash duck), wires a {@link HostEndpoint} to the * connected {@link PortLike}, and returns an {@link IsolatedService} whose `.api` is a plain object of * promise-returning methods / `ReadableStream`-returning streams matching `spec`. * * @remarks * `.api` is built once, up front, by iterating `spec.methods`/`spec.streams` — NOT a `Proxy` — so every * call site gets ordinary, debuggable function properties. Calls/stream-starts made before the guest's * `ready` envelope arrives queue transparently inside `HostEndpoint`; a `readyTimeoutMs` watchdog (default * 30s) rejects the connection attempt with `E_ISOLATION_READY_TIMEOUT` if `ready` never arrives. * * `dispose()` asks the guest to shut down gracefully, gives it `disposeGraceMs` (default 2000ms) to exit * on its own, then forces `transport.terminate()` regardless. `recycle()` terminates and reconnects * through the SAME `transport.connect()` — the returned `IsolatedService` object's identity and every * `.on(...)` subscription survive a recycle; only in-flight work is rejected with `E_ISOLATED_TERMINATED`. * * A transport-reported crash (`transport.onCrash`) rejects in-flight calls/streams with * `E_ISOLATED_CRASHED`, flips `state` to `'crashed'`, and fans out to `.onCrash(...)` subscribers. With * `autoRespawn: { policy }` opted in, a crash instead consults `policy.record()`: `'respawn'` triggers an * automatic `recycle()`, `'giveUp'` leaves the service crashed. Default: off. */ import { type HostcallHandler, type HostcallQuotas } from "./protocol"; import { type IsolationObservabilityHooks } from "./observability"; import type { CrashPolicy } from "./crash_policy"; import type { CrashInfo, IsolatedEventListener, IsolatedFacade, IsolatedServiceSpec, IsolationTransport } from "./types"; /** Options accepted by {@link createIsolatedService}. */ export interface IsolatedServiceOptions extends IsolationObservabilityHooks { /** Max time to wait for the guest's `ready` envelope after `transport.connect()` resolves. Default * `30_000`. Rejects the pending `connect`/first call with `E_ISOLATION_READY_TIMEOUT`. */ readyTimeoutMs?: number; /** Grace period `dispose()` gives the guest to exit cleanly after `shutdown` before forcing * `transport.terminate()`. Default `2000`. */ disposeGraceMs?: number; /** Opt-in automatic recovery: on a transport-reported crash, consult `policy.record()` and `recycle()` * automatically when it returns `'respawn'`. Default: not set (crashes are surfaced, never auto-healed). */ autoRespawn?: { policy: CrashPolicy; }; /** Classes to register with `@nhtio/encoder`'s custom-encodable round-trip on this side. */ encodables?: ReadonlyArray<{ readonly name: string; }>; /** Permitted guest-to-host capability handlers. */ hostcallHandlers?: ReadonlyMap; /** Resolved quotas enforced for guest-to-host calls. */ hostcallQuotas?: HostcallQuotas; /** Producer-side argument/result byte cap. */ maxHostcallBytes?: number; } /** Lifecycle state of an {@link IsolatedService}. */ export type IsolatedServiceState = 'starting' | 'ready' | 'crashed' | 'disposed'; /** The host-side handle `createIsolatedService` returns. */ export interface IsolatedService { /** The callable facade — one function per declared method/stream. */ readonly api: IsolatedFacade; /** Subscribe to a declared event channel. Returns an unsubscribe function. Subscriptions survive * `recycle()` (the same underlying map is reused across guest respawns). */ on(channel: K, fn: IsolatedEventListener): () => void; /** Subscribe to crash notifications. Returns an unsubscribe function. */ onCrash(fn: (info: CrashInfo) => void): () => void; /** Current lifecycle state. */ readonly state: IsolatedServiceState; /** Send `shutdown`, wait up to `disposeGraceMs` for the guest to exit on its own, then force * `transport.terminate()` regardless. Idempotent past the first call. */ dispose(): Promise; /** Terminate the current guest and reconnect through the same `transport.connect()`. Object identity * and `.on(...)` subscriptions survive; in-flight calls/streams reject with `E_ISOLATED_TERMINATED`. */ recycle(): Promise; } /** * Build an {@link IsolatedService} over `transport` for `spec`. Connection + the first `ready` handshake * begin immediately (fire-and-forget internally); calls made before `ready` queue inside the underlying * {@link HostEndpoint} and flush in order once it arrives. * * @throws {@link @nhtio/adk/batteries/isolation!E_INVALID_ISOLATION_OPTIONS} when `options` fails * validation. */ export declare const createIsolatedService: (spec: S, transport: IsolationTransport, options?: IsolatedServiceOptions) => IsolatedService;