@assistant-ui/store 0.0.0

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -0
  3. package/dist/AssistantContext.d.ts +22 -0
  4. package/dist/AssistantContext.d.ts.map +1 -0
  5. package/dist/AssistantContext.js +44 -0
  6. package/dist/AssistantContext.js.map +1 -0
  7. package/dist/DerivedScope.d.ts +18 -0
  8. package/dist/DerivedScope.d.ts.map +1 -0
  9. package/dist/DerivedScope.js +11 -0
  10. package/dist/DerivedScope.js.map +1 -0
  11. package/dist/ScopeRegistry.d.ts +41 -0
  12. package/dist/ScopeRegistry.d.ts.map +1 -0
  13. package/dist/ScopeRegistry.js +17 -0
  14. package/dist/ScopeRegistry.js.map +1 -0
  15. package/dist/asStore.d.ts +20 -0
  16. package/dist/asStore.d.ts.map +1 -0
  17. package/dist/asStore.js +23 -0
  18. package/dist/asStore.js.map +1 -0
  19. package/dist/index.d.ts +13 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +20 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/tapApi.d.ts +36 -0
  24. package/dist/tapApi.d.ts.map +1 -0
  25. package/dist/tapApi.js +52 -0
  26. package/dist/tapApi.js.map +1 -0
  27. package/dist/tapLookupResources.d.ts +44 -0
  28. package/dist/tapLookupResources.d.ts.map +1 -0
  29. package/dist/tapLookupResources.js +21 -0
  30. package/dist/tapLookupResources.js.map +1 -0
  31. package/dist/tapStoreList.d.ts +76 -0
  32. package/dist/tapStoreList.d.ts.map +1 -0
  33. package/dist/tapStoreList.js +46 -0
  34. package/dist/tapStoreList.js.map +1 -0
  35. package/dist/types.d.ts +86 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +1 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/useAssistantClient.d.ts +42 -0
  40. package/dist/useAssistantClient.d.ts.map +1 -0
  41. package/dist/useAssistantClient.js +153 -0
  42. package/dist/useAssistantClient.js.map +1 -0
  43. package/dist/useAssistantState.d.ts +18 -0
  44. package/dist/useAssistantState.d.ts.map +1 -0
  45. package/dist/useAssistantState.js +53 -0
  46. package/dist/useAssistantState.js.map +1 -0
  47. package/dist/utils/splitScopes.d.ts +24 -0
  48. package/dist/utils/splitScopes.d.ts.map +1 -0
  49. package/dist/utils/splitScopes.js +18 -0
  50. package/dist/utils/splitScopes.js.map +1 -0
  51. package/package.json +50 -0
  52. package/src/AssistantContext.tsx +64 -0
  53. package/src/DerivedScope.ts +21 -0
  54. package/src/ScopeRegistry.ts +58 -0
  55. package/src/asStore.ts +40 -0
  56. package/src/index.ts +13 -0
  57. package/src/tapApi.ts +91 -0
  58. package/src/tapLookupResources.ts +62 -0
  59. package/src/tapStoreList.ts +133 -0
  60. package/src/types.ts +120 -0
  61. package/src/useAssistantClient.tsx +250 -0
  62. package/src/useAssistantState.tsx +80 -0
  63. package/src/utils/splitScopes.ts +38 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AgentbaseAI Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # @assistant-ui/store
