@assistant-ui/store 0.2.10 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +36 -65
  2. package/dist/AuiIf.d.ts +43 -8
  3. package/dist/AuiIf.d.ts.map +1 -1
  4. package/dist/AuiIf.js +28 -3
  5. package/dist/AuiIf.js.map +1 -1
  6. package/dist/Derived.d.ts +15 -13
  7. package/dist/Derived.d.ts.map +1 -1
  8. package/dist/Derived.js +24 -20
  9. package/dist/Derived.js.map +1 -1
  10. package/dist/RenderChildrenWithAccessor.d.ts +13 -6
  11. package/dist/RenderChildrenWithAccessor.d.ts.map +1 -1
  12. package/dist/RenderChildrenWithAccessor.js +42 -48
  13. package/dist/RenderChildrenWithAccessor.js.map +1 -1
  14. package/dist/attachTransformScopes.d.ts +11 -10
  15. package/dist/attachTransformScopes.d.ts.map +1 -1
  16. package/dist/attachTransformScopes.js +20 -23
  17. package/dist/attachTransformScopes.js.map +1 -1
  18. package/dist/index.d.ts +15 -16
  19. package/dist/index.js +14 -18
  20. package/dist/tapClientList.d.ts +26 -23
  21. package/dist/tapClientList.d.ts.map +1 -1
  22. package/dist/tapClientList.js +66 -63
  23. package/dist/tapClientList.js.map +1 -1
  24. package/dist/tapClientLookup.d.ts +14 -11
  25. package/dist/tapClientLookup.d.ts.map +1 -1
  26. package/dist/tapClientLookup.js +31 -37
  27. package/dist/tapClientLookup.js.map +1 -1
  28. package/dist/tapClientResource.d.ts +12 -9
  29. package/dist/tapClientResource.d.ts.map +1 -1
  30. package/dist/tapClientResource.js +92 -104
  31. package/dist/tapClientResource.js.map +1 -1
  32. package/dist/types/client.d.ts +50 -42
  33. package/dist/types/client.d.ts.map +1 -1
  34. package/dist/types/client.js +0 -2
  35. package/dist/types/events.d.ts +23 -24
  36. package/dist/types/events.d.ts.map +1 -1
  37. package/dist/types/events.js +13 -6
  38. package/dist/types/events.js.map +1 -1
  39. package/dist/useAui.d.ts +76 -15
  40. package/dist/useAui.d.ts.map +1 -1
  41. package/dist/useAui.js +178 -175
  42. package/dist/useAui.js.map +1 -1
  43. package/dist/useAuiEvent.d.ts +47 -2
  44. package/dist/useAuiEvent.d.ts.map +1 -1
  45. package/dist/useAuiEvent.js +60 -7
  46. package/dist/useAuiEvent.js.map +1 -1
  47. package/dist/useAuiState.d.ts +31 -10
  48. package/dist/useAuiState.d.ts.map +1 -1
  49. package/dist/useAuiState.js +44 -25
  50. package/dist/useAuiState.js.map +1 -1
  51. package/dist/utils/BaseProxyHandler.d.ts +19 -16
  52. package/dist/utils/BaseProxyHandler.d.ts.map +1 -1
  53. package/dist/utils/BaseProxyHandler.js +46 -43
  54. package/dist/utils/BaseProxyHandler.js.map +1 -1
  55. package/dist/utils/NotificationManager.d.ts +13 -9
  56. package/dist/utils/NotificationManager.d.ts.map +1 -1
  57. package/dist/utils/NotificationManager.js +69 -82
  58. package/dist/utils/NotificationManager.js.map +1 -1
  59. package/dist/utils/proxied-assistant-state.d.ts +8 -4
  60. package/dist/utils/proxied-assistant-state.d.ts.map +1 -1
  61. package/dist/utils/proxied-assistant-state.js +28 -26
  62. package/dist/utils/proxied-assistant-state.js.map +1 -1
  63. package/dist/utils/react-assistant-context.d.ts +31 -13
  64. package/dist/utils/react-assistant-context.d.ts.map +1 -1
  65. package/dist/utils/react-assistant-context.js +69 -56
  66. package/dist/utils/react-assistant-context.js.map +1 -1
  67. package/dist/utils/splitClients.d.ts +12 -8
  68. package/dist/utils/splitClients.d.ts.map +1 -1
  69. package/dist/utils/splitClients.js +39 -43
  70. package/dist/utils/splitClients.js.map +1 -1
  71. package/dist/utils/tap-assistant-context.d.ts +17 -14
  72. package/dist/utils/tap-assistant-context.d.ts.map +1 -1
  73. package/dist/utils/tap-assistant-context.js +18 -15
  74. package/dist/utils/tap-assistant-context.js.map +1 -1
  75. package/dist/utils/tap-client-stack-context.d.ts +10 -6
  76. package/dist/utils/tap-client-stack-context.d.ts.map +1 -1
  77. package/dist/utils/tap-client-stack-context.js +22 -19
  78. package/dist/utils/tap-client-stack-context.js.map +1 -1
  79. package/dist/wrapperResource.d.ts +6 -2
  80. package/dist/wrapperResource.d.ts.map +1 -1
  81. package/dist/wrapperResource.js +12 -9
  82. package/dist/wrapperResource.js.map +1 -1
  83. package/package.json +7 -7
  84. package/src/AuiIf.ts +35 -1
  85. package/src/Derived.ts +1 -1
  86. package/src/types/client.ts +1 -2
  87. package/src/useAui.ts +101 -32
  88. package/src/useAuiEvent.ts +41 -0
  89. package/src/useAuiState.ts +25 -8
  90. package/src/utils/react-assistant-context.tsx +18 -5
  91. package/src/utils/splitClients.ts +4 -2
  92. package/dist/index.d.ts.map +0 -1
  93. package/dist/index.js.map +0 -1
  94. package/dist/types/client.js.map +0 -1
