@assistant-ui/react 0.12.9 → 0.12.10

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 (298) hide show
  1. package/dist/client/ExternalThread.d.ts.map +1 -1
  2. package/dist/client/ExternalThread.js +10 -0
  3. package/dist/client/ExternalThread.js.map +1 -1
  4. package/dist/client/NoOpComposerClient.d.ts.map +1 -1
  5. package/dist/client/NoOpComposerClient.js +4 -0
  6. package/dist/client/NoOpComposerClient.js.map +1 -1
  7. package/dist/context/providers/ChainOfThoughtByIndicesProvider.js +1 -1
  8. package/dist/context/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
  9. package/dist/context/react/utils/ensureBinding.js +1 -1
  10. package/dist/context/react/utils/ensureBinding.js.map +1 -1
  11. package/dist/hooks/useMessageQuote.d.ts +17 -0
  12. package/dist/hooks/useMessageQuote.d.ts.map +1 -0
  13. package/dist/hooks/useMessageQuote.js +20 -0
  14. package/dist/hooks/useMessageQuote.js.map +1 -0
  15. package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
  16. package/dist/legacy-runtime/AssistantRuntimeProvider.js +1 -2
  17. package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
  18. package/dist/legacy-runtime/client/ComposerRuntimeClient.d.ts.map +1 -1
  19. package/dist/legacy-runtime/client/ComposerRuntimeClient.js +2 -0
  20. package/dist/legacy-runtime/client/ComposerRuntimeClient.js.map +1 -1
  21. package/dist/legacy-runtime/hooks/AssistantContext.d.ts +1 -1
  22. package/dist/legacy-runtime/hooks/AssistantContext.js +1 -1
  23. package/dist/legacy-runtime/hooks/AttachmentContext.d.ts +1 -1
  24. package/dist/legacy-runtime/hooks/AttachmentContext.js +1 -1
  25. package/dist/legacy-runtime/hooks/ComposerContext.d.ts +6 -6
  26. package/dist/legacy-runtime/hooks/ComposerContext.js +4 -4
  27. package/dist/legacy-runtime/hooks/MessageContext.d.ts +5 -5
  28. package/dist/legacy-runtime/hooks/MessageContext.js +5 -5
  29. package/dist/legacy-runtime/hooks/MessagePartContext.d.ts +1 -1
  30. package/dist/legacy-runtime/hooks/MessagePartContext.js +1 -1
  31. package/dist/legacy-runtime/hooks/ThreadContext.d.ts +5 -5
  32. package/dist/legacy-runtime/hooks/ThreadContext.js +4 -4
  33. package/dist/legacy-runtime/hooks/ThreadListItemContext.d.ts +1 -1
  34. package/dist/legacy-runtime/hooks/ThreadListItemContext.js +1 -1
  35. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts +12 -0
  36. package/dist/legacy-runtime/runtime/ComposerRuntime.d.ts.map +1 -1
  37. package/dist/legacy-runtime/runtime/ComposerRuntime.js +9 -0
  38. package/dist/legacy-runtime/runtime/ComposerRuntime.js.map +1 -1
  39. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +2 -0
  40. package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +1 -1
  41. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +5 -0
  42. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +1 -1
  43. package/dist/legacy-runtime/runtime-cores/assistant-transport/types.js.map +1 -1
  44. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
  45. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +36 -26
  46. package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
  47. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js +7 -7
  48. package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
  49. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts +4 -0
  50. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.d.ts.map +1 -1
  51. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.js +16 -2
  52. package/dist/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.js.map +1 -1
  53. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts +3 -0
  54. package/dist/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.d.ts.map +1 -1
  55. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js +1 -1
  56. package/dist/legacy-runtime/runtime-cores/external-store/createMessageConverter.js.map +1 -1
  57. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.d.ts.map +1 -1
  58. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.js +1 -1
  59. package/dist/legacy-runtime/runtime-cores/local/useLocalRuntime.js.map +1 -1
  60. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.d.ts.map +1 -1
  61. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js +4 -0
  62. package/dist/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.js.map +1 -1
  63. package/dist/primitives/actionBar/ActionBarCopy.d.ts.map +1 -1
  64. package/dist/primitives/actionBar/ActionBarCopy.js +7 -6
  65. package/dist/primitives/actionBar/ActionBarCopy.js.map +1 -1
  66. package/dist/primitives/actionBar/ActionBarEdit.js +1 -1
  67. package/dist/primitives/actionBar/ActionBarEdit.js.map +1 -1
  68. package/dist/primitives/actionBar/ActionBarExportMarkdown.d.ts.map +1 -1
  69. package/dist/primitives/actionBar/ActionBarExportMarkdown.js +4 -3
  70. package/dist/primitives/actionBar/ActionBarExportMarkdown.js.map +1 -1
  71. package/dist/primitives/actionBar/ActionBarSpeak.d.ts.map +1 -1
  72. package/dist/primitives/actionBar/ActionBarSpeak.js +4 -3
  73. package/dist/primitives/actionBar/ActionBarSpeak.js.map +1 -1
  74. package/dist/primitives/actionBar/ActionBarStopSpeaking.js +1 -1
  75. package/dist/primitives/actionBar/ActionBarStopSpeaking.js.map +1 -1
  76. package/dist/primitives/actionBar/useActionBarFloatStatus.js +5 -5
  77. package/dist/primitives/actionBar/useActionBarFloatStatus.js.map +1 -1
  78. package/dist/primitives/attachment/AttachmentName.js +1 -1
  79. package/dist/primitives/attachment/AttachmentName.js.map +1 -1
  80. package/dist/primitives/attachment/AttachmentThumb.js +2 -2
  81. package/dist/primitives/attachment/AttachmentThumb.js.map +1 -1
  82. package/dist/primitives/branchPicker/BranchPickerCount.js +1 -1
  83. package/dist/primitives/branchPicker/BranchPickerCount.js.map +1 -1
  84. package/dist/primitives/branchPicker/BranchPickerNext.js +3 -3
  85. package/dist/primitives/branchPicker/BranchPickerNext.js.map +1 -1
  86. package/dist/primitives/branchPicker/BranchPickerNumber.js +1 -1
  87. package/dist/primitives/branchPicker/BranchPickerNumber.js.map +1 -1
  88. package/dist/primitives/branchPicker/BranchPickerPrevious.js +3 -3
  89. package/dist/primitives/branchPicker/BranchPickerPrevious.js.map +1 -1
  90. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.d.ts.map +1 -1
  91. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js +1 -1
  92. package/dist/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.js.map +1 -1
  93. package/dist/primitives/chainOfThought/ChainOfThoughtParts.d.ts.map +1 -1
  94. package/dist/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  95. package/dist/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  96. package/dist/primitives/composer/ComposerAddAttachment.js +1 -1
  97. package/dist/primitives/composer/ComposerAddAttachment.js.map +1 -1
  98. package/dist/primitives/composer/ComposerAttachments.js +1 -1
  99. package/dist/primitives/composer/ComposerAttachments.js.map +1 -1
  100. package/dist/primitives/composer/ComposerCancel.js +1 -1
  101. package/dist/primitives/composer/ComposerCancel.js.map +1 -1
  102. package/dist/primitives/composer/ComposerDictate.js +3 -3
  103. package/dist/primitives/composer/ComposerDictate.js.map +1 -1
  104. package/dist/primitives/composer/ComposerDictationTranscript.d.ts.map +1 -1
  105. package/dist/primitives/composer/ComposerDictationTranscript.js +1 -1
  106. package/dist/primitives/composer/ComposerDictationTranscript.js.map +1 -1
  107. package/dist/primitives/composer/ComposerIf.js +4 -4
  108. package/dist/primitives/composer/ComposerIf.js.map +1 -1
  109. package/dist/primitives/composer/ComposerInput.d.ts +35 -45
  110. package/dist/primitives/composer/ComposerInput.d.ts.map +1 -1
  111. package/dist/primitives/composer/ComposerInput.js +25 -9
  112. package/dist/primitives/composer/ComposerInput.js.map +1 -1
  113. package/dist/primitives/composer/ComposerQuote.d.ts +52 -0
  114. package/dist/primitives/composer/ComposerQuote.d.ts.map +1 -0
  115. package/dist/primitives/composer/ComposerQuote.js +57 -0
  116. package/dist/primitives/composer/ComposerQuote.js.map +1 -0
  117. package/dist/primitives/composer/ComposerStopDictation.js +1 -1
  118. package/dist/primitives/composer/ComposerStopDictation.js.map +1 -1
  119. package/dist/primitives/composer/index.d.ts +3 -0
  120. package/dist/primitives/composer/index.d.ts.map +1 -1
  121. package/dist/primitives/composer/index.js +3 -0
  122. package/dist/primitives/composer/index.js.map +1 -1
  123. package/dist/primitives/error/ErrorMessage.js +4 -4
  124. package/dist/primitives/error/ErrorMessage.js.map +1 -1
  125. package/dist/primitives/index.d.ts +2 -0
  126. package/dist/primitives/index.d.ts.map +1 -1
  127. package/dist/primitives/index.js +2 -0
  128. package/dist/primitives/index.js.map +1 -1
  129. package/dist/primitives/message/MessageAttachments.js +4 -4
  130. package/dist/primitives/message/MessageAttachments.js.map +1 -1
  131. package/dist/primitives/message/MessageError.js +2 -2
  132. package/dist/primitives/message/MessageError.js.map +1 -1
  133. package/dist/primitives/message/MessageIf.js +3 -3
  134. package/dist/primitives/message/MessageIf.js.map +1 -1
  135. package/dist/primitives/message/MessageParts.js +7 -7
  136. package/dist/primitives/message/MessageParts.js.map +1 -1
  137. package/dist/primitives/message/MessagePartsGrouped.js +5 -5
  138. package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
  139. package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
  140. package/dist/primitives/message/MessageRoot.js +6 -5
  141. package/dist/primitives/message/MessageRoot.js.map +1 -1
  142. package/dist/primitives/messagePart/MessagePartInProgress.d.ts.map +1 -1
  143. package/dist/primitives/messagePart/MessagePartInProgress.js +1 -1
  144. package/dist/primitives/messagePart/MessagePartInProgress.js.map +1 -1
  145. package/dist/primitives/messagePart/useMessagePartData.js +3 -3
  146. package/dist/primitives/messagePart/useMessagePartData.js.map +1 -1
  147. package/dist/primitives/messagePart/useMessagePartFile.js +3 -3
  148. package/dist/primitives/messagePart/useMessagePartFile.js.map +1 -1
  149. package/dist/primitives/messagePart/useMessagePartImage.js +3 -3
  150. package/dist/primitives/messagePart/useMessagePartImage.js.map +1 -1
  151. package/dist/primitives/messagePart/useMessagePartReasoning.js +3 -3
  152. package/dist/primitives/messagePart/useMessagePartReasoning.js.map +1 -1
  153. package/dist/primitives/messagePart/useMessagePartSource.js +3 -3
  154. package/dist/primitives/messagePart/useMessagePartSource.js.map +1 -1
  155. package/dist/primitives/messagePart/useMessagePartText.d.ts.map +1 -1
  156. package/dist/primitives/messagePart/useMessagePartText.js +3 -3
  157. package/dist/primitives/messagePart/useMessagePartText.js.map +1 -1
  158. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts +24 -0
  159. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.d.ts.map +1 -0
  160. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js +37 -0
  161. package/dist/primitives/selectionToolbar/SelectionToolbarQuote.js.map +1 -0
  162. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts +31 -0
  163. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.d.ts.map +1 -0
  164. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js +85 -0
  165. package/dist/primitives/selectionToolbar/SelectionToolbarRoot.js.map +1 -0
  166. package/dist/primitives/selectionToolbar/index.d.ts +3 -0
  167. package/dist/primitives/selectionToolbar/index.d.ts.map +1 -0
  168. package/dist/primitives/selectionToolbar/index.js +3 -0
  169. package/dist/primitives/selectionToolbar/index.js.map +1 -0
  170. package/dist/primitives/suggestion/SuggestionDescription.js +1 -1
  171. package/dist/primitives/suggestion/SuggestionDescription.js.map +1 -1
  172. package/dist/primitives/suggestion/SuggestionTitle.js +1 -1
  173. package/dist/primitives/suggestion/SuggestionTitle.js.map +1 -1
  174. package/dist/primitives/suggestion/SuggestionTrigger.d.ts.map +1 -1
  175. package/dist/primitives/suggestion/SuggestionTrigger.js +6 -3
  176. package/dist/primitives/suggestion/SuggestionTrigger.js.map +1 -1
  177. package/dist/primitives/thread/ThreadEmpty.js +1 -1
  178. package/dist/primitives/thread/ThreadEmpty.js.map +1 -1
  179. package/dist/primitives/thread/ThreadIf.js +7 -7
  180. package/dist/primitives/thread/ThreadIf.js.map +1 -1
  181. package/dist/primitives/thread/ThreadMessages.js +3 -3
  182. package/dist/primitives/thread/ThreadMessages.js.map +1 -1
  183. package/dist/primitives/thread/ThreadSuggestion.d.ts.map +1 -1
  184. package/dist/primitives/thread/ThreadSuggestion.js +5 -2
  185. package/dist/primitives/thread/ThreadSuggestion.js.map +1 -1
  186. package/dist/primitives/thread/ThreadSuggestions.js +1 -1
  187. package/dist/primitives/thread/ThreadSuggestions.js.map +1 -1
  188. package/dist/primitives/thread/ThreadViewportSlack.js +4 -4
  189. package/dist/primitives/thread/ThreadViewportSlack.js.map +1 -1
  190. package/dist/primitives/threadList/ThreadListItems.js +1 -1
  191. package/dist/primitives/threadList/ThreadListItems.js.map +1 -1
  192. package/dist/primitives/threadList/ThreadListNew.js +1 -1
  193. package/dist/primitives/threadList/ThreadListNew.js.map +1 -1
  194. package/dist/primitives/threadListItem/ThreadListItemRoot.js +1 -1
  195. package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
  196. package/dist/primitives/threadListItem/ThreadListItemTitle.js +1 -1
  197. package/dist/primitives/threadListItem/ThreadListItemTitle.js.map +1 -1
  198. package/dist/types/QuoteTypes.d.ts +5 -0
  199. package/dist/types/QuoteTypes.d.ts.map +1 -0
  200. package/dist/types/QuoteTypes.js +2 -0
  201. package/dist/types/QuoteTypes.js.map +1 -0
  202. package/dist/types/index.d.ts +1 -0
  203. package/dist/types/index.d.ts.map +1 -1
  204. package/dist/types/scopes/composer.d.ts +10 -0
  205. package/dist/types/scopes/composer.d.ts.map +1 -1
  206. package/dist/utils/getSelectionMessageId.d.ts +2 -0
  207. package/dist/utils/getSelectionMessageId.d.ts.map +1 -0
  208. package/dist/utils/getSelectionMessageId.js +21 -0
  209. package/dist/utils/getSelectionMessageId.js.map +1 -0
  210. package/dist/utils/smooth/useSmooth.js +1 -1
  211. package/dist/utils/smooth/useSmooth.js.map +1 -1
  212. package/dist/utils/useToolArgsFieldStatus.js +5 -5
  213. package/dist/utils/useToolArgsFieldStatus.js.map +1 -1
  214. package/package.json +2 -2
  215. package/src/client/ExternalThread.ts +12 -0
  216. package/src/client/NoOpComposerClient.tsx +4 -0
  217. package/src/context/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
  218. package/src/context/react/utils/ensureBinding.ts +1 -1
  219. package/src/hooks/useMessageQuote.ts +27 -0
  220. package/src/legacy-runtime/AssistantRuntimeProvider.tsx +1 -4
  221. package/src/legacy-runtime/client/ComposerRuntimeClient.ts +2 -0
  222. package/src/legacy-runtime/hooks/AssistantContext.ts +1 -1
  223. package/src/legacy-runtime/hooks/AttachmentContext.ts +1 -1
  224. package/src/legacy-runtime/hooks/ComposerContext.ts +6 -6
  225. package/src/legacy-runtime/hooks/MessageContext.ts +5 -5
  226. package/src/legacy-runtime/hooks/MessagePartContext.ts +1 -1
  227. package/src/legacy-runtime/hooks/ThreadContext.ts +5 -5
  228. package/src/legacy-runtime/hooks/ThreadListItemContext.ts +1 -1
  229. package/src/legacy-runtime/runtime/ComposerRuntime.ts +22 -0
  230. package/src/legacy-runtime/runtime-cores/assistant-transport/types.ts +5 -0
  231. package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx +41 -31
  232. package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +8 -8
  233. package/src/legacy-runtime/runtime-cores/composer/BaseComposerRuntimeCore.tsx +21 -2
  234. package/src/legacy-runtime/runtime-cores/core/ComposerRuntimeCore.tsx +4 -0
  235. package/src/legacy-runtime/runtime-cores/external-store/createMessageConverter.tsx +2 -2
  236. package/src/legacy-runtime/runtime-cores/local/useLocalRuntime.tsx +1 -3
  237. package/src/legacy-runtime/runtime-cores/remote-thread-list/EMPTY_THREAD_CORE.tsx +6 -0
  238. package/src/primitives/actionBar/ActionBarCopy.tsx +7 -6
  239. package/src/primitives/actionBar/ActionBarEdit.tsx +1 -1
  240. package/src/primitives/actionBar/ActionBarExportMarkdown.tsx +4 -3
  241. package/src/primitives/actionBar/ActionBarSpeak.tsx +4 -3
  242. package/src/primitives/actionBar/ActionBarStopSpeaking.tsx +1 -1
  243. package/src/primitives/actionBar/useActionBarFloatStatus.tsx +5 -5
  244. package/src/primitives/attachment/AttachmentName.tsx +1 -1
  245. package/src/primitives/attachment/AttachmentThumb.tsx +2 -2
  246. package/src/primitives/branchPicker/BranchPickerCount.tsx +1 -1
  247. package/src/primitives/branchPicker/BranchPickerNext.tsx +3 -3
  248. package/src/primitives/branchPicker/BranchPickerNumber.tsx +1 -1
  249. package/src/primitives/branchPicker/BranchPickerPrevious.tsx +3 -3
  250. package/src/primitives/chainOfThought/ChainOfThoughtAccordionTrigger.tsx +1 -3
  251. package/src/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -3
  252. package/src/primitives/composer/ComposerAddAttachment.tsx +1 -1
  253. package/src/primitives/composer/ComposerAttachments.tsx +1 -1
  254. package/src/primitives/composer/ComposerCancel.tsx +1 -1
  255. package/src/primitives/composer/ComposerDictate.tsx +4 -4
  256. package/src/primitives/composer/ComposerDictationTranscript.tsx +1 -3
  257. package/src/primitives/composer/ComposerIf.tsx +4 -4
  258. package/src/primitives/composer/ComposerInput.tsx +57 -17
  259. package/src/primitives/composer/ComposerQuote.tsx +109 -0
  260. package/src/primitives/composer/ComposerStopDictation.tsx +1 -1
  261. package/src/primitives/composer/index.ts +3 -0
  262. package/src/primitives/error/ErrorMessage.tsx +4 -4
  263. package/src/primitives/index.ts +2 -0
  264. package/src/primitives/message/MessageAttachments.tsx +4 -4
  265. package/src/primitives/message/MessageError.tsx +3 -3
  266. package/src/primitives/message/MessageIf.tsx +3 -3
  267. package/src/primitives/message/MessageParts.tsx +7 -7
  268. package/src/primitives/message/MessagePartsGrouped.tsx +5 -5
  269. package/src/primitives/message/MessageRoot.tsx +6 -5
  270. package/src/primitives/messagePart/MessagePartInProgress.tsx +1 -3
  271. package/src/primitives/messagePart/useMessagePartData.tsx +3 -3
  272. package/src/primitives/messagePart/useMessagePartFile.tsx +3 -3
  273. package/src/primitives/messagePart/useMessagePartImage.tsx +3 -3
  274. package/src/primitives/messagePart/useMessagePartReasoning.tsx +3 -3
  275. package/src/primitives/messagePart/useMessagePartSource.tsx +3 -3
  276. package/src/primitives/messagePart/useMessagePartText.tsx +4 -3
  277. package/src/primitives/selectionToolbar/SelectionToolbarQuote.tsx +62 -0
  278. package/src/primitives/selectionToolbar/SelectionToolbarRoot.tsx +131 -0
  279. package/src/primitives/selectionToolbar/index.ts +8 -0
  280. package/src/primitives/suggestion/SuggestionDescription.tsx +1 -1
  281. package/src/primitives/suggestion/SuggestionTitle.tsx +1 -1
  282. package/src/primitives/suggestion/SuggestionTrigger.tsx +6 -3
  283. package/src/primitives/thread/ThreadEmpty.tsx +1 -1
  284. package/src/primitives/thread/ThreadIf.tsx +8 -8
  285. package/src/primitives/thread/ThreadMessages.tsx +3 -3
  286. package/src/primitives/thread/ThreadSuggestion.tsx +5 -2
  287. package/src/primitives/thread/ThreadSuggestions.tsx +1 -1
  288. package/src/primitives/thread/ThreadViewportSlack.tsx +5 -5
  289. package/src/primitives/threadList/ThreadListItems.tsx +2 -2
  290. package/src/primitives/threadList/ThreadListNew.tsx +1 -1
  291. package/src/primitives/threadListItem/ThreadListItemRoot.tsx +1 -1
  292. package/src/primitives/threadListItem/ThreadListItemTitle.tsx +1 -1
  293. package/src/types/QuoteTypes.ts +4 -0
  294. package/src/types/index.ts +2 -0
  295. package/src/types/scopes/composer.ts +12 -0
  296. package/src/utils/getSelectionMessageId.ts +20 -0
  297. package/src/utils/smooth/useSmooth.tsx +1 -1
  298. package/src/utils/useToolArgsFieldStatus.tsx +5 -5
