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
209 lines
4.5 KiB
Plaintext
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);
|
|
```
|