framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
84 lines • 4.35 kB
TypeScript
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