import { S as Scenario, D as DispatchFn, b as DispatchContext } from '../types-Beb6KPqZ.js';

/**
 * # `@tangle-network/agent-eval/adapters/http` — distributed Dispatch over HTTP.
 *
 * Decouples driver and worker. The driver (running `runImprovementLoop` or
 * `runCampaign`) can live anywhere — your VPC, a dev laptop, a cron VM. The
 * workers (running the actual agent) can live anywhere else — different
 * regions, different clouds, different boxes — as long as they speak HTTP.
 *
 * Both sides:
 *
 *   - **`httpDispatch({ url | resolveUrl, ... })`** — client. Returns a
 *     `Dispatch` that POSTs `{ scenario, ctx }` to a worker URL and parses
 *     the artifact back. AbortSignal-aware, retries on idempotent errors,
 *     bounded timeout per call.
 *   - **`runDispatchServer({ dispatch, port, ... })`** — server. Wraps your
 *     local `Dispatch` as an HTTP endpoint. Handles auth, JSON parsing,
 *     error mapping, and cancellation when the client aborts.
 *
 * # Topology examples
 *
 * **Single-worker:** driver on box A, worker on box B. Set
 * `httpDispatch({ url: 'https://box-b/dispatch' })`.
 *
 * **Multi-region:** N workers across regions. Use `httpDispatch({ resolveUrl })`
 * with a function that picks the URL per cell from `ctx.placement`. Combined
 * with `cellPlacement` on `RunCampaignOptions`, the substrate fans cells
 * across geographies in parallel.
 *
 * **Driver-as-a-service:** driver runs as a long-lived process or service
 * (holds optimization state across generations); workers are stateless
 * HTTP services that can scale horizontally per cell.
 */

interface HttpDispatchOptions<TScenario extends Scenario, _TArtifact> {
    /** Static endpoint URL. Mutually exclusive with `resolveUrl`. */
    url?: string;
    /**
     * Dynamic per-cell URL resolver. Receives the scenario + the substrate
     * placement key (from `RunCampaignOptions.cellPlacement`) and returns the
     * worker URL to invoke. Mutually exclusive with `url`.
     */
    resolveUrl?: (input: {
        scenario: TScenario;
        placement?: string;
        cellId: string;
    }) => string;
    /** Bearer token or static auth string set as `Authorization`. */
    auth?: string | (() => string | Promise<string>);
    /** Extra headers merged into every request. */
    headers?: Record<string, string>;
    /** Per-call timeout in ms. Default 5 minutes. */
    timeoutMs?: number;
    /** How many idempotent retries on 5xx / network errors. Default 2. */
    retries?: number;
    /** Optional fetch override (auth wrappers, custom agent, mocks). */
    fetchImpl?: typeof fetch;
}
interface HttpDispatchRequestBody<TScenario extends Scenario> {
    scenario: TScenario;
    cellId: string;
    rep: number;
    generation?: number;
    seed: number;
    placement?: string;
    cycleId?: string;
}
interface HttpDispatchResponseBody<TArtifact> {
    artifact: TArtifact;
}
/**
 * Wrap a remote HTTP endpoint as a `Dispatch`. The remote side should run
 * `runDispatchServer` (or any service that speaks the same wire shape).
 *
 * Cancellation: the substrate's per-cell `AbortSignal` is forwarded; the
 * server's `runDispatchServer` translates the resulting `AbortError` into
 * a 499 (client-closed) so the client doesn't retry.
 */
declare function httpDispatch<TScenario extends Scenario, TArtifact>(opts: HttpDispatchOptions<TScenario, TArtifact>): DispatchFn<TScenario, TArtifact>;
interface RunDispatchServerOptions<TScenario extends Scenario, TArtifact> {
    /** The Dispatch this server exposes — what runs when a request lands. */
    dispatch: DispatchFn<TScenario, TArtifact>;
    /** TCP port to bind. */
    port: number;
    /** Optional bind host; defaults to 0.0.0.0. */
    host?: string;
    /** Required for any non-test deployment: the bearer token clients must
     *  send. The substrate refuses to start without auth unless `auth: false`
     *  is set explicitly (intended ONLY for closed-network/internal testing). */
    auth: string | false;
    /** Path the server listens on. Default `/dispatch`. */
    path?: string;
    /**
     * Per-request handler that wraps `dispatch` with whatever context the
     * worker side needs to construct a `DispatchContext` — typically the
     * trace writer, artifact writer, and cost meter. The substrate provides
     * synthetic-but-typed defaults if not supplied; production deployments
     * should wire real ones (e.g. ship traces to your OTel collector).
     */
    contextFactory?: (req: HttpDispatchRequestBody<TScenario>, signal: AbortSignal) => Promise<DispatchContext>;
    /** Optional max payload size for the request body (bytes). Default 10 MB. */
    maxBodyBytes?: number;
    /** Hook for observability — called on every successful or failed turn. */
    onRequest?: (event: {
        cellId: string;
        durationMs: number;
        success: boolean;
        error?: unknown;
    }) => void;
}
interface DispatchServerHandle {
    /** The actual bound port (useful when `port: 0` requests an ephemeral port). */
    port: number;
    /** Stop accepting new connections and drain existing ones. */
    close: () => Promise<void>;
}
/**
 * Start an HTTP server exposing a local `Dispatch` over the wire. Pair with
 * `httpDispatch` on the driver side.
 *
 * Wire shape:
 *
 *   POST /dispatch
 *   Authorization: Bearer <token>
 *   Body: HttpDispatchRequestBody
 *   200 OK: HttpDispatchResponseBody
 *   401: missing/invalid auth
 *   408: per-request timeout exceeded
 *   499: client aborted before completion
 *   500: dispatch threw
 *
 * The server is `node:http`-based to keep the runtime dependency surface
 * minimal — works in plain Node, sandbox, or any container.
 */
declare function runDispatchServer<TScenario extends Scenario, TArtifact>(opts: RunDispatchServerOptions<TScenario, TArtifact>): Promise<DispatchServerHandle>;

export { type DispatchServerHandle, type HttpDispatchOptions, type HttpDispatchRequestBody, type HttpDispatchResponseBody, type RunDispatchServerOptions, httpDispatch, runDispatchServer };
