import type { ChatMessage, ChatTurn, ToolSpec } from "@boardwalk-labs/engine/core"; import type { NormalizedReasoning } from "@boardwalk-labs/workflow"; /** `POST /runner/v1/runs/{run_id}/inference` (run-token authed; the addressed run must match). */ export declare const RUNNER_INFERENCE_PATH_RE: RegExp; /** Build the inference path for a run. */ export declare function runnerInferencePath(runId: string): string; /** Response content type — newline-delimited JSON frames. */ export declare const INFERENCE_NDJSON_CONTENT_TYPE = "application/x-ndjson"; /** * The request body the worker POSTs to `/inference` — one neutral model turn (the engine's * `ModelTurnRequest`, minus the seam: no endpoint, no key). `model`/`provider` are the `agent()` * call's (both opaque, both optional); the broker resolves them SERVER-SIDE against the run's org * (the orgId comes from the verified run token, never the body — so this can't reach another org). */ export interface InferenceProxyRequest { /** The model id, as the agent() call gave it (opaque, passed verbatim). Undefined ⇒ provider routes. */ model: string | undefined; /** The provider the agent() call named (undefined ⇒ the managed `boardwalk` lane). */ provider: string | undefined; /** The conversation so far. */ messages: readonly ChatMessage[]; /** The tools advertised to the model this turn. */ tools: readonly ToolSpec[]; /** Normalized reasoning-effort control (the agent() call's `AgentOptions.reasoning`, undefined ⇒ * provider default). The broker encodes it into the resolved provider's wire body per protocol. */ reasoning?: NormalizedReasoning; /** True when the leaf has desktop tools bound. The broker admits such turns only for an explicit * GUI-grounder model (its desktop-tier gate); it MUST know the field before any runner sends it. */ desktopSession?: true; } /** A broker/model error surfaced as the terminal frame so the worker's stream throws. */ export interface ProxyError { code: string; message: string; } /** A parsed response frame. `ping` is a no-payload heartbeat the broker emits during a long model * turn to keep the connection producing bytes (so idle/body timeouts don't sever it); the worker * ignores it. `reset` voids every delta/reasoning relayed so far for the in-progress turn — the * broker restarts a turn after a transient mid-stream drop; the worker signals the viewer to discard * the turn's streamed output (the authoritative turn still arrives in the single `result`). */ export type InferenceFrame = { kind: "delta"; text: string; } | { kind: "reasoning"; text: string; } | { kind: "reset"; } | { kind: "result"; turn: ChatTurn; modelRef: string; costMicros: number; contextTokens?: number; } | { kind: "error"; error: ProxyError; } | { kind: "ping"; }; /** Serialize the request body. Multimodal image content rides transparently: message content parts * (incl. `{ type: "image" }`) are plain JSON here — the broker's engine adapters render them per * provider (@boardwalk-labs/engine ≥ 0.1.32). */ export declare function serializeInferenceRequest(req: InferenceProxyRequest): string; /** Parse + minimally validate the request body (the runner is semi-trusted; fail closed on shape). * The conversation is shape-trusted past the array check — it was built by the engine loop on the * runner from the broker's own prior frames, and the broker's adapters re-render every field. */ export declare function parseInferenceRequest(body: string): InferenceProxyRequest; /** Serialize one streamed text delta as a single NDJSON line (trailing "\n" included). */ export declare function serializeDeltaFrame(text: string): string; /** Serialize one streamed reasoning/thinking delta as a single NDJSON line. Separate from a `delta` * frame so the worker routes it to the thinking trace, never into the assistant answer. */ export declare function serializeReasoningFrame(text: string): string; /** Serialize the single terminal turn result as one NDJSON line. `costMicros` is the turn's EXACT * upstream cost (the managed provider's per-request cost × 1e6) on the managed lane — 0 for BYO or when unavailable. * The worker feeds it to the budget guardrail so `max_usd` tracks real spend, not a token estimate. */ export declare function serializeResultFrame(turn: ChatTurn, modelRef: string, costMicros?: number, contextTokens?: number): string; /** Serialize a terminal error as a single NDJSON line. */ export declare function serializeErrorFrame(error: ProxyError): string; /** Serialize a `reset` frame (no payload): the broker restarted a turn after a transient mid-stream * drop, so every delta/reasoning relayed so far is void. The broker is the producer; this mirror * exists so runner tests can construct the frame. */ export declare function serializeResetFrame(): string; /** Serialize a heartbeat (no payload) as a single NDJSON line. The broker emits these on an interval * during a long model turn so the worker↔broker connection keeps producing bytes — neither side's * idle/body timeout fires while the model is generating but not yet streaming text. */ export declare function serializeHeartbeatFrame(): string; /** Parse one NDJSON frame line. Throws on a malformed/unknown frame (the line must be non-empty). */ export declare function parseInferenceFrame(line: string): InferenceFrame;