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

395 lines
9.9 KiB
Plaintext

---
title: API Reference
description: All exports from @assistant-ui/store.
---
## Hooks
### useAui()
```ts
function useAui(): AssistantClient;
```
Returns the store from the nearest `AuiProvider`. Does not re-render when scopes change — returns a stable reference.
### useAui(scopes)
```ts
function useAui(scopes: useAui.Props): AssistantClient;
```
Takes the store from the nearest `AuiProvider` and extends it by filling the provided scopes. Returns a new `AssistantClient` that includes both the parent's scopes and the newly provided ones.
```ts
type useAui.Props = {
[K in ClientNames]?: ClientElement<K> | DerivedElement<K>;
};
```
### useAuiState
```ts
function useAuiState<T>(selector: (state: AssistantState) => T): T;
```
Subscribes to a slice of state. Re-renders only when the selected value changes (compared by `Object.is`). The selector must return a specific value — not the entire state object.
### useAuiEvent
```ts
function useAuiEvent<TEvent extends AssistantEventName>(
selector: AssistantEventSelector<TEvent>,
callback: AssistantEventCallback<TEvent>,
): void;
```
Subscribes to events. The selector can be a string (`"scope.event"`) or an object (`{ scope, event }`). Unsubscribes on unmount.
---
## Components
### AuiProvider
```tsx
<AuiProvider value={aui}>{children}</AuiProvider>
```
Provides an `AssistantClient` to the React tree. Child components can access it via `useAui()`.
### AuiIf
```tsx
<AuiIf condition={(s) => s.counter.count > 0}>
<ResetButton />
</AuiIf>
```
Renders children only when the condition returns `true`. Uses `useAuiState` internally.
### RenderChildrenWithAccessor
```tsx
<RenderChildrenWithAccessor
getItemState={(aui) => aui.todoList().todo({ index }).getState()}
>
{(getItem) =>
children({
get todo() {
return getItem();
},
})
}
</RenderChildrenWithAccessor>
```
Sets up a lazy item accessor for list rendering. The `getItem` function defers reading state until the consumer accesses it — if the children render function never reads the item, no subscription is created. When children returns a propless component (e.g. `{() => <Todo />}`), the output is automatically memoized.
| Prop | Type |
|------|------|
| `getItemState` | `(aui: AssistantClient) => T` |
| `children` | `(getItem: () => T) => ReactNode` |
See [Rendering Lists](/tap/docs/store/rendering-lists) for the full pattern.
---
## Resource utilities
### Derived
```ts
function Derived<K extends ClientNames>(config: Derived.Props<K>): DerivedElement<K>;
```
Creates a derived scope that points to data in a parent scope.
```ts
Derived({
source: "thread",
query: { index: 0 },
get: (aui) => aui.thread().message({ index: 0 }),
});
```
The `get` function receives the current `AssistantClient` and must return the result of calling a parent scope method. The meta (`source`, `query`) acts as identity: when `query` changes between renders, a new derived client function is returned in the same render pass — useful for keying child consumers like `MessageByIndex` by index.
### attachTransformScopes
```ts
function attachTransformScopes<T extends (...args: any[]) => ResourceElement<any>>(
resource: T,
transform: (scopes: ScopesConfig, parent: AssistantClient) => ScopesConfig,
): void;
```
Attaches a transform function to a resource. When the resource is mounted via `useAui`, the transform runs and can add or modify sibling scopes. Transforms are applied iteratively — new root scopes trigger their own transforms.
One transform per resource. Throws on duplicate.
---
## Resource hooks
These are used inside Tap resources to integrate with Store.
### useClientResource
```ts
function useClientResource<TMethods extends ClientMethods>(
element: ResourceElement<TMethods>,
): {
state: InferClientState<TMethods>;
methods: TMethods;
key: string | number | undefined;
};
```
Wraps a single resource element into a client. Adds the client to the internal client stack for event scoping.
`state` is inferred from the element's `getState()` return type. If `getState` is not defined, `state` is `undefined`.
### useClientLookup
```ts
function useClientLookup<TMethods extends ClientMethods>(
elements: readonly ResourceElement<TMethods>[],
): {
state: InferClientState<TMethods>[];
get: (lookup: { index: number } | { key: string }) => TMethods;
};
```
Wraps a list of resource elements into clients. Each element must have a key (via `withKey`). Uses `useClientResource` internally for each element.
`get` resolves a client by index or key. Throws if the lookup doesn't match.
### useClientList
```ts
function useClientList<TData, TMethods extends ClientMethods>(
props: useClientList.Props<TData, TMethods>,
): {
state: InferClientState<TMethods>[];
get: (lookup: { index: number } | { key: string }) => TMethods;
add: (data: TData) => void;
};
```
Manages a dynamic list of clients with add/remove. Built on `useClientLookup`.
```ts
type useClientList.Props<TData, TMethods> = {
initialValues: TData[];
getKey: (data: TData) => string;
resource: ContravariantResource<TMethods, useClientList.ResourceProps<TData>>;
};
type useClientList.ResourceProps<TData> = {
key: string;
getInitialData: () => TData;
remove: () => void;
};
```
`getInitialData()` is called once on mount. `remove()` removes the item from the list. Throws on duplicate key.
### useAssistantClientRef
```ts
function useAssistantClientRef(): {
parent: AssistantClient;
current: AssistantClient | null;
};
```
Returns a ref to the store being built. `current` is `null` during resource creation and populated after all sibling scopes are mounted. Use in `useEffect` to access sibling scopes at runtime.
### useAssistantEmit
```ts
function useAssistantEmit(): <TEvent extends Exclude<AssistantEventName, "*">>(
event: TEvent,
payload: AssistantEventPayload[TEvent],
) => void;
```
Returns a stable emit function. Events are delivered via microtask — listeners fire after the current state update settles.
---
## Types
### ScopeRegistry
```ts
interface ScopeRegistry {}
```
Module augmentation point. Augment this interface to register scopes:
```ts
declare module "@assistant-ui/store" {
interface ScopeRegistry {
counter: {
methods: {
getState: () => { count: number };
increment: () => void;
};
meta?: { source: ClientNames; query: Record<string, unknown> };
events?: { "counter.incremented": { newCount: number } };
};
}
}
```
`methods` is required. `meta` and `events` are optional.
### ClientOutput
```ts
type ClientOutput<K extends ClientNames> = ClientSchemas[K]["methods"] & ClientMethods;
```
The return type for a resource implementing scope `K`. Use as the return type annotation on your resource function.
### ClientNames
```ts
type ClientNames = keyof ClientSchemas;
```
Union of all registered scope names.
### AssistantClient
```ts
type AssistantClient = {
[K in ClientNames]: AssistantClientAccessor<K>;
} & {
subscribe(listener: () => void): Unsubscribe;
on<TEvent extends AssistantEventName>(
selector: AssistantEventSelector<TEvent>,
callback: AssistantEventCallback<TEvent>,
): Unsubscribe;
};
```
The store object returned by `useAui()`. Each scope is an accessor. `subscribe` fires on any state change. `on` subscribes to typed events.
### AssistantClientAccessor
```ts
type AssistantClientAccessor<K extends ClientNames> =
(() => ClientSchemas[K]["methods"]) &
(
| ClientMeta<K>
| { source: "root"; query: Record<string, never> }
| { source: null; query: null }
) &
{ name: K };
```
A scope accessor. Call it (`aui.counter()`) to resolve the scope's methods. Read `.source`, `.query`, and `.name` for metadata.
### AssistantState
```ts
type AssistantState = {
[K in ClientNames]: ClientSchemas[K]["methods"] extends {
getState: () => infer S;
}
? S
: never;
};
```
The state object passed to `useAuiState` selectors. Each key is the return type of that scope's `getState()`.
### ClientMeta
```ts
type ClientMeta<K extends ClientNames> =
"meta" extends keyof ClientSchemas[K]
? Pick<ClientSchemas[K]["meta"], "source" | "query">
: never;
```
The `source` and `query` shape for scope `K`, if `meta` is declared in `ScopeRegistry`.
### ClientElement
```ts
type ClientElement<K extends ClientNames> = ResourceElement<ClientOutput<K>>;
```
A resource element that implements scope `K`.
### Unsubscribe
```ts
type Unsubscribe = () => void;
```
---
## Event types
### AssistantEventName
```ts
type AssistantEventName = keyof AssistantEventPayload;
```
Union of all registered event names, plus `"*"`.
### AssistantEventPayload
```ts
type AssistantEventPayload = ClientEventMap & {
"*": { [K in keyof ClientEventMap]: { event: K; payload: ClientEventMap[K] } }[keyof ClientEventMap];
};
```
Maps event names to their payload types. The `"*"` key receives a wrapped `{ event, payload }` object.
### AssistantEventSelector
```ts
type AssistantEventSelector<TEvent extends AssistantEventName> =
| TEvent
| { scope: AssistantEventScope<TEvent>; event: TEvent };
```
A string (`"scope.event"`) or object (`{ scope, event }`). Strings default to `scope` matching the event's source.
### AssistantEventScope
```ts
type AssistantEventScope<TEvent extends AssistantEventName> =
| "*"
| EventSource<TEvent>
| AncestorsOf<EventSource<TEvent>>;
```
Valid scopes to listen at: the event's source scope, any ancestor of that scope, or `"*"` for all.
### AssistantEventCallback
```ts
type AssistantEventCallback<TEvent extends AssistantEventName> = (
payload: AssistantEventPayload[TEvent],
) => void;
```
### normalizeEventSelector
```ts
function normalizeEventSelector<TEvent extends AssistantEventName>(
selector: AssistantEventSelector<TEvent>,
): { scope: AssistantEventScope<TEvent>; event: TEvent };
```
Converts a string selector to `{ scope, event }` form. Strings like `"counter.incremented"` become `{ scope: "counter", event: "counter.incremented" }`.