@assistant-ui/mcp-docs-server 0.1.15 → 0.1.17

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 (55) hide show
  1. package/.docs/organized/code-examples/store-example.md +249 -147
  2. package/.docs/organized/code-examples/with-ag-ui.md +250 -186
  3. package/.docs/organized/code-examples/with-ai-sdk-v5.md +250 -199
  4. package/.docs/organized/code-examples/with-assistant-transport.md +195 -243
  5. package/.docs/organized/code-examples/with-cloud.md +277 -226
  6. package/.docs/organized/code-examples/with-custom-thread-list.md +1855 -0
  7. package/.docs/organized/code-examples/with-external-store.md +246 -180
  8. package/.docs/organized/code-examples/with-ffmpeg.md +255 -189
  9. package/.docs/organized/code-examples/with-langgraph.md +293 -242
  10. package/.docs/organized/code-examples/with-parent-id-grouping.md +243 -263
  11. package/.docs/organized/code-examples/with-react-hook-form.md +262 -196
  12. package/.docs/organized/code-examples/with-tanstack.md +1578 -0
  13. package/.docs/raw/blog/2024-07-29-hello/index.mdx +2 -2
  14. package/.docs/raw/docs/api-reference/overview.mdx +6 -6
  15. package/.docs/raw/docs/api-reference/primitives/ActionBar.mdx +85 -4
  16. package/.docs/raw/docs/api-reference/primitives/AssistantIf.mdx +200 -0
  17. package/.docs/raw/docs/api-reference/primitives/Composer.mdx +0 -20
  18. package/.docs/raw/docs/api-reference/primitives/Message.mdx +0 -45
  19. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +0 -50
  20. package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +2 -3
  21. package/.docs/raw/docs/cloud/persistence/langgraph.mdx +2 -3
  22. package/.docs/raw/docs/devtools.mdx +2 -3
  23. package/.docs/raw/docs/getting-started.mdx +36 -1102
  24. package/.docs/raw/docs/guides/Attachments.mdx +3 -25
  25. package/.docs/raw/docs/guides/Branching.mdx +1 -1
  26. package/.docs/raw/docs/guides/Speech.mdx +1 -1
  27. package/.docs/raw/docs/guides/ToolUI.mdx +1 -1
  28. package/.docs/raw/docs/legacy/styled/AssistantModal.mdx +2 -3
  29. package/.docs/raw/docs/legacy/styled/Decomposition.mdx +6 -5
  30. package/.docs/raw/docs/legacy/styled/Markdown.mdx +2 -3
  31. package/.docs/raw/docs/legacy/styled/Thread.mdx +2 -3
  32. package/.docs/raw/docs/react-compatibility.mdx +2 -5
  33. package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +3 -4
  34. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +3 -6
  35. package/.docs/raw/docs/runtimes/custom/external-store.mdx +2 -3
  36. package/.docs/raw/docs/runtimes/custom/local.mdx +11 -41
  37. package/.docs/raw/docs/runtimes/data-stream.mdx +15 -11
  38. package/.docs/raw/docs/runtimes/langgraph/index.mdx +3 -3
  39. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  40. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +2 -3
  41. package/.docs/raw/docs/runtimes/langserve.mdx +2 -3
  42. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +2 -3
  43. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +2 -3
  44. package/.docs/raw/docs/ui/AssistantModal.mdx +3 -25
  45. package/.docs/raw/docs/ui/AssistantSidebar.mdx +2 -24
  46. package/.docs/raw/docs/ui/Attachment.mdx +3 -25
  47. package/.docs/raw/docs/ui/Markdown.mdx +2 -24
  48. package/.docs/raw/docs/ui/Mermaid.mdx +2 -24
  49. package/.docs/raw/docs/ui/Reasoning.mdx +2 -24
  50. package/.docs/raw/docs/ui/Scrollbar.mdx +4 -6
  51. package/.docs/raw/docs/ui/SyntaxHighlighting.mdx +3 -47
  52. package/.docs/raw/docs/ui/Thread.mdx +38 -53
  53. package/.docs/raw/docs/ui/ThreadList.mdx +4 -47
  54. package/.docs/raw/docs/ui/ToolFallback.mdx +2 -24
  55. package/package.json +6 -7