@@ -10,7 +10,7 @@ export namespace AttachmentPrimitiveName {
10
10
  export const AttachmentPrimitiveName: FC<
11
11
  AttachmentPrimitiveName.Props
12
12
  > = () => {
13
- const name = useAuiState(({ attachment }) => attachment.name);
13
+ const name = useAuiState((s) => s.attachment.name);
14
14
  return <>{name}</>;
15
15
  };
16
16
 
@@ -15,8 +15,8 @@ export const AttachmentPrimitiveThumb = forwardRef<
15
15
  AttachmentPrimitiveThumb.Element,
16
16
  AttachmentPrimitiveThumb.Props
17
17
  >((props, ref) => {
18
- const ext = useAuiState(({ attachment }) => {
19
- const parts = attachment.name.split(".");
18
+ const ext = useAuiState((s) => {
19
+ const parts = s.attachment.name.split(".");
20
20
  return parts.length > 1 ? parts.pop()! : "";
21
21
  });
22
22
  return (
@@ -4,7 +4,7 @@ import type { FC } from "react";
4
4
  import { useAuiState } from "@assistant-ui/store";
5
5
 
6
6
  const useBranchPickerCount = () => {
7
- const branchCount = useAuiState(({ message }) => message.branchCount);
7
+ const branchCount = useAuiState((s) => s.message.branchCount);
8
8
  return branchCount;
9
9
  };
10
10
 
@@ -10,12 +10,12 @@ import { useAuiState, useAui } from "@assistant-ui/store";
10
10
 
11
11
  const useBranchPickerNext = () => {
12
12
  const aui = useAui();
13
- const disabled = useAuiState(({ thread, message }) => {
13
+ const disabled = useAuiState((s) => {
14
14
  // Disabled if no next branch
15
- if (message.branchNumber >= message.branchCount) return true;
15
+ if (s.message.branchNumber >= s.message.branchCount) return true;
16
16
 
17
17
  // Disabled if running and capability not supported
18
- if (thread.isRunning && !thread.capabilities.switchBranchDuringRun) {
18
+ if (s.thread.isRunning && !s.thread.capabilities.switchBranchDuringRun) {
19
19
  return true;
20
20
  }
21
21
 
@@ -4,7 +4,7 @@ import type { FC } from "react";
4
4
  import { useAuiState } from "@assistant-ui/store";
5
5
 
6
6
  const useBranchPickerNumber = () => {
7
- const branchNumber = useAuiState(({ message }) => message.branchNumber);
7
+ const branchNumber = useAuiState((s) => s.message.branchNumber);
8
8
  return branchNumber;
9
9
  };
10
10
 
@@ -31,12 +31,12 @@ import { useAuiState, useAui } from "@assistant-ui/store";
31
31
  */
32
32
  const useBranchPickerPrevious = () => {
33
33
  const aui = useAui();
34
- const disabled = useAuiState(({ thread, message }) => {
34
+ const disabled = useAuiState((s) => {
35
35
  // Disabled if no previous branch
36
- if (message.branchNumber <= 1) return true;
36
+ if (s.message.branchNumber <= 1) return true;
37
37
 
38
38
  // Disabled if running and capability not supported
39
- if (thread.isRunning && !thread.capabilities.switchBranchDuringRun) {
39
+ if (s.thread.isRunning && !s.thread.capabilities.switchBranchDuringRun) {
40
40
  return true;
41
41
  }
42
42
 
@@ -10,9 +10,7 @@ import { useAuiState, useAui } from "@assistant-ui/store";
10
10
 
11
11
  const useChainOfThoughtAccordionTrigger = () => {
12
12
  const aui = useAui();
13
- const collapsed = useAuiState(
14
- ({ chainOfThought }) => chainOfThought.collapsed,
15
- );
13
+ const collapsed = useAuiState((s) => s.chainOfThought.collapsed);
16
14
 
17
15
  const callback = useCallback(() => {
18
16
  aui.chainOfThought().setCollapsed(!collapsed);
@@ -53,9 +53,7 @@ export namespace ChainOfThoughtPrimitiveParts {
53
53
  export const ChainOfThoughtPrimitiveParts: FC<
54
54
  ChainOfThoughtPrimitiveParts.Props
55
55
  > = ({ components }) => {
56
- const partsLength = useAuiState(
57
- ({ chainOfThought }) => chainOfThought.parts.length,
58
- );
56
+ const partsLength = useAuiState((s) => s.chainOfThought.parts.length);
59
57
 
60
58
  const messageComponents = useMemo(
61
59
  () => ({
@@ -14,7 +14,7 @@ const useComposerAddAttachment = ({
14
14
  /** allow selecting multiple files */
15
15
  multiple?: boolean | undefined;
16
16
  } = {}) => {
17
- const disabled = useAuiState(({ composer }) => !composer.isEditing);
17
+ const disabled = useAuiState((s) => !s.composer.isEditing);
18
18
  const aui = useAui();
19
19
 
20
20
  const callback = useCallback(() => {
@@ -39,7 +39,7 @@ const getComponent = (
39
39
  const AttachmentComponent: FC<{
40
40
  components: ComposerPrimitiveAttachments.Props["components"];
41
41
  }> = ({ components }) => {
42
- const attachment = useAuiState(({ attachment }) => attachment);
42
+ const attachment = useAuiState((s) => s.attachment);
43
43
  if (!attachment) return null;
44
44
 
45
45
  const Component = getComponent(components, attachment);
@@ -10,7 +10,7 @@ import { useAuiState, useAui } from "@assistant-ui/store";
10
10
 
11
11
  const useComposerCancel = () => {
12
12
  const aui = useAui();
13
- const disabled = useAuiState(({ composer }) => !composer.canCancel);
13
+ const disabled = useAuiState((s) => !s.composer.canCancel);
14
14
 
15
15
  const callback = useCallback(() => {
16
16
  aui.composer().cancel();
@@ -11,10 +11,10 @@ import { createActionButton } from "../../utils/createActionButton";
11
11
  const useComposerDictate = () => {
12
12
  const aui = useAui();
13
13
  const disabled = useAuiState(
14
- ({ thread, composer }) =>
15
- composer.dictation != null ||
16
- !thread.capabilities.dictation ||
17
- !composer.isEditing,
14
+ (s) =>
15
+ s.composer.dictation != null ||
16
+ !s.thread.capabilities.dictation ||
17
+ !s.composer.isEditing,
18
18
  );
19
19
 
20
20
  const callback = useCallback(() => {
@@ -28,9 +28,7 @@ export const ComposerPrimitiveDictationTranscript = forwardRef<
28
28
  ComposerPrimitiveDictationTranscript.Element,
29
29
  ComposerPrimitiveDictationTranscript.Props
30
30
  >(({ children, ...props }, forwardRef) => {
31
- const transcript = useAuiState(
32
- ({ composer }) => composer.dictation?.transcript,
33
- );
31
+ const transcript = useAuiState((s) => s.composer.dictation?.transcript);
34
32
 
35
33
  if (!transcript) return null;
36
34
 
@@ -14,11 +14,11 @@ type ComposerIfFilters = {
14
14
  export type UseComposerIfProps = RequireAtLeastOne<ComposerIfFilters>;
15
15
 
16
16
  const useComposerIf = (props: UseComposerIfProps) => {
17
- return useAuiState(({ composer }) => {
18
- if (props.editing === true && !composer.isEditing) return false;
19
- if (props.editing === false && composer.isEditing) return false;
17
+ return useAuiState((s) => {
18
+ if (props.editing === true && !s.composer.isEditing) return false;
19
+ if (props.editing === false && s.composer.isEditing) return false;
20
20
 
21
- const isDictating = composer.dictation != null;
21
+ const isDictating = s.composer.dictation != null;
22
22
  if (props.dictation === true && !isDictating) return false;
23
23
  if (props.dictation === false && isDictating) return false;
24
24
 
@@ -21,17 +21,13 @@ import { flushResourcesSync } from "@assistant-ui/tap";
21
21
 
22
22
  export namespace ComposerPrimitiveInput {
23
23
  export type Element = HTMLTextAreaElement;
24
- export type Props = TextareaAutosizeProps & {
24
+
25
+ type BaseProps = {
25
26
  /**
26
27
  * Whether to render as a child component using Slot.
27
28
  * When true, the component will merge its props with its child.
28
29
  */
29
30
  asChild?: boolean | undefined;
30
- /**
31
- * Whether to submit the message when Enter is pressed (without Shift).
32
- * @default true
33
- */
34
- submitOnEnter?: boolean | undefined;
35
31
  /**
36
32
  * Whether to cancel message composition when Escape is pressed.
37
33
  * @default true
@@ -58,6 +54,34 @@ export namespace ComposerPrimitiveInput {
58
54
  */
59
55
  addAttachmentOnPaste?: boolean | undefined;
60
56
  };
57
+
58
+ type SubmitModeProps =
59
+ | {
60
+ /**
61
+ * Controls how the Enter key submits messages.
62
+ * - "enter": Plain Enter submits (Shift+Enter for newline)
63
+ * - "ctrlEnter": Ctrl/Cmd+Enter submits (plain Enter for newline)
64
+ * - "none": Keyboard submission disabled
65
+ * @default "enter"
66
+ */
67
+ submitMode?: "enter" | "ctrlEnter" | "none" | undefined;
68
+ /**
69
+ * @deprecated Use `submitMode` instead
70
+ * @ignore
71
+ */
72
+ submitOnEnter?: never;
73
+ }
74
+ | {
75
+ submitMode?: never;
76
+ /**
77
+ * Whether to submit the message when Enter is pressed (without Shift).
78
+ * @default true
79
+ * @deprecated Use `submitMode` instead. Will be removed in a future version.
80
+ */
81
+ submitOnEnter?: boolean | undefined;
82
+ };
83
+
84
+ export type Props = TextareaAutosizeProps & BaseProps & SubmitModeProps;
61
85
  }
62
86
 
63
87
  /**
@@ -69,10 +93,16 @@ export namespace ComposerPrimitiveInput {
69
93
  *
70
94
  * @example
71
95
  * ```tsx
96
+ * // Ctrl/Cmd+Enter to submit (plain Enter inserts newline)
97
+ * <ComposerPrimitive.Input
98
+ * placeholder="Type your message..."
99
+ * submitMode="ctrlEnter"
100
+ * />
101
+ *
102
+ * // Old API (deprecated, still supported)
72
103
  * <ComposerPrimitive.Input
73
104
  * placeholder="Type your message..."
74
105
  * submitOnEnter={true}
75
- * addAttachmentOnPaste={true}
76
106
  * />
77
107
  * ```
78
108
  */
@@ -88,7 +118,8 @@ export const ComposerPrimitiveInput = forwardRef<
88
118
  onChange,
89
119
  onKeyDown,
90
120
  onPaste,
91
- submitOnEnter = true,
121
+ submitOnEnter,
122
+ submitMode,
92
123
  cancelOnEscape = true,
93
124
  unstable_focusOnRunStart = true,
94
125
  unstable_focusOnScrollToBottom = true,
@@ -100,17 +131,19 @@ export const ComposerPrimitiveInput = forwardRef<
100
131
  ) => {
101
132
  const aui = useAui();
102
133
 
103
- const value = useAuiState(({ composer }) => {
104
- if (!composer.isEditing) return "";
105
- return composer.text;
134
+ const effectiveSubmitMode =
135
+ submitMode ?? (submitOnEnter === false ? "none" : "enter");
136
+
137
+ const value = useAuiState((s) => {
138
+ if (!s.composer.isEditing) return "";
139
+ return s.composer.text;
106
140
  });
107
141
 
108
142
  const Component = asChild ? Slot : TextareaAutosize;
109
143
 
110
144
  const isDisabled =
111
145
  useAuiState(
112
- ({ thread, composer }) =>
113
- thread.isDisabled || composer.dictation?.inputDisabled,
146
+ (s) => s.thread.isDisabled || s.composer.dictation?.inputDisabled,
114
147
  ) || disabledProp;
115
148
  const textareaRef = useRef<HTMLTextAreaElement>(null);
116
149
  const ref = useComposedRefs(forwardedRef, textareaRef);
@@ -129,17 +162,24 @@ export const ComposerPrimitiveInput = forwardRef<
129
162
  });
130
163
 
131
164
  const handleKeyPress = (e: KeyboardEvent) => {
132
- if (isDisabled || !submitOnEnter) return;
165
+ if (isDisabled) return;
133
166
 
134
167
  // ignore IME composition events
135
168
  if (e.nativeEvent.isComposing) return;
136
169
 
137
- if (e.key === "Enter" && e.shiftKey === false) {
170
+ if (e.key === "Enter" && !e.shiftKey) {
138
171
  const isRunning = aui.thread().getState().isRunning;
172
+ if (isRunning) return;
139
173
 
140
- if (!isRunning) {
141
- e.preventDefault();
174
+ let shouldSubmit = false;
175
+ if (effectiveSubmitMode === "ctrlEnter") {
176
+ shouldSubmit = e.ctrlKey || e.metaKey;
177
+ } else if (effectiveSubmitMode === "enter") {
178
+ shouldSubmit = true;
179
+ }
142
180
 
181
+ if (shouldSubmit) {
182
+ e.preventDefault();
143
183
  textareaRef.current?.closest("form")?.requestSubmit();
144
184
  }
145
185
  }
@@ -0,0 +1,109 @@
1
+ "use client";
2
+
3
+ import { Primitive } from "@radix-ui/react-primitive";
4
+ import {
5
+ type ComponentRef,
6
+ type ComponentPropsWithoutRef,
7
+ forwardRef,
8
+ useCallback,
9
+ } from "react";
10
+ import { useAui, useAuiState } from "@assistant-ui/store";
11
+ import { composeEventHandlers } from "@radix-ui/primitive";
12
+
13
+ // ---- Root ----
14
+
15
+ export namespace ComposerPrimitiveQuote {
16
+ export type Element = ComponentRef<typeof Primitive.div>;
17
+ export type Props = ComponentPropsWithoutRef<typeof Primitive.div>;
18
+ }
19
+
20
+ /**
21
+ * Renders a container for the quoted text preview in the composer.
22
+ * Only renders when a quote is set.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <ComposerPrimitive.Quote>
27
+ * <ComposerPrimitive.QuoteText />
28
+ * <ComposerPrimitive.QuoteDismiss>×</ComposerPrimitive.QuoteDismiss>
29
+ * </ComposerPrimitive.Quote>
30
+ * ```
31
+ */
32
+ export const ComposerPrimitiveQuote = forwardRef<
33
+ ComposerPrimitiveQuote.Element,
34
+ ComposerPrimitiveQuote.Props
35
+ >((props, forwardedRef) => {
36
+ const quote = useAuiState((s) => s.composer.quote);
37
+ if (!quote) return null;
38
+
39
+ return <Primitive.div {...props} ref={forwardedRef} />;
40
+ });
41
+
42
+ ComposerPrimitiveQuote.displayName = "ComposerPrimitive.Quote";
43
+
44
+ // ---- QuoteText ----
45
+
46
+ export namespace ComposerPrimitiveQuoteText {
47
+ export type Element = ComponentRef<typeof Primitive.span>;
48
+ export type Props = ComponentPropsWithoutRef<typeof Primitive.span>;
49
+ }
50
+
51
+ /**
52
+ * Renders the quoted text content.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * <ComposerPrimitive.QuoteText />
57
+ * ```
58
+ */
59
+ export const ComposerPrimitiveQuoteText = forwardRef<
60
+ ComposerPrimitiveQuoteText.Element,
61
+ ComposerPrimitiveQuoteText.Props
62
+ >(({ children, ...props }, forwardedRef) => {
63
+ const text = useAuiState((s) => s.composer.quote?.text);
64
+ if (!text) return null;
65
+
66
+ return (
67
+ <Primitive.span {...props} ref={forwardedRef}>
68
+ {children ?? text}
69
+ </Primitive.span>
70
+ );
71
+ });
72
+
73
+ ComposerPrimitiveQuoteText.displayName = "ComposerPrimitive.QuoteText";
74
+
75
+ // ---- QuoteDismiss ----
76
+
77
+ export namespace ComposerPrimitiveQuoteDismiss {
78
+ export type Element = ComponentRef<typeof Primitive.button>;
79
+ export type Props = ComponentPropsWithoutRef<typeof Primitive.button>;
80
+ }
81
+
82
+ /**
83
+ * A button that clears the current quote from the composer.
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <ComposerPrimitive.QuoteDismiss>×</ComposerPrimitive.QuoteDismiss>
88
+ * ```
89
+ */
90
+ export const ComposerPrimitiveQuoteDismiss = forwardRef<
91
+ ComposerPrimitiveQuoteDismiss.Element,
92
+ ComposerPrimitiveQuoteDismiss.Props
93
+ >(({ onClick, ...props }, forwardedRef) => {
94
+ const aui = useAui();
95
+ const handleDismiss = useCallback(() => {
96
+ aui.composer().setQuote(undefined);
97
+ }, [aui]);
98
+
99
+ return (
100
+ <Primitive.button
101
+ type="button"
102
+ {...props}
103
+ ref={forwardedRef}
104
+ onClick={composeEventHandlers(onClick, handleDismiss)}
105
+ />
106
+ );
107
+ });
108
+
109
+ ComposerPrimitiveQuoteDismiss.displayName = "ComposerPrimitive.QuoteDismiss";
@@ -11,7 +11,7 @@ import { useAuiState } from "@assistant-ui/store";
11
11
 
12
12
  const useComposerStopDictation = () => {
13
13
  const aui = useAui();
14
- const isDictating = useAuiState(({ composer }) => composer.dictation != null);
14
+ const isDictating = useAuiState((s) => s.composer.dictation != null);
15
15
 
16
16
  const callback = useCallback(() => {
17
17
  aui.composer().stopDictation();
@@ -10,3 +10,6 @@ export { ComposerPrimitiveDictate as Dictate } from "./ComposerDictate";
10
10
  export { ComposerPrimitiveStopDictation as StopDictation } from "./ComposerStopDictation";
11
11
  export { ComposerPrimitiveDictationTranscript as DictationTranscript } from "./ComposerDictationTranscript";
12
12
  export { ComposerPrimitiveIf as If } from "./ComposerIf";
13
+ export { ComposerPrimitiveQuote as Quote } from "./ComposerQuote";
14
+ export { ComposerPrimitiveQuoteText as QuoteText } from "./ComposerQuote";
15
+ export { ComposerPrimitiveQuoteDismiss as QuoteDismiss } from "./ComposerQuote";
@@ -13,10 +13,10 @@ export const ErrorPrimitiveMessage = forwardRef<
13
13
  ErrorPrimitiveMessage.Element,
14
14
  ErrorPrimitiveMessage.Props
15
15
  >(({ children, ...props }, forwardRef) => {
16
- const error = useAuiState(({ message }) => {
17
- return message.status?.type === "incomplete" &&
18
- message.status.reason === "error"
19
- ? message.status.error
16
+ const error = useAuiState((s) => {
17
+ return s.message.status?.type === "incomplete" &&
18
+ s.message.status.reason === "error"
19
+ ? s.message.status.error
20
20
  : undefined;
21
21
  });
22
22
 
@@ -13,6 +13,7 @@ export * as SuggestionPrimitive from "./suggestion";
13
13
  export * as ThreadListPrimitive from "./threadList";
14
14
  export * as ThreadListItemPrimitive from "./threadListItem";
15
15
  export * as ThreadListItemMorePrimitive from "./threadListItemMore";
16
+ export * as SelectionToolbarPrimitive from "./selectionToolbar";
16
17
 
17
18
  export { useMessagePartText } from "./messagePart/useMessagePartText";
18
19
  export { useMessagePartReasoning } from "./messagePart/useMessagePartReasoning";
@@ -22,3 +23,4 @@ export { useMessagePartImage } from "./messagePart/useMessagePartImage";
22
23
  export { useMessagePartData } from "./messagePart/useMessagePartData";
23
24
  export { useThreadViewportAutoScroll } from "./thread/useThreadViewportAutoScroll";
24
25
  export { useScrollLock } from "./reasoning";
26
+ export { useMessageQuote } from "../hooks/useMessageQuote";
@@ -39,7 +39,7 @@ const getComponent = (
39
39
  const AttachmentComponent: FC<{
40
40
  components: MessagePrimitiveAttachments.Props["components"];
41
41
  }> = ({ components }) => {
42
- const attachment = useAuiState(({ attachment }) => attachment);
42
+ const attachment = useAuiState((s) => s.attachment);
43
43
  if (!attachment) return null;
44
44
 
45
45
  const Component = getComponent(components, attachment as CompleteAttachment);
@@ -94,9 +94,9 @@ MessagePrimitiveAttachmentByIndex.displayName =
94
94
  export const MessagePrimitiveAttachments: FC<
95
95
  MessagePrimitiveAttachments.Props
96
96
  > = ({ components }) => {
97
- const attachmentsCount = useAuiState(({ message }) => {
98
- if (message.role !== "user") return 0;
99
- return message.attachments.length;
97
+ const attachmentsCount = useAuiState((s) => {
98
+ if (s.message.role !== "user") return 0;
99
+ return s.message.attachments.length;
100
100
  });
101
101
 
102
102
  const attachmentElements = useMemo(() => {
@@ -5,9 +5,9 @@ import { useAuiState } from "@assistant-ui/store";
5
5
 
6
6
  export const MessagePrimitiveError: FC<PropsWithChildren> = ({ children }) => {
7
7
  const hasError = useAuiState(
8
- ({ message }) =>
9
- message.status?.type === "incomplete" &&
10
- message.status.reason === "error",
8
+ (s) =>
9
+ s.message.status?.type === "incomplete" &&
10
+ s.message.status.reason === "error",
11
11
  );
12
12
  return hasError ? children : null;
13
13
  };
@@ -20,7 +20,7 @@ type MessageIfFilters = {
20
20
  type UseMessageIfProps = RequireAtLeastOne<MessageIfFilters>;
21
21
 
22
22
  const useMessageIf = (props: UseMessageIfProps) => {
23
- return useAuiState(({ message }) => {
23
+ return useAuiState((s) => {
24
24
  const {
25
25
  role,
26
26
  attachments,
@@ -30,7 +30,7 @@ const useMessageIf = (props: UseMessageIfProps) => {
30
30
  speech,
31
31
  isCopied,
32
32
  isHovering,
33
- } = message;
33
+ } = s.message;
34
34
 
35
35
  if (props.hasBranches === true && branchCount < 2) return false;
36
36
 
@@ -64,7 +64,7 @@ const useMessageIf = (props: UseMessageIfProps) => {
64
64
 
65
65
  if (
66
66
  props.submittedFeedback !== undefined &&
67
- (message.metadata.submittedFeedback?.type ?? null) !==
67
+ (s.message.metadata.submittedFeedback?.type ?? null) !==
68
68
  props.submittedFeedback
69
69
  )
70
70
  return false;
@@ -321,8 +321,8 @@ const ToolUIDisplay = ({
321
321
  }: {
322
322
  Fallback: ToolCallMessagePartComponent | undefined;
323
323
  } & ToolCallMessagePartProps) => {
324
- const Render = useAuiState(({ tools }) => {
325
- const Render = tools.tools[props.toolName] ?? Fallback;
324
+ const Render = useAuiState((s) => {
325
+ const Render = s.tools.tools[props.toolName] ?? Fallback;
326
326
  if (Array.isArray(Render)) return Render[0] ?? Fallback;
327
327
  return Render;
328
328
  });
@@ -364,7 +364,7 @@ export const MessagePartComponent: FC<MessagePartComponentProps> = ({
364
364
  } = {},
365
365
  }) => {
366
366
  const aui = useAui();
367
- const part = useAuiState(({ part }) => part);
367
+ const part = useAuiState((s) => s.part);
368
368
 
369
369
  const type = part.type;
370
370
  if (type === "tool-call") {
@@ -503,11 +503,11 @@ const ConditionalEmptyImpl: FC<{
503
503
  components: MessagePrimitiveParts.Props["components"];
504
504
  enabled: boolean;
505
505
  }> = ({ components, enabled }) => {
506
- const shouldShowEmpty = useAuiState(({ message }) => {
506
+ const shouldShowEmpty = useAuiState((s) => {
507
507
  if (!enabled) return false;
508
- if (message.parts.length === 0) return false;
508
+ if (s.message.parts.length === 0) return false;
509
509
 
510
- const lastPart = message.parts[message.parts.length - 1];
510
+ const lastPart = s.message.parts[s.message.parts.length - 1];
511
511
  return lastPart?.type !== "text" && lastPart?.type !== "reasoning";
512
512
  });
513
513
 
@@ -551,7 +551,7 @@ export const MessagePrimitiveParts: FC<MessagePrimitiveParts.Props> = ({
551
551
  components,
552
552
  unstable_showEmptyOnNonTextEnd = true,
553
553
  }) => {
554
- const contentLength = useAuiState(({ message }) => message.parts.length);
554
+ const contentLength = useAuiState((s) => s.message.parts.length);
555
555
  const useChainOfThought = !!components?.ChainOfThought;
556
556
  const messageRanges = useMessagePartsGroups(useChainOfThought);
557
557
 
@@ -74,7 +74,7 @@ const groupMessagePartsByParentId: GroupingFunction = (
74
74
  const useMessagePartsGrouped = (
75
75
  groupingFunction: GroupingFunction,
76
76
  ): MessagePartGroup[] => {
77
- const parts = useAuiState(({ message }) => message.parts);
77
+ const parts = useAuiState((s) => s.message.parts);
78
78
 
79
79
  return useMemo(() => {
80
80
  if (parts.length === 0) {
@@ -219,8 +219,8 @@ const ToolUIDisplay = ({
219
219
  }: {
220
220
  Fallback: ToolCallMessagePartComponent | undefined;
221
221
  } & ToolCallMessagePartProps) => {
222
- const Render = useAuiState(({ tools }) => {
223
- const Render = tools.tools[props.toolName] ?? Fallback;
222
+ const Render = useAuiState((s) => {
223
+ const Render = s.tools.tools[props.toolName] ?? Fallback;
224
224
  if (Array.isArray(Render)) return Render[0] ?? Fallback;
225
225
  return Render;
226
226
  });
@@ -261,7 +261,7 @@ const MessagePartComponent: FC<MessagePartComponentProps> = ({
261
261
  } = {},
262
262
  }) => {
263
263
  const aui = useAui();
264
- const part = useAuiState(({ part }) => part);
264
+ const part = useAuiState((s) => s.part);
265
265
 
266
266
  const type = part.type;
267
267
  if (type === "tool-call") {
@@ -426,7 +426,7 @@ const EmptyParts = memo(
426
426
  export const MessagePrimitiveUnstable_PartsGrouped: FC<
427
427
  MessagePrimitiveUnstable_PartsGrouped.Props
428
428
  > = ({ groupingFunction, components }) => {
429
- const contentLength = useAuiState(({ message }) => message.parts.length);
429
+ const contentLength = useAuiState((s) => s.message.parts.length);
430
430
  const messageGroups = useMessagePartsGrouped(groupingFunction);
431
431
 
432
432
  const partsElements = useMemo(() => {
@@ -60,11 +60,11 @@ const useMessageViewportRef = () => {
60
60
  // inset rules:
61
61
  // - the previous user message before the last assistant message registers its full height
62
62
  const shouldRegisterAsInset = useAuiState(
63
- ({ thread, message }) =>
63
+ (s) =>
64
64
  turnAnchor === "top" &&
65
- message.role === "user" &&
66
- message.index === thread.messages.length - 2 &&
67
- thread.messages.at(-1)?.role === "assistant",
65
+ s.message.role === "user" &&
66
+ s.message.index === s.thread.messages.length - 2 &&
67
+ s.thread.messages.at(-1)?.role === "assistant",
68
68
  );
69
69
 
70
70
  const getHeight = useCallback((el: HTMLElement) => el.offsetHeight, []);
@@ -116,10 +116,11 @@ export const MessagePrimitiveRoot = forwardRef<
116
116
  isHoveringRef,
117
117
  anchorUserMessageRef,
118
118
  );
119
+ const messageId = useAuiState((s) => s.message.id);
119
120
 
120
121
  return (
121
122
  <ThreadPrimitiveViewportSlack>
122
- <Primitive.div {...props} ref={ref} />
123
+ <Primitive.div {...props} ref={ref} data-message-id={messageId} />
123
124
  </ThreadPrimitiveViewportSlack>
124
125
  );
125
126
  });
@@ -11,9 +11,7 @@ export namespace MessagePartPrimitiveInProgress {
11
11
  export const MessagePartPrimitiveInProgress: FC<
12
12
  MessagePartPrimitiveInProgress.Props
13
13
  > = ({ children }) => {
14
- const isInProgress = useAuiState(
15
- ({ part }) => part.status.type === "running",
16
- );
14
+ const isInProgress = useAuiState((s) => s.part.status.type === "running");
17
15
 
18
16
  return isInProgress ? children : null;
19
17
  };