@langchain/langgraph-sdk
Version:
Client library for interacting with the LangGraph API
139 lines (138 loc) • 5.63 kB
TypeScript
import { Command, CommandResponse, ErrorResponse, Message, SubscribeParams } from "@langchain/protocol";
//#region src/client/stream/transport.d.ts
/**
* Handle returned by {@link TransportAdapter.openEventStream} representing
* a single filtered SSE connection.
*
* The `ready` promise resolves once the underlying connection is
* established (response headers received), letting callers ensure the
* subscription is active server-side before proceeding.
*/
interface EventStreamHandle {
events: AsyncIterable<Message>;
ready: Promise<void>;
close(): void;
}
/**
* Transport abstraction implemented by concrete client transports such as
* WebSocket or SSE adapters.
*
* In the thread-centric protocol the thread ID is part of the request
* URLs. Transports may be bound at construction time, or left unbound and
* bound later via {@link setThreadId} (see that method) — which lets a
* single instance follow a lazily-created thread.
*/
interface TransportAdapter {
/**
* Thread ID this transport currently targets.
*/
readonly threadId: string;
/**
* Rebind this transport to a different thread.
*
* `client.threads.stream(threadId, { transport })` calls this (when
* implemented) whenever the framework binds or re-binds the active
* thread — including the lazily-minted id from the first `submit()` on
* a `threadId: null` controller. Implementing it lets an adapter be
* constructed once (optionally with no `threadId`) and reused as the
* active thread becomes known, so the framework doesn't have to tear
* down and rebuild a custom transport when the thread id appears.
*
* Optional: adapters that bake `threadId` at construction can omit it,
* in which case the per-call `threadId` is ignored (prior behaviour).
*/
setThreadId?(threadId: string): void;
/**
* Opens the underlying connection (e.g. WebSocket handshake).
* For HTTP/SSE transports this is a no-op.
*/
open(): Promise<void>;
/**
* Sends a command and optionally returns an immediate response.
*
* @param command - Protocol command to send over the transport.
*/
send(command: Command): Promise<CommandResponse | ErrorResponse | void>;
/**
* Streams incoming protocol messages from the remote peer.
* Used by WebSocket transports where all events share one connection.
*/
events(): AsyncIterable<Message>;
/**
* Opens an independent filtered SSE event stream.
* Each call creates a new server connection with the given filter.
* Returns `undefined` when the transport does not support per-subscription
* streams (e.g. WebSocket), in which case the caller should fall back to
* command-based subscriptions over {@link events}.
*
* **Replay contract.** Implementations MUST buffer events emitted for
* the thread/run and replay them through every newly-opened stream
* whose filter matches. The SDK's shared-stream rotation relies on
* this: when a subscription's filter widens the union, the SDK opens
* a fresh stream and expects to receive the run's full history from
* `seq=0` (deduplication is handled client-side via `event_id`). The
* SDK also defers the open until after `run.start` has committed the
* thread server-side to avoid a `404: Thread not found`, which means
* events emitted during that window MUST be delivered to the late
* opener. The protocol v2 server implements this via a bounded
* per-run replay buffer; custom adapters should mirror that.
*/
openEventStream?(params: SubscribeParams): EventStreamHandle;
/**
* Shuts down the transport and releases any underlying resources.
*/
close(): Promise<void>;
}
/**
* Public v1 name for {@link TransportAdapter} plus optional high-level
* capabilities. Renamed to reflect that this interface now denotes the
* full agent-server protocol contract (not merely wire transport):
* any object that satisfies it can back a `useStream` call. See
* `plan-custom-transport.md` §4 for the rollout.
*
* The extra optional methods let adapters surface thread state and
* history without the framework needing to issue a parallel HTTP
* request — `useStream.hydrate()` calls `getState?()` when present
* and falls back to `client.threads.getState` otherwise. Adapters
* that don't know how to produce these values can simply omit them.
*
* The legacy `TransportAdapter` export is retained for back-compat and
* resolves to the same structural type; new code should prefer
* `AgentServerAdapter`.
*/
interface AgentServerAdapter extends TransportAdapter {
/**
* Fetch the latest checkpointed state for the bound thread via
* `GET /threads/:threadId/state` (or an adapter-specific override).
* When omitted, {@link StreamController.hydrate} falls back to
* `client.threads.getState()`.
*/
getState?<StateType = unknown>(): Promise<{
values: StateType;
next?: unknown;
tasks?: unknown;
metadata?: unknown;
checkpoint?: {
checkpoint_id?: string;
} | null;
parent_checkpoint?: {
checkpoint_id?: string;
} | null;
} | null>;
/**
* Fetch a slice of checkpoint history for the bound thread. Used
* by branching and time-travel UIs. Optional — omitting it turns
* those UIs into no-ops rather than surfacing an error.
*/
getHistory?<StateType = unknown>(options?: {
limit?: number;
}): Promise<Array<{
values: StateType;
checkpoint?: {
checkpoint_id?: string;
} | null;
}>>;
}
//#endregion
export { AgentServerAdapter, EventStreamHandle, TransportAdapter };
//# sourceMappingURL=transport.d.ts.map