@assistant-ui/react 0.12.27 → 0.14.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 (140) hide show
  1. package/dist/client/ExternalThread.d.ts.map +1 -1
  2. package/dist/client/ExternalThread.js +0 -2
  3. package/dist/client/ExternalThread.js.map +1 -1
  4. package/dist/client/InMemoryThreadList.d.ts.map +1 -1
  5. package/dist/client/InMemoryThreadList.js +3 -0
  6. package/dist/client/InMemoryThreadList.js.map +1 -1
  7. package/dist/client/SingleThreadList.d.ts.map +1 -1
  8. package/dist/client/SingleThreadList.js +3 -0
  9. package/dist/client/SingleThreadList.js.map +1 -1
  10. package/dist/context/providers/ThreadViewportProvider.d.ts.map +1 -1
  11. package/dist/context/providers/ThreadViewportProvider.js +2 -10
  12. package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
  13. package/dist/context/stores/ThreadViewport.d.ts +46 -4
  14. package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
  15. package/dist/context/stores/ThreadViewport.js +51 -7
  16. package/dist/context/stores/ThreadViewport.js.map +1 -1
  17. package/dist/index.d.ts +2 -30
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -28
  20. package/dist/index.js.map +1 -1
  21. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts +1 -1
  22. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts.map +1 -1
  23. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js +1 -1
  24. package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.js.map +1 -1
  25. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  26. package/dist/primitives/composer/ComposerInput.js +9 -4
  27. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  28. package/dist/primitives/message/MessagePartsGrouped.d.ts +6 -21
  29. package/dist/primitives/message/MessagePartsGrouped.d.ts.map +1 -1
  30. package/dist/primitives/message/MessagePartsGrouped.js +6 -21
  31. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  32. package/dist/primitives/message/MessageRoot.d.ts +6 -30
  33. package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
  34. package/dist/primitives/message/MessageRoot.js +68 -25
  35. package/dist/primitives/message/MessageRoot.js.map +1 -1
  36. package/dist/primitives/message.d.ts +1 -0
  37. package/dist/primitives/message.d.ts.map +1 -1
  38. package/dist/primitives/message.js +1 -0
  39. package/dist/primitives/message.js.map +1 -1
  40. package/dist/primitives/thread/ThreadViewport.d.ts +38 -0
  41. package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
  42. package/dist/primitives/thread/ThreadViewport.js +53 -5
  43. package/dist/primitives/thread/ThreadViewport.js.map +1 -1
  44. package/dist/primitives/thread/ThreadViewportFooter.d.ts +2 -1
  45. package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -1
  46. package/dist/primitives/thread/ThreadViewportFooter.js +2 -1
  47. package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
  48. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts +22 -0
  49. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.d.ts.map +1 -0
  50. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js +53 -0
  51. package/dist/primitives/thread/topAnchor/computeTopAnchorSlack.js.map +1 -0
  52. package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts +5 -0
  53. package/dist/primitives/thread/topAnchor/createReserveObservers.d.ts.map +1 -0
  54. package/dist/primitives/thread/topAnchor/createReserveObservers.js +38 -0
  55. package/dist/primitives/thread/topAnchor/createReserveObservers.js.map +1 -0
  56. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts +22 -0
  57. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.d.ts.map +1 -0
  58. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js +75 -0
  59. package/dist/primitives/thread/topAnchor/mountTopAnchorReserve.js.map +1 -0
  60. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts +15 -0
  61. package/dist/primitives/thread/topAnchor/topAnchorTurn.d.ts.map +1 -0
  62. package/dist/primitives/thread/topAnchor/topAnchorTurn.js +13 -0
  63. package/dist/primitives/thread/topAnchor/topAnchorTurn.js.map +1 -0
  64. package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts +15 -0
  65. package/dist/primitives/thread/topAnchor/topAnchorUtils.d.ts.map +1 -0
  66. package/dist/primitives/thread/topAnchor/topAnchorUtils.js +51 -0
  67. package/dist/primitives/thread/topAnchor/topAnchorUtils.js.map +1 -0
  68. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts +7 -0
  69. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.d.ts.map +1 -0
  70. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js +18 -0
  71. package/dist/primitives/thread/topAnchor/useTopAnchorReserve.js.map +1 -0
  72. package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
  73. package/dist/primitives/thread/useThreadViewportAutoScroll.js +13 -1
  74. package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
  75. package/dist/primitives/thread.d.ts +0 -1
  76. package/dist/primitives/thread.d.ts.map +1 -1
  77. package/dist/primitives/thread.js +0 -1
  78. package/dist/primitives/thread.js.map +1 -1
  79. package/dist/primitives/threadList/ThreadListLoadMore.d.ts +13 -0
  80. package/dist/primitives/threadList/ThreadListLoadMore.d.ts.map +1 -0
  81. package/dist/primitives/threadList/ThreadListLoadMore.js +11 -0
  82. package/dist/primitives/threadList/ThreadListLoadMore.js.map +1 -0
  83. package/dist/primitives/threadList.d.ts +1 -0
  84. package/dist/primitives/threadList.d.ts.map +1 -1
  85. package/dist/primitives/threadList.js +1 -0
  86. package/dist/primitives/threadList.js.map +1 -1
  87. package/dist/tests/remote-thread-list-test-helpers.d.ts +3 -0
  88. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -0
  89. package/dist/tests/remote-thread-list-test-helpers.js +27 -0
  90. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -0
  91. package/dist/utils/hooks/useManagedRef.d.ts.map +1 -1
  92. package/dist/utils/hooks/useManagedRef.js +1 -0
  93. package/dist/utils/hooks/useManagedRef.js.map +1 -1
  94. package/dist/utils/hooks/useOnResizeContent.d.ts.map +1 -1
  95. package/dist/utils/hooks/useOnResizeContent.js +1 -2
  96. package/dist/utils/hooks/useOnResizeContent.js.map +1 -1
  97. package/package.json +10 -10
  98. package/src/client/ExternalThread.ts +0 -2
  99. package/src/client/InMemoryThreadList.ts +3 -0
  100. package/src/client/SingleThreadList.ts +3 -0
  101. package/src/context/providers/ThreadViewportProvider.tsx +2 -12
  102. package/src/context/stores/ThreadViewport.ts +111 -11
  103. package/src/index.ts +2 -35
  104. package/src/legacy-runtime/runtime-cores/assistant-transport/utils.ts +1 -5
  105. package/src/primitives/composer/ComposerInput.test.tsx +232 -0
  106. package/src/primitives/composer/ComposerInput.tsx +9 -4
  107. package/src/primitives/message/MessagePartsGrouped.tsx +6 -21
  108. package/src/primitives/message/MessageRoot.tsx +135 -57
  109. package/src/primitives/message.ts +1 -0
  110. package/src/primitives/thread/ThreadViewport.tsx +95 -4
  111. package/src/primitives/thread/ThreadViewportFooter.tsx +2 -1
  112. package/src/primitives/thread/topAnchor/computeTopAnchorSlack.test.ts +131 -0
  113. package/src/primitives/thread/topAnchor/computeTopAnchorSlack.ts +94 -0
  114. package/src/primitives/thread/topAnchor/createReserveObservers.ts +50 -0
  115. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.test.ts +131 -0
  116. package/src/primitives/thread/topAnchor/mountTopAnchorReserve.ts +127 -0
  117. package/src/primitives/thread/topAnchor/topAnchorTurn.test.ts +46 -0
  118. package/src/primitives/thread/topAnchor/topAnchorTurn.ts +30 -0
  119. package/src/primitives/thread/topAnchor/topAnchorUtils.ts +58 -0
  120. package/src/primitives/thread/topAnchor/useTopAnchorReserve.ts +19 -0
  121. package/src/primitives/thread/useThreadViewportAutoScroll.ts +15 -1
  122. package/src/primitives/thread.ts +0 -1
  123. package/src/primitives/threadList/ThreadListLoadMore.tsx +24 -0
  124. package/src/primitives/threadList.ts +1 -0
  125. package/src/tests/BaseComposerRuntimeCore.test.ts +9 -0
  126. package/src/tests/RemoteThreadListRuntime.adapterProvider.test.tsx +138 -0
  127. package/src/tests/RemoteThreadListRuntime.deferredProvider.test.tsx +29 -18
  128. package/src/tests/remote-thread-list-test-helpers.ts +33 -0
  129. package/src/utils/hooks/useManagedRef.ts +1 -0
  130. package/src/utils/hooks/useOnResizeContent.ts +1 -2
  131. package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.d.ts +0 -3
  132. package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.d.ts.map +0 -1
  133. package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.js +0 -3
  134. package/dist/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.js.map +0 -1
  135. package/dist/primitives/thread/ThreadViewportSlack.d.ts +0 -20
  136. package/dist/primitives/thread/ThreadViewportSlack.d.ts.map +0 -1
  137. package/dist/primitives/thread/ThreadViewportSlack.js +0 -80
  138. package/dist/primitives/thread/ThreadViewportSlack.js.map +0 -1
  139. package/src/legacy-runtime/runtime-cores/external-store/getExternalStoreMessage.ts +0 -6
  140. package/src/primitives/thread/ThreadViewportSlack.tsx +0 -116
