Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

209 lines
4.5 KiB
Plaintext

---
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<T> = { state: T };
```
### GorpSessionsState
Snapshot shape returned by `GorpSessions.serialize`.
```ts
type GorpSessionsState = {
sessions: Record<string, { highWater: number }>;
};
```
---
## GorpClient
Leaf-side replica with an optimistic view layered on top of the latest
server-confirmed state.
```ts
new GorpClient<T, C>(config: GorpClient.Config<T, C>)
```
### `GorpClient.Config<T, C>`
```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<T> // 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<T, C>(config: GorpServer.Config<T, C>)
```
### `GorpServer.Config<T, C>`
```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<T, C>(config: GorpRelay.Config<T, C>)
```
### `GorpRelay.Config<T, C>`
```ts
{
initialState: T;
send: (command: C) => void; // upstream transport callback
}
```
### Properties
```ts
relay.state: DeepReadonly<T>
```
### 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<T>
relay.restore(state: RelaySerializedState<T>): 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<C>(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);
```