2
+
3
+ Tap-based state management for assistant-ui with React Context integration.
4
+
5
+ ## Overview
6
+
7
+ The store package provides a bridge between tap Resources and React Components via React Context. It implements a scope-based system where you can define custom scopes using TypeScript module augmentation.
8
+
9
+ ## Key Concepts
10
+
11
+ ### Scopes
12
+
13
+ A **scope** defines a piece of state in your application. Each scope has:
14
+
15
+ - **value**: The state type (e.g., `{ bar: string }`)
16
+ - **source**: Where this scope comes from (`"root"` for top-level, or name of parent scope)
17
+ - **query**: Parameters needed to access this scope (e.g., `{ type: "index", index: number }`)
18
+
19
+ ### Module Augmentation
20
+
21
+ Define custom scopes by extending the `AssistantScopes` interface:
22
+
23
+ ```typescript
24
+ import type { ScopeDefinition } from "@assistant-ui/store";
25
+
26
+ declare module "@assistant-ui/store" {
27
+ interface AssistantScopes {
28
+ foo: ScopeDefinition<{ bar: string }, "root", {}>;
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### 1. Define a Scope
36
+
37
+ ```typescript
38
+ // foo-scope.ts
39
+ import { resource, tapState } from "@assistant-ui/tap";
40
+ import { tapApi } from "@assistant-ui/store";
41
+
42
+ // Define the scope type via module augmentation
43
+ // Implement the scope definition raw (no need to import ScopeDefinition)
44
+ declare module "@assistant-ui/store" {
45
+ interface AssistantScopes {
46
+ foo: {
47
+ value: {
48
+ getState: () => { bar: string };
49
+ updateBar: (newBar: string) => void;
50
+ };
51
+ source: "root";
52
+ query: Record<string, never>;
53
+ };
54
+ }
55
+ }
56
+
57
+ // Create the resource
58
+ export const FooResource = resource(() => {
59
+ const [state, setState] = tapState<{ bar: string }>({ bar: "Hello, World!" });
60
+
61
+ const updateBar = (newBar: string) => {
62
+ setState({ bar: newBar });
63
+ };
64
+
65
+ // Use tapApi to wrap the API for stability and reactivity
66
+ return tapApi({
67
+ getState: () => state,
68
+ updateBar,
69
+ });
70
+ });
71
+ ```
72
+
73
+ ### 2. Use in React Component
74
+
75
+ ```typescript
76
+ import { useAssistantClient } from "@assistant-ui/store";
77
+ import { FooResource } from "./foo-scope";
78
+
79
+ function MyComponent() {
80
+ // Create a client with the foo scope
81
+ const client = useAssistantClient({
82
+ foo: FooResource(),
83
+ });
84
+
85
+ // Access the state
86
+ const fooState = client.foo.getState();
87
+ console.log(fooState.bar); // "Hello, World!"
88
+
89
+ // Call actions
90
+ const handleClick = () => {
91
+ client.foo.updateBar("New value!");
92
+ };
93
+
94
+ return <div onClick={handleClick}>{fooState.bar}</div>;
95
+ }
96
+ ```
97
+
98
+ ### 3. Use with Provider (Optional)
99
+
100
+ ```typescript
101
+ import { AssistantProvider, useAssistantClient } from "@assistant-ui/store";
102
+ import { FooResource } from "./foo-scope";
103
+
104
+ function App() {
105
+ const client = useAssistantClient({
106
+ foo: FooResource,
107
+ });
108
+
109
+ return (
110
+ <AssistantProvider client={client}>
111
+ <MyComponent />
112
+ </AssistantProvider>
113
+ );
114
+ }
115
+
116
+ function MyComponent() {
117
+ // Access client from context
118
+ const client = useAssistantClient();
119
+ const fooState = client.foo.getState();
120
+
121
+ return <div>{fooState.bar}</div>;
122
+ }
123
+ ```
124
+
125
+ ### 4. Derived Scopes
126
+
127
+ Create scopes that depend on other scopes:
128
+
129
+ ```typescript
130
+ import { DerivedScope } from "@assistant-ui/store";
131
+
132
+ function MyComponent() {
133
+ const client = useAssistantClient({
134
+ foo: FooResource,
135
+ message: DerivedScope({
136
+ source: "thread",
137
+ query: { type: "index", index: 0 },
138
+ get: () => messageApi,
139
+ }),
140
+ });
141
+
142
+ return <div>{client.message.getState().content}</div>;
143
+ }
144
+ ```
145
+
146
+ ## API
147
+
148
+ ### `useAssistantClient()`
149
+
150
+ Returns the AssistantClient from context.
151
+
152
+ ```typescript
153
+ const client = useAssistantClient();
154
+ ```
155
+
156
+ ### `useAssistantClient(scopes)`
157
+
158
+ Creates a new AssistantClient with the provided scopes, merging with any client from context.
159
+
160
+ ```typescript
161
+ const client = useAssistantClient({
162
+ foo: FooResource,
163
+ });
164
+ ```
165
+
166
+ ### `AssistantProvider`
167
+
168
+ Provides an AssistantClient via React Context.
169
+
170
+ ```typescript
171
+ <AssistantProvider client={client}>
172
+ {children}
173
+ </AssistantProvider>
174
+ ```
175
+
176
+ ### `DerivedScope(config)`
177
+
178
+ Creates a derived scope field that memoizes based on source and query.
179
+
180
+ ```typescript
181
+ DerivedScope({
182
+ source: "thread",
183
+ query: { type: "index", index: 0 },
184
+ get: () => messageApi,
185
+ });
186
+ ```
187
+
188
+ ## Advanced: List Management with tapLookupResources
189
+
190
+ For managing lists of items, use `tapLookupResources`:
191
+
192
+ ```typescript
193
+ import { tapLookupResources, tapApi } from "@assistant-ui/store";
194
+
195
+ // Define item resource
196
+ const FooItemResource = resource(
197
+ ({ id, initialBar }: { id: string; initialBar: string }) => {
198
+ const [state, setState] = tapState({ id, bar: initialBar });
199
+
200
+ return {
201
+ key: id,
202
+ state,
203
+ api: tapApi({
204
+ getState: () => state,
205
+ updateBar: (newBar: string) => setState({ ...state, bar: newBar }),
206
+ }),
207
+ };
208
+ },
209
+ );
210
+
211
+ // Define list resource
212
+ const FooListResource = resource(() => {
213
+ const items = [
214
+ { id: "foo-1", initialBar: "First" },
215
+ { id: "foo-2", initialBar: "Second" },
216
+ ];
217
+
218
+ const foos = tapLookupResources(
219
+ items.map((item) => FooItemResource(item, { key: item.id })),
220
+ );
221
+
222
+ return tapApi({
223
+ getState: () => ({ foos: foos.state }),
224
+ // Wrap to rename "key" field to "id"
225
+ foo: (lookup: { index: number } | { id: string }) => {
226
+ return "id" in lookup
227
+ ? foos.api({ key: lookup.id })
228
+ : foos.api({ index: lookup.index });
229
+ },
230
+ }).api;
231
+ });
232
+ ```
233
+
234
+ ### Provider Pattern
235
+
236
+ Create providers to scope access to specific list items:
237
+
238
+ ```typescript
239
+ const FooProvider = ({ index, children }) => {
240
+ const parentAui = useAssistantClient();
241
+
242
+ const aui = useAssistantClient({
243
+ foo: DerivedScope({
244
+ source: "fooList",
245
+ query: { index },
246
+ get: () => parentAui.fooList().foo({ index }),
247
+ }),
248
+ });
249
+
250
+ return <AssistantProvider client={aui}>{children}</AssistantProvider>;
251
+ };
252
+
253
+ // Render list
254
+ const FooList = ({ components }) => {
255
+ const aui = useAssistantClient();
256
+ const { foos } = aui.fooList().getState();
257
+
258
+ return (
259
+ <div>
260
+ {foos.map((_, index) => (
261
+ <FooProvider key={index} index={index}>
262
+ <components.Foo />
263
+ </FooProvider>
264
+ ))}
265
+ </div>
266
+ );
267
+ };
268
+ ```
269
+
270
+ ## Examples
271
+
272
+ See the [store-example](../store-example) Next.js app for a complete working example including:
273
+
274
+ - Basic scope definition with `tapApi`
275
+ - List management with `tapLookupResources`
276
+ - Provider pattern for scoped access
277
+ - Component composition
278
+ - Tailwind CSS styling
279
+
280
+ ## How It Works
281
+
282
+ The store is implemented using tap resources:
283
+
284
+ 1. Each scope is a tap resource that manages its own state
285
+ 2. `useAssistantClient` creates a resource that composes all provided scopes
286
+ 3. The React Context provides the client to child components
287
+ 4. Scopes can be extended/overridden by calling `useAssistantClient` with new scope definitions
288
+
289
+ This design allows for:
290
+
291
+ - ✅ Type-safe scope definitions via module augmentation
292
+ - ✅ Automatic cleanup of resources when components unmount
293
+ - ✅ Composable scope hierarchy (root → derived scopes)
294
+ - ✅ Full TypeScript inference for state and APIs
295
+ - ✅ Zero runtime overhead for scopes that aren't used
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import type { AssistantClient } from "./types";
3
+ /**
4
+ * React Context for the AssistantClient
5
+ */
6
+ export declare const AssistantContext: React.Context<AssistantClient>;
7
+ export declare const useAssistantContextValue: () => AssistantClient;
8
+ /**
9
+ * Provider component for AssistantClient
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * <AssistantProvider client={client}>
14
+ * <YourApp />
15
+ * </AssistantProvider>
16
+ * ```
17
+ */
18
+ export declare const AssistantProvider: ({ client, children, }: {
19
+ client: AssistantClient;
20
+ children: React.ReactNode;
21
+ }) => React.ReactElement;
22
+ //# sourceMappingURL=AssistantContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantContext.d.ts","sourceRoot":"","sources":["../src/AssistantContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,SAAS,CAAC;AAgB5E;;GAEG;AACH,eAAO,MAAM,gBAAgB,gCAe5B,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAAO,eAE3C,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,uBAG/B;IACD,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,KAAG,KAAK,CAAC,YAMT,CAAC"}
@@ -0,0 +1,44 @@
1
+ // src/AssistantContext.tsx
2
+ import { createContext, useContext } from "react";
3
+ import { hasRegisteredScope } from "./ScopeRegistry.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var NO_OP_SUBSCRIBE = () => () => {
6
+ };
7
+ var NO_OP_FLUSH_SYNC = () => {
8
+ };
9
+ var NO_OP_SCOPE_FIELD = (() => {
10
+ const fn = (() => {
11
+ throw new Error(
12
+ "You need to wrap this component/hook in <AssistantProvider>"
13
+ );
14
+ });
15
+ fn.source = null;
16
+ fn.query = null;
17
+ return fn;
18
+ })();
19
+ var AssistantContext = createContext(
20
+ new Proxy({}, {
21
+ get(_, prop) {
22
+ if (prop === "subscribe") return NO_OP_SUBSCRIBE;
23
+ if (prop === "flushSync") return NO_OP_FLUSH_SYNC;
24
+ if (hasRegisteredScope(prop))
25
+ return NO_OP_SCOPE_FIELD;
26
+ return null;
27
+ }
28
+ })
29
+ );
30
+ var useAssistantContextValue = () => {
31
+ return useContext(AssistantContext);
32
+ };
33
+ var AssistantProvider = ({
34
+ client,
35
+ children
36
+ }) => {
37
+ return /* @__PURE__ */ jsx(AssistantContext.Provider, { value: client, children });
38
+ };
39
+ export {
40
+ AssistantContext,
41
+ AssistantProvider,
42
+ useAssistantContextValue
43
+ };
44
+ //# sourceMappingURL=AssistantContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/AssistantContext.tsx"],"sourcesContent":["import React, { createContext, useContext } from \"react\";\nimport type { AssistantClient, AssistantScopes, ScopeField } from \"./types\";\nimport { hasRegisteredScope } from \"./ScopeRegistry\";\n\nconst NO_OP_SUBSCRIBE = () => () => {};\nconst NO_OP_FLUSH_SYNC = () => {};\nconst NO_OP_SCOPE_FIELD = (() => {\n const fn = (() => {\n throw new Error(\n \"You need to wrap this component/hook in <AssistantProvider>\",\n );\n }) as ScopeField<never>;\n fn.source = null;\n fn.query = null;\n return fn;\n})();\n\n/**\n * React Context for the AssistantClient\n */\nexport const AssistantContext = createContext<AssistantClient>(\n new Proxy({} as AssistantClient, {\n get(_, prop: string) {\n // Allow access to subscribe and flushSync without error\n if (prop === \"subscribe\") return NO_OP_SUBSCRIBE;\n\n if (prop === \"flushSync\") return NO_OP_FLUSH_SYNC;\n\n // If this is a registered scope, return a function that errors when called or accessed\n if (hasRegisteredScope(prop as keyof AssistantScopes))\n return NO_OP_SCOPE_FIELD;\n\n return null;\n },\n }),\n);\n\nexport const useAssistantContextValue = (): AssistantClient => {\n return useContext(AssistantContext);\n};\n\n/**\n * Provider component for AssistantClient\n *\n * @example\n * ```typescript\n * <AssistantProvider client={client}>\n * <YourApp />\n * </AssistantProvider>\n * ```\n */\nexport const AssistantProvider = ({\n client,\n children,\n}: {\n client: AssistantClient;\n children: React.ReactNode;\n}): React.ReactElement => {\n return (\n <AssistantContext.Provider value={client}>\n {children}\n </AssistantContext.Provider>\n );\n};\n"],"mappings":";AAAA,SAAgB,eAAe,kBAAkB;AAEjD,SAAS,0BAA0B;AAyD/B;AAvDJ,IAAM,kBAAkB,MAAM,MAAM;AAAC;AACrC,IAAM,mBAAmB,MAAM;AAAC;AAChC,IAAM,qBAAqB,MAAM;AAC/B,QAAM,MAAM,MAAM;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,KAAG,SAAS;AACZ,KAAG,QAAQ;AACX,SAAO;AACT,GAAG;AAKI,IAAM,mBAAmB;AAAA,EAC9B,IAAI,MAAM,CAAC,GAAsB;AAAA,IAC/B,IAAI,GAAG,MAAc;AAEnB,UAAI,SAAS,YAAa,QAAO;AAEjC,UAAI,SAAS,YAAa,QAAO;AAGjC,UAAI,mBAAmB,IAA6B;AAClD,eAAO;AAET,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEO,IAAM,2BAA2B,MAAuB;AAC7D,SAAO,WAAW,gBAAgB;AACpC;AAYO,IAAM,oBAAoB,CAAC;AAAA,EAChC;AAAA,EACA;AACF,MAG0B;AACxB,SACE,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,QAC/B,UACH;AAEJ;","names":[]}
@@ -0,0 +1,18 @@
1
+ import type { ScopeDefinition, ScopeValue, DerivedScopeProps } from "./types";
2
+ /**
3
+ * Creates a derived scope field that memoizes based on source and query.
4
+ * The get callback always calls the most recent version (useEffectEvent pattern).
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * const MessageScope = DerivedScope<MessageScopeDefinition>({
9
+ * source: "thread",
10
+ * query: { type: "index", index: 0 },
11
+ * get: () => messageApi,
12
+ * });
13
+ * ```
14
+ */
15
+ export declare const DerivedScope: <T extends ScopeDefinition>(props: DerivedScopeProps<T>, options?: {
16
+ key?: string | number;
17
+ } | undefined) => import("@assistant-ui/tap").ResourceElement<ScopeValue<T>, DerivedScopeProps<T>>;
18
+ //# sourceMappingURL=DerivedScope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DerivedScope.d.ts","sourceRoot":"","sources":["../src/DerivedScope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE9E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GACtB,CAAC,SAAS,eAAe;;kGAG3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ // src/DerivedScope.ts
2
+ import { resource } from "@assistant-ui/tap";
3
+ var DerivedScope = resource(
4
+ (config) => {
5
+ return config;
6
+ }
7
+ );
8
+ export {
9
+ DerivedScope
10
+ };
11
+ //# sourceMappingURL=DerivedScope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/DerivedScope.ts"],"sourcesContent":["import { resource } from \"@assistant-ui/tap\";\nimport type { ScopeDefinition, ScopeValue, DerivedScopeProps } from \"./types\";\n\n/**\n * Creates a derived scope field that memoizes based on source and query.\n * The get callback always calls the most recent version (useEffectEvent pattern).\n *\n * @example\n * ```typescript\n * const MessageScope = DerivedScope<MessageScopeDefinition>({\n * source: \"thread\",\n * query: { type: \"index\", index: 0 },\n * get: () => messageApi,\n * });\n * ```\n */\nexport const DerivedScope = resource(\n <T extends ScopeDefinition>(config: DerivedScopeProps<T>): ScopeValue<T> => {\n return config;\n },\n);\n"],"mappings":";AAAA,SAAS,gBAAgB;AAgBlB,IAAM,eAAe;AAAA,EAC1B,CAA4B,WAAgD;AAC1E,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,41 @@
1
+ import type { AssistantScopes } from "./types";
2
+ import type { ResourceElement } from "@assistant-ui/tap";
3
+ type ScopeRegistryEntry<K extends keyof AssistantScopes> = {
4
+ name: K;
5
+ defaultInitialize: ResourceElement<AssistantScopes[K]["value"]> | {
6
+ error: string;
7
+ };
8
+ };
9
+ /**
10
+ * Register a default scope implementation.
11
+ * This allows scopes to have default values when not explicitly provided.
12
+ *
13
+ * @example With a resource:
14
+ * ```typescript
15
+ * registerAssistantScope({
16
+ * name: "myScope",
17
+ * defaultInitialize: MyResource(),
18
+ * });
19
+ * ```
20
+ *
21
+ * @example With an error:
22
+ * ```typescript
23
+ * registerAssistantScope({
24
+ * name: "myScope",
25
+ * defaultInitialize: { error: "MyScope is not configured" },
26
+ * });
27
+ * ```
28
+ */
29
+ export declare function registerAssistantScope<K extends keyof AssistantScopes>(config: ScopeRegistryEntry<K>): void;
30
+ /**
31
+ * Get the default initializer for a scope, if registered.
32
+ */
33
+ export declare function getDefaultScopeInitializer<K extends keyof AssistantScopes>(name: K): (ResourceElement<AssistantScopes[K]["value"]> | {
34
+ error: string;
35
+ }) | undefined;
36
+ /**
37
+ * Get all registered scope names.
38
+ */
39
+ export declare function hasRegisteredScope(name: keyof AssistantScopes): boolean;
40
+ export {};
41
+ //# sourceMappingURL=ScopeRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScopeRegistry.d.ts","sourceRoot":"","sources":["../src/ScopeRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,kBAAkB,CAAC,CAAC,SAAS,MAAM,eAAe,IAAI;IACzD,IAAI,EAAE,CAAC,CAAC;IACR,iBAAiB,EACb,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAC5C;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACvB,CAAC;AAOF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,eAAe,EACpE,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC5B,IAAI,CAEN;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,eAAe,EACxE,IAAI,EAAE,CAAC,GAEL,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAClE,SAAS,CAEZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,eAAe,GAAG,OAAO,CAEvE"}
@@ -0,0 +1,17 @@
1
+ // src/ScopeRegistry.ts
2
+ var scopeRegistry = /* @__PURE__ */ new Map();
3
+ function registerAssistantScope(config) {
4
+ scopeRegistry.set(config.name, config.defaultInitialize);
5
+ }
6
+ function getDefaultScopeInitializer(name) {
7
+ return scopeRegistry.get(name);
8
+ }
9
+ function hasRegisteredScope(name) {
10
+ return scopeRegistry.has(name);
11
+ }
12
+ export {
13
+ getDefaultScopeInitializer,
14
+ hasRegisteredScope,
15
+ registerAssistantScope
16
+ };
17
+ //# sourceMappingURL=ScopeRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ScopeRegistry.ts"],"sourcesContent":["import type { AssistantScopes } from \"./types\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\n\ntype ScopeRegistryEntry<K extends keyof AssistantScopes> = {\n name: K;\n defaultInitialize:\n | ResourceElement<AssistantScopes[K][\"value\"]>\n | { error: string };\n};\n\nconst scopeRegistry = new Map<\n keyof AssistantScopes,\n ResourceElement<any> | { error: string }\n>();\n\n/**\n * Register a default scope implementation.\n * This allows scopes to have default values when not explicitly provided.\n *\n * @example With a resource:\n * ```typescript\n * registerAssistantScope({\n * name: \"myScope\",\n * defaultInitialize: MyResource(),\n * });\n * ```\n *\n * @example With an error:\n * ```typescript\n * registerAssistantScope({\n * name: \"myScope\",\n * defaultInitialize: { error: \"MyScope is not configured\" },\n * });\n * ```\n */\nexport function registerAssistantScope<K extends keyof AssistantScopes>(\n config: ScopeRegistryEntry<K>,\n): void {\n scopeRegistry.set(config.name, config.defaultInitialize);\n}\n\n/**\n * Get the default initializer for a scope, if registered.\n */\nexport function getDefaultScopeInitializer<K extends keyof AssistantScopes>(\n name: K,\n):\n | (ResourceElement<AssistantScopes[K][\"value\"]> | { error: string })\n | undefined {\n return scopeRegistry.get(name);\n}\n\n/**\n * Get all registered scope names.\n */\nexport function hasRegisteredScope(name: keyof AssistantScopes): boolean {\n return scopeRegistry.has(name);\n}\n"],"mappings":";AAUA,IAAM,gBAAgB,oBAAI,IAGxB;AAsBK,SAAS,uBACd,QACM;AACN,gBAAc,IAAI,OAAO,MAAM,OAAO,iBAAiB;AACzD;AAKO,SAAS,2BACd,MAGY;AACZ,SAAO,cAAc,IAAI,IAAI;AAC/B;AAKO,SAAS,mBAAmB,MAAsC;AACvE,SAAO,cAAc,IAAI,IAAI;AAC/B;","names":[]}
@@ -0,0 +1,20 @@
1
+ import { ResourceElement } from "@assistant-ui/tap";
2
+ import { Unsubscribe } from "./types";
3
+ export interface Store<TState> {
4
+ /**
5
+ * Get the current state of the store.
6
+ */
7
+ getState(): TState;
8
+ /**
9
+ * Subscribe to the store.
10
+ */
11
+ subscribe(listener: () => void): Unsubscribe;
12
+ /**
13
+ * Synchronously flush all the updates to the store.
14
+ */
15
+ flushSync(): void;
16
+ }
17
+ export declare const asStore: <TState, TProps>(props: ResourceElement<TState, TProps>, options?: {
18
+ key?: string | number;
19
+ } | undefined) => ResourceElement<Store<TState>, ResourceElement<TState, TProps>>;
20
+ //# sourceMappingURL=asStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asStore.d.ts","sourceRoot":"","sources":["../src/asStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,MAAM,WAAW,KAAK,CAAC,MAAM;IAC3B;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAAC;IAE7C;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,OAAO,GACjB,MAAM,EAAE,MAAM;;iFAYhB,CAAC"}
@@ -0,0 +1,23 @@
1
+ // src/asStore.ts
2
+ import {
3
+ tapMemo,
4
+ tapEffect,
5
+ resource,
6
+ createResource
7
+ } from "@assistant-ui/tap";
8
+ var asStore = resource(
9
+ (element) => {
10
+ const resource2 = tapMemo(
11
+ () => createResource(element, true),
12
+ [element.type]
13
+ );
14
+ tapEffect(() => {
15
+ resource2.updateInput(element.props);
16
+ });
17
+ return resource2;
18
+ }
19
+ );
20
+ export {
21
+ asStore
22
+ };
23
+ //# sourceMappingURL=asStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/asStore.ts"],"sourcesContent":["import {\n tapMemo,\n tapEffect,\n ResourceElement,\n resource,\n createResource,\n} from \"@assistant-ui/tap\";\nimport { Unsubscribe } from \"./types\";\n\nexport interface Store<TState> {\n /**\n * Get the current state of the store.\n */\n getState(): TState;\n\n /**\n * Subscribe to the store.\n */\n subscribe(listener: () => void): Unsubscribe;\n\n /**\n * Synchronously flush all the updates to the store.\n */\n flushSync(): void;\n}\n\nexport const asStore = resource(\n <TState, TProps>(element: ResourceElement<TState, TProps>): Store<TState> => {\n const resource = tapMemo(\n () => createResource(element, true),\n [element.type],\n );\n\n tapEffect(() => {\n resource.updateInput(element.props);\n });\n\n return resource;\n },\n);\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AAoBA,IAAM,UAAU;AAAA,EACrB,CAAiB,YAA4D;AAC3E,UAAMA,YAAW;AAAA,MACf,MAAM,eAAe,SAAS,IAAI;AAAA,MAClC,CAAC,QAAQ,IAAI;AAAA,IACf;AAEA,cAAU,MAAM;AACd,MAAAA,UAAS,YAAY,QAAQ,KAAK;AAAA,IACpC,CAAC;AAED,WAAOA;AAAA,EACT;AACF;","names":["resource"]}
@@ -0,0 +1,13 @@
1
+ export { useAssistantClient } from "./useAssistantClient";
2
+ export { useAssistantState } from "./useAssistantState";
3
+ export { AssistantProvider } from "./AssistantContext";
4
+ export type { AssistantScopes, AssistantClient, AssistantState } from "./types";
5
+ export { DerivedScope } from "./DerivedScope";
6
+ export type { ApiObject } from "./tapApi";
7
+ export { tapApi } from "./tapApi";
8
+ export { tapLookupResources } from "./tapLookupResources";
9
+ export { tapStoreList } from "./tapStoreList";
10
+ export type { TapStoreListConfig } from "./tapStoreList";
11
+ export { registerAssistantScope } from "./ScopeRegistry";
12
+ export type { AssistantScopeRegistry } from "./types";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,YAAY,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ // src/index.ts
2
+ import { useAssistantClient } from "./useAssistantClient.js";
3
+ import { useAssistantState } from "./useAssistantState.js";
4
+ import { AssistantProvider } from "./AssistantContext.js";
5
+ import { DerivedScope } from "./DerivedScope.js";
6
+ import { tapApi } from "./tapApi.js";
7
+ import { tapLookupResources } from "./tapLookupResources.js";
8
+ import { tapStoreList } from "./tapStoreList.js";
9
+ import { registerAssistantScope } from "./ScopeRegistry.js";
10
+ export {
11
+ AssistantProvider,
12
+ DerivedScope,
13
+ registerAssistantScope,
14
+ tapApi,
15
+ tapLookupResources,
16
+ tapStoreList,
17
+ useAssistantClient,
18
+ useAssistantState
19
+ };
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { useAssistantClient } from \"./useAssistantClient\";\nexport { useAssistantState } from \"./useAssistantState\";\nexport { AssistantProvider } from \"./AssistantContext\";\nexport type { AssistantScopes, AssistantClient, AssistantState } from \"./types\";\nexport { DerivedScope } from \"./DerivedScope\";\nexport type { ApiObject } from \"./tapApi\";\nexport { tapApi } from \"./tapApi\";\nexport { tapLookupResources } from \"./tapLookupResources\";\nexport { tapStoreList } from \"./tapStoreList\";\nexport type { TapStoreListConfig } from \"./tapStoreList\";\nexport { registerAssistantScope } from \"./ScopeRegistry\";\n\nexport type { AssistantScopeRegistry } from \"./types\";\n"],"mappings":";AAAA,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,yBAAyB;AAElC,SAAS,oBAAoB;AAE7B,SAAS,cAAc;AACvB,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAE7B,SAAS,8BAA8B;","names":[]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * API object type
3
+ */
4
+ export interface ApiObject {
5
+ [key: string]: ((...args: any[]) => any) | ApiObject;
6
+ }
7
+ /**
8
+ * Wraps an API object to make it stable across renders while keeping getState reactive.
9
+ * This is the recommended pattern for scope resources.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * export const FooResource = resource(() => {
14
+ * const [state, setState] = tapState({ bar: "Hello" });
15
+ *
16
+ * const updateBar = (newBar: string) => {
17
+ * setState({ bar: newBar });
18
+ * };
19
+ *
20
+ * return tapApi({
21
+ * getState: () => state,
22
+ * updateBar,
23
+ * });
24
+ * });
25
+ * ```
26
+ */
27
+ export declare const tapApi: <TApi extends ApiObject & {
28
+ getState: () => any;
29
+ }>(api: TApi, options?: {
30
+ key?: string | undefined;
31
+ }) => {
32
+ key: string | undefined;
33
+ state: any;
34
+ api: TApi;
35
+ };
36
+ //# sourceMappingURL=tapApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tapApi.d.ts","sourceRoot":"","sources":["../src/tapApi.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;CACtD;AAmCD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,MAAM,GAAI,IAAI,SAAS,SAAS,GAAG;IAAE,QAAQ,EAAE,MAAM,GAAG,CAAA;CAAE,EACrE,KAAK,IAAI,EACT,UAAU;IACR,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;;;;CAwBF,CAAC"}