--- title: API Reference description: All exports from @assistant-ui/gorp. --- ## Types ### GorpMessage Server-to-client envelope. ```ts type GorpMessage = { ops: GorpOperation[]; ack?: number; }; ``` `ops` is a deep patch list; `ack` is the per-session high-water seq the inner has processed. Receiving the same `ack` twice is harmless. ### RelaySerializedState Snapshot shape returned by `GorpRelay.serialize`. ```ts type RelaySerializedState = { state: T }; ``` ### GorpSessionsState Snapshot shape returned by `GorpSessions.serialize`. ```ts type GorpSessionsState = { sessions: Record; }; ``` --- ## GorpClient Leaf-side replica with an optimistic view layered on top of the latest server-confirmed state. ```ts new GorpClient(config: GorpClient.Config) ``` ### `GorpClient.Config` ```ts { initialState: T; mutator: (state: T, command: C, seq: number) => void; send: (command: C) => void; } ``` The mutator must be deterministic in `(state, command, seq)` — `GorpClient` re-runs it on every replay to rebuild the optimistic view. The shape matches `GorpServer.Config` so a single function can run on both sides. `send` is invoked synchronously on every `client.send(cmd)` and again for every pending entry when `client.resync()` is called. ### Properties ```ts client.state: DeepReadonly // optimistic view (committed + replay(pending)) client.pending: readonly C[] client.firstPendingSeq: number // pass on (re)connect handshake ``` ### Methods ```ts client.send(command: C): void client.apply(message: GorpMessage): void client.resync(): void // re-emit pending via config.send client.onChange(cb: () => void): () => void client.isChangedAt(path: string[]): boolean client.getChangedKeys(path: string[]): string[] ``` `isChangedAt` / `getChangedKeys` are valid synchronously after `apply()` or `send()` — they describe what moved since the last public method call. --- ## GorpServer Authoritative state container. Pair with [`GorpSessions`](#gorpsessions) for the sessioned wire protocol. ```ts new GorpServer(config: GorpServer.Config) ``` ### `GorpServer.Config` ```ts { initialState: T; mutator: (state: T, command: C, seq: number) => void; } ``` ### Properties ```ts server.state: T // live mutable proxy — writes queue ops, batched per microtask server.state = newValue // root replace — emits a single `set []` op ``` Mutating array methods (`push`, `pop`, `splice`, …) throw — use `state.list = [...state.list, x]` instead. ### Methods ```ts server.receive(command: C): void server.subscribe(cb: (env: GorpMessage) => void): () => void ``` --- ## GorpRelay State mirror + upstream pipe. Same `state`/`receive`/`subscribe` surface as `GorpServer`, but state changes come from upstream `GorpMessage` envelopes instead of a local mutator. ```ts new GorpRelay(config: GorpRelay.Config) ``` ### `GorpRelay.Config` ```ts { initialState: T; send: (command: C) => void; // upstream transport callback } ``` ### Properties ```ts relay.state: DeepReadonly ``` ### Methods ```ts relay.receive(command: C): void // forward upstream via config.send relay.applyUpstream(msg: GorpMessage): void // inbound from upstream relay.subscribe(cb: (env: GorpMessage) => void): () => void relay.serialize(): RelaySerializedState relay.restore(state: RelaySerializedState): void ``` --- ## GorpSessions Wraps either a `GorpServer` or `GorpRelay` and adds the sessioned wire protocol: per-`sessionId` dedup, ack flushing, and resume-after-reconnect. ```ts new GorpSessions(inner: GorpServer | GorpRelay) ``` ### Methods ```ts sessions.addClient( sessionId: string, fromSeq: number, send: (msg: GorpMessage) => void, ): { receive(command: C): void; remove(): void } sessions.close(): void sessions.serialize(): GorpSessionsState sessions.restore(state: GorpSessionsState): void ``` `addClient` sends an initial `{ ops: [{ set [] state }], ack? }` envelope so a reconnecting client splices any already-processed pending without a round-trip. Sessions are retained for 1 hour after their last activity; currently-connected sessions are never pruned. --- ## Functions ### appendText Marker for the `append-text` op type — streaming text concatenation without retransmitting prior content. Works inside `GorpClient`'s optimistic mutator too. ```ts import { appendText } from "@assistant-ui/gorp"; server.state.messages[id].parts[0].text = appendText(chunk); ```