import type { FrameworkEvent } from './events.js';
/**
 * The hosted run relay (#230): the first slice toward shared team sessions. It
 * ingests a run's {@link FrameworkEvent} stream over HTTP and re-serves the same new
 * dashboard (#405) to N remote browsers, keyed by run id. So two people on different
 * machines open one run URL and both watch it live.
 *
 * It serves the prerendered dashboard SPA and streams events over Telefunc, exactly
 * like the daemon — except the run comes from the relay's own in-memory stream (fed by
 * publishers over HTTP), not a file. The dashboard opens in a read-only, single-run
 * "watch" mode (no Projects/Runs/Docs rails, no Stop/Start), and only the live event
 * stream is exposed: an empty projects provider (#426) makes the file/registry-backed
 * RPCs return nothing on this public host.
 *
 * Deliberately unauthenticated: anyone with a run's URL can watch it. Accounts, teams,
 * RBAC, and authorized steering layer on later (via vike-auth/-rbac). The relay only
 * projects the stream — it never runs an agent.
 *
 * Endpoints:
 * - `POST /r/:id/publish` — ingest one event (JSON object) or a batch (JSON array)
 * - `GET  /?run=:id`      — the dashboard SPA in read-only watch mode for that run
 * - `GET  /r/:id[/]`      — redirects to `/?run=:id` (the viewer URL)
 * - `POST /_telefunc`     — the dashboard's Telefunc surface (only `onEvents` is live)
 * - `GET  /assets/…`      — the SPA's static assets
 * - `GET  /healthz`       — liveness probe for the host
 */
export interface RelayOptions {
    /** Port to bind. Default `4488`; pass `0` for an ephemeral port. */
    port?: number;
    /**
     * Host to bind. Default `0.0.0.0` — the relay exists to be reached from other
     * machines. Bind `127.0.0.1` to keep it local (e.g. tests).
     */
    host?: string;
    /** Page title. Default `"The Framework"`. */
    title?: string;
    /** Max bytes accepted per publish request body. Default 256 KiB. */
    maxBodyBytes?: number;
    /**
     * Max concurrent runs kept in memory. The relay is unauthenticated, so any
     * request to `/r/<id>/…` would otherwise create a run that never frees — an
     * anonymous caller could exhaust memory. On overflow the least-recently-touched
     * run is evicted (its stream closed, its viewers dropped). Default 200.
     */
    maxRuns?: number;
    /**
     * The prerendered dashboard bundle to serve (the SPA `index.html` + `assets/**`).
     * Defaults to {@link resolveDashboardBundle}; pass a directory to override (tests).
     * When no bundle is found, the SPA routes 404 while publish/telefunc/healthz still work.
     */
    clientBundleDir?: string;
}
/** A running relay. Ingest events programmatically or over HTTP; browsers watch by run id. */
export interface Relay {
    /** The base URL of the relay (e.g. `http://0.0.0.0:4488`). */
    readonly url: string;
    /** The viewer URL for a run id (`<url>/?run=<id>`). */
    viewerUrl(runId: string): string;
    /** Push one event into a run's stream, creating the run on first use. */
    ingest(runId: string, event: FrameworkEvent): void;
    /** The run ids seen so far. */
    runIds(): string[];
    /** Close every stream and stop the server. Idempotent. */
    close(): Promise<void>;
}
/** Start the hosted run relay. See {@link Relay}. */
export declare function startRelay(opts?: RelayOptions): Promise<Relay>;
/** A publisher that forwards a run's events to a relay. Best-effort and ordered. */
export interface RelayPublisher {
    /** The viewer URL to share (`<base>/?run=<id>`). */
    readonly url: string;
    /** Queue one event to POST to the relay (serialized, so the relay replays in order). */
    publish(event: FrameworkEvent): void;
    /** Resolve once every queued POST has been sent (or failed), for a clean shutdown. */
    flush(): Promise<void>;
}
/**
 * Forward a live run's {@link FrameworkEvent}s to a {@link startRelay} relay so
 * remote browsers can watch it. POSTs are serialized (chained) so the relay's
 * replay order matches the run, and best-effort: a failed POST is reported via
 * `onError` but never interrupts the run.
 */
export declare function relayPublisher(base: string, runId: string, onError?: (err: unknown) => void, timeoutMs?: number): RelayPublisher;
//# sourceMappingURL=relay.d.ts.map