@assistant-ui/react 0.11.48 → 0.11.50

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 (91) hide show
  1. package/dist/client/AssistantClient.d.ts.map +1 -1
  2. package/dist/client/AssistantClient.js +1 -2
  3. package/dist/client/AssistantClient.js.map +1 -1
  4. package/dist/client/ModelContextClient.d.ts +1 -1
  5. package/dist/client/ThreadMessageClient.d.ts.map +1 -1
  6. package/dist/client/ThreadMessageClient.js +8 -9
  7. package/dist/client/ThreadMessageClient.js.map +1 -1
  8. package/dist/client/util-hooks/tapLookupResources.d.ts +2 -2
  9. package/dist/client/util-hooks/tapLookupResources.d.ts.map +1 -1
  10. package/dist/client/util-hooks/tapLookupResources.js +13 -4
  11. package/dist/client/util-hooks/tapLookupResources.js.map +1 -1
  12. package/dist/context/providers/MessageProvider.d.ts.map +1 -1
  13. package/dist/context/providers/MessageProvider.js +1 -2
  14. package/dist/context/providers/MessageProvider.js.map +1 -1
  15. package/dist/context/providers/TextMessagePartProvider.d.ts.map +1 -1
  16. package/dist/context/providers/TextMessagePartProvider.js +1 -2
  17. package/dist/context/providers/TextMessagePartProvider.js.map +1 -1
  18. package/dist/context/react/AssistantApiContext.d.ts +1 -2
  19. package/dist/context/react/AssistantApiContext.d.ts.map +1 -1
  20. package/dist/context/react/AssistantApiContext.js +1 -12
  21. package/dist/context/react/AssistantApiContext.js.map +1 -1
  22. package/dist/legacy-runtime/client/ComposerRuntimeClient.d.ts.map +1 -1
  23. package/dist/legacy-runtime/client/ComposerRuntimeClient.js +4 -6
  24. package/dist/legacy-runtime/client/ComposerRuntimeClient.js.map +1 -1
  25. package/dist/legacy-runtime/client/EventManagerRuntimeClient.d.ts +1 -1
  26. package/dist/legacy-runtime/client/MessageRuntimeClient.d.ts.map +1 -1
  27. package/dist/legacy-runtime/client/MessageRuntimeClient.js +8 -6
  28. package/dist/legacy-runtime/client/MessageRuntimeClient.js.map +1 -1
  29. package/dist/legacy-runtime/client/ThreadListRuntimeClient.d.ts.map +1 -1
  30. package/dist/legacy-runtime/client/ThreadListRuntimeClient.js +4 -3
  31. package/dist/legacy-runtime/client/ThreadListRuntimeClient.js.map +1 -1
  32. package/dist/legacy-runtime/client/ThreadRuntimeClient.d.ts.map +1 -1
  33. package/dist/legacy-runtime/client/ThreadRuntimeClient.js +4 -6
  34. package/dist/legacy-runtime/client/ThreadRuntimeClient.js.map +1 -1
  35. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +1 -1
  36. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  37. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts +1 -4
  38. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.d.ts.map +1 -1
  39. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js +34 -12
  40. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
  41. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  42. package/dist/primitives/composer/ComposerInput.js +4 -2
  43. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  44. package/dist/primitives/thread/ThreadViewport.d.ts +36 -0
  45. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  46. package/dist/primitives/thread/ThreadViewport.js +21 -12
  47. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  48. package/dist/primitives/thread/ThreadViewportSlack.d.ts.map +1 -1
  49. package/dist/primitives/thread/ThreadViewportSlack.js +4 -1
  50. package/dist/primitives/thread/ThreadViewportSlack.js.map +1 -1
  51. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts +20 -2
  52. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  53. package/dist/primitives/thread/useThreadViewportAutoScroll.js +21 -2
  54. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  55. package/dist/tests/setup.js +7 -7
  56. package/dist/tests/setup.js.map +1 -1
  57. package/dist/utils/tap-store/derived-scopes.d.ts +3 -10
  58. package/dist/utils/tap-store/derived-scopes.d.ts.map +1 -1
  59. package/dist/utils/tap-store/derived-scopes.js +14 -20
  60. package/dist/utils/tap-store/derived-scopes.js.map +1 -1
  61. package/dist/utils/tap-store/index.d.ts +1 -1
  62. package/dist/utils/tap-store/index.d.ts.map +1 -1
  63. package/dist/utils/tap-store/index.js.map +1 -1
  64. package/dist/utils/tap-store/store.d.ts +1 -7
  65. package/dist/utils/tap-store/store.d.ts.map +1 -1
  66. package/dist/utils/tap-store/store.js +2 -2
  67. package/dist/utils/tap-store/store.js.map +1 -1
  68. package/dist/utils/tap-store/tap-api.d.ts.map +1 -1
  69. package/dist/utils/tap-store/tap-api.js +13 -7
  70. package/dist/utils/tap-store/tap-api.js.map +1 -1
  71. package/package.json +5 -5
  72. package/src/client/AssistantClient.ts +0 -1
  73. package/src/client/ThreadMessageClient.tsx +10 -9
  74. package/src/client/util-hooks/tapLookupResources.ts +26 -11
  75. package/src/context/providers/MessageProvider.tsx +0 -1
  76. package/src/context/providers/TextMessagePartProvider.tsx +0 -1
  77. package/src/context/react/AssistantApiContext.tsx +1 -18
  78. package/src/legacy-runtime/client/ComposerRuntimeClient.ts +4 -6
  79. package/src/legacy-runtime/client/MessageRuntimeClient.ts +10 -6
  80. package/src/legacy-runtime/client/ThreadListRuntimeClient.ts +4 -3
  81. package/src/legacy-runtime/client/ThreadRuntimeClient.ts +4 -6
  82. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx +1 -1
  83. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +40 -17
  84. package/src/primitives/composer/ComposerInput.tsx +4 -2
  85. package/src/primitives/thread/ThreadViewport.tsx +49 -18
  86. package/src/primitives/thread/ThreadViewportSlack.tsx +4 -1
  87. package/src/primitives/thread/useThreadViewportAutoScroll.tsx +48 -2
  88. package/src/utils/tap-store/derived-scopes.ts +17 -28
  89. package/src/utils/tap-store/index.ts +1 -2
  90. package/src/utils/tap-store/store.ts +2 -7
  91. package/src/utils/tap-store/tap-api.ts +12 -7
