Skip to main content
This is the transport layer beneath the UI: a typed client that speaks the Gateway’s HTTP RPC and WebSocket protocol, plus the TanStack DB collection factory that turns those calls into live, reconnecting data. It is framework-free on purpose.
Most UIs should not touch this. Reach for the React bindings in /reference/gateway-react, which hold one client for you and expose live hooks. Drop down to the client only for non-React hosts, custom transports, or scripts.
Everything on this page lives at the subpath smithers-orchestrator/gateway-client, not on the bare smithers-orchestrator facade. Import from the subpath or the build fails.

SmithersGatewayClient

The typed client. Construct it with a base URL (and optional auth token); call a named RPC method, or open a WebSocket and subscribe to a run’s event stream.
options
SmithersGatewayClientOptions

RPC methods

Each method is a thin typed wrapper over rpc(method, params), which POSTs to /v1/rpc/<method> and unwraps the response frame. Params and return shapes come from the method catalog; see /rpc/launch-run for one method in full.
run lifecycle
methods
launchRun, resumeRun, pauseRun, cancelRun, hijackRun, rewindRun.
human-in-the-loop
methods
submitApproval, submitSignal, listApprovals.
reads
methods
getRun, listRuns, listWorkflows, getNodeOutput, getNodeDiff, getRunDiff, whatHappened.
crons
methods
cronList, cronCreate, cronDelete, cronRun.
escape hatches
methods
rpc(method, params, { signal? }) for any typed method, rpcRaw(method, params?, { signal? }) for an untyped one, and extensionRpc(namespace, key, params?) / streamExtension(namespace, key, params?) for gateway extensions.

Subscribing to events

connect() opens a SmithersGatewayConnection. The higher-level generators filter and yield frames for you, so most callers iterate one of those instead of driving the connection directly.
streamRunEvents(params, { signal? })
AsyncGenerator<GatewayEventFrame>
Subscribes to one run and yields its run.* frames (run.event, run.gap_resync, run.heartbeat, run.error). Pass afterSeq to resume. Closes the socket when iteration ends.
streamRunEventsResilient(params, options?)
AsyncGenerator<GatewayEventFrame>
Same frames, but reconnects with backoff + jitter on a silent drop and resumes from the last observed seq. Stops on terminal completion or abort. Options: signal, backoff (GatewayBackoffOptions), healthyAfterMs, and onReconnect(event).
streamDevTools(params, { signal? })
AsyncGenerator<GatewayEventFrame>
Subscribes to a run’s DevTools snapshot stream.
connect({ subscribe?, signal? })
Promise<SmithersGatewayConnection>
Opens the WebSocket, performs the connect handshake (protocol + auth), and returns the live connection. Use this only when you need request/response over the socket or raw event frames.

SmithersGatewayConnection

A single open WebSocket. RPC over the socket via request / requestRaw, and a single in-order async stream of server event frames via events(signal?). One consumer per connection; the generators above own a connection each.
request(method, params)
Promise<payload>
Typed request/response over the socket.
requestRaw(method, params?)
Promise<unknown>
Untyped request/response over the socket.
events(signal?)
AsyncGenerator<GatewayEventFrame>
In-order server event frames. Ends on close; throws on an error or invalid frame.
close()
void
Closes the socket, rejects pending requests, and ends events().
Source SmithersGatewayClient.ts · SmithersGatewayConnection.ts · Tests SmithersGatewayClient.test.ts · See also /rpc/launch-run, Gateway integration

GatewayRpcError

The error every RPC rejects with on a failed frame or HTTP error. Inspect code to branch (for example, requiredScope is set on an authorization failure).
method
string
The RPC method that failed (or "websocket" for a malformed socket frame).
code
string
Machine-readable error code, e.g. HTTP_ERROR, INVALID_GATEWAY_RESPONSE, or the gateway’s own code from the response frame.
status
number
HTTP status when the failure came over HTTP RPC.
requiredScope
string
The scope the call needed, on an authorization failure.
refresh
string
Set when the gateway asks the client to refresh credentials.
details
unknown
Extra context attached by the gateway.
Source GatewayRpcError.ts · Tests gateway-client.test.ts