@@ -82,10 +82,10 @@ export default function Home() {
82
82
  <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 p-8 dark:from-gray-900 dark:to-gray-800">
83
83
  <div className="mx-auto max-w-4xl">
84
84
  <div className="mb-8">
85
- <h1 className="mb-2 text-4xl font-bold text-gray-900 dark:text-white">
85
+ <h1 className="mb-2 font-bold text-4xl text-gray-900 dark:text-white">
86
86
  @assistant-ui/store Example
87
87
  </h1>
88
- <p className="text-lg text-gray-600 dark:text-gray-400">
88
+ <p className="text-gray-600 text-lg dark:text-gray-400">
89
89
  Demonstrating tap-based state management with scopes, lists, and
90
90
  providers
91
91
  </p>
@@ -104,57 +104,59 @@ export default function Home() {
104
104
  ```tsx
105
105
  "use client";
106
106
 
107
+ import { useState } from "react";
107
108
  import {
108
109
  useAssistantClient,
109
110
  AssistantProvider,
110
111
  useAssistantState,
112
+ useAssistantEvent,
111
113
  } from "@assistant-ui/store";
112
114
  import { FooList, FooListResource } from "./store/foo-store";
113
115
 
114
- import "./store/foo-scope"; // Register the fooList scope (demonstrates scope registry)
115
-
116
116
  /**
117
117
  * Single Foo component - displays and allows editing a single foo
118
118
  */
119
119
  const Foo = () => {
120
120
  const aui = useAssistantClient();
121
- const fooState = useAssistantState(({ foo }) => {
122
- console.log("selector called with state", foo);
123
- return foo;
121
+ const fooId = useAssistantState(({ foo }) => foo.id);
122
+ const fooBar = useAssistantState(({ foo }) => foo.bar);
123
+
124
+ // Each foo logs its own events - only receives events from THIS foo instance
125
+ useAssistantEvent("foo.updated", (payload) => {
126
+ console.log(`[${fooId}] Updated to: ${payload.newValue}`);
124
127
  });
125
128
 
126
129
  const handleUpdate = () => {
127
130
  aui.foo().updateBar(`Updated at ${new Date().toLocaleTimeString()}`);
128
- console.log("Foo state", aui.foo().getState(), fooState);
129
131
  };
130
132
 
131
133
  return (
132
134
  <div className="rounded-lg border border-gray-200 bg-white p-6 shadow-md transition-shadow hover:shadow-lg dark:border-gray-700 dark:bg-gray-800">
133
135
  <div className="space-y-3">
134
136
  <div className="flex items-center gap-2">
135
- <span className="text-sm font-semibold text-gray-500 dark:text-gray-400">
137
+ <span className="font-semibold text-gray-500 text-sm dark:text-gray-400">
136
138
  ID:
137
139
  </span>
138
- <span className="font-mono text-sm text-gray-900 dark:text-white">
139
- {fooState.id}
140
+ <span className="font-mono text-gray-900 text-sm dark:text-white">
141
+ {fooId}
140
142
  </span>
141
143
  </div>
142
144
  <div className="flex items-center gap-2">
143
- <span className="text-sm font-semibold text-gray-500 dark:text-gray-400">
145
+ <span className="font-semibold text-gray-500 text-sm dark:text-gray-400">
144
146
  Value:
145
147
  </span>
146
- <span className="text-gray-900 dark:text-white">{fooState.bar}</span>
148
+ <span className="text-gray-900 dark:text-white">{fooBar}</span>
147
149
  </div>
148
150
  <div className="mt-2 flex gap-2">
149
151
  <button
150
152
  onClick={handleUpdate}
151
- className="flex-1 rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none dark:focus:ring-offset-gray-800"
153
+ className="flex-1 rounded-md bg-blue-600 px-4 py-2 font-medium text-white transition-colors hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
152
154
  >
153
155
  Update
154
156
  </button>
155
157
  <button
156
158
  onClick={() => aui.foo().remove()}
157
- className="rounded-md bg-red-600 px-4 py-2 font-medium text-white transition-colors hover:bg-red-700 focus:ring-2 focus:ring-red-500 focus:ring-offset-2 focus:outline-none dark:focus:ring-offset-gray-800"
159
+ className="rounded-md bg-red-600 px-4 py-2 font-medium text-white transition-colors hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
158
160
  >
159
161
  Delete
160
162
  </button>
@@ -178,13 +180,73 @@ const AddFooButton = () => {
178
180
  return (
179
181
  <button
180
182
  onClick={() => aui.fooList().addFoo()}
181
- className="rounded-md bg-green-600 px-4 py-2 font-medium text-white transition-colors hover:bg-green-700 focus:ring-2 focus:ring-green-500 focus:ring-offset-2 focus:outline-none dark:focus:ring-offset-gray-800"
183
+ className="rounded-md bg-green-600 px-4 py-2 font-medium text-white transition-colors hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
182
184
  >
183
185
  Add New
184
186
  </button>
185
187
  );
186
188
  };
187
189
 
190
+ type EventLogEntry = {
191
+ id: number;
192
+ event: string;
193
+ payload: unknown;
194
+ timestamp: Date;
195
+ };
196
+
197
+ let idCounter = 0;
198
+ /**
199
+ * EventLog component - demonstrates event subscription
200
+ */
201
+ const EventLog = () => {
202
+ const [logs, setLogs] = useState<EventLogEntry[]>([]);
203
+
204
+ // Subscribe to all events using the wildcard selector
205
+ useAssistantEvent("*", (data) => {
206
+ setLogs((prev) => [
207
+ {
208
+ id: ++idCounter,
209
+ event: data.event,
210
+ payload: data.payload,
211
+ timestamp: new Date(),
212
+ },
213
+ ...prev.slice(0, 9), // Keep last 10 entries
214
+ ]);
215
+ });
216
+
217
+ return (
218
+ <div className="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
219
+ <h3 className="mb-3 font-semibold text-gray-900 dark:text-white">
220
+ Event Log
221
+ </h3>
222
+ <div className="max-h-48 space-y-2 overflow-y-auto">
223
+ {logs.length === 0 ? (
224
+ <p className="text-gray-500 text-sm dark:text-gray-400">
225
+ No events yet. Try updating or deleting a foo.
226
+ </p>
227
+ ) : (
228
+ logs.map((log) => (
229
+ <div
230
+ key={log.id}
231
+ className="rounded border border-gray-100 bg-gray-50 p-2 font-mono text-xs dark:border-gray-600 dark:bg-gray-700"
232
+ >
233
+ <span className="font-semibold text-blue-600 dark:text-blue-400">
234
+ {log.event}
235
+ </span>
236
+ <span className="ml-2 text-gray-600 dark:text-gray-300">
237
+ {JSON.stringify(log.payload)}
238
+ </span>
239
+ <span className="ml-2 text-gray-400 dark:text-gray-500">
240
+ {log.timestamp.toLocaleTimeString()}
241
+ </span>
242
+ </div>
243
+ ))
244
+ )}
245
+ </div>
246
+ </div>
247
+ );
248
+ };
249
+
188
250
  /**
189
251
  * Example App - demonstrates the store with styled components
190
252
  *
@@ -192,27 +254,28 @@ const AddFooButton = () => {
192
254
  * but we're explicitly passing it here for clarity in the example.
193
255
  */
194
256
  export const ExampleApp = () => {
195
- const rootClient = useAssistantClient({
196
- fooList: FooListResource(),
257
+ const aui = useAssistantClient({
258
+ fooList: FooListResource({ initialValues: true }),
197
259
  });
198
260
 
199
261
  return (
200
- <AssistantProvider client={rootClient}>
262
+ <AssistantProvider client={aui}>
201
263
  <div className="space-y-6">
202
264
  <div className="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
203
265
  <div className="flex items-center justify-between">
204
- <h2 className="text-xl font-semibold text-gray-900 dark:text-white">
266
+ <h2 className="font-semibold text-gray-900 text-xl dark:text-white">
205
267
  Foo List <FooListLength />
206
268
  </h2>
207
269
  <AddFooButton />
208
270
  </div>
209
- <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
271
+ <p className="mt-1 text-gray-600 text-sm dark:text-gray-400">
210
272
  Each item is rendered in its own FooProvider with scoped access
211
273
  </p>
212
274
  </div>
213
275
  <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
214
276
  <FooList components={{ Foo }} />
215
277
  </div>
278
+ <EventLog />
216
279
  </div>
217
280
  </AssistantProvider>
218
281
  );
@@ -223,46 +286,48 @@ export const ExampleApp = () => {
223
286
  ## lib/store/foo-scope.ts
224
287
 
225
288
  ```typescript
226
- /**
227
- * Scope registration for the foo example
228
- * Import this file to register the default fooList scope
229
- */
230
- import { registerAssistantScope } from "@assistant-ui/store";
289
+ type FooState = { id: string; bar: string };
290
+ type FooMethods = {
291
+ getState: () => FooState;
292
+ updateBar: (newBar: string) => void;
293
+ remove: () => void;
294
+ };
295
+ type FooMeta = {
296
+ source: "fooList";
297
+ query: { index: number } | { key: string };
298
+ };
299
+ type FooEvents = {
300
+ "foo.updated": { id: string; newValue: string };
301
+ "foo.removed": { id: string };
302
+ };
303
+
304
+ type FooListState = { foos: FooState[] };
305
+ type FooListMethods = {
306
+ getState: () => FooListState;
307
+ foo: (lookup: FooMeta["query"]) => FooMethods;
308
+ addFoo: () => void;
309
+ };
310
+ type FooListEvents = {
311
+ "fooList.added": { id: string };
312
+ };
231
313
 
232
- /**
233
- * Define scopes via module augmentation
234
- * Implement the scope definition raw without importing ScopeDefinition
235
- */
236
314
  declare module "@assistant-ui/store" {
237
- interface AssistantScopeRegistry {
315
+ interface ClientRegistry {
238
316
  foo: {
239
- value: {
240
- getState: () => { id: string; bar: string };
241
- updateBar: (newBar: string) => void;
242
- remove: () => void;
243
- };
244
- source: "fooList";
245
- query: { index: number } | { id: string };
317
+ state: FooState;
318
+ methods: FooMethods;
319
+ meta: FooMeta;
320
+ events: FooEvents;
246
321
  };
247
322
  fooList: {
248
- value: {
249
- getState: () => { foos: Array<{ id: string; bar: string }> };
250
- foo: (
251
- lookup: { index: number } | { id: string },
252
- ) => AssistantScopeRegistry["foo"]["value"];
253
- addFoo: (id?: string) => void;
254
- };
255
- source: "root";
256
- query: Record<string, never>;
323
+ state: FooListState;
324
+ methods: FooListMethods;
325
+ events: FooListEvents;
257
326
  };
258
327
  }
259
328
  }
260
329
 
261
- // Register the fooList scope with a default implementation
262
- registerAssistantScope({
263
- name: "fooList",
264
- defaultInitialize: { error: "FooList is not configured" },
265
- });
330
+ export default {};
266
331
 
267
332
  ```
268
333
 
@@ -271,77 +336,88 @@ registerAssistantScope({
271
336
  ```tsx
272
337
  "use client";
273
338
 
339
+ import "./foo-scope";
340
+
274
341
  import React from "react";
275
- import { resource, tapState } from "@assistant-ui/tap";
342
+ import { resource, tapMemo, tapState } from "@assistant-ui/tap";
276
343
  import {
277
344
  useAssistantClient,
278
345
  AssistantProvider,
279
- tapApi,
280
- tapStoreList,
281
- DerivedScope,
346
+ tapClientList,
347
+ Derived,
282
348
  useAssistantState,
349
+ tapAssistantEmit,
350
+ type ClientOutput,
283
351
  } from "@assistant-ui/store";
284
352
 
285
- /**
286
- * Single Foo item resource
287
- * Manages the state and actions for a single foo item
288
- */
353
+ type FooData = { id: string; bar: string };
354
+
289
355
  export const FooItemResource = resource(
290
356
  ({
291
- initialValue: { id, initialBar },
357
+ getInitialData,
292
358
  remove,
293
- }: {
294
- initialValue: { id: string; initialBar: string };
295
- remove: () => void;
296
- }) => {
297
- const [state, setState] = tapState<{ id: string; bar: string }>({
298
- id,
299
- bar: initialBar,
300
- });
359
+ }: tapClientList.ResourceProps<FooData>): ClientOutput<"foo"> => {
360
+ const emit = tapAssistantEmit();
361
+
362
+ const [state, setState] = tapState<FooData>(getInitialData);
301
363
 
302
364
  const updateBar = (newBar: string) => {
303
365
  setState({ ...state, bar: newBar });
366
+ emit("foo.updated", { id: state.id, newValue: newBar });
304
367
  };
305
368
 
306
- return tapApi(
307
- {
369
+ const handleRemove = () => {
370
+ emit("foo.removed", { id: state.id });
371
+ remove();
372
+ };
373
+
374
+ return {
375
+ state,
376
+ methods: {
308
377
  getState: () => state,
309
378
  updateBar,
310
- remove,
379
+ remove: handleRemove,
311
380
  },
312
- { key: id },
313
- );
381
+ };
314
382
  },
315
383
  );
316
384
 
317
- /**
318
- * FooList resource implementation
319
- * Manages a list of foos using tapStoreList
320
- */
321
385
  let counter = 3;
322
- export const FooListResource = resource(() => {
323
- const idGenerator = () => `foo-${++counter}`;
324
-
325
- const foos = tapStoreList({
326
- initialValues: [
327
- { id: "foo-1", initialBar: "First Foo" },
328
- { id: "foo-2", initialBar: "Second Foo" },
329
- { id: "foo-3", initialBar: "Third Foo" },
330
- ],
331
- resource: FooItemResource,
332
- idGenerator,
333
- });
386
+ export const FooListResource = resource(
387
+ ({ initialValues }: { initialValues: boolean }): ClientOutput<"fooList"> => {
388
+ const emit = tapAssistantEmit();
389
+
390
+ const foos = tapClientList({
391
+ initialValues: initialValues
392
+ ? [
393
+ { id: "foo-1", bar: "First Foo" },
394
+ { id: "foo-2", bar: "Second Foo" },
395
+ { id: "foo-3", bar: "Third Foo" },
396
+ ]
397
+ : [],
398
+ getKey: (foo) => foo.id,
399
+ resource: FooItemResource,
400
+ });
334
401
 
335
- return tapApi({
336
- getState: () => ({ foos: foos.state }),
337
- foo: foos.api,
338
- addFoo: (id?: string) => foos.add(id),
339
- });
340
- });
402
+ const addFoo = () => {
403
+ const id = `foo-${++counter}`;
404
+ foos.add({ id: id, bar: `New Foo` });
405
+ emit("fooList.added", { id: id });
406
+ };
407
+
408
+ const state = tapMemo(() => ({ foos: foos.state }), [foos.state]);
409
+
410
+ return {
411
+ state,
412
+ methods: {
413
+ getState: () => state,
414
+ foo: foos.get,
415
+ addFoo,
416
+ },
417
+ };
418
+ },
419
+ );
341
420
 
342
- /**
343
- * FooProvider - Provides foo scope for a specific index
344
- */
345
421
  export const FooProvider = ({
346
422
  index,
347
423
  children,
@@ -349,11 +425,10 @@ export const FooProvider = ({
349
425
  index: number;
350
426
  children: React.ReactNode;
351
427
  }) => {
352
- // Create a derived client with the foo scope at the specified index
353
428
  const aui = useAssistantClient({
354
- foo: DerivedScope({
429
+ foo: Derived({
355
430
  source: "fooList",
356
- query: { index },
431
+ query: { index: index },
357
432
  get: (aui) => aui.fooList().foo({ index }),
358
433
  }),
359
434
  });
@@ -361,10 +436,6 @@ export const FooProvider = ({
361
436
  return <AssistantProvider client={aui}>{children}</AssistantProvider>;
362
437
  };
363
438
 
364
- /**
365
- * FooList component - minimal mapping component
366
- * Maps over the list and renders each item in a FooProvider
367
- */
368
439
  export const FooList = ({
369
440
  components,
370
441
  }: {
@@ -408,24 +479,21 @@ export default nextConfig;
408
479
  "scripts": {
409
480
  "dev": "next dev",
410
481
  "build": "next build",
411
- "start": "next start",
412
- "lint": "eslint"
482
+ "start": "next start"
413
483
  },
414
484
  "dependencies": {
415
485
  "@assistant-ui/store": "workspace:*",
416
486
  "@assistant-ui/tap": "workspace:*",
417
- "next": "16.0.4",
418
- "react": "19.2.0",
419
- "react-dom": "19.2.0"
487
+ "next": "16.0.10",
488
+ "react": "19.2.3",
489
+ "react-dom": "19.2.3"
420
490
  },
421
491
  "devDependencies": {
422
492
  "@assistant-ui/x-buildutils": "workspace:*",
423
493
  "@tailwindcss/postcss": "^4",
424
- "@types/node": "^24",
494
+ "@types/node": "^25",
425
495
  "@types/react": "19.2.7",
426
496
  "@types/react-dom": "19.2.3",
427
- "eslint": "^9",
428
- "eslint-config-next": "16.0.4",
429
497
  "tailwindcss": "^4",
430
498
  "typescript": "^5"
431
499
  }
@@ -442,9 +510,10 @@ This is a Next.js application demonstrating the `@assistant-ui/store` package.
442
510
 
443
511
  ## Features Demonstrated
444
512
 
445
- - **Scope Definition**: Module augmentation for type-safe scopes
446
- - **tapApi**: Wrapping API objects for stability and reactivity
447
- - **tapLookupResources**: Managing lists with index and ID lookup
513
+ - **Client Registry**: Module augmentation for type-safe client definitions
514
+ - **tapClientList**: Managing lists with index and key lookup
515
+ - **tapAssistantEmit**: Emitting and subscribing to scoped events
516
+ - **Derived**: Creating derived client scopes from parent resources
448
517
  - **Provider Pattern**: Scoped access to list items via FooProvider
449
518
  - **Component Composition**: Render props pattern with components prop
450
519
 
@@ -463,33 +532,42 @@ Open [http://localhost:3000](http://localhost:3000) to see the example.
463
532
 
464
533
  ## Project Structure
465
534
 
466
- - `lib/store/foo-store.tsx` - Clean store implementation with:
467
- - Scope definitions (foo, fooList) via module augmentation
535
+ - `lib/store/foo-scope.ts` - Type definitions via module augmentation:
536
+ - Client registry definitions (foo, fooList)
537
+ - State, methods, meta, and events types
538
+ - `lib/store/foo-store.tsx` - Store implementation with:
468
539
  - Resource implementations (FooItemResource, FooListResource)
469
540
  - Provider component (FooProvider)
470
- - Minimal FooList mapping component
541
+ - FooList mapping component
471
542
  - `lib/example-app.tsx` - Example app with styled components:
472
- - Styled Foo component
543
+ - Foo component with update/delete actions
544
+ - EventLog component demonstrating event subscriptions
473
545
  - ExampleApp with layout and styling
474
546
  - `app/page.tsx` - Main page that renders the ExampleApp
475
547
 
476
548
  ## Key Concepts
477
549
 
478
- ### Scope Definition
550
+ ### Client Registry
479
551
 
480
552
  ```typescript
481
553
  declare module "@assistant-ui/store" {
482
- namespace AssistantStore {
483
- interface Scopes {
484
- foo: {
485
- value: {
486
- getState: () => { id: string; bar: string };
487
- updateBar: (newBar: string) => void;
488
- };
554
+ interface ClientRegistry {
555
+ foo: {
556
+ state: { id: string; bar: string };
557
+ methods: {
558
+ getState: () => FooState;
559
+ updateBar: (newBar: string) => void;
560
+ remove: () => void;
561
+ };
562
+ meta: {
489
563
  source: "fooList";
490
- query: { index: number } | { id: string };
564
+ query: { index: number } | { key: string };
491
565
  };
492
- }
566
+ events: {
567
+ "foo.updated": { id: string; newValue: string };
568
+ "foo.removed": { id: string };
569
+ };
570
+ };
493
571
  }
494
572
  }
495
573
  ```
@@ -497,33 +575,57 @@ declare module "@assistant-ui/store" {
497
575
  ### Resource Implementation
498
576
 
499
577
  ```typescript
500
- const FooListResource = resource(() => {
501
- const items = [
502
- /* ... */
503
- ];
504
- const foos = tapLookupResources(
505
- items.map((item) => FooItemResource(item, { key: item.id })),
506
- );
578
+ const FooListResource = resource(
579
+ ({ initialValues }): ClientOutput<"fooList"> => {
580
+ const emit = tapAssistantEmit();
581
+
582
+ const foos = tapClientList({
583
+ initialValues: initialValues ? [/* ... */] : [],
584
+ getKey: (foo) => foo.id,
585
+ resource: FooItemResource,
586
+ });
507
587
 
508
- return tapApi({
509
- getState: () => ({ foos: foos.state }),
510
- foo: foos.api,
511
- });
512
- });
588
+ return {
589
+ state: { foos: foos.state },
590
+ methods: {
591
+ getState: () => state,
592
+ foo: foos.get,
593
+ addFoo: () => { /* ... */ },
594
+ },
595
+ };
596
+ },
597
+ );
513
598
  ```
514
599
 
515
- ### Provider Pattern
600
+ ### Provider Pattern with Derived
516
601
 
517
602
  ```typescript
518
603
  const FooProvider = ({ index, children }) => {
519
- const parentAui = useAssistantClient();
520
604
  const aui = useAssistantClient({
521
- foo: resource(() => parentAui.fooList().foo({ index }))(),
605
+ foo: Derived({
606
+ source: "fooList",
607
+ query: { index },
608
+ get: (aui) => aui.fooList().foo({ index }),
609
+ }),
522
610
  });
523
- return <AssistantClientProvider client={aui}>{children}</AssistantClientProvider>;
611
+ return <AssistantProvider client={aui}>{children}</AssistantProvider>;
524
612
  };
525
613
  ```
526
614
 
615
+ ### Event Subscriptions
616
+
617
+ ```typescript
618
+ // Subscribe to specific events within a scope
619
+ useAssistantEvent("foo.updated", (payload) => {
620
+ console.log(`Updated to: ${payload.newValue}`);
621
+ });
622
+
623
+ // Subscribe to all events using wildcard
624
+ useAssistantEvent("*", (data) => {
625
+ console.log(data.event, data.payload);
626
+ });
627
+ ```
628
+
527
629
  ## Learn More
528
630
 
529
631
  - [@assistant-ui/store Documentation](../store/README.md)