@@ -25,7 +25,7 @@ type AssistantApiFieldNames = {
25
25
  /**
26
26
  * Configuration for a derived scope field - infers types from the actual values provided
27
27
  */
28
- export type DerivedScopeConfig<TSource extends string | null, TQuery, TApi> = {
28
+ export type DerivedConfig<TSource extends string | null, TQuery, TApi> = {
29
29
  source: TSource;
30
30
  query: TQuery;
31
31
  get: () => TApi;
@@ -38,17 +38,12 @@ export type OnCallbackFn = <TEvent extends AssistantEvent>(selector: AssistantEv
38
38
  * Type for the special `subscribe` callback function
39
39
  */
40
40
  export type SubscribeCallbackFn = (listener: () => void) => Unsubscribe;
41
- /**
42
- * Type for the special `flushSync` callback function
43
- */
44
- export type FlushSyncCallbackFn = () => void;
45
41
  /**
46
42
  * Type for special non-field functions in AssistantApi
47
43
  */
48
44
  export type SpecialCallbacks = {
49
45
  on?: OnCallbackFn;
50
46
  subscribe?: SubscribeCallbackFn;
51
- flushSync?: FlushSyncCallbackFn;
52
47
  };
53
48
  /**
54
49
  * Type for the scopes parameter - allows both DerivedScope elements and special callbacks.
@@ -67,12 +62,10 @@ export type DerivedScopesInput = {
67
62
  * TypeScript infers TSource, TQuery, and TApi from the config object.
68
63
  * Validation happens at the DerivedScopesInput level.
69
64
  */
70
- export declare const DerivedScope: <TSource extends string | null, TQuery, TApi>(props: DerivedScopeConfig<TSource, TQuery, TApi>, options?: {
71
- key?: string | number;
72
- } | undefined) => ResourceElement<AssistantApiField<TApi, {
65
+ export declare const DerivedScope: <TSource extends string | null, TQuery, TApi>(props: DerivedConfig<TSource, TQuery, TApi>) => ResourceElement<AssistantApiField<TApi, {
73
66
  source: TSource;
74
67
  query: TQuery;
75
- }>, DerivedScopeConfig<TSource, TQuery, TApi>>;
68
+ }>, DerivedConfig<TSource, TQuery, TApi>>;
76
69
  /**
77
70
  * DerivedScopes resource - takes an object of DerivedScope resource elements and special callbacks,
78
71
  * and returns a Partial<AssistantApi> with all the derived fields.
@@ -1 +1 @@
1
- {"version":3,"file":"derived-scopes.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/derived-scopes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,CAAC,CAAC,IACnB,CAAC,SAAS,iBAAiB,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAE9D;;;;;GAKG;AACH,KAAK,WAAW,CAAC,CAAC,IAChB,CAAC,SAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,KAAK,sBAAsB,GAAG;KAC3B,CAAC,IAAI,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,GAC1E,CAAC,GACD,KAAK;CACV,CAAC,MAAM,YAAY,CAAC,CAAC;AAEtB;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI;IAC5E,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,SAAS,cAAc,EACvD,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,EACxC,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,KACrC,WAAW,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;KAC9B,CAAC,IAAI,sBAAsB,CAAC,CAAC,EAAE,eAAe,CAC7C,iBAAiB,CACf,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/B;QACE,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;KAC9C,CACF,CACF;CACF,GAAG,gBAAgB,CAAC;AAErB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACtB,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI;;;YAKhC,OAAO;WACR,MAAM;8CAgBlB,CAAC;AAmBF;;;GAGG;AACH,eAAO,MAAM,aAAa,iFAyCzB,CAAC"}
1
+ {"version":3,"file":"derived-scopes.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/derived-scopes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,CAAC,CAAC,IACnB,CAAC,SAAS,iBAAiB,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAE9D;;;;;GAKG;AACH,KAAK,WAAW,CAAC,CAAC,IAChB,CAAC,SAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,KAAK,sBAAsB,GAAG;KAC3B,CAAC,IAAI,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,GAC1E,CAAC,GACD,KAAK;CACV,CAAC,MAAM,YAAY,CAAC,CAAC;AAEtB;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI;IACvE,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,SAAS,cAAc,EACvD,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,EACxC,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,KACrC,WAAW,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;KAC9B,CAAC,IAAI,sBAAsB,CAAC,CAAC,EAAE,eAAe,CAC7C,iBAAiB,CACf,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/B;QACE,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;KAC9C,CACF,CACF;CACF,GAAG,gBAAgB,CAAC;AAErB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACtB,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI;YAKhC,OAAO;WACR,MAAM;yCAgBlB,CAAC;AAmBF;;;GAGG;AACH,eAAO,MAAM,aAAa,iFAoCzB,CAAC"}
@@ -28,36 +28,30 @@ var ScopeFieldWithNameResource = resource(
28
28
  );
29
29
  var DerivedScopes = resource(
30
30
  (scopes) => {
31
- const { on, subscribe, flushSync, ...scopeFields } = scopes;
32
- const callbacksRef = tapRef({ on, subscribe, flushSync });
31
+ const { on, subscribe, ...scopeFields } = scopes;
32
+ const callbacksRef = tapRef({ on, subscribe });
33
33
  tapEffect(() => {
34
- callbacksRef.current = { on, subscribe, flushSync };
34
+ callbacksRef.current = { on, subscribe };
35
35
  });
36
36
  const results = tapResources(
37
- Object.entries(scopeFields).map(
38
- ([fieldName, scopeElement]) => ScopeFieldWithNameResource(
39
- {
40
- fieldName,
41
- scopeElement
42
- },
43
- { key: fieldName }
44
- )
45
- )
37
+ scopeFields,
38
+ (scopeElement, fieldName) => ScopeFieldWithNameResource({
39
+ fieldName,
40
+ scopeElement
41
+ }),
42
+ []
46
43
  );
47
44
  return tapMemo(() => {
48
- const result = Object.fromEntries(results);
49
- const {
50
- on: onCb,
51
- subscribe: subCb,
52
- flushSync: flushCb
53
- } = callbacksRef.current;
45
+ const result = Object.fromEntries(
46
+ Object.values(results)
47
+ );
48
+ const { on: onCb, subscribe: subCb } = callbacksRef.current;
54
49
  if (onCb) {
55
50
  result.on = (selector, callback) => onCb(selector, callback);
56
51
  }
57
52
  if (subCb) result.subscribe = (listener) => subCb(listener);
58
- if (flushCb) result.flushSync = () => flushCb();
59
53
  return result;
60
- }, [...results]);
54
+ }, [results]);
61
55
  }
62
56
  );
63
57
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/tap-store/derived-scopes.ts"],"sourcesContent":["import { resource, tapEffect } from \"@assistant-ui/tap\";\nimport { tapMemo, tapRef, tapResource, tapResources } from \"@assistant-ui/tap\";\nimport { createAssistantApiField } from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantApi,\n AssistantApiField,\n} from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n} from \"../../types/EventTypes\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { Unsubscribe } from \"../../types\";\n\n/**\n * Extract the API return type from an AssistantApiField\n */\ntype ExtractApiType<T> =\n T extends AssistantApiField<infer TApi, any> ? TApi : never;\n\n/**\n * Extract the metadata type from an AssistantApiField\n *\n * Used in DerivedScopesInput to validate that each field's source/query types match\n * the expected types from AssistantApi.\n */\ntype ExtractMeta<T> =\n T extends AssistantApiField<any, infer TMeta> ? TMeta : never;\n\n/**\n * Get only the field names from AssistantApi (exclude method names)\n */\ntype AssistantApiFieldNames = {\n [K in keyof AssistantApi]: AssistantApi[K] extends { source: any; query: any }\n ? K\n : never;\n}[keyof AssistantApi];\n\n/**\n * Configuration for a derived scope field - infers types from the actual values provided\n */\nexport type DerivedScopeConfig<TSource extends string | null, TQuery, TApi> = {\n source: TSource;\n query: TQuery;\n get: () => TApi;\n};\n\n/**\n * Type for the special `on` callback function\n */\nexport type OnCallbackFn = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n) => Unsubscribe;\n\n/**\n * Type for the special `subscribe` callback function\n */\nexport type SubscribeCallbackFn = (listener: () => void) => Unsubscribe;\n\n/**\n * Type for the special `flushSync` callback function\n */\nexport type FlushSyncCallbackFn = () => void;\n\n/**\n * Type for special non-field functions in AssistantApi\n */\nexport type SpecialCallbacks = {\n on?: OnCallbackFn;\n subscribe?: SubscribeCallbackFn;\n flushSync?: FlushSyncCallbackFn;\n};\n\n/**\n * Type for the scopes parameter - allows both DerivedScope elements and special callbacks.\n * Field names are restricted to valid AssistantApi field names.\n * TypeScript validates that the source/query/get types match the expected field type.\n */\nexport type DerivedScopesInput = {\n [K in AssistantApiFieldNames]?: ResourceElement<\n AssistantApiField<\n ExtractApiType<AssistantApi[K]>,\n {\n source: ExtractMeta<AssistantApi[K]>[\"source\"];\n query: ExtractMeta<AssistantApi[K]>[\"query\"];\n }\n >\n >;\n} & SpecialCallbacks;\n\n/**\n * DerivedScope resource - memoizes an AssistantApiField based on source and query.\n * The get callback always calls the most recent version (useEffectEvent pattern).\n * TypeScript infers TSource, TQuery, and TApi from the config object.\n * Validation happens at the DerivedScopesInput level.\n */\nexport const DerivedScope = resource(\n <TSource extends string | null, TQuery, TApi>(\n config: DerivedScopeConfig<TSource, TQuery, TApi>,\n ): AssistantApiField<\n TApi,\n {\n source: TSource;\n query: TQuery;\n }\n > => {\n const getRef = tapRef(config.get);\n tapEffect(() => {\n getRef.current = config.get;\n });\n\n return tapMemo(() => {\n return createAssistantApiField({\n source: config.source,\n query: config.query,\n get: () => getRef.current(),\n });\n }, [config.source, JSON.stringify(config.query)]);\n },\n);\n\n/**\n * Helper resource to wrap each scope field - stable resource identity for proper memoization.\n * Creating this outside the map ensures tapResources can properly track and memoize each field.\n */\nconst ScopeFieldWithNameResource = resource(\n (config: {\n fieldName: string;\n scopeElement: ReturnType<typeof DerivedScope>;\n }) => {\n const field = tapResource(config.scopeElement);\n return tapMemo(\n () => [config.fieldName, field] as const,\n [config.fieldName, field],\n );\n },\n);\n\n/**\n * DerivedScopes resource - takes an object of DerivedScope resource elements and special callbacks,\n * and returns a Partial<AssistantApi> with all the derived fields.\n */\nexport const DerivedScopes = resource(\n (scopes: DerivedScopesInput): Partial<AssistantApi> => {\n const { on, subscribe, flushSync, ...scopeFields } = scopes;\n const callbacksRef = tapRef({ on, subscribe, flushSync });\n tapEffect(() => {\n callbacksRef.current = { on, subscribe, flushSync };\n });\n\n const results = tapResources(\n Object.entries(scopeFields).map(([fieldName, scopeElement]) =>\n ScopeFieldWithNameResource(\n {\n fieldName,\n scopeElement: scopeElement as ReturnType<typeof DerivedScope>,\n },\n { key: fieldName },\n ),\n ),\n );\n\n return tapMemo(() => {\n const result = Object.fromEntries(results) as Partial<AssistantApi>;\n\n const {\n on: onCb,\n subscribe: subCb,\n flushSync: flushCb,\n } = callbacksRef.current;\n\n if (onCb) {\n result.on = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n ) => onCb(selector, callback);\n }\n if (subCb) result.subscribe = (listener) => subCb(listener);\n if (flushCb) result.flushSync = () => flushCb();\n\n return result;\n }, [...results]);\n },\n);\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AACpC,SAAS,SAAS,QAAQ,aAAa,oBAAoB;AAC3D,SAAS,+BAA+B;AAgGjC,IAAM,eAAe;AAAA,EAC1B,CACE,WAOG;AACH,UAAM,SAAS,OAAO,OAAO,GAAG;AAChC,cAAU,MAAM;AACd,aAAO,UAAU,OAAO;AAAA,IAC1B,CAAC;AAED,WAAO,QAAQ,MAAM;AACnB,aAAO,wBAAwB;AAAA,QAC7B,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,KAAK,MAAM,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH,GAAG,CAAC,OAAO,QAAQ,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,EAClD;AACF;AAMA,IAAM,6BAA6B;AAAA,EACjC,CAAC,WAGK;AACJ,UAAM,QAAQ,YAAY,OAAO,YAAY;AAC7C,WAAO;AAAA,MACL,MAAM,CAAC,OAAO,WAAW,KAAK;AAAA,MAC9B,CAAC,OAAO,WAAW,KAAK;AAAA,IAC1B;AAAA,EACF;AACF;AAMO,IAAM,gBAAgB;AAAA,EAC3B,CAAC,WAAsD;AACrD,UAAM,EAAE,IAAI,WAAW,WAAW,GAAG,YAAY,IAAI;AACrD,UAAM,eAAe,OAAO,EAAE,IAAI,WAAW,UAAU,CAAC;AACxD,cAAU,MAAM;AACd,mBAAa,UAAU,EAAE,IAAI,WAAW,UAAU;AAAA,IACpD,CAAC;AAED,UAAM,UAAU;AAAA,MACd,OAAO,QAAQ,WAAW,EAAE;AAAA,QAAI,CAAC,CAAC,WAAW,YAAY,MACvD;AAAA,UACE;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,UACA,EAAE,KAAK,UAAU;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,QAAQ,MAAM;AACnB,YAAM,SAAS,OAAO,YAAY,OAAO;AAEzC,YAAM;AAAA,QACJ,IAAI;AAAA,QACJ,WAAW;AAAA,QACX,WAAW;AAAA,MACb,IAAI,aAAa;AAEjB,UAAI,MAAM;AACR,eAAO,KAAK,CACV,UACA,aACG,KAAK,UAAU,QAAQ;AAAA,MAC9B;AACA,UAAI,MAAO,QAAO,YAAY,CAAC,aAAa,MAAM,QAAQ;AAC1D,UAAI,QAAS,QAAO,YAAY,MAAM,QAAQ;AAE9C,aAAO;AAAA,IACT,GAAG,CAAC,GAAG,OAAO,CAAC;AAAA,EACjB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/tap-store/derived-scopes.ts"],"sourcesContent":["import { resource, tapEffect } from \"@assistant-ui/tap\";\nimport { tapMemo, tapRef, tapResource, tapResources } from \"@assistant-ui/tap\";\nimport { createAssistantApiField } from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantApi,\n AssistantApiField,\n} from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n} from \"../../types/EventTypes\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { Unsubscribe } from \"../../types\";\n\n/**\n * Extract the API return type from an AssistantApiField\n */\ntype ExtractApiType<T> =\n T extends AssistantApiField<infer TApi, any> ? TApi : never;\n\n/**\n * Extract the metadata type from an AssistantApiField\n *\n * Used in DerivedScopesInput to validate that each field's source/query types match\n * the expected types from AssistantApi.\n */\ntype ExtractMeta<T> =\n T extends AssistantApiField<any, infer TMeta> ? TMeta : never;\n\n/**\n * Get only the field names from AssistantApi (exclude method names)\n */\ntype AssistantApiFieldNames = {\n [K in keyof AssistantApi]: AssistantApi[K] extends { source: any; query: any }\n ? K\n : never;\n}[keyof AssistantApi];\n\n/**\n * Configuration for a derived scope field - infers types from the actual values provided\n */\nexport type DerivedConfig<TSource extends string | null, TQuery, TApi> = {\n source: TSource;\n query: TQuery;\n get: () => TApi;\n};\n\n/**\n * Type for the special `on` callback function\n */\nexport type OnCallbackFn = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n) => Unsubscribe;\n\n/**\n * Type for the special `subscribe` callback function\n */\nexport type SubscribeCallbackFn = (listener: () => void) => Unsubscribe;\n\n/**\n * Type for special non-field functions in AssistantApi\n */\nexport type SpecialCallbacks = {\n on?: OnCallbackFn;\n subscribe?: SubscribeCallbackFn;\n};\n\n/**\n * Type for the scopes parameter - allows both DerivedScope elements and special callbacks.\n * Field names are restricted to valid AssistantApi field names.\n * TypeScript validates that the source/query/get types match the expected field type.\n */\nexport type DerivedScopesInput = {\n [K in AssistantApiFieldNames]?: ResourceElement<\n AssistantApiField<\n ExtractApiType<AssistantApi[K]>,\n {\n source: ExtractMeta<AssistantApi[K]>[\"source\"];\n query: ExtractMeta<AssistantApi[K]>[\"query\"];\n }\n >\n >;\n} & SpecialCallbacks;\n\n/**\n * DerivedScope resource - memoizes an AssistantApiField based on source and query.\n * The get callback always calls the most recent version (useEffectEvent pattern).\n * TypeScript infers TSource, TQuery, and TApi from the config object.\n * Validation happens at the DerivedScopesInput level.\n */\nexport const DerivedScope = resource(\n <TSource extends string | null, TQuery, TApi>(\n config: DerivedConfig<TSource, TQuery, TApi>,\n ): AssistantApiField<\n TApi,\n {\n source: TSource;\n query: TQuery;\n }\n > => {\n const getRef = tapRef(config.get);\n tapEffect(() => {\n getRef.current = config.get;\n });\n\n return tapMemo(() => {\n return createAssistantApiField({\n source: config.source,\n query: config.query,\n get: () => getRef.current(),\n });\n }, [config.source, JSON.stringify(config.query)]);\n },\n);\n\n/**\n * Helper resource to wrap each scope field - stable resource identity for proper memoization.\n * Creating this outside the map ensures tapResources can properly track and memoize each field.\n */\nconst ScopeFieldWithNameResource = resource(\n (config: {\n fieldName: string;\n scopeElement: ReturnType<typeof DerivedScope>;\n }) => {\n const field = tapResource(config.scopeElement);\n return tapMemo(\n () => [config.fieldName, field] as const,\n [config.fieldName, field],\n );\n },\n);\n\n/**\n * DerivedScopes resource - takes an object of DerivedScope resource elements and special callbacks,\n * and returns a Partial<AssistantApi> with all the derived fields.\n */\nexport const DerivedScopes = resource(\n (scopes: DerivedScopesInput): Partial<AssistantApi> => {\n const { on, subscribe, ...scopeFields } = scopes;\n const callbacksRef = tapRef({ on, subscribe });\n tapEffect(() => {\n callbacksRef.current = { on, subscribe };\n });\n\n const results = tapResources(\n scopeFields as Record<string, ReturnType<typeof DerivedScope>>,\n (scopeElement, fieldName) =>\n ScopeFieldWithNameResource({\n fieldName,\n scopeElement,\n }),\n [],\n );\n\n return tapMemo(() => {\n const result = Object.fromEntries(\n Object.values(results),\n ) as Partial<AssistantApi>;\n\n const { on: onCb, subscribe: subCb } = callbacksRef.current;\n\n if (onCb) {\n result.on = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n ) => onCb(selector, callback);\n }\n if (subCb) result.subscribe = (listener) => subCb(listener);\n\n return result;\n }, [results]);\n },\n);\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AACpC,SAAS,SAAS,QAAQ,aAAa,oBAAoB;AAC3D,SAAS,+BAA+B;AA0FjC,IAAM,eAAe;AAAA,EAC1B,CACE,WAOG;AACH,UAAM,SAAS,OAAO,OAAO,GAAG;AAChC,cAAU,MAAM;AACd,aAAO,UAAU,OAAO;AAAA,IAC1B,CAAC;AAED,WAAO,QAAQ,MAAM;AACnB,aAAO,wBAAwB;AAAA,QAC7B,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,KAAK,MAAM,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH,GAAG,CAAC,OAAO,QAAQ,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,EAClD;AACF;AAMA,IAAM,6BAA6B;AAAA,EACjC,CAAC,WAGK;AACJ,UAAM,QAAQ,YAAY,OAAO,YAAY;AAC7C,WAAO;AAAA,MACL,MAAM,CAAC,OAAO,WAAW,KAAK;AAAA,MAC9B,CAAC,OAAO,WAAW,KAAK;AAAA,IAC1B;AAAA,EACF;AACF;AAMO,IAAM,gBAAgB;AAAA,EAC3B,CAAC,WAAsD;AACrD,UAAM,EAAE,IAAI,WAAW,GAAG,YAAY,IAAI;AAC1C,UAAM,eAAe,OAAO,EAAE,IAAI,UAAU,CAAC;AAC7C,cAAU,MAAM;AACd,mBAAa,UAAU,EAAE,IAAI,UAAU;AAAA,IACzC,CAAC;AAED,UAAM,UAAU;AAAA,MACd;AAAA,MACA,CAAC,cAAc,cACb,2BAA2B;AAAA,QACzB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,QAAQ,MAAM;AACnB,YAAM,SAAS,OAAO;AAAA,QACpB,OAAO,OAAO,OAAO;AAAA,MACvB;AAEA,YAAM,EAAE,IAAI,MAAM,WAAW,MAAM,IAAI,aAAa;AAEpD,UAAI,MAAM;AACR,eAAO,KAAK,CACV,UACA,aACG,KAAK,UAAU,QAAQ;AAAA,MAC9B;AACA,UAAI,MAAO,QAAO,YAAY,CAAC,aAAa,MAAM,QAAQ;AAE1D,aAAO;AAAA,IACT,GAAG,CAAC,OAAO,CAAC;AAAA,EACd;AACF;","names":[]}
@@ -1,4 +1,4 @@
1
1
  export { type Store, asStore } from "./store";
2
2
  export { tapApi, type ApiObject } from "./tap-api";
3
- export { DerivedScope, type DerivedScopeConfig, type OnCallbackFn, type SubscribeCallbackFn, type FlushSyncCallbackFn, type SpecialCallbacks, type DerivedScopesInput, } from "./derived-scopes";
3
+ export { DerivedScope, type DerivedConfig, type OnCallbackFn, type SubscribeCallbackFn, type SpecialCallbacks, type DerivedScopesInput, } from "./derived-scopes";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/tap-store/index.ts"],"sourcesContent":["export { type Store, asStore } from \"./store\";\nexport { tapApi, type ApiObject } from \"./tap-api\";\nexport {\n DerivedScope,\n type DerivedScopeConfig,\n type OnCallbackFn,\n type SubscribeCallbackFn,\n type FlushSyncCallbackFn,\n type SpecialCallbacks,\n type DerivedScopesInput,\n} from \"./derived-scopes\";\n"],"mappings":";AAAA,SAAqB,eAAe;AACpC,SAAS,cAA8B;AACvC;AAAA,EACE;AAAA,OAOK;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/tap-store/index.ts"],"sourcesContent":["export { type Store, asStore } from \"./store\";\nexport { tapApi, type ApiObject } from \"./tap-api\";\nexport {\n DerivedScope,\n type DerivedConfig,\n type OnCallbackFn,\n type SubscribeCallbackFn,\n type SpecialCallbacks,\n type DerivedScopesInput,\n} from \"./derived-scopes\";\n"],"mappings":";AAAA,SAAqB,eAAe;AACpC,SAAS,cAA8B;AACvC;AAAA,EACE;AAAA,OAMK;","names":[]}
@@ -9,12 +9,6 @@ export interface Store<TState> {
9
9
  * Subscribe to the store.
10
10
  */
11
11
  subscribe(listener: () => void): Unsubscribe;
12
- /**
13
- * Synchronously flush all the updates to the store.
14
- */
15
- flushSync(): void;
16
12
  }
17
- export declare const asStore: <TState, TProps>(props: ResourceElement<TState, TProps>, options?: {
18
- key?: string | number;
19
- } | undefined) => ResourceElement<Store<TState>, ResourceElement<TState, TProps>>;
13
+ export declare const asStore: <TState, TProps>(props: ResourceElement<TState, TProps>) => ResourceElement<Store<TState>, ResourceElement<TState, TProps>>;
20
14
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,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"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,KAAK,CAAC,MAAM;IAC3B;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAAC;CAC9C;AAED,eAAO,MAAM,OAAO,GACjB,MAAM,EAAE,MAAM,4GAYhB,CAAC"}
@@ -8,11 +8,11 @@ import {
8
8
  var asStore = resource(
9
9
  (element) => {
10
10
  const resource2 = tapMemo(
11
- () => createResource(element, true),
11
+ () => createResource(element, { mount: false }),
12
12
  [element.type]
13
13
  );
14
14
  tapEffect(() => {
15
- resource2.updateInput(element.props);
15
+ resource2.render(element);
16
16
  });
17
17
  return resource2;
18
18
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/tap-store/store.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"]}
1
+ {"version":3,"sources":["../../../src/utils/tap-store/store.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\nexport const asStore = resource(\n <TState, TProps>(element: ResourceElement<TState, TProps>): Store<TState> => {\n const resource = tapMemo(\n () => createResource(element, { mount: false }),\n [element.type],\n );\n\n tapEffect(() => {\n resource.render(element);\n });\n\n return resource;\n },\n);\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AAeA,IAAM,UAAU;AAAA,EACrB,CAAiB,YAA4D;AAC3E,UAAMA,YAAW;AAAA,MACf,MAAM,eAAe,SAAS,EAAE,OAAO,MAAM,CAAC;AAAA,MAC9C,CAAC,QAAQ,IAAI;AAAA,IACf;AAEA,cAAU,MAAM;AACd,MAAAA,UAAS,OAAO,OAAO;AAAA,IACzB,CAAC;AAED,WAAOA;AAAA,EACT;AACF;","names":["resource"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tap-api.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/tap-api.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;CACtD;AAgCD,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"}
1
+ {"version":3,"file":"tap-api.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/tap-api.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;CACtD;AAsCD,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;;;;CAuBF,CAAC"}
@@ -1,30 +1,36 @@
1
1
  // src/utils/tap-store/tap-api.ts
2
2
  import { tapEffect, tapMemo, tapRef } from "@assistant-ui/tap";
3
3
  var ReadonlyApiHandler = class {
4
- constructor(getApi) {
5
- this.getApi = getApi;
4
+ constructor(ref) {
5
+ this.ref = ref;
6
6
  }
7
7
  get(_, prop) {
8
- return this.getApi()[prop];
8
+ return this.ref.current[prop];
9
9
  }
10
10
  ownKeys() {
11
- return Object.keys(this.getApi());
11
+ return Object.keys(this.ref.current);
12
12
  }
13
13
  has(_, prop) {
14
- return prop in this.getApi();
14
+ return prop in this.ref.current;
15
15
  }
16
16
  getOwnPropertyDescriptor(_, prop) {
17
- return Object.getOwnPropertyDescriptor(this.getApi(), prop);
17
+ return Object.getOwnPropertyDescriptor(this.ref.current, prop);
18
18
  }
19
19
  set() {
20
20
  return false;
21
21
  }
22
+ setPrototypeOf() {
23
+ return false;
24
+ }
22
25
  defineProperty() {
23
26
  return false;
24
27
  }
25
28
  deleteProperty() {
26
29
  return false;
27
30
  }
31
+ preventExtensions() {
32
+ return false;
33
+ }
28
34
  };
29
35
  var tapApi = (api, options) => {
30
36
  const ref = tapRef(api);
@@ -32,7 +38,7 @@ var tapApi = (api, options) => {
32
38
  ref.current = api;
33
39
  });
34
40
  const apiProxy = tapMemo(
35
- () => new Proxy({}, new ReadonlyApiHandler(() => ref.current)),
41
+ () => new Proxy({}, new ReadonlyApiHandler(ref)),
36
42
  []
37
43
  );
38
44
  const key = options?.key;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/tap-store/tap-api.ts"],"sourcesContent":["import { tapEffect, tapMemo, tapRef } from \"@assistant-ui/tap\";\n\nexport interface ApiObject {\n [key: string]: ((...args: any[]) => any) | ApiObject;\n}\n\nclass ReadonlyApiHandler<TApi extends ApiObject> implements ProxyHandler<TApi> {\n constructor(private readonly getApi: () => TApi) {}\n\n get(_: unknown, prop: string | symbol) {\n return this.getApi()[prop as keyof TApi];\n }\n\n ownKeys(): ArrayLike<string | symbol> {\n return Object.keys(this.getApi() as object);\n }\n\n has(_: unknown, prop: string | symbol) {\n return prop in (this.getApi() as object);\n }\n\n getOwnPropertyDescriptor(_: unknown, prop: string | symbol) {\n return Object.getOwnPropertyDescriptor(this.getApi(), prop);\n }\n\n set() {\n return false;\n }\n defineProperty() {\n return false;\n }\n deleteProperty() {\n return false;\n }\n}\n\nexport const tapApi = <TApi extends ApiObject & { getState: () => any }>(\n api: TApi,\n options?: {\n key?: string | undefined;\n },\n) => {\n const ref = tapRef(api);\n tapEffect(() => {\n ref.current = api;\n });\n\n const apiProxy = tapMemo(\n () =>\n new Proxy<TApi>({} as TApi, new ReadonlyApiHandler(() => ref.current)),\n [],\n );\n\n const key = options?.key;\n const state = api.getState();\n\n return tapMemo(\n () => ({\n key,\n state,\n api: apiProxy,\n }),\n [state, key],\n );\n};\n"],"mappings":";AAAA,SAAS,WAAW,SAAS,cAAc;AAM3C,IAAM,qBAAN,MAA+E;AAAA,EAC7E,YAA6B,QAAoB;AAApB;AAAA,EAAqB;AAAA,EAElD,IAAI,GAAY,MAAuB;AACrC,WAAO,KAAK,OAAO,EAAE,IAAkB;AAAA,EACzC;AAAA,EAEA,UAAsC;AACpC,WAAO,OAAO,KAAK,KAAK,OAAO,CAAW;AAAA,EAC5C;AAAA,EAEA,IAAI,GAAY,MAAuB;AACrC,WAAO,QAAS,KAAK,OAAO;AAAA,EAC9B;AAAA,EAEA,yBAAyB,GAAY,MAAuB;AAC1D,WAAO,OAAO,yBAAyB,KAAK,OAAO,GAAG,IAAI;AAAA,EAC5D;AAAA,EAEA,MAAM;AACJ,WAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AACF;AAEO,IAAM,SAAS,CACpB,KACA,YAGG;AACH,QAAM,MAAM,OAAO,GAAG;AACtB,YAAU,MAAM;AACd,QAAI,UAAU;AAAA,EAChB,CAAC;AAED,QAAM,WAAW;AAAA,IACf,MACE,IAAI,MAAY,CAAC,GAAW,IAAI,mBAAmB,MAAM,IAAI,OAAO,CAAC;AAAA,IACvE,CAAC;AAAA,EACH;AAEA,QAAM,MAAM,SAAS;AACrB,QAAM,QAAQ,IAAI,SAAS;AAE3B,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,IACA,CAAC,OAAO,GAAG;AAAA,EACb;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/tap-store/tap-api.ts"],"sourcesContent":["import { tapEffect, tapMemo, tapRef } from \"@assistant-ui/tap\";\n\nexport interface ApiObject {\n [key: string]: ((...args: any[]) => any) | ApiObject;\n}\n\nclass ReadonlyApiHandler<TApi extends ApiObject> implements ProxyHandler<TApi> {\n constructor(private readonly ref: tapRef.RefObject<TApi>) {}\n\n get(_: unknown, prop: string | symbol) {\n return this.ref.current[prop as keyof TApi];\n }\n\n ownKeys(): ArrayLike<string | symbol> {\n return Object.keys(this.ref.current as object);\n }\n\n has(_: unknown, prop: string | symbol) {\n return prop in (this.ref.current as object);\n }\n\n getOwnPropertyDescriptor(_: unknown, prop: string | symbol) {\n return Object.getOwnPropertyDescriptor(this.ref.current, prop);\n }\n\n set() {\n return false;\n }\n setPrototypeOf() {\n return false;\n }\n defineProperty() {\n return false;\n }\n deleteProperty() {\n return false;\n }\n preventExtensions(): boolean {\n return false;\n }\n}\n\nexport const tapApi = <TApi extends ApiObject & { getState: () => any }>(\n api: TApi,\n options?: {\n key?: string | undefined;\n },\n) => {\n const ref = tapRef(api);\n tapEffect(() => {\n ref.current = api;\n });\n\n const apiProxy = tapMemo(\n () => new Proxy<TApi>({} as TApi, new ReadonlyApiHandler(ref)),\n [],\n );\n\n const key = options?.key;\n const state = api.getState();\n\n return tapMemo(\n () => ({\n key,\n state,\n api: apiProxy,\n }),\n [state, key],\n );\n};\n"],"mappings":";AAAA,SAAS,WAAW,SAAS,cAAc;AAM3C,IAAM,qBAAN,MAA+E;AAAA,EAC7E,YAA6B,KAA6B;AAA7B;AAAA,EAA8B;AAAA,EAE3D,IAAI,GAAY,MAAuB;AACrC,WAAO,KAAK,IAAI,QAAQ,IAAkB;AAAA,EAC5C;AAAA,EAEA,UAAsC;AACpC,WAAO,OAAO,KAAK,KAAK,IAAI,OAAiB;AAAA,EAC/C;AAAA,EAEA,IAAI,GAAY,MAAuB;AACrC,WAAO,QAAS,KAAK,IAAI;AAAA,EAC3B;AAAA,EAEA,yBAAyB,GAAY,MAAuB;AAC1D,WAAO,OAAO,yBAAyB,KAAK,IAAI,SAAS,IAAI;AAAA,EAC/D;AAAA,EAEA,MAAM;AACJ,WAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EACA,oBAA6B;AAC3B,WAAO;AAAA,EACT;AACF;AAEO,IAAM,SAAS,CACpB,KACA,YAGG;AACH,QAAM,MAAM,OAAO,GAAG;AACtB,YAAU,MAAM;AACd,QAAI,UAAU;AAAA,EAChB,CAAC;AAED,QAAM,WAAW;AAAA,IACf,MAAM,IAAI,MAAY,CAAC,GAAW,IAAI,mBAAmB,GAAG,CAAC;AAAA,IAC7D,CAAC;AAAA,EACH;AAEA,QAAM,MAAM,SAAS;AACrB,QAAM,QAAQ,IAAI,SAAS;AAE3B,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAAA,IACA,CAAC,OAAO,GAAG;AAAA,EACb;AACF;","names":[]}
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "conversational-ui",
29
29
  "conversational-ai"
30
30
  ],
31
- "version": "0.11.48",
31
+ "version": "0.11.50",
32
32
  "license": "MIT",
33
33
  "type": "module",
34
34
  "exports": {
@@ -48,8 +48,8 @@
48
48
  ],
49
49
  "sideEffects": false,
50
50
  "dependencies": {
51
- "assistant-cloud": "^0.1.10",
52
- "@assistant-ui/tap": "^0.3.2",
51
+ "assistant-cloud": "^0.1.11",
52
+ "@assistant-ui/tap": "^0.3.3",
53
53
  "@radix-ui/primitive": "^1.1.3",
54
54
  "@radix-ui/react-compose-refs": "^1.1.2",
55
55
  "@radix-ui/react-context": "^1.1.3",
@@ -59,7 +59,7 @@
59
59
  "@radix-ui/react-use-callback-ref": "^1.1.1",
60
60
  "@radix-ui/react-use-escape-keydown": "^1.1.1",
61
61
  "@standard-schema/spec": "^1.0.0",
62
- "assistant-stream": "^0.2.43",
62
+ "assistant-stream": "^0.2.45",
63
63
  "nanoid": "5.1.6",
64
64
  "react-textarea-autosize": "^8.5.9",
65
65
  "zod": "^4.1.13",
@@ -83,7 +83,7 @@
83
83
  "@stryker-mutator/core": "^9.4.0",
84
84
  "@stryker-mutator/vitest-runner": "^9.4.0",
85
85
  "@types/json-schema": "^7.0.15",
86
- "@types/node": "^24.10.1",
86
+ "@types/node": "^25.0.0",
87
87
  "tsx": "^4.21.0",
88
88
  "vitest": "^4.0.15",
89
89
  "@assistant-ui/x-buildutils": "0.0.1"
@@ -147,7 +147,6 @@ const getClientFromStore = (client: Store<{ api: AssistantClientApi }>) => {
147
147
  );
148
148
  },
149
149
  subscribe: client.subscribe,
150
- flushSync: client.flushSync,
151
150
  } satisfies Partial<AssistantApi>;
152
151
  };
153
152
 
@@ -80,18 +80,19 @@ export const ThreadMessageClient = resource(
80
80
  const [isHoveringState, setIsHovering] = tapState(false);
81
81
 
82
82
  const parts = tapLookupResources(
83
- message.content.map((_, idx) =>
84
- ThreadMessagePartClient({ part: message.content[idx]! }, { key: idx }),
85
- ),
83
+ message.content.map((part, idx) => [
84
+ "toolCallId" in part && part.toolCallId != null
85
+ ? `toolCallId-${part.toolCallId}`
86
+ : `index-${idx}`,
87
+ ThreadMessagePartClient({ part }),
88
+ ]),
86
89
  );
87
90
 
88
91
  const attachments = tapLookupResources(
89
- message.attachments?.map((_, idx) =>
90
- ThreadMessageAttachmentClient(
91
- { attachment: message.attachments![idx]! },
92
- { key: idx },
93
- ),
94
- ) ?? [],
92
+ message.attachments?.map((attachment) => [
93
+ attachment.id,
94
+ ThreadMessageAttachmentClient({ attachment }),
95
+ ]) ?? [],
95
96
  );
96
97
 
97
98
  const composerState = tapInlineResource(
@@ -1,22 +1,37 @@
1
- import { ResourceElement, tapResources } from "@assistant-ui/tap";
1
+ import { ResourceElement, tapMemo, tapResources } from "@assistant-ui/tap";
2
2
  import { ApiObject } from "../../utils/tap-store";
3
3
 
4
4
  export const tapLookupResources = <TState, TApi extends ApiObject>(
5
- elements: ResourceElement<{
6
- key: string | undefined;
7
- state: TState;
8
- api: TApi;
9
- }>[],
10
- ) => {
11
- const resources = tapResources(elements);
5
+ elements: readonly (readonly [
6
+ string,
7
+ ResourceElement<{
8
+ key: string | undefined;
9
+ state: TState;
10
+ api: TApi;
11
+ }>,
12
+ ])[],
13
+ ): {
14
+ state: TState[];
15
+ api: (lookup: { index: number } | { key: string }) => TApi;
16
+ } => {
17
+ const elementsMap = tapMemo(() => Object.fromEntries(elements), [elements]);
18
+ const resources = tapResources(elementsMap, (t) => t, []);
19
+ const keys = tapMemo(() => Object.keys(resources), [resources]);
20
+ const state = tapMemo(() => {
21
+ const result = new Array(keys.length);
22
+ for (let i = 0; i < keys.length; i++) {
23
+ result[i] = resources[keys[i]!]!.state;
24
+ }
25
+ return result;
26
+ }, [keys, resources]);
12
27
 
13
28
  return {
14
- state: resources.map((r) => r.state),
29
+ state,
15
30
  api: (lookup: { index: number } | { key: string }) => {
16
31
  const value =
17
32
  "index" in lookup
18
- ? resources[lookup.index]?.api
19
- : resources.find((r) => r.key === lookup.key)?.api;
33
+ ? resources[keys[lookup.index]!]?.api
34
+ : resources[lookup.key]?.api;
20
35
 
21
36
  if (!value) {
22
37
  throw new Error(
@@ -24,7 +24,6 @@ export const MessageProvider: FC<
24
24
  get: () => store.getState().api,
25
25
  }),
26
26
  subscribe: store.subscribe,
27
- flushSync: store.flushSync,
28
27
  });
29
28
 
30
29
  return <AssistantProvider api={api}>{children}</AssistantProvider>;
@@ -53,7 +53,6 @@ export const TextMessagePartProvider: FC<
53
53
  get: () => store.getState().api,
54
54
  }),
55
55
  subscribe: store.subscribe,
56
- flushSync: store.flushSync,
57
56
  });
58
57
 
59
58
  return <AssistantProvider api={api}>{children}</AssistantProvider>;
@@ -133,7 +133,6 @@ export type AssistantApi = {
133
133
  attachment: AssistantApiField<AttachmentClientApi, AttachmentMeta>;
134
134
 
135
135
  subscribe(listener: () => void): Unsubscribe;
136
- flushSync(): void;
137
136
 
138
137
  on<TEvent extends AssistantEvent>(
139
138
  event: AssistantEventSelector<TEvent>,
@@ -235,7 +234,6 @@ const AssistantApiContext = createContext<AssistantApi>({
235
234
  }),
236
235
 
237
236
  subscribe: NO_OP_FN,
238
- flushSync: NO_OP_FN,
239
237
  on: (selector) => {
240
238
  const { scope } = normalizeEventSelector(selector);
241
239
  throw new Error(`Event scope is not available in this component: ${scope}`);
@@ -250,7 +248,7 @@ export const useAssistantApiImpl = (): AssistantApi => {
250
248
  * Hook to extend the current AssistantApi with additional derived scope fields and special callbacks.
251
249
  * This merges the derived fields with the existing API from context.
252
250
  * Fields are automatically memoized based on source and query changes.
253
- * Special callbacks (on, subscribe, flushSync) use the useEffectEvent pattern to always access latest values.
251
+ * Special callbacks (on, subscribe) use the useEffectEvent pattern to always access latest values.
254
252
  *
255
253
  * @param scopes - Record of field names to DerivedScope resource elements, plus optional special callbacks
256
254
  * @returns The merged AssistantApi
@@ -293,19 +291,6 @@ export function useAssistantApi(config?: AssistantClientProps): AssistantApi {
293
291
  }
294
292
  }
295
293
 
296
- const mergeFns = <TArgs extends Array<unknown>>(
297
- fn1: (...args: TArgs) => void,
298
- fn2: (...args: TArgs) => void,
299
- ) => {
300
- if (fn1 === NO_OP_FN) return fn2;
301
- if (fn2 === NO_OP_FN) return fn1;
302
-
303
- return (...args: TArgs) => {
304
- fn1(...args);
305
- fn2(...args);
306
- };
307
- };
308
-
309
294
  const mergeFnsWithUnsubscribe = <TArgs extends Array<unknown>>(
310
295
  fn1: (...args: TArgs) => Unsubscribe,
311
296
  fn2: (...args: TArgs) => Unsubscribe,
@@ -329,7 +314,6 @@ export const extendApi = (
329
314
  api2: Partial<AssistantApi>,
330
315
  ): AssistantApi => {
331
316
  const api2Subscribe = api2.subscribe;
332
- const api2FlushSync = api2.flushSync;
333
317
  return {
334
318
  ...api,
335
319
  ...api2,
@@ -337,7 +321,6 @@ export const extendApi = (
337
321
  api.subscribe,
338
322
  api2Subscribe ?? NO_OP_FN,
339
323
  ),
340
- flushSync: mergeFns(api.flushSync, api2FlushSync ?? NO_OP_FN),
341
324
  };
342
325
  };
343
326
 
@@ -76,12 +76,10 @@ export const ComposerClient = resource(
76
76
  }, [runtime, events, threadIdRef, messageIdRef]);
77
77
 
78
78
  const attachments = tapLookupResources(
79
- runtimeState.attachments.map((_, idx) =>
80
- ComposerAttachmentClientByIndex(
81
- { runtime: runtime, index: idx },
82
- { key: idx },
83
- ),
84
- ),
79
+ runtimeState.attachments.map((attachment, idx) => [
80
+ attachment.id,
81
+ ComposerAttachmentClientByIndex({ runtime: runtime, index: idx }),
82
+ ]),
85
83
  );
86
84
 
87
85
  const state = tapMemo<ComposerClientState>(() => {
@@ -70,15 +70,19 @@ export const MessageClient = resource(
70
70
  );
71
71
 
72
72
  const parts = tapLookupResources(
73
- runtimeState.content.map((_, idx) =>
74
- MessagePartByIndex({ runtime, index: idx }, { key: idx }),
75
- ),
73
+ runtimeState.content.map((part, idx) => [
74
+ "toolCallId" in part && part.toolCallId != null
75
+ ? `toolCallId-${part.toolCallId}`
76
+ : `index-${idx}`,
77
+ MessagePartByIndex({ runtime, index: idx }),
78
+ ]),
76
79
  );
77
80
 
78
81
  const attachments = tapLookupResources(
79
- runtimeState.attachments?.map((_, idx) =>
80
- MessageAttachmentClientByIndex({ runtime, index: idx }, { key: idx }),
81
- ) ?? [],
82
+ runtimeState.attachments?.map((attachment, idx) => [
83
+ attachment.id,
84
+ MessageAttachmentClientByIndex({ runtime, index: idx }),
85
+ ]) ?? [],
82
86
  );
83
87
 
84
88
  const state = tapMemo<MessageClientState>(() => {
@@ -42,9 +42,10 @@ export const ThreadListClient = resource(
42
42
  );
43
43
 
44
44
  const threadItems = tapLookupResources(
45
- Object.keys(runtimeState.threadItems).map((id) =>
46
- ThreadListItemClientById({ runtime, id }, { key: id }),
47
- ),
45
+ Object.keys(runtimeState.threadItems).map((id) => [
46
+ id,
47
+ ThreadListItemClientById({ runtime, id }),
48
+ ]),
48
49
  );
49
50
 
50
51
  const state = tapMemo<ThreadListClientState>(() => {
@@ -87,12 +87,10 @@ export const ThreadClient = resource(
87
87
  );
88
88
 
89
89
  const messages = tapLookupResources(
90
- runtimeState.messages.map((m) =>
91
- MessageClientById(
92
- { runtime: runtime, id: m.id, threadIdRef },
93
- { key: m.id },
94
- ),
95
- ),
90
+ runtimeState.messages.map((m) => [
91
+ m.id,
92
+ MessageClientById({ runtime: runtime, id: m.id, threadIdRef }),
93
+ ]),
96
94
  );
97
95
 
98
96
  const state = tapMemo<ThreadClientState>(() => {
@@ -274,7 +274,7 @@ const useAssistantTransportThreadRuntime = <T,>(
274
274
  },
275
275
  onCancel: async () => {
276
276
  runManager.cancel();
277
- toolInvocations.abort();
277
+ await toolInvocations.abort();
278
278
  },
279
279
  onResume: async () => {
280
280
  if (!options.resumeApi)