isGatewayUnavailableError

True when an error means nothing that speaks the gateway protocol answered the URL: a 2xx response whose body is not an { ok, ... } envelope, or a fetch-level rejection (connection refused, DNS failure) because nothing is listening at all. The usual cause is a host app’s SPA fallback serving index.html for /v1/api/* because no gateway is wired. The data client throws these with code GATEWAY_UNAVAILABLE, and the QueryCollection layer already degrades them quietly: collections settle on the last rows a real gateway served (empty before the first success), a single session-level console.info notice replaces the per-collection [QueryCollection] error spam, and the SSE change stream refuses non-text/event-stream answers so the connection status parks offline instead of flapping online. Recovery is automatic: the stream’s reconnect backoff keeps probing, and the reset emitted on a real reconnect refetches every collection. Branch on it when you call api.* directly and want the same behavior.
Real gateway errors and non-2xx HTTP failures never classify as unavailable. Source isGatewayUnavailableError.ts · Tests gatewayUnavailableQuietDegrade.test.ts

gatewayBackoffDelay

Exponential backoff with full jitter for one 0-based attempt. The resilient stream uses it internally; call it directly when you write your own reconnect loop.
attempt
number
required
0-based attempt index. The base delay grows by factor ** attempt, capped at maxMs.
options
GatewayBackoffOptions
number
number
Milliseconds to wait, never negative.
Source gatewayBackoffDelay.ts · Tests gatewayBackoffDelay.test.ts

createSmithersCollections

Builds the TanStack DB collection registry. Local mode uses the Gateway REST domain API plus /v1/api/stream SSE invalidation. Multiplayer mode uses Electric shapes from electricBaseUrl for reads and keeps the same domain API write path.
mode
WorkspaceMode
required
{ kind: "local", apiBaseUrl, token? } or { kind: "multiplayer", apiBaseUrl, electricBaseUrl, workspaceId, token? }.
queryClient
QueryClient
required
The TanStack Query client used by QueryCollection and invalidation.
SmithersCollections
object
Registry methods include runs, run, runTree, runEvents, nodes, approvals, workflows, docs, prompts, scores, tickets, memoryFacts, and crons, plus connect, invalidate, and close.
Source createSmithersCollections.ts · Tests smithers-collections

createSmithersDataClient

Creates the domain API client that collection mutation handlers call. Reads and writes target /v1/api/*; stream.subscribe opens /v1/api/stream and emits change, reset, and heartbeat invalidation events.
options.mode
WorkspaceMode
required
Workspace mode and auth token.
options.fetch
typeof fetch
Fetch override for tests or custom runtimes.
options.EventSource
typeof EventSource
SSE implementation override. When omitted, the client falls back to streaming fetch.
SmithersDataClient
object
{ mode, api, stream, close }. The api object covers run lifecycle, approvals, signals, crons, docs, prompts, memory facts, scores, tickets, node output, node diffs, and schema signatures.

Collection keys and row types

smithersCollectionKeys contains the TanStack Query keys used by the registry. The row types are exported from the same package, including GatewayRunRow, GatewayRunSummaryRow, GatewayRunEventRow, GatewayRunNode, GatewayApprovalRow, GatewayWorkflowRow, GatewayCronRow, GatewayMemoryFactRow, GatewayScoreRow, GatewayTicketRow, and GatewayPromptRow. Run-tree helpers remain public for custom inspectors: flattenGatewayRunNode, snapshotToGatewayRunNode, and reconcileSnapshotNodes.
Source index.ts · Tests packages/gateway-client/tests · See also Gateway React API, Gateway integration, /rpc/launch-run