@@ -1,11 +1,14 @@
1
- import { resource, withKey, } from "@assistant-ui/tap";
2
- export const wrapperResource = (fn) => {
3
- const res = resource(fn);
4
- return (props) => {
5
- const el = res(props);
6
- if (props.key === undefined)
7
- return el;
8
- return withKey(props.key, el);
9
- };
1
+ import { resource, withKey } from "@assistant-ui/tap";
2
+ //#region src/wrapperResource.ts
3
+ const wrapperResource = (fn) => {
4
+ const res = resource(fn);
5
+ return (props) => {
6
+ const el = res(props);
7
+ if (props.key === void 0) return el;
8
+ return withKey(props.key, el);
9
+ };
10
10
  };
11
+ //#endregion
12
+ export { wrapperResource };
13
+
11
14
  //# sourceMappingURL=wrapperResource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapperResource.js","sourceRoot":"","sources":["../src/wrapperResource.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,QAAQ,EACR,OAAO,GACR,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,EAAoC,EACH,EAAE;IACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzB,OAAO,CAAC,KAAyB,EAAE,EAAE;QACnC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;QACtB,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QACvC,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"wrapperResource.js","names":[],"sources":["../src/wrapperResource.ts"],"sourcesContent":["import {\n type ResourceElement,\n type Resource,\n resource,\n withKey,\n} from \"@assistant-ui/tap\";\n\nexport const wrapperResource = <R, P>(\n fn: (props: ResourceElement<P>) => R,\n): Resource<R, ResourceElement<P>> => {\n const res = resource(fn);\n return (props: ResourceElement<P>) => {\n const el = res(props);\n if (props.key === undefined) return el;\n return withKey(props.key, el);\n };\n};\n"],"mappings":";;AAOA,MAAa,mBACX,OACoC;CACpC,MAAM,MAAM,SAAS,EAAE;CACvB,QAAQ,UAA8B;EACpC,MAAM,KAAK,IAAI,KAAK;EACpB,IAAI,MAAM,QAAQ,KAAA,GAAW,OAAO;EACpC,OAAO,QAAQ,MAAM,KAAK,EAAE;CAC9B;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/store",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "Tap-based state management for @assistant-ui",
5
5
  "keywords": [
6
6
  "state-management",
@@ -30,7 +30,7 @@
30
30
  "use-effect-event": "^2.0.3"
31
31
  },
32
32
  "peerDependencies": {
33
- "@assistant-ui/tap": "^0.5.11",
33
+ "@assistant-ui/tap": "^0.5.12",
34
34
  "@types/react": "*",
35
35
  "react": "^18 || ^19"
36
36
  },
@@ -41,13 +41,13 @@
41
41
  },
