@anvia/client
Connect any frontend to Anvia with a framework-neutral streaming protocol. This package provides HTTP and direct transports, runtime validation, and UI message state for text, tools, and interactions.
Install
pnpm add @anvia/client @anvia/core
Quickstart
Consume a chat endpoint that returns an Anvia client stream, such as one created with
@anvia/server:
import {
applyClientStreamEvent,
createHttpClientTransport,
messagesToUIMessages,
type UIMessage,
} from "@anvia/client";
import type { Message } from "@anvia/core/completion";
const transport = createHttpClientTransport({ endpoint: "/api/chat" });
const messages: Message[] = [{ role: "user", content: "Hello!" }];
let uiMessages: readonly UIMessage[] = messagesToUIMessages(messages);
for await (const frame of transport.send({ request: { type: "messages", messages } })) {
if (frame.type === "stream_event") {
uiMessages = applyClientStreamEvent(uiMessages, frame.event);
console.log(uiMessages);
}
}
The transport validates framing, event order, and stream identity. Send Core Message[] to the
server; keep UIMessage[] as presentation state in your application.
Capabilities
- HTTP transport for JSONL or SSE, plus direct transport for in-process integrations.
- Adapters for native completion and Agent events at the server boundary.
- Validated requests, events, frames, and persisted UI messages.
- Message conversion and reduction, including streamed tool arguments and generation usage.
- Typed custom stream data, Agent interactions, and HTTP resume cursors.
For React, @anvia/react manages this state through useChat and useCompletion. Generic JSONL/SSE
readers are also available from @anvia/client/transport for other event contracts. Malformed
frames are skipped and reported through onParseError (or thrown with strict: true), and
readSseFrames exposes SSE event names, last event IDs, and retry hints.
Learn more
Durable HTTP client
The optional @anvia/client/durable entrypoint exports DurableClient and
DurableHttpError. Install @anvia/durable to use it. It supports submit, list, snapshot,
SSE observation, queued steering, approval responses, retry, cancellation, and tool reconciliation.
Use client.steer(runId, { prompt: "Focus on recovery" }, { requestId: "correction-123" })
to receive a persisted receipt. Reuse the optional request ID to deduplicate delivery;
observe steering_applied to confirm the input entered the conversation. Steering requires
the matching durable release (0.8 or newer within the supported peer range).
Construct it with an absolute endpoint, optional fetch, credentials, and static or
per-request headers. Restore UI state from snapshot(runId), then observe
stream(runId, { after: snapshot.cursor }). Incoming records and event ordering are
validated. Reconnection is explicit; aborting observation does not cancel execution.
These committed progress events are separate from token-delta chat streams.
See the durable HTTP guide.
Chat UI transport
The optional @anvia/client/durable-chat entrypoint exports createDurableChatTransport, which
adapts a durable endpoint to the ClientTransport contract used by useChat from @anvia/react
and the @anvia/react-ui primitives. Create one transport per chat session; the agent, session and
request identity live there, not in an individual message request.
const transport = createDurableChatTransport({ client, agentId, sessionId });
const chat = useChat({ transport });
The adapter submits the last user message with enqueue: true by default, maps durable journal
events to anvia.client.v3 frames, routes interaction responses to the run that produced them, and
uses the durable run id and sequence as { streamId, after } for resume. Aborting the subscription
detaches only; use transport.controller.cancel(), retry(), resolveTool() or
reattach(runId, after) for explicit run control. A busy session is reported as
DurableBusyError with the run to reattach to. Client history is discarded in favour of the
durable transcript, so regenerate() and reset() are approximate; thread lists are not covered.
DurableClient also exposes submitGraph, listGraphs, graphSnapshot, streamGraph, and
cancelGraph. Graph snapshots contain renderable nodes/edges and explicit waiting reasons.
Use each node's runId with the existing response/retry/reconciliation methods. Graph streams
carry graphId and taskId; refresh the snapshot to obtain the latest graph-wide state.
Restarted generations
A repeated generation_start for an unfinished turn emits message_reset before
new content. The reducer clears that message's parts, metadata, and generation state
while preserving its ID and role. Completed turns and other agent scopes are unaffected.
Upgrade both server and frontend copies of @anvia/client together so the frontend
validator recognizes this event.