@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.
- package/README.md +36 -65
- package/dist/AuiIf.d.ts +43 -8
- package/dist/AuiIf.d.ts.map +1 -1
- package/dist/AuiIf.js +28 -3
- package/dist/AuiIf.js.map +1 -1
- package/dist/Derived.d.ts +15 -13
- package/dist/Derived.d.ts.map +1 -1
- package/dist/Derived.js +24 -20
- package/dist/Derived.js.map +1 -1
- package/dist/RenderChildrenWithAccessor.d.ts +13 -6
- package/dist/RenderChildrenWithAccessor.d.ts.map +1 -1
- package/dist/RenderChildrenWithAccessor.js +42 -48
- package/dist/RenderChildrenWithAccessor.js.map +1 -1
- package/dist/attachTransformScopes.d.ts +11 -10
- package/dist/attachTransformScopes.d.ts.map +1 -1
- package/dist/attachTransformScopes.js +20 -23
- package/dist/attachTransformScopes.js.map +1 -1
- package/dist/index.d.ts +15 -16
- package/dist/index.js +14 -18
- package/dist/tapClientList.d.ts +26 -23
- package/dist/tapClientList.d.ts.map +1 -1
- package/dist/tapClientList.js +66 -63
- package/dist/tapClientList.js.map +1 -1
- package/dist/tapClientLookup.d.ts +14 -11
- package/dist/tapClientLookup.d.ts.map +1 -1
- package/dist/tapClientLookup.js +31 -37
- package/dist/tapClientLookup.js.map +1 -1
- package/dist/tapClientResource.d.ts +12 -9
- package/dist/tapClientResource.d.ts.map +1 -1
- package/dist/tapClientResource.js +92 -104
- package/dist/tapClientResource.js.map +1 -1
- package/dist/types/client.d.ts +50 -42
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js +0 -2
- package/dist/types/events.d.ts +23 -24
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/events.js +13 -6
- package/dist/types/events.js.map +1 -1
- package/dist/useAui.d.ts +76 -15
- package/dist/useAui.d.ts.map +1 -1
- package/dist/useAui.js +178 -175
- package/dist/useAui.js.map +1 -1
- package/dist/useAuiEvent.d.ts +47 -2
- package/dist/useAuiEvent.d.ts.map +1 -1
- package/dist/useAuiEvent.js +60 -7
- package/dist/useAuiEvent.js.map +1 -1
- package/dist/useAuiState.d.ts +31 -10
- package/dist/useAuiState.d.ts.map +1 -1
- package/dist/useAuiState.js +44 -25
- package/dist/useAuiState.js.map +1 -1
- package/dist/utils/BaseProxyHandler.d.ts +19 -16
- package/dist/utils/BaseProxyHandler.d.ts.map +1 -1
- package/dist/utils/BaseProxyHandler.js +46 -43
- package/dist/utils/BaseProxyHandler.js.map +1 -1
- package/dist/utils/NotificationManager.d.ts +13 -9
- package/dist/utils/NotificationManager.d.ts.map +1 -1
- package/dist/utils/NotificationManager.js +69 -82
- package/dist/utils/NotificationManager.js.map +1 -1
- package/dist/utils/proxied-assistant-state.d.ts +8 -4
- package/dist/utils/proxied-assistant-state.d.ts.map +1 -1
- package/dist/utils/proxied-assistant-state.js +28 -26
- package/dist/utils/proxied-assistant-state.js.map +1 -1
- package/dist/utils/react-assistant-context.d.ts +31 -13
- package/dist/utils/react-assistant-context.d.ts.map +1 -1
- package/dist/utils/react-assistant-context.js +69 -56
- package/dist/utils/react-assistant-context.js.map +1 -1
- package/dist/utils/splitClients.d.ts +12 -8
- package/dist/utils/splitClients.d.ts.map +1 -1
- package/dist/utils/splitClients.js +39 -43
- package/dist/utils/splitClients.js.map +1 -1
- package/dist/utils/tap-assistant-context.d.ts +17 -14
- package/dist/utils/tap-assistant-context.d.ts.map +1 -1
- package/dist/utils/tap-assistant-context.js +18 -15
- package/dist/utils/tap-assistant-context.js.map +1 -1
- package/dist/utils/tap-client-stack-context.d.ts +10 -6
- package/dist/utils/tap-client-stack-context.d.ts.map +1 -1
- package/dist/utils/tap-client-stack-context.js +22 -19
- package/dist/utils/tap-client-stack-context.js.map +1 -1
- package/dist/wrapperResource.d.ts +6 -2
- package/dist/wrapperResource.d.ts.map +1 -1
- package/dist/wrapperResource.js +12 -9
- package/dist/wrapperResource.js.map +1 -1
- package/package.json +7 -7
- package/src/AuiIf.ts +35 -1
- package/src/Derived.ts +1 -1
- package/src/types/client.ts +1 -2
- package/src/useAui.ts +101 -32
- package/src/useAuiEvent.ts +41 -0
- package/src/useAuiState.ts +25 -8
- package/src/utils/react-assistant-context.tsx +18 -5
- package/src/utils/splitClients.ts +4 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types/client.js.map +0 -1
package/dist/wrapperResource.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { resource, withKey
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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","
|
|
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.
|
|
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.
|
|
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.
|
|
44
|
+
"@types/react": "^19.2.15",
|
|
45
45
|
"@types/react-dom": "^19.2.3",
|
|
46
46
|
"jsdom": "^29.1.1",
|
|
47
|
-
"react": "^19.2.
|
|
48
|
-
"vitest": "^4.1.
|
|
49
|
-
"@assistant-ui/tap": "0.5.
|
|
50
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
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
|
-
|
|
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
|
-
} &
|
|
45
|
+
} & ClientMeta<K>;
|
|
46
46
|
}
|
package/src/types/client.ts
CHANGED
|
@@ -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
|
|
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 {
|
|
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
|
-
|
|
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 = () =>
|
|
244
|
-
const metaMemo = {};
|
|
232
|
+
const clientFunction = () => propsRef.current.get(clientRef.current!);
|
|
245
233
|
Object.defineProperties(clientFunction, {
|
|
246
234
|
source: {
|
|
247
|
-
|
|
235
|
+
value: propsRef.current.source,
|
|
248
236
|
},
|
|
249
237
|
query: {
|
|
250
|
-
|
|
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
|
-
|
|
275
|
-
|
|
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
|
|
287
|
+
element,
|
|
278
288
|
clientRef,
|
|
279
|
-
name
|
|
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 },
|
package/src/useAuiEvent.ts
CHANGED
|
@@ -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>,
|
package/src/useAuiState.ts
CHANGED
|
@@ -4,18 +4,35 @@ import { useAui } from "./useAui";
|
|
|
4
4
|
import { getProxiedAssistantState } from "./utils/proxied-assistant-state";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Subscribes to a slice of {@link AssistantState} and re-renders the
|
|
8
|
+
* component whenever that slice changes.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
-
* ```
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* ```
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
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(
|
|
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;
|
package/dist/index.d.ts.map
DELETED
|
@@ -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"}
|
package/dist/types/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/types/client.ts"],"names":[],"mappings":""}
|