@@ -0,0 +1,27 @@
1
+ import { vi } from "vitest";
2
+ export function makeAdapter(overrides = {}) {
3
+ return {
4
+ list: vi.fn(async () => ({ threads: [] })),
5
+ initialize: vi.fn(async (threadId) => ({
6
+ remoteId: threadId,
7
+ externalId: threadId,
8
+ })),
9
+ rename: vi.fn(async () => { }),
10
+ archive: vi.fn(async () => { }),
11
+ unarchive: vi.fn(async () => { }),
12
+ delete: vi.fn(async () => { }),
13
+ generateTitle: vi.fn(async () => new ReadableStream({
14
+ start(c) {
15
+ c.close();
16
+ },
17
+ })),
18
+ fetch: vi.fn(async (id) => ({
19
+ status: "regular",
20
+ remoteId: id,
21
+ externalId: id,
22
+ title: "Test",
23
+ })),
24
+ ...overrides,
25
+ };
26
+ }
27
+ //# sourceMappingURL=remote-thread-list-test-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-thread-list-test-helpers.js","sourceRoot":"","sources":["../../src/tests/remote-thread-list-test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG5B,MAAM,UAAU,WAAW,CACzB,YAA8C,EAAE;IAEhD,OAAO;QACL,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE,CAAC,CAAC;YAC7C,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,QAAQ;SACrB,CAAC,CAAC;QACH,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;QAC7B,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;QAC9B,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;QAChC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;QAC7B,aAAa,EAAE,EAAE,CAAC,EAAE,CAClB,KAAK,IAAI,EAAE,CACT,IAAI,cAAc,CAAC;YACjB,KAAK,CAAC,CAAC;gBACL,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,CAAC;SACF,CAAU,CACd;QACD,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE,CAAC,CAAC;YAClC,MAAM,EAAE,SAAkB;YAC1B,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QACH,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useManagedRef.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useManagedRef.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,GAAI,KAAK,EACjC,UAAU,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,UAK5C,KAAK,GAAG,IAAI,SAepB,CAAC"}
1
+ {"version":3,"file":"useManagedRef.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useManagedRef.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,GAAI,KAAK,EACjC,UAAU,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,UAK5C,KAAK,GAAG,IAAI,SAgBpB,CAAC"}
@@ -5,6 +5,7 @@ export const useManagedRef = (callback) => {
5
5
  // Call the previous cleanup function
6
6
  if (cleanupRef.current) {
7
7
  cleanupRef.current();
8
+ cleanupRef.current = undefined;
8
9
  }
9
10
  // Call the new callback and store its cleanup function
10
11
  if (el) {
@@ -1 +1 @@
1
- {"version":3,"file":"useManagedRef.js","sourceRoot":"","sources":["../../../src/utils/hooks/useManagedRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,QAAmD,EACnD,EAAE;IACF,MAAM,UAAU,GAAG,MAAM,CAA2B,SAAS,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,WAAW,CACrB,CAAC,EAAgB,EAAE,EAAE;QACnB,qCAAqC;QACrC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;QAED,uDAAuD;QACvD,IAAI,EAAE,EAAE,CAAC;YACP,UAAU,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
1
+ {"version":3,"file":"useManagedRef.js","sourceRoot":"","sources":["../../../src/utils/hooks/useManagedRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,QAAmD,EACnD,EAAE;IACF,MAAM,UAAU,GAAG,MAAM,CAA2B,SAAS,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,WAAW,CACrB,CAAC,EAAgB,EAAE,EAAE;QACnB,qCAAqC;QACrC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,UAAU,CAAC,OAAO,EAAE,CAAC;YACrB,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC;QACjC,CAAC;QAED,uDAAuD;QACvD,IAAI,EAAE,EAAE,CAAC;YACP,UAAU,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useOnResizeContent.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,IAAI,qCAsCtD,CAAC"}
1
+ {"version":3,"file":"useOnResizeContent.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,IAAI,qCAqCtD,CAAC"}
@@ -9,8 +9,7 @@ export const useOnResizeContent = (callback) => {
9
9
  });
10
10
  const mutationObserver = new MutationObserver((mutations) => {
11
11
  // Filter out style-only attribute mutations to prevent feedback loops
12
- // with components like ThreadViewportSlack that write styles in response
13
- // to viewport changes
12
+ // with code paths that write styles in response to viewport changes.
14
13
  const hasRelevantMutation = mutations.some((m) => m.type !== "attributes" || m.attributeName !== "style");
15
14
  if (hasRelevantMutation) {
16
15
  callbackRef();
@@ -1 +1 @@
1
- {"version":3,"file":"useOnResizeContent.js","sourceRoot":"","sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAoB,EAAE,EAAE;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,EAAe,EAAE,EAAE;QAClB,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;YAC7C,WAAW,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;YAC1D,sEAAsE;YACtE,yEAAyE;YACzE,sBAAsB;YACtB,MAAM,mBAAmB,GAAG,SAAS,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,aAAa,KAAK,OAAO,CAC9D,CAAC;YACF,IAAI,mBAAmB,EAAE,CAAC;gBACxB,WAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3B,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE;YAC3B,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,cAAc,CAAC,UAAU,EAAE,CAAC;YAC5B,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAChC,CAAC,CAAC;IACJ,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC,CAAC"}
1
+ {"version":3,"file":"useOnResizeContent.js","sourceRoot":"","sources":["../../../src/utils/hooks/useOnResizeContent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAEhD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAoB,EAAE,EAAE;IACzD,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,EAAe,EAAE,EAAE;QAClB,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;YAC7C,WAAW,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;YAC1D,sEAAsE;YACtE,qEAAqE;YACrE,MAAM,mBAAmB,GAAG,SAAS,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,aAAa,KAAK,OAAO,CAC9D,CAAC;YACF,IAAI,mBAAmB,EAAE,CAAC;gBACxB,WAAW,EAAE,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3B,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE;YAC3B,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,cAAc,CAAC,UAAU,EAAE,CAAC;YAC5B,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAChC,CAAC,CAAC;IACJ,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.12.27",
3
+ "version": "0.14.0",
4
4
  "description": "TypeScript/React library for AI Chat",
5
5
  "keywords": [
6
6
  "radix-ui",
@@ -48,9 +48,9 @@
48
48
  ],
49
49
  "sideEffects": false,
50
50
  "dependencies": {
51
- "@assistant-ui/core": "^0.1.16",
52
- "@assistant-ui/store": "^0.2.9",
53
- "@assistant-ui/tap": "^0.5.10",
51
+ "@assistant-ui/core": "^0.2.0",
52
+ "@assistant-ui/store": "^0.2.10",
53
+ "@assistant-ui/tap": "^0.5.11",
54
54
  "@radix-ui/primitive": "^1.1.3",
55
55
  "@radix-ui/react-compose-refs": "^1.1.2",
56
56
  "@radix-ui/react-context": "^1.1.3",
@@ -58,12 +58,12 @@
58
58
  "@radix-ui/react-use-callback-ref": "^1.1.1",
59
59
  "@radix-ui/react-use-escape-keydown": "^1.1.1",
60
60
  "assistant-cloud": "^0.1.27",
61
- "assistant-stream": "^0.3.12",
62
- "nanoid": "^5.1.9",
61
+ "assistant-stream": "^0.3.13",
62
+ "nanoid": "^5.1.11",
63
63
  "radix-ui": "^1.4.3",
64
64
  "react-textarea-autosize": "^8.5.9",
65
- "zod": "^4.3.6",
66
- "zustand": "^5.0.12"
65
+ "zod": "^4.4.3",
66
+ "zustand": "^5.0.13"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@types/react": "*",
@@ -85,11 +85,11 @@
85
85
  "@types/node": "^25.6.0",
86
86
  "@types/react": "^19.2.14",
87
87
  "@types/react-dom": "^19.2.3",
88
- "jsdom": "^29.1.0",
88
+ "jsdom": "^29.1.1",
89
89
  "react": "^19.2.5",
90
90
  "react-dom": "^19.2.5",
91
91
  "vitest": "^4.1.5",
92
- "@assistant-ui/x-buildutils": "0.0.6"
92
+ "@assistant-ui/x-buildutils": "0.0.7"
93
93
  },
94
94
  "publishConfig": {
95
95
  "access": "public",
@@ -146,7 +146,6 @@ const MessageClient = resource(
146
146
  branchNumber: 1,
147
147
  branchCount: 1,
148
148
  speech: undefined,
149
- submittedFeedback: undefined,
150
149
  parts: partClients.state,
151
150
  isCopied,
152
151
  isHovering,
@@ -589,7 +588,6 @@ export const ExternalThread = resource(
589
588
  onStartRun?.();
590
589
  },
591
590
  resumeRun: () => {},
592
- unstable_resumeRun: () => {},
593
591
  cancelRun: handleCancelRun,
594
592
  getModelContext: () => ({ tools: {}, config: {} }),
595
593
  export: () => ({ messages: [] }),
@@ -142,6 +142,8 @@ export const InMemoryThreadList = resource(
142
142
  mainThreadId,
143
143
  newThreadId: null,
144
144
  isLoading: false,
145
+ isLoadingMore: false,
146
+ hasMore: false,
145
147
  threadIds: regularThreads.map((t) => t.id),
146
148
  archivedThreadIds: archivedThreads.map((t) => t.id),
147
149
  threadItems: threadListItems.state,
@@ -155,6 +157,7 @@ export const InMemoryThreadList = resource(
155
157
  switchToNewThread: handleSwitchToNewThread,
156
158
  getLoadThreadsPromise: () => RESOLVED_PROMISE,
157
159
  reload: () => RESOLVED_PROMISE,
160
+ loadMore: () => RESOLVED_PROMISE,
158
161
  item: (selector) => {
159
162
  if (selector === "main") {
160
163
  const index = threads.findIndex((t) => t.id === mainThreadId);
@@ -47,6 +47,8 @@ export const SingleThreadList = resource(
47
47
  mainThreadId: THREAD_ID,
48
48
  newThreadId: null,
49
49
  isLoading: false,
50
+ isLoadingMore: false,
51
+ hasMore: false,
50
52
  threadIds: [THREAD_ID],
51
53
  archivedThreadIds: [],
52
54
  threadItems: [itemClient.state],
@@ -65,6 +67,7 @@ export const SingleThreadList = resource(
65
67
  },
66
68
  getLoadThreadsPromise: () => RESOLVED_PROMISE,
67
69
  reload: () => RESOLVED_PROMISE,
70
+ loadMore: () => RESOLVED_PROMISE,
68
71
  item: (selector) => {
69
72
  if (
70
73
  selector !== "main" &&
@@ -19,6 +19,8 @@ export type ThreadViewportProviderProps = PropsWithChildren<{
19
19
 
20
20
  const useThreadViewportStoreValue = (options: ThreadViewportStoreOptions) => {
21
21
  const outerViewport = useThreadViewportStore({ optional: true });
22
+ // Viewport options are initial configuration. Keeping them non-reactive avoids
23
+ // fanout through every message in long threads when anchoring config changes.
22
24
  const [store] = useState(() => makeThreadViewportStore(options));
23
25
 
24
26
  // Forward scrollToBottom from outer viewport to inner viewport
@@ -37,18 +39,6 @@ const useThreadViewportStoreValue = (options: ThreadViewportStoreOptions) => {
37
39
  });
38
40
  }, [store, outerViewport]);
39
41
 
40
- // Sync options to store when they change
41
- useEffect(() => {
42
- const nextState = {
43
- turnAnchor: options.turnAnchor ?? "bottom",
44
- };
45
-
46
- const currentState = store.getState();
47
- if (currentState.turnAnchor !== nextState.turnAnchor) {
48
- writableStore(store).setState(nextState);
49
- }
50
- }, [store, options.turnAnchor]);
51
-
52
42
  return store;
53
43
  };
54
44
 
@@ -60,28 +60,80 @@ export type ThreadViewportState = {
60
60
  /** Controls scroll anchoring: "top" anchors user messages at top, "bottom" is classic behavior */
61
61
  readonly turnAnchor: "top" | "bottom";
62
62
 
63
+ /** Clamps tall user messages so the assistant response stays in view. */
64
+ readonly topAnchorMessageClamp: {
65
+ readonly tallerThan: string;
66
+ readonly visibleHeight: string;
67
+ };
68
+
63
69
  /** Raw height values from registered elements */
64
70
  readonly height: {
65
71
  /** Total viewport height */
66
72
  readonly viewport: number;
67
73
  /** Total content inset height (footer, anchor message, etc.) */
68
74
  readonly inset: number;
69
- /** Height of the anchor user message (full height) */
70
- readonly userMessage: number;
71
75
  };
72
76
 
77
+ /** Current DOM elements used for geometry-based top anchoring */
78
+ readonly element: {
79
+ readonly viewport: HTMLElement | null;
80
+ readonly anchor: HTMLElement | null;
81
+ readonly target: HTMLElement | null;
82
+ };
83
+
84
+ /** Numeric clamp configuration for the active top-anchor target message */
85
+ readonly targetConfig: {
86
+ readonly tallerThan: number;
87
+ readonly visibleHeight: number;
88
+ } | null;
89
+
90
+ /**
91
+ * The current top-anchor turn activated in this viewport session.
92
+ * History-loaded messages do not populate this; it is set when a run creates
93
+ * a live user/assistant pair and remains after the run completes.
94
+ */
95
+ readonly topAnchorTurn: {
96
+ readonly anchorId: string;
97
+ readonly targetId: string;
98
+ } | null;
99
+
73
100
  /** Register a viewport and get a handle to update its height */
74
101
  readonly registerViewport: () => SizeHandle;
75
102
 
76
103
  /** Register a content inset (footer, anchor message, etc.) and get a handle to update its height */
77
104
  readonly registerContentInset: () => SizeHandle;
78
105
 
79
- /** Register the anchor user message height */
80
- readonly registerUserMessageHeight: () => SizeHandle;
106
+ /** Register the scroll viewport element */
107
+ readonly registerViewportElement: (
108
+ element: HTMLElement | null,
109
+ ) => Unsubscribe;
110
+
111
+ /** Register the current anchor user message element */
112
+ readonly registerAnchorElement: (element: HTMLElement | null) => Unsubscribe;
113
+
114
+ /**
115
+ * Register the current top-anchor target (last assistant response) element
116
+ * along with its numeric clamp configuration. When unregistered, both
117
+ * `element.target` and `targetConfig` clear together.
118
+ */
119
+ readonly registerAnchorTargetElement: (
120
+ element: HTMLElement | null,
121
+ config?: { readonly tallerThan: number; readonly visibleHeight: number },
122
+ ) => Unsubscribe;
123
+
124
+ readonly setTopAnchorTurn: (
125
+ turn: { readonly anchorId: string; readonly targetId: string } | null,
126
+ ) => void;
81
127
  };
82
128
 
83
129
  export type ThreadViewportStoreOptions = {
84
130
  turnAnchor?: "top" | "bottom" | undefined;
131
+ topAnchorMessageClamp?:
132
+ | {
133
+ tallerThan?: string | undefined;
134
+ visibleHeight?: string | undefined;
135
+ }
136
+ | undefined;
85
137
  };
86
138
 
87
139
  export const makeThreadViewportStore = (
@@ -107,14 +159,27 @@ export const makeThreadViewportStore = (
107
159
  },
108
160
  });
109
161
  });
110
- const userMessageRegistry = createSizeRegistry((total) => {
162
+ const registerElementSlot = (
163
+ key: "viewport" | "anchor",
164
+ element: HTMLElement | null,
165
+ ) => {
111
166
  store.setState({
112
- height: {
113
- ...store.getState().height,
114
- userMessage: total,
167
+ element: {
168
+ ...store.getState().element,
169
+ [key]: element,
115
170
  },
116
171
  });
117
- });
172
+
173
+ return () => {
174
+ if (store.getState().element[key] !== element) return;
175
+ store.setState({
176
+ element: {
177
+ ...store.getState().element,
178
+ [key]: null,
179
+ },
180
+ });
181
+ };
182
+ };
118
183
 
119
184
  const store = create<ThreadViewportState>(() => ({
120
185
  isAtBottom: true,
@@ -131,16 +196,51 @@ export const makeThreadViewportStore = (
131
196
  },
132
197
 
133
198
  turnAnchor: options.turnAnchor ?? "bottom",
199
+ topAnchorMessageClamp: {
200
+ tallerThan: options.topAnchorMessageClamp?.tallerThan ?? "10em",
201
+ visibleHeight: options.topAnchorMessageClamp?.visibleHeight ?? "6em",
202
+ },
134
203
 
135
204
  height: {
136
205
  viewport: 0,
137
206
  inset: 0,
138
- userMessage: 0,
139
207
  },
208
+ element: {
209
+ viewport: null,
210
+ anchor: null,
211
+ target: null,
212
+ },
213
+ targetConfig: null,
214
+ topAnchorTurn: null,
140
215
 
141
216
  registerViewport: viewportRegistry.register,
142
217
  registerContentInset: insetRegistry.register,
143
- registerUserMessageHeight: userMessageRegistry.register,
218
+ registerViewportElement: (element) =>
219
+ registerElementSlot("viewport", element),
220
+ registerAnchorElement: (element) => registerElementSlot("anchor", element),
221
+ registerAnchorTargetElement: (element, config) => {
222
+ store.setState({
223
+ element: {
224
+ ...store.getState().element,
225
+ target: element,
226
+ },
227
+ targetConfig: element && config ? config : null,
228
+ });
229
+
230
+ return () => {
231
+ if (store.getState().element.target !== element) return;
232
+ store.setState({
233
+ element: {
234
+ ...store.getState().element,
235
+ target: null,
236
+ },
237
+ targetConfig: null,
238
+ });
239
+ };
240
+ },
241
+ setTopAnchorTurn: (topAnchorTurn) => {
242
+ store.setState({ topAnchorTurn });
243
+ },
144
244
  }));
145
245
 
146
246
  return store;
package/src/index.ts CHANGED
@@ -125,7 +125,6 @@ export type {
125
125
  // --- external-store ---
126
126
  export type { ThreadMessageLike } from "@assistant-ui/core";
127
127
  export {
128
- getExternalStoreMessage,
129
128
  getExternalStoreMessages,
130
129
  bindExternalStoreMessage,
131
130
  } from "@assistant-ui/core";
@@ -151,25 +150,13 @@ export type {
151
150
  LocalRuntimeOptionsBase,
152
151
  } from "@assistant-ui/core";
153
152
  export { useLocalRuntime } from "./legacy-runtime/runtime-cores/local/useLocalRuntime";
154
- /**
155
- * @deprecated Use `useLocalRuntime` instead.
156
- */
157
- export { useLocalRuntime as useLocalThreadRuntime } from "./legacy-runtime/runtime-cores/local/useLocalRuntime";
158
153
  export type { LocalRuntimeOptions } from "./legacy-runtime/runtime-cores/local/LocalRuntimeOptions";
159
154
 
160
155
  // --- remote-thread-list ---
161
156
  export { useRemoteThreadListRuntime } from "./legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime";
162
- /** @deprecated Use `useRemoteThreadListRuntime` instead. */
163
- export { useRemoteThreadListRuntime as unstable_useRemoteThreadListRuntime } from "./legacy-runtime/runtime-cores/remote-thread-list/useRemoteThreadListRuntime";
164
157
  export { useCloudThreadListAdapter } from "./legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud";
165
- /** @deprecated Use `useCloudThreadListAdapter` instead. */
166
- export { useCloudThreadListAdapter as unstable_useCloudThreadListAdapter } from "./legacy-runtime/runtime-cores/remote-thread-list/adapter/cloud";
167
158
  export type { RemoteThreadListAdapter } from "@assistant-ui/core";
168
- /** @deprecated Use `RemoteThreadListAdapter` instead. */
169
- export type { RemoteThreadListAdapter as unstable_RemoteThreadListAdapter } from "@assistant-ui/core";
170
159
  export { InMemoryThreadListAdapter } from "@assistant-ui/core";
171
- /** @deprecated Use `InMemoryThreadListAdapter` instead. */
172
- export { InMemoryThreadListAdapter as unstable_InMemoryThreadListAdapter } from "@assistant-ui/core";
173
160
 
174
161
  // Re-export from @assistant-ui/core (runtime-cores root)
175
162
  export type { ExportedMessageRepositoryItem } from "@assistant-ui/core";
@@ -332,6 +319,8 @@ export type {
332
319
  ReasoningGroupComponent,
333
320
  QuoteMessagePartComponent,
334
321
  QuoteMessagePartProps,
322
+ EnrichedPartState,
323
+ PartState,
335
324
  } from "@assistant-ui/core/react";
336
325
 
337
326
  // Thread list item types
@@ -389,25 +378,3 @@ export {
389
378
  } from "./primitives/composer/trigger";
390
379
 
391
380
  export type { Assistant } from "./augmentations";
392
-
393
- // Backwards compatibility — deprecated exports, to be removed in v0.13
394
-
395
- /**
396
- * @deprecated Use `useAui` instead. This alias will be removed in v0.13.
397
- */
398
- export { useAui as useAssistantApi } from "@assistant-ui/store";
399
-
400
- /**
401
- * @deprecated Use `useAuiState` instead. This alias will be removed in v0.13.
402
- */
403
- export { useAuiState as useAssistantState } from "@assistant-ui/store";
404
-
405
- /**
406
- * @deprecated Use `useAuiEvent` instead. This alias will be removed in v0.13.
407
- */
408
- export { useAuiEvent as useAssistantEvent } from "@assistant-ui/store";
409
-
410
- /**
411
- * @deprecated Use `AuiIf` instead. This alias will be removed in v0.13.
412
- */
413
- export { AuiIf as AssistantIf } from "@assistant-ui/store";
@@ -1,5 +1 @@
1
- export {
2
- toAISDKTools,
3
- getEnabledTools,
4
- createRequestHeaders,
5
- } from "@assistant-ui/core";
1
+ export { createRequestHeaders } from "@assistant-ui/core";