42
42
  "devDependencies": {
43
43
  "@testing-library/react": "^16.3.2",
44
- "@types/react": "^19.2.14",
44
+ "@types/react": "^19.2.15",
45
45
  "@types/react-dom": "^19.2.3",
46
46
  "jsdom": "^29.1.1",
47
- "react": "^19.2.5",
48
- "vitest": "^4.1.5",
49
- "@assistant-ui/tap": "0.5.11",
50
- "@assistant-ui/x-buildutils": "0.0.7"
47
+ "react": "^19.2.6",
48
+ "vitest": "^4.1.7",
49
+ "@assistant-ui/tap": "0.5.12",
50
+ "@assistant-ui/x-buildutils": "0.0.9"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public",
package/src/AuiIf.ts CHANGED
@@ -5,10 +5,44 @@ import { useAuiState } from "./useAuiState";
5
5
  import type { AssistantState } from "./types/client";
6
6
 
7
7
  export namespace AuiIf {
8
- export type Props = PropsWithChildren<{ condition: AuiIf.Condition }>;
8
+ /** Props for `AuiIf`. */
9
+ export type Props = PropsWithChildren<{
10
+ /**
11
+ * Selector that decides whether to render `children`. Children render
12
+ * when this returns `true` and unmount when it returns `false`.
13
+ */
14
+ condition: AuiIf.Condition;
15
+ }>;
16
+
17
+ /**
18
+ * Selector passed to `AuiIf`. Receives the assistant state and must
19
+ * return a boolean.
20
+ */
9
21
  export type Condition = (state: AssistantState) => boolean;
10
22
  }
11
23
 
24
+ /**
25
+ * Conditionally renders children based on a slice of assistant state.
26
+ *
27
+ * A thin wrapper around {@link useAuiState} that renders its children
28
+ * when `condition` returns `true` and unmounts them when it returns
29
+ * `false`. Keeps render logic declarative without mounting unused
30
+ * subtrees.
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * <AuiIf condition={(s) => s.thread.isRunning}>
35
+ * <CancelButton />
36
+ * </AuiIf>
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * <AuiIf condition={(s) => s.thread.messages.length === 0}>
42
+ * <EmptyState />
43
+ * </AuiIf>
44
+ * ```
45
+ */
12
46
  export const AuiIf: FC<AuiIf.Props> = ({ children, condition }) => {
13
47
  const result = useAuiState(condition);
14
48
  return result ? children : null;
package/src/Derived.ts CHANGED
@@ -42,5 +42,5 @@ export namespace Derived {
42
42
  */
43
43
  export type Props<K extends ClientNames> = {
44
44
  get: (client: AssistantClient) => ReturnType<AssistantClientAccessor<K>>;
45
- } & (ClientMeta<K> | { getMeta: (client: AssistantClient) => ClientMeta<K> });
45
+ } & ClientMeta<K>;
46
46
  }
@@ -15,12 +15,11 @@ export interface ClientMethods {
15
15
  type ClientMetaType = { source: ClientNames; query: Record<string, unknown> };
16
16
 
17
17
  /**
18
- * Schema of a client in the assistant system (internal type).
18
+ * Schema of a client in the assistant system.
19
19
  * @template TState - The state type for this client
20
20
  * @template TMethods - The methods available on this client
21
21
  * @template TMeta - Source/query metadata (optional)
22
22
  * @template TEvents - Events that this client can emit (optional)
23
- * @internal
24
23
  */
25
24
  export type ClientSchema<
26
25
  TMethods extends ClientMethods = ClientMethods,
package/src/useAui.ts CHANGED
@@ -5,7 +5,6 @@ import {
5
5
  resource,
6
6
  tapMemo,
7
7
  tapResources,
8
- tapEffectEvent,
9
8
  tapEffect,
10
9
  tapRef,
11
10
  tapResource,
@@ -19,7 +18,7 @@ import type {
19
18
  ClientElement,
20
19
  ClientMeta,
21
20
  } from "./types/client";
22
- import type { Derived, DerivedElement } from "./Derived";
21
+ import type { DerivedElement } from "./Derived";
23
22
  import {
24
23
  useAssistantContextValue,
25
24
  DefaultAssistantClient,
@@ -209,24 +208,6 @@ const RootClientsAccessorsResource = resource(
209
208
  },
210
209
  );
211
210
 
212
- type MetaMemo<K extends ClientNames> = {
213
- meta?: ClientMeta<K>;
214
- dep?: unknown;
215
- };
216
-
217
- const getMeta = <K extends ClientNames>(
218
- props: Derived.Props<K>,
219
- clientRef: { parent: AssistantClient; current: AssistantClient | null },
220
- memo: MetaMemo<K>,
221
- ): ClientMeta<K> => {
222
- if ("source" in props && "query" in props) return props;
223
- if (memo.dep === props) return memo.meta!;
224
- const meta = props.getMeta(clientRef.current!);
225
- memo.meta = meta;
226
- memo.dep = props;
227
- return meta;
228
- };
229
-
230
211
  const DerivedClientAccessorResource = resource(
231
212
  <K extends ClientNames>({
232
213
  element,
@@ -237,17 +218,24 @@ const DerivedClientAccessorResource = resource(
237
218
  clientRef: { parent: AssistantClient; current: AssistantClient | null };
238
219
  name: K;
239
220
  }) => {
240
- const get = tapEffectEvent(() => element.props);
221
+ // Track the latest props on a ref updated in render. The fiber is
222
+ // keyed on the scope's meta by DerivedClientsAccessorsResource, so
223
+ // source/query are stable for this fiber's lifetime and the only
224
+ // value that can change between renders for the same fiber is the
225
+ // identity of the `get` closure. Routing reads through the ref
226
+ // avoids the one-commit lag that the previous `tapEffectEvent`
227
+ // path imposed.
228
+ const propsRef = tapRef(element.props);
229
+ propsRef.current = element.props;
241
230
 
242
231
  return tapMemo(() => {
243
- const clientFunction = () => get().get(clientRef.current!);
244
- const metaMemo = {};
232
+ const clientFunction = () => propsRef.current.get(clientRef.current!);
245
233
  Object.defineProperties(clientFunction, {
246
234
  source: {
247
- get: () => getMeta(get(), clientRef, metaMemo).source,
235
+ value: propsRef.current.source,
248
236
  },
249
237
  query: {
250
- get: () => getMeta(get(), clientRef, metaMemo).query,
238
+ value: propsRef.current.query,
251
239
  },
252
240
  name: {
253
241
  value: name,
@@ -259,6 +247,26 @@ const DerivedClientAccessorResource = resource(
259
247
  },
260
248
  );
261
249
 
250
+ const serializeMeta = <K extends ClientNames>(
251
+ name: K,
252
+ meta: ClientMeta<K>,
253
+ ): string => {
254
+ // Sort top-level keys so {a, b} and {b, a} hash to the same fiber
255
+ // identity, and guard JSON.stringify against unusual values (BigInt,
256
+ // circular refs) so render never throws here.
257
+ let queryKey: string;
258
+ try {
259
+ const sorted: Record<string, unknown> = {};
260
+ for (const k of Object.keys(meta.query as object).sort()) {
261
+ sorted[k] = (meta.query as Record<string, unknown>)[k];
262
+ }
263
+ queryKey = JSON.stringify(sorted);
264
+ } catch {
265
+ queryKey = String(meta.query);
266
+ }
267
+ return `${name}::${meta.source}::${queryKey}`;
268
+ };
269
+
262
270
  const DerivedClientsAccessorsResource = resource(
263
271
  ({
264
272
  clients,
@@ -270,16 +278,18 @@ const DerivedClientsAccessorsResource = resource(
270
278
  return tapShallowMemoArray(
271
279
  tapResources(
272
280
  () =>
273
- Object.keys(clients).map((key) =>
274
- withKey(
275
- key,
281
+ Object.keys(clients).map((key) => {
282
+ const name = key as keyof typeof clients;
283
+ const element = clients[name]!;
284
+ return withKey(
285
+ serializeMeta(name, element.props),
276
286
  DerivedClientAccessorResource({
277
- element: clients[key as keyof typeof clients]!,
287
+ element,
278
288
  clientRef,
279
- name: key as keyof typeof clients,
289
+ name,
280
290
  }),
281
- ),
282
- ),
291
+ );
292
+ }),
283
293
  [clients, clientRef],
284
294
  ),
285
295
  );
@@ -359,8 +369,67 @@ export namespace useAui {
359
369
  };
360
370
  }
361
371
 
372
+ /**
373
+ * Returns the current `AssistantClient` from context.
374
+ *
375
+ * Read the client supplied by the nearest {@link AuiProvider} or
376
+ * {@link AssistantRuntimeProvider}, then access a scope on it —
377
+ * `aui.thread()`, `aui.composer()`, `aui.message()`, and so on. Pair
378
+ * with {@link useAuiState} to read reactive state and {@link useAuiEvent}
379
+ * to subscribe to events. The returned client also exposes lower-level
380
+ * methods such as `aui.on(...)` and `aui.subscribe(...)`; prefer
381
+ * `useAuiEvent` for React event subscriptions.
382
+ *
383
+ * Rendered outside a provider, the returned client's scope accessors
384
+ * throw a descriptive error whenever they are called.
385
+ *
386
+ * @example
387
+ * ```tsx
388
+ * const aui = useAui();
389
+ *
390
+ * const onSend = () => aui.composer().send();
391
+ * const onCancel = () => aui.thread().cancelRun();
392
+ * ```
393
+ *
394
+ * @example
395
+ * ```tsx
396
+ * // Combine with useAuiState to drive disabled state.
397
+ * const aui = useAui();
398
+ * const isRunning = useAuiState((s) => s.thread.isRunning);
399
+ *
400
+ * return (
401
+ * <button disabled={isRunning} onClick={() => aui.composer().send()}>
402
+ * Send
403
+ * </button>
404
+ * );
405
+ * ```
406
+ */
362
407
  export function useAui(): AssistantClient;
408
+ /**
409
+ * Extends the parent `AssistantClient` with additional scopes.
410
+ *
411
+ * Advanced overload used when building primitives or providers — for example,
412
+ * when a custom provider needs to register a `message`, `part`, or other scope
413
+ * onto the client visible to its descendants. Application code rarely reaches
414
+ * for this; use {@link useAui} with no arguments to read the existing client.
415
+ *
416
+ * @example
417
+ * ```tsx
418
+ * const aui = useAui({
419
+ * message: Derived({
420
+ * source: "thread",
421
+ * query: { index: 0 },
422
+ * get: (aui) => aui.thread().message({ index: 0 }),
423
+ * }),
424
+ * });
425
+ *
426
+ * const role = useAuiState((s) => s.message.role);
427
+ * ```
428
+ */
363
429
  export function useAui(clients: useAui.Props): AssistantClient;
430
+ /**
431
+ * Extends an explicit parent `AssistantClient` with additional scopes.
432
+ */
364
433
  export function useAui(
365
434
  clients: useAui.Props,
366
435
  config: { parent: null | AssistantClient },
@@ -8,6 +8,47 @@ import type {
8
8
  } from "./types/events";
9
9
  import { normalizeEventSelector } from "./types/events";
10
10
 
11
+ /**
12
+ * Subscribes to an assistant event for the lifetime of the component.
13
+ *
14
+ * The subscription is established on mount and re-established whenever the
15
+ * scope or event name changes. The `callback` is wrapped in an effect-event
16
+ * shim, so the latest closure is invoked on each emission — you do not
17
+ * need to memoize it.
18
+ *
19
+ * @param selector - Either a dotted event name like
20
+ * `"thread.modelContextUpdate"` or an object `{ scope, event }`. Use
21
+ * `scope: "*"` to subscribe at the root client and receive emissions
22
+ * from any descendant scope, regardless of which one is in React
23
+ * context.
24
+ * @param callback - Invoked with the event payload. The most recent
25
+ * reference is always called. Return values are ignored, async callbacks
26
+ * are not awaited, and the callback cannot be called during render.
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * // React to transient model-context changes.
31
+ * useAuiEvent("thread.modelContextUpdate", ({ threadId }) => {
32
+ * analytics.track("model_context_update", { threadId });
33
+ * });
34
+ * ```
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * // React to thread switches.
39
+ * useAuiEvent("threadListItem.switchedTo", () => {
40
+ * resetLocalState();
41
+ * });
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * // Listen from the root client rather than the current React context.
47
+ * useAuiEvent({ scope: "*", event: "thread.modelContextUpdate" }, (payload) => {
48
+ * analytics.track("model_context_update", payload);
49
+ * });
50
+ * ```
51
+ */
11
52
  export const useAuiEvent = <TEvent extends AssistantEventName>(
12
53
  selector: AssistantEventSelector<TEvent>,
13
54
  callback: AssistantEventCallback<TEvent>,
@@ -4,18 +4,35 @@ import { useAui } from "./useAui";
4
4
  import { getProxiedAssistantState } from "./utils/proxied-assistant-state";
5
5
 
6
6
  /**
7
- * Hook to access a slice of the assistant state with automatic subscription
7
+ * Subscribes to a slice of {@link AssistantState} and re-renders the
8
+ * component whenever that slice changes.
8
9
  *
9
- * @param selector - Function to select a slice of the state
10
- * @returns The selected state slice
10
+ * The `selector` is called on every store update; its return value is
11
+ * compared by `Object.is`, and the component re-renders only when the
12
+ * selected slice changes. Returning the entire state object is not
13
+ * supported and throws at runtime — select a specific field instead, or
14
+ * compose multiple `useAuiState` calls. Returning a new object or array
15
+ * literal, including spreading `s.thread` into a new object, causes a
16
+ * re-render on every store update; either select primitives or return a
17
+ * memoized reference.
18
+ *
19
+ * @param selector - Pure function that derives a value from the current
20
+ * assistant state. Should be cheap and referentially stable for equal
21
+ * inputs (plain field reads, primitives, or memoized values).
22
+ * @returns The currently selected slice.
11
23
  *
12
24
  * @example
13
- * ```typescript
14
- * const aui = useAui({
15
- * foo: RootScope({ ... }),
16
- * });
25
+ * ```tsx
26
+ * // Disable a button while a run is in flight.
27
+ * const isRunning = useAuiState((s) => s.thread.isRunning);
28
+ * ```
17
29
  *
18
- * const bar = useAuiState((s) => s.foo.bar);
30
+ * @example
31
+ * ```tsx
32
+ * // Prefer multiple selectors over an inline object literal, which would
33
+ * // create a new reference on every render.
34
+ * const text = useAuiState((s) => s.composer.text);
35
+ * const canSend = useAuiState((s) => s.composer.canSend);
19
36
  * ```
20
37
  */
21
38
  export const useAuiState = <T>(selector: (state: AssistantState) => T): T => {
@@ -85,20 +85,33 @@ export const useAssistantContextValue = (): AssistantClient => {
85
85
  };
86
86
 
87
87
  /**
88
- * Provider component for AssistantClient
88
+ * Supplies an `AssistantClient` to the React tree.
89
+ *
90
+ * Place near the root of any subtree that uses {@link useAui} or the
91
+ * primitives built on it. Components rendered outside an `AuiProvider`
92
+ * receive a default client whose scope accessors throw on use, so
93
+ * missing-provider mistakes surface at the point of use.
94
+ *
95
+ * When mounting a runtime built with one of the runtime hooks, use
96
+ * {@link AssistantRuntimeProvider} — it installs an `AuiProvider`
97
+ * internally — rather than wiring `AuiProvider` yourself.
89
98
  *
90
99
  * @example
91
- * ```typescript
92
- * <AuiProvider value={aui}>
93
- * <YourApp />
94
- * </AuiProvider>
100
+ * ```tsx
101
+ * function ScopedAssistant({ children, scopes }) {
102
+ * const aui = useAui(scopes);
103
+ *
104
+ * return <AuiProvider value={aui}>{children}</AuiProvider>;
105
+ * }
95
106
  * ```
96
107
  */
97
108
  export const AuiProvider = ({
98
109
  value,
99
110
  children,
100
111
  }: {
112
+ /** Assistant client to expose to descendants. */
101
113
  value: AssistantClient;
114
+ /** Subtree that may read from the client. */
102
115
  children: React.ReactNode;
103
116
  }): React.ReactElement => {
104
117
  return (
@@ -6,7 +6,7 @@ import type {
6
6
  } from "../types/client";
7
7
  import { getTransformScopes } from "../attachTransformScopes";
8
8
  import type { useAui } from "../useAui";
9
- import { tapMemo } from "@assistant-ui/tap";
9
+ import { tapMemo, type ResourceElement } from "@assistant-ui/tap";
10
10
 
11
11
  export type RootClients = Partial<
12
12
  Record<ClientNames, ClientElement<ClientNames>>
@@ -35,7 +35,9 @@ function splitClients(clients: useAui.Props, baseClient: AssistantClient) {
35
35
  if (visited.has(clientElement.type)) continue;
36
36
  visited.add(clientElement.type);
37
37
 
38
- const transform = getTransformScopes(clientElement.type);
38
+ const transform = getTransformScopes(
39
+ clientElement.type as (props: any) => ResourceElement<any>,
40
+ );
39
41
  if (transform) {
40
42
  transform(scopes, baseClient);
41
43
  changed = true;
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,0BAA0B,EAAE,wCAAqC;AAG1E,OAAO,EAAE,KAAK,EAAE,mBAAgB;AAChC,OAAO,EAAE,WAAW,EAAE,2CAAwC;AAG9D,OAAO,EAAE,OAAO,EAAE,qBAAkB;AACpC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,mCAAgC;AACjC,YAAY,EAAE,YAAY,EAAE,mCAAgC;AAG5D,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,yCAAsC;AACvC,OAAO,EAAE,iBAAiB,EAAE,+BAA4B;AACxD,OAAO,EAAE,eAAe,EAAE,6BAA0B;AACpD,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAGhD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,eAAe,EACf,cAAc,GACf,0BAAuB;AACxB,OAAO,EACL,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,GACzB,0BAAuB"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,0BAA0B,EAAE,wCAAqC;AAE1E,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,mBAAgB;AAChC,OAAO,EAAE,WAAW,EAAE,2CAAwC;AAE9D,YAAY;AACZ,OAAO,EAAE,OAAO,EAAE,qBAAkB;AACpC,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,mCAAgC;AAGjC,YAAY;AACZ,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,yCAAsC;AACvC,OAAO,EAAE,iBAAiB,EAAE,+BAA4B;AACxD,OAAO,EAAE,eAAe,EAAE,6BAA0B;AACpD,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAiBhD,OAAO,EACL,sBAAsB,GAMvB,0BAAuB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/types/client.ts"],"names":[],"mappings":""}