@assistant-ui/core 0.2.12 → 0.2.15

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 (445) hide show
  1. package/dist/adapters/attachment.js.map +1 -1
  2. package/dist/adapters/directive-formatter.js.map +1 -1
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +3 -1
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/adapters/voice.js.map +1 -1
  7. package/dist/index.d.ts +3 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal/duplicate-detection.js.map +1 -1
  10. package/dist/internal.d.ts +2 -1
  11. package/dist/internal.js +2 -1
  12. package/dist/model-context/frame/host.js.map +1 -1
  13. package/dist/model-context/frame/provider.js.map +1 -1
  14. package/dist/model-context/frame/types.js.map +1 -1
  15. package/dist/model-context/registry.js.map +1 -1
  16. package/dist/model-context/tool.js.map +1 -1
  17. package/dist/model-context/types.d.ts +1 -0
  18. package/dist/model-context/types.d.ts.map +1 -1
  19. package/dist/model-context/types.js.map +1 -1
  20. package/dist/react/AssistantProvider.js +7 -1
  21. package/dist/react/AssistantProvider.js.map +1 -1
  22. package/dist/react/AssistantRuntimeProvider.js +18 -6
  23. package/dist/react/AssistantRuntimeProvider.js.map +1 -1
  24. package/dist/react/RuntimeAdapter.d.ts +1 -1
  25. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  26. package/dist/react/RuntimeAdapter.js +35 -6
  27. package/dist/react/RuntimeAdapter.js.map +1 -1
  28. package/dist/react/adapters/LocalStorageThreadListAdapter.js +29 -7
  29. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  30. package/dist/react/adapters/TitleGenerationAdapter.js.map +1 -1
  31. package/dist/react/client/DataRenderers.d.ts +1 -8
  32. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  33. package/dist/react/client/DataRenderers.js +56 -36
  34. package/dist/react/client/DataRenderers.js.map +1 -1
  35. package/dist/react/client/Interactables.d.ts +1 -1
  36. package/dist/react/client/Interactables.d.ts.map +1 -1
  37. package/dist/react/client/Interactables.js +71 -70
  38. package/dist/react/client/Interactables.js.map +1 -1
  39. package/dist/react/client/Tools.d.ts +2 -13
  40. package/dist/react/client/Tools.d.ts.map +1 -1
  41. package/dist/react/client/Tools.js +121 -57
  42. package/dist/react/client/Tools.js.map +1 -1
  43. package/dist/react/client/interactable-model-context.js.map +1 -1
  44. package/dist/react/model-context/define-mcp-toolkit.js.map +1 -1
  45. package/dist/react/model-context/define-toolkit.js.map +1 -1
  46. package/dist/react/model-context/external-tool.js.map +1 -1
  47. package/dist/react/model-context/human-tool.js.map +1 -1
  48. package/dist/react/model-context/makeAssistantDataUI.js.map +1 -1
  49. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  50. package/dist/react/model-context/makeAssistantToolUI.js.map +1 -1
  51. package/dist/react/model-context/provider-tool.js.map +1 -1
  52. package/dist/react/model-context/stub-tool.js.map +1 -1
  53. package/dist/react/model-context/toolbox.js.map +1 -1
  54. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  55. package/dist/react/model-context/useAssistantDataUI.js +27 -8
  56. package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
  57. package/dist/react/model-context/useAssistantInstructions.js +33 -10
  58. package/dist/react/model-context/useAssistantInstructions.js.map +1 -1
  59. package/dist/react/model-context/useAssistantInteractable.js.map +1 -1
  60. package/dist/react/model-context/useAssistantTool.js +59 -17
  61. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  62. package/dist/react/model-context/useAssistantToolUI.js +30 -9
  63. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  64. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
  65. package/dist/react/model-context/useInlineRender.js +35 -8
  66. package/dist/react/model-context/useInlineRender.js.map +1 -1
  67. package/dist/react/model-context/useInteractableState.js +65 -19
  68. package/dist/react/model-context/useInteractableState.js.map +1 -1
  69. package/dist/react/model-context/useToolArgsStatus.js +42 -14
  70. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  71. package/dist/react/primitive-hooks/useActionBarCopy.js +59 -22
  72. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  73. package/dist/react/primitive-hooks/useActionBarEdit.js +25 -7
  74. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  75. package/dist/react/primitive-hooks/useActionBarFeedback.js +49 -13
  76. package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
  77. package/dist/react/primitive-hooks/useActionBarReload.js +25 -7
  78. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  79. package/dist/react/primitive-hooks/useActionBarSpeak.js +28 -9
  80. package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
  81. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +25 -7
  82. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
  83. package/dist/react/primitive-hooks/useBranchPickerNext.js +27 -11
  84. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  85. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +27 -11
  86. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  87. package/dist/react/primitive-hooks/useComposerAddAttachment.js +24 -8
  88. package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
  89. package/dist/react/primitive-hooks/useComposerCancel.js +25 -7
  90. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  91. package/dist/react/primitive-hooks/useComposerDictate.js +25 -7
  92. package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
  93. package/dist/react/primitive-hooks/useComposerSend.js +25 -7
  94. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  95. package/dist/react/primitive-hooks/useEditComposerCancel.js +18 -4
  96. package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
  97. package/dist/react/primitive-hooks/useEditComposerSend.js +25 -7
  98. package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
  99. package/dist/react/primitive-hooks/useMessageBranching.js +41 -9
  100. package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
  101. package/dist/react/primitive-hooks/useMessageError.js +4 -1
  102. package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
  103. package/dist/react/primitive-hooks/useMessageReload.js +25 -7
  104. package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
  105. package/dist/react/primitive-hooks/useSuggestionTrigger.js +31 -13
  106. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  107. package/dist/react/primitive-hooks/useThreadIsEmpty.js +4 -1
  108. package/dist/react/primitive-hooks/useThreadIsEmpty.js.map +1 -1
  109. package/dist/react/primitive-hooks/useThreadIsRunning.js +4 -1
  110. package/dist/react/primitive-hooks/useThreadIsRunning.js.map +1 -1
  111. package/dist/react/primitive-hooks/useThreadListItemArchive.js +18 -4
  112. package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
  113. package/dist/react/primitive-hooks/useThreadListItemDelete.js +18 -4
  114. package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
  115. package/dist/react/primitive-hooks/useThreadListItemTrigger.js +18 -4
  116. package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
  117. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +18 -4
  118. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
  119. package/dist/react/primitive-hooks/useThreadListLoadMore.js +25 -7
  120. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  121. package/dist/react/primitive-hooks/useThreadListNew.js +18 -4
  122. package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
  123. package/dist/react/primitive-hooks/useThreadMessages.js +4 -1
  124. package/dist/react/primitive-hooks/useThreadMessages.js.map +1 -1
  125. package/dist/react/primitive-hooks/useVoice.js +63 -13
  126. package/dist/react/primitive-hooks/useVoice.js.map +1 -1
  127. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +42 -7
  128. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  129. package/dist/react/primitives/composer/ComposerAttachments.js +67 -16
  130. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  131. package/dist/react/primitives/composer/ComposerIf.js +30 -9
  132. package/dist/react/primitives/composer/ComposerIf.js.map +1 -1
  133. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  134. package/dist/react/primitives/generativeUI/GenerativeUI.js +55 -13
  135. package/dist/react/primitives/generativeUI/GenerativeUI.js.map +1 -1
  136. package/dist/react/primitives/message/MessageAttachments.js +68 -16
  137. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  138. package/dist/react/primitives/message/MessageGroupedParts.d.ts +3 -2
  139. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  140. package/dist/react/primitives/message/MessageGroupedParts.js +6 -6
  141. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  142. package/dist/react/primitives/message/MessageParts.d.ts +28 -1
  143. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  144. package/dist/react/primitives/message/MessageParts.js +665 -163
  145. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  146. package/dist/react/primitives/message/MessageQuote.js +18 -2
  147. package/dist/react/primitives/message/MessageQuote.js.map +1 -1
  148. package/dist/react/primitives/messagePart/MessagePartInProgress.js +6 -2
  149. package/dist/react/primitives/messagePart/MessagePartInProgress.js.map +1 -1
  150. package/dist/react/primitives/part/PartMessages.js +46 -14
  151. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  152. package/dist/react/primitives/thread/ThreadMessages.js +67 -10
  153. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  154. package/dist/react/primitives/thread/ThreadSuggestions.js +50 -10
  155. package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
  156. package/dist/react/primitives/threadList/ThreadListItems.js +55 -14
  157. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  158. package/dist/react/primitives/threadListItem/ThreadListItemTitle.js +15 -2
  159. package/dist/react/primitives/threadListItem/ThreadListItemTitle.js.map +1 -1
  160. package/dist/react/providers/AttachmentByIndexProvider.js +57 -12
  161. package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
  162. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js +33 -11
  163. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
  164. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +29 -6
  165. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
  166. package/dist/react/providers/MessageByIndexProvider.js +49 -19
  167. package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
  168. package/dist/react/providers/PartByIndexProvider.js +29 -6
  169. package/dist/react/providers/PartByIndexProvider.js.map +1 -1
  170. package/dist/react/providers/QueueItemByIndexProvider.js +29 -6
  171. package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
  172. package/dist/react/providers/ReadonlyThreadProvider.js +83 -28
  173. package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
  174. package/dist/react/providers/SuggestionByIndexProvider.js +29 -6
  175. package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
  176. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  177. package/dist/react/providers/TextMessagePartProvider.js +75 -26
  178. package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
  179. package/dist/react/providers/ThreadListItemByIndexProvider.js +30 -6
  180. package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
  181. package/dist/react/providers/ThreadListItemRuntimeProvider.js +28 -5
  182. package/dist/react/providers/ThreadListItemRuntimeProvider.js.map +1 -1
  183. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -0
  184. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  185. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +19 -4
  186. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  187. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +2 -0
  188. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  189. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +1 -0
  190. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  191. package/dist/react/runtimes/RuntimeAdapterProvider.js +27 -10
  192. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  193. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  194. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +16 -1
  195. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  196. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  197. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  198. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  199. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +19 -17
  200. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  201. package/dist/react/runtimes/createMessageConverter.js.map +1 -1
  202. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  203. package/dist/react/runtimes/external-message-converter.js +67 -30
  204. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  205. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -10
  206. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  207. package/dist/react/runtimes/useExternalStoreSharedOptions.js +17 -12
  208. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  209. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  210. package/dist/react/runtimes/useRemoteThreadListRuntime.js +34 -6
  211. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  212. package/dist/react/types/MessagePartComponentTypes.d.ts +5 -6
  213. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  214. package/dist/react/utils/getMessageQuote.js.map +1 -1
  215. package/dist/react/utils/groupParts.d.ts +13 -1
  216. package/dist/react/utils/groupParts.d.ts.map +1 -1
  217. package/dist/react/utils/groupParts.js +17 -5
  218. package/dist/react/utils/groupParts.js.map +1 -1
  219. package/dist/runtime/api/assistant-runtime.js.map +1 -1
  220. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  221. package/dist/runtime/api/bindings.d.ts +1 -0
  222. package/dist/runtime/api/bindings.d.ts.map +1 -1
  223. package/dist/runtime/api/composer-runtime.js.map +1 -1
  224. package/dist/runtime/api/message-part-runtime.d.ts +3 -9
  225. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  226. package/dist/runtime/api/message-part-runtime.js +3 -6
  227. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  228. package/dist/runtime/api/message-runtime.d.ts +2 -0
  229. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  230. package/dist/runtime/api/message-runtime.js +5 -0
  231. package/dist/runtime/api/message-runtime.js.map +1 -1
  232. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  233. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  234. package/dist/runtime/api/thread-list-runtime.js +1 -0
  235. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  236. package/dist/runtime/api/thread-runtime.d.ts +3 -0
  237. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  238. package/dist/runtime/api/thread-runtime.js +4 -0
  239. package/dist/runtime/api/thread-runtime.js.map +1 -1
  240. package/dist/runtime/base/base-assistant-runtime-core.js.map +1 -1
  241. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  242. package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
  243. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  244. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  245. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  246. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  247. package/dist/runtime/branch/external-thread-branch-adapter.d.ts +30 -0
  248. package/dist/runtime/branch/external-thread-branch-adapter.d.ts.map +1 -0
  249. package/dist/runtime/branch/external-thread-branch-adapter.js +0 -0
  250. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
  251. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  252. package/dist/runtime/interfaces/thread-runtime-core.d.ts +4 -1
  253. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  254. package/dist/runtime/queue/message-queue.js.map +1 -1
  255. package/dist/runtime/utils/auto-status.js.map +1 -1
  256. package/dist/runtime/utils/external-store-message.js.map +1 -1
  257. package/dist/runtime/utils/message-repository.js.map +1 -1
  258. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +15 -0
  259. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -0
  260. package/dist/runtime/utils/resolveToolApprovalResponse.js +35 -0
  261. package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -0
  262. package/dist/runtime/utils/thread-message-like.d.ts +5 -1
  263. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  264. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  265. package/dist/runtimes/assistant-transport/utils.js.map +1 -1
  266. package/dist/runtimes/external-store/external-store-adapter.d.ts +1 -0
  267. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  268. package/dist/runtimes/external-store/external-store-runtime-core.js.map +1 -1
  269. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  270. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  271. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +1 -0
  272. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  273. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +13 -0
  274. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  275. package/dist/runtimes/external-store/thread-message-converter.js.map +1 -1
  276. package/dist/runtimes/local/local-runtime-core.js.map +1 -1
  277. package/dist/runtimes/local/local-runtime-options.d.ts +1 -1
  278. package/dist/runtimes/local/local-thread-list-runtime-core.js.map +1 -1
  279. package/dist/runtimes/local/local-thread-runtime-core.d.ts +9 -1
  280. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  281. package/dist/runtimes/local/local-thread-runtime-core.js +65 -5
  282. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  283. package/dist/runtimes/local/should-continue.js +4 -2
  284. package/dist/runtimes/local/should-continue.js.map +1 -1
  285. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +2 -0
  286. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  287. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +4 -0
  288. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  289. package/dist/runtimes/remote-thread-list/adapter/in-memory.js.map +1 -1
  290. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  291. package/dist/runtimes/remote-thread-list/empty-thread-core.js +4 -0
  292. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  293. package/dist/runtimes/remote-thread-list/optimistic-state.js.map +1 -1
  294. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +1 -0
  295. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  296. package/dist/runtimes/remote-thread-list/remote-thread-state.js +1 -0
  297. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  298. package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
  299. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  300. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  301. package/dist/store/clients/chain-of-thought-client.d.ts +2 -7
  302. package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
  303. package/dist/store/clients/chain-of-thought-client.js +39 -20
  304. package/dist/store/clients/chain-of-thought-client.js.map +1 -1
  305. package/dist/store/clients/model-context-client.d.ts +1 -1
  306. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  307. package/dist/store/clients/model-context-client.js +67 -16
  308. package/dist/store/clients/model-context-client.js.map +1 -1
  309. package/dist/store/clients/no-op-composer-client.d.ts +2 -4
  310. package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
  311. package/dist/store/clients/no-op-composer-client.js +96 -54
  312. package/dist/store/clients/no-op-composer-client.js.map +1 -1
  313. package/dist/store/clients/runtime-adapter.d.ts +1 -3
  314. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  315. package/dist/store/clients/runtime-adapter.js +2 -15
  316. package/dist/store/clients/runtime-adapter.js.map +1 -1
  317. package/dist/store/clients/suggestions.d.ts +1 -4
  318. package/dist/store/clients/suggestions.d.ts.map +1 -1
  319. package/dist/store/clients/suggestions.js +63 -23
  320. package/dist/store/clients/suggestions.js.map +1 -1
  321. package/dist/store/clients/thread-message-client.d.ts +1 -1
  322. package/dist/store/clients/thread-message-client.d.ts.map +1 -1
  323. package/dist/store/clients/thread-message-client.js +184 -73
  324. package/dist/store/clients/thread-message-client.js.map +1 -1
  325. package/dist/store/internal.d.ts +2 -2
  326. package/dist/store/internal.js +2 -2
  327. package/dist/store/runtime-clients/attachment-runtime-client.d.ts +2 -4
  328. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  329. package/dist/store/runtime-clients/attachment-runtime-client.js +31 -7
  330. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  331. package/dist/store/runtime-clients/composer-runtime-client.d.ts +2 -10
  332. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  333. package/dist/store/runtime-clients/composer-runtime-client.js +195 -72
  334. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  335. package/dist/store/runtime-clients/liveRef.d.ts +7 -0
  336. package/dist/store/runtime-clients/liveRef.d.ts.map +1 -0
  337. package/dist/store/runtime-clients/liveRef.js +8 -0
  338. package/dist/store/runtime-clients/liveRef.js.map +1 -0
  339. package/dist/store/runtime-clients/message-part-runtime-client.d.ts +2 -4
  340. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  341. package/dist/store/runtime-clients/message-part-runtime-client.js +49 -9
  342. package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
  343. package/dist/store/runtime-clients/message-runtime-client.d.ts +2 -7
  344. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  345. package/dist/store/runtime-clients/message-runtime-client.js +220 -54
  346. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  347. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +2 -4
  348. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  349. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +71 -26
  350. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  351. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +2 -5
  352. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  353. package/dist/store/runtime-clients/thread-list-runtime-client.js +141 -36
  354. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  355. package/dist/store/runtime-clients/thread-runtime-client.d.ts +2 -4
  356. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  357. package/dist/store/runtime-clients/thread-runtime-client.js +196 -72
  358. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  359. package/dist/store/runtime-clients/useSubscribable.js +2 -9
  360. package/dist/store/runtime-clients/useSubscribable.js.map +1 -1
  361. package/dist/store/scopes/message.d.ts +1 -0
  362. package/dist/store/scopes/message.d.ts.map +1 -1
  363. package/dist/store/scopes/part.d.ts +5 -6
  364. package/dist/store/scopes/part.d.ts.map +1 -1
  365. package/dist/store/scopes/queue-item.js.map +1 -1
  366. package/dist/store/scopes/thread-list-item.d.ts +1 -0
  367. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  368. package/dist/store/scopes/thread.d.ts +1 -0
  369. package/dist/store/scopes/thread.d.ts.map +1 -1
  370. package/dist/subscribable/subscribable.js.map +1 -1
  371. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -1
  372. package/dist/types/message.d.ts +38 -5
  373. package/dist/types/message.d.ts.map +1 -1
  374. package/dist/types/message.js.map +1 -1
  375. package/dist/utils/composite-context-provider.js.map +1 -1
  376. package/dist/utils/id.js.map +1 -1
  377. package/dist/utils/json/is-json-equal.js.map +1 -1
  378. package/dist/utils/json/is-json.js.map +1 -1
  379. package/dist/utils/text.js.map +1 -1
  380. package/package.json +6 -6
  381. package/src/adapters/thread-history.ts +2 -0
  382. package/src/index.ts +5 -0
  383. package/src/internal.ts +1 -0
  384. package/src/model-context/types.ts +1 -0
  385. package/src/react/AssistantProvider.tsx +10 -1
  386. package/src/react/RuntimeAdapter.ts +25 -8
  387. package/src/react/client/DataRenderers.ts +42 -45
  388. package/src/react/client/Interactables.ts +261 -261
  389. package/src/react/client/Tools.ts +9 -9
  390. package/src/react/primitives/message/MessageGroupedParts.tsx +19 -7
  391. package/src/react/primitives/message/MessageParts.tsx +64 -13
  392. package/src/react/providers/TextMessagePartProvider.tsx +5 -3
  393. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +1 -0
  394. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +11 -0
  395. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +6 -0
  396. package/src/react/runtimes/external-message-converter.ts +3 -1
  397. package/src/react/types/MessagePartComponentTypes.ts +5 -5
  398. package/src/react/utils/groupParts.ts +27 -0
  399. package/src/runtime/api/bindings.ts +1 -0
  400. package/src/runtime/api/message-part-runtime.ts +14 -11
  401. package/src/runtime/api/message-runtime.ts +7 -0
  402. package/src/runtime/api/thread-list-runtime.ts +1 -0
  403. package/src/runtime/api/thread-runtime.ts +7 -0
  404. package/src/runtime/base/base-thread-runtime-core.ts +1 -0
  405. package/src/runtime/branch/external-thread-branch-adapter.ts +26 -0
  406. package/src/runtime/interfaces/thread-list-runtime-core.ts +1 -0
  407. package/src/runtime/interfaces/thread-runtime-core.ts +4 -0
  408. package/src/runtime/utils/resolveToolApprovalResponse.test.ts +91 -0
  409. package/src/runtime/utils/resolveToolApprovalResponse.ts +55 -0
  410. package/src/runtime/utils/thread-message-like.ts +10 -1
  411. package/src/runtimes/external-store/external-store-adapter.ts +1 -0
  412. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +24 -0
  413. package/src/runtimes/local/local-runtime-options.ts +1 -1
  414. package/src/runtimes/local/local-thread-runtime-core.test.ts +370 -0
  415. package/src/runtimes/local/local-thread-runtime-core.ts +113 -7
  416. package/src/runtimes/local/should-continue.ts +24 -13
  417. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +5 -0
  418. package/src/runtimes/remote-thread-list/empty-thread-core.ts +5 -0
  419. package/src/runtimes/remote-thread-list/remote-thread-state.ts +2 -0
  420. package/src/runtimes/remote-thread-list/types.ts +1 -0
  421. package/src/store/clients/chain-of-thought-client.ts +5 -3
  422. package/src/store/clients/model-context-client.test.ts +5 -4
  423. package/src/store/clients/model-context-client.ts +21 -21
  424. package/src/store/clients/no-op-composer-client.ts +5 -3
  425. package/src/store/clients/runtime-adapter.ts +0 -24
  426. package/src/store/clients/suggestions.ts +12 -23
  427. package/src/store/clients/thread-message-client.ts +42 -40
  428. package/src/store/internal.ts +1 -4
  429. package/src/store/runtime-clients/attachment-runtime-client.ts +14 -14
  430. package/src/store/runtime-clients/composer-runtime-client.ts +48 -45
  431. package/src/store/runtime-clients/liveRef.ts +5 -0
  432. package/src/store/runtime-clients/message-part-runtime-client.ts +5 -3
  433. package/src/store/runtime-clients/message-runtime-client.ts +42 -40
  434. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +5 -3
  435. package/src/store/runtime-clients/thread-list-runtime-client.ts +13 -11
  436. package/src/store/runtime-clients/thread-runtime-client.ts +20 -16
  437. package/src/store/runtime-clients/useSubscribable.ts +2 -10
  438. package/src/store/scopes/message.ts +1 -0
  439. package/src/store/scopes/part.ts +5 -2
  440. package/src/store/scopes/thread-list-item.ts +1 -0
  441. package/src/store/scopes/thread.ts +1 -0
  442. package/src/tests/external-store-thread-runtime-core.test.ts +57 -0
  443. package/src/tests/groupMessageParts.test.ts +84 -0
  444. package/src/tests/groupParts.test.ts +55 -0
  445. package/src/types/message.ts +45 -3
@@ -30,7 +30,7 @@ export type { McpAppResourceOutput };
30
30
  * context, while each tool renderer is registered with the tools scope for
31
31
  * message rendering.
32
32
  */
33
- export const Tools = resource(function Tools({
33
+ const useTools = ({
34
34
  toolkit,
35
35
  mcpApp,
36
36
  }: {
@@ -38,11 +38,8 @@ export const Tools = resource(function Tools({
38
38
  toolkit?: Toolkit;
39
39
  /** Optional MCP app resource whose tools should be merged into context. */
40
40
  mcpApp?: ResourceElement<McpAppResourceOutput> | undefined;
41
- }): ClientOutput<"tools"> {
42
- const mcpAppOutputs = useResources(
43
- () => (mcpApp ? [withKey("mcpApp", mcpApp)] : []),
44
- [mcpApp],
45
- );
41
+ }): ClientOutput<"tools"> => {
42
+ const mcpAppOutputs = useResources(mcpApp ? [withKey("mcpApp", mcpApp)] : []);
46
43
  const mcpAppOutput = mcpAppOutputs[0];
47
44
 
48
45
  const [toolUIs, setToolUIs] = useState<ToolsState["toolUIs"]>(() => ({}));
@@ -88,7 +85,8 @@ export const Tools = resource(function Tools({
88
85
  if (next.length > 0) return { ...prev, [toolName]: next };
89
86
  // Drop the key entirely so repeatedly mounted/unmounted tools
90
87
  // don't leave empty arrays accumulating across a long session.
91
- const { [toolName]: _removed, ...rest } = prev;
88
+ const rest = { ...prev };
89
+ delete rest[toolName];
92
90
  return rest;
93
91
  });
94
92
  };
@@ -155,9 +153,11 @@ export const Tools = resource(function Tools({
155
153
  getState: () => state,
156
154
  setToolUI,
157
155
  };
158
- });
156
+ };
157
+
158
+ export const Tools = resource(useTools);
159
159
 
160
- attachTransformScopes(Tools, (scopes, parent) => {
160
+ attachTransformScopes(useTools, (scopes, parent) => {
161
161
  if (!scopes.modelContext && parent.modelContext.source === null) {
162
162
  scopes.modelContext = ModelContext();
163
163
  }
@@ -49,8 +49,9 @@ export namespace MessagePrimitiveGroupedParts {
49
49
  * which running states qualify:
50
50
  * - `"never"` — never.
51
51
  * - `"empty"` — only when the message has no parts yet.
52
- * - `"no-text"` (default) — when the last part isn't `text`/`reasoning`
53
- * (e.g. it ended on a tool call, so the assistant likely isn't done).
52
+ * - `"no-text"` (default) — when the message has no parts yet or the last
53
+ * part isn't `text`/`reasoning` (e.g. it ended on a tool call, so the
54
+ * assistant likely isn't done).
54
55
  * - `"always"` — whenever the message is running, regardless of parts.
55
56
  */
56
57
  export type IndicatorMode = "never" | "empty" | "no-text" | "always";
@@ -153,7 +154,8 @@ const shouldShowIndicator = (
153
154
  case "no-text": {
154
155
  const last = parts[parts.length - 1];
155
156
  return (
156
- last !== undefined && last.type !== "text" && last.type !== "reasoning"
157
+ last === undefined ||
158
+ (last.type !== "text" && last.type !== "reasoning")
157
159
  );
158
160
  }
159
161
  }
@@ -179,9 +181,14 @@ const renderNode = <TKey extends `group-${string}`>(
179
181
  render: (info: MessagePrimitiveGroupedParts.RenderInfo<TKey>) => ReactNode,
180
182
  ): ReactNode => {
181
183
  if (node.type === "part") {
182
- // Key by absolute part index, not structural nodeKey — prevents zombie fiber subscriptions when parts reshape (#4051).
184
+ // Key by part identity when available, else absolute part index — never
185
+ // the structural nodeKey, which leaves zombie fiber subscriptions when
186
+ // parts reshape (#4051).
183
187
  return (
184
- <MessagePartChildren key={`part-${node.index}`} index={node.index}>
188
+ <MessagePartChildren
189
+ key={node.idKey ? `part-${node.idKey}` : `part-${node.index}`}
190
+ index={node.index}
191
+ >
185
192
  {({ part }) => render({ part, children: <PartChildrenSentinel /> })}
186
193
  </MessagePartChildren>
187
194
  );
@@ -195,7 +202,7 @@ const renderNode = <TKey extends `group-${string}`>(
195
202
  };
196
203
 
197
204
  return (
198
- <Fragment key={node.nodeKey}>
205
+ <Fragment key={node.idKey ?? node.nodeKey}>
199
206
  {render({
200
207
  part: groupPart,
201
208
  children: (
@@ -264,7 +271,12 @@ export const MessagePrimitiveGroupedParts = <TKey extends `group-${string}`>({
264
271
  const memoDep = memoKey ?? groupBy;
265
272
  const tree = useMemo(() => {
266
273
  const context: GroupByContext = { toolUIs };
267
- return buildGroupTree(parts.map((part) => groupBy(part, context) ?? []));
274
+ return buildGroupTree(
275
+ parts.map((part) => groupBy(part, context) ?? []),
276
+ parts.map((part) =>
277
+ part.type === "tool-call" ? part.toolCallId : undefined,
278
+ ),
279
+ );
268
280
  // oxlint-disable-next-line react/exhaustive-deps -- groupBy is captured via memoDep (either its identity or the helper's memoKey fingerprint); listing it directly would defeat the helper-tagged memo path
269
281
  }, [parts, memoDep, toolUIs]);
270
282
 
@@ -44,9 +44,24 @@ import { useShallow } from "zustand/shallow";
44
44
 
45
45
  type MessagePartRange =
46
46
  | { type: "single"; index: number }
47
- | { type: "toolGroup"; startIndex: number; endIndex: number }
48
- | { type: "reasoningGroup"; startIndex: number; endIndex: number }
49
- | { type: "chainOfThoughtGroup"; startIndex: number; endIndex: number };
47
+ | {
48
+ type: "toolGroup";
49
+ startIndex: number;
50
+ endIndex: number;
51
+ idKey?: string | undefined;
52
+ }
53
+ | {
54
+ type: "reasoningGroup";
55
+ startIndex: number;
56
+ endIndex: number;
57
+ idKey?: string | undefined;
58
+ }
59
+ | {
60
+ type: "chainOfThoughtGroup";
61
+ startIndex: number;
62
+ endIndex: number;
63
+ idKey?: string | undefined;
64
+ };
50
65
 
51
66
  /**
52
67
  * Creates a group state manager for a specific part type.
@@ -91,10 +106,13 @@ const createGroupState = <
91
106
  * Groups consecutive tool-call and reasoning message parts into ranges.
92
107
  * Always groups tool calls and reasoning parts, even if there's only one.
93
108
  * When useChainOfThought is true, groups tool-call and reasoning parts together.
109
+ * `partIds[i]` optionally carries a stable identity for part `i`; group
110
+ * ranges derive an `idKey` from their first part's id (first claim wins).
94
111
  */
95
- const groupMessageParts = (
112
+ export const groupMessageParts = (
96
113
  messageTypes: readonly string[],
97
114
  useChainOfThought: boolean,
115
+ partIds?: readonly (string | undefined)[],
98
116
  ): MessagePartRange[] => {
99
117
  const ranges: MessagePartRange[] = [];
100
118
 
@@ -137,22 +155,44 @@ const groupMessageParts = (
137
155
  reasoningGroup.finalize(messageTypes.length - 1, ranges);
138
156
  }
139
157
 
158
+ if (partIds) {
159
+ const claimed = new Set<string>();
160
+ for (const range of ranges) {
161
+ if (range.type === "single") continue;
162
+ const id = partIds[range.startIndex];
163
+ if (id !== undefined && !claimed.has(id)) {
164
+ claimed.add(id);
165
+ range.idKey = `id:${id}`;
166
+ }
167
+ }
168
+ }
169
+
140
170
  return ranges;
141
171
  };
142
172
 
143
173
  const useMessagePartsGroups = (
144
174
  useChainOfThought: boolean,
145
- ): MessagePartRange[] => {
175
+ ): { ranges: MessagePartRange[]; partIds: (string | undefined)[] } => {
146
176
  const messageTypes = useAuiState(
147
177
  useShallow((s) => s.message.parts.map((c: any) => c.type)),
148
178
  );
179
+ const partIds = useAuiState(
180
+ useShallow((s) =>
181
+ s.message.parts.map((c: any) =>
182
+ c.type === "tool-call" ? c.toolCallId : undefined,
183
+ ),
184
+ ),
185
+ );
149
186
 
150
187
  return useMemo(() => {
151
188
  if (messageTypes.length === 0) {
152
- return [];
189
+ return { ranges: [], partIds };
153
190
  }
154
- return groupMessageParts(messageTypes, useChainOfThought);
155
- }, [messageTypes, useChainOfThought]);
191
+ return {
192
+ ranges: groupMessageParts(messageTypes, useChainOfThought, partIds),
193
+ partIds,
194
+ };
195
+ }, [messageTypes, partIds, useChainOfThought]);
156
196
  };
157
197
 
158
198
  export namespace MessagePrimitiveParts {
@@ -795,13 +835,24 @@ const MessagePrimitivePartsCompat: FC<{
795
835
  }> = ({ components, unstable_showEmptyOnNonTextEnd }) => {
796
836
  const contentLength = useAuiState((s) => s.message.parts.length);
797
837
  const useChainOfThought = !!components?.ChainOfThought;
798
- const messageRanges = useMessagePartsGroups(useChainOfThought);
838
+ const { ranges: messageRanges, partIds } =
839
+ useMessagePartsGroups(useChainOfThought);
799
840
 
800
841
  const partsElements = useMemo(() => {
801
842
  if (contentLength === 0) {
802
843
  return <EmptyParts components={components} />;
803
844
  }
804
845
 
846
+ const claimed = new Set<string>();
847
+ const toolLeafKey = (partIndex: number) => {
848
+ const id = partIds[partIndex];
849
+ if (id !== undefined && !claimed.has(id)) {
850
+ claimed.add(id);
851
+ return `part-id:${id}`;
852
+ }
853
+ return `part-${partIndex}`;
854
+ };
855
+
805
856
  return messageRanges.map((range) => {
806
857
  if (range.type === "single") {
807
858
  return (
@@ -816,7 +867,7 @@ const MessagePrimitivePartsCompat: FC<{
816
867
  if (!ChainOfThoughtComponent) return null;
817
868
  return (
818
869
  <ChainOfThoughtByIndicesProvider
819
- key={`chainOfThought-${range.startIndex}`}
870
+ key={`chainOfThought-${range.idKey ?? range.startIndex}`}
820
871
  startIndex={range.startIndex}
821
872
  endIndex={range.endIndex}
822
873
  >
@@ -828,7 +879,7 @@ const MessagePrimitivePartsCompat: FC<{
828
879
  components?.ToolGroup ?? defaultComponents.ToolGroup;
829
880
  return (
830
881
  <ToolGroupComponent
831
- key={`tool-${range.startIndex}`}
882
+ key={`tool-${range.idKey ?? range.startIndex}`}
832
883
  startIndex={range.startIndex}
833
884
  endIndex={range.endIndex}
834
885
  >
@@ -838,7 +889,7 @@ const MessagePrimitivePartsCompat: FC<{
838
889
  const partIndex = range.startIndex + i;
839
890
  return (
840
891
  <MessagePrimitivePartByIndex
841
- key={`part-${partIndex}`}
892
+ key={toolLeafKey(partIndex)}
842
893
  index={partIndex}
843
894
  components={components}
844
895
  />
@@ -874,7 +925,7 @@ const MessagePrimitivePartsCompat: FC<{
874
925
  );
875
926
  }
876
927
  });
877
- }, [messageRanges, components, contentLength]);
928
+ }, [messageRanges, partIds, components, contentLength]);
878
929
 
879
930
  return (
880
931
  <>
@@ -4,13 +4,13 @@ import type { PartState } from "../../store/scopes/part";
4
4
 
5
5
  import { resource } from "@assistant-ui/tap";
6
6
 
7
- const TextMessagePartClient = resource(function TextMessagePartClient({
7
+ const useTextMessagePartClient = ({
8
8
  text,
9
9
  isRunning,
10
10
  }: {
11
11
  text: string;
12
12
  isRunning: boolean;
13
- }): ClientOutput<"part"> {
13
+ }): ClientOutput<"part"> => {
14
14
  const state = useMemo<PartState>(
15
15
  () => ({
16
16
  type: "text",
@@ -32,7 +32,9 @@ const TextMessagePartClient = resource(function TextMessagePartClient({
32
32
  throw new Error("Not supported");
33
33
  },
34
34
  };
35
- });
35
+ };
36
+
37
+ const TextMessagePartClient = resource(useTextMessagePartClient);
36
38
 
37
39
  export const TextMessagePartProvider: FC<
38
40
  PropsWithChildren<{
@@ -296,6 +296,7 @@ export class RemoteThreadListThreadListRuntimeCore
296
296
  externalId: remoteMetadata.externalId,
297
297
  status: remoteMetadata.status,
298
298
  title: remoteMetadata.title,
299
+ lastMessageAt: remoteMetadata.lastMessageAt,
299
300
  custom: remoteMetadata.custom,
300
301
  } as RemoteThreadData,
301
302
  };
@@ -57,6 +57,11 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
57
57
  if (!remoteId) return;
58
58
  await formatted.update?.(remoteId, item, localMessageId);
59
59
  },
60
+ async delete() {
61
+ throw new Error(
62
+ "Assistant Cloud does not support deleting thread messages yet.",
63
+ );
64
+ },
60
65
  reportTelemetry(
61
66
  items: MessageFormatItem<TMessage>[],
62
67
  options?: {
@@ -97,6 +102,12 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
97
102
  }
98
103
  }
99
104
 
105
+ async delete() {
106
+ throw new Error(
107
+ "Assistant Cloud does not support deleting thread messages yet.",
108
+ );
109
+ }
110
+
100
111
  async load() {
101
112
  const remoteId = this.aui.threadListItem().getState().remoteId;
102
113
  if (!remoteId) return { messages: [] };
@@ -94,6 +94,9 @@ export const useCloudThreadListAdapter = (
94
94
  status: t.is_archived ? "archived" : "regular",
95
95
  remoteId: t.id,
96
96
  title: t.title,
97
+ lastMessageAt: t.last_message_at
98
+ ? new Date(t.last_message_at)
99
+ : undefined,
97
100
  externalId: t.external_id ?? undefined,
98
101
  custom: toCustom(t.metadata),
99
102
  })),
@@ -153,6 +156,9 @@ export const useCloudThreadListAdapter = (
153
156
  status: thread.is_archived ? "archived" : "regular",
154
157
  remoteId: thread.id,
155
158
  title: thread.title,
159
+ lastMessageAt: thread.last_message_at
160
+ ? new Date(thread.last_message_at)
161
+ : undefined,
156
162
  externalId: thread.external_id ?? undefined,
157
163
  custom: toCustom(thread.metadata),
158
164
  };
@@ -36,7 +36,9 @@ const isInterruptedToolCall = (c: ThreadMessageLikeContentItem): boolean => {
36
36
  if (c.type !== "tool-call" || c.result !== undefined) return false;
37
37
  return (
38
38
  c.interrupt != null ||
39
- (c.approval != null && c.approval.approved === undefined)
39
+ (c.approval != null &&
40
+ c.approval.approved === undefined &&
41
+ c.approval.resolution === undefined)
40
42
  );
41
43
  };
42
44
 
@@ -9,6 +9,7 @@ import type {
9
9
  ReasoningMessagePart,
10
10
  SourceMessagePart,
11
11
  TextMessagePart,
12
+ ToolApprovalResponse,
12
13
  ToolCallMessagePart,
13
14
  Unstable_AudioMessagePart,
14
15
  QuoteInfo,
@@ -73,12 +74,11 @@ export type ToolCallMessagePartProps<
73
74
  resume: (payload: unknown) => void;
74
75
  /**
75
76
  * Responds to a server-side tool approval gate. Only valid while
76
- * `approval` is set on the part and `approval.approved === undefined`.
77
+ * `approval` is set on the part, `approval.approved === undefined`, and
78
+ * no `approval.resolution` is recorded. Accepts a boolean decision or the
79
+ * id of one of `approval.options`; option kinds resolve to the boolean.
77
80
  */
78
- respondToApproval: (response: {
79
- approved: boolean;
80
- reason?: string;
81
- }) => void;
81
+ respondToApproval: (response: ToolApprovalResponse) => void;
82
82
  };
83
83
 
84
84
  /** Component used to render a tool-call message part. */
@@ -119,6 +119,11 @@ export interface GroupNodeGroup {
119
119
  readonly key: string;
120
120
  /** Structural React key: sibling-index path, e.g. `"0.1.0"`. */
121
121
  readonly nodeKey: string;
122
+ /**
123
+ * Identity key (`"id:<partId>"`) from the group's first part; undefined
124
+ * when absent or already claimed by an earlier sibling.
125
+ */
126
+ readonly idKey: string | undefined;
122
127
  /** Indices of parts in this subtree, in order. */
123
128
  readonly indices: readonly number[];
124
129
  readonly children: readonly GroupNode[];
@@ -130,6 +135,11 @@ export interface GroupNodePart {
130
135
  readonly index: number;
131
136
  /** Structural React key: sibling-index path within parent. */
132
137
  readonly nodeKey: string;
138
+ /**
139
+ * Identity key (`"id:<partId>"`); undefined when absent or already
140
+ * claimed by an earlier sibling.
141
+ */
142
+ readonly idKey: string | undefined;
133
143
  }
134
144
 
135
145
  interface BuildFrame {
@@ -138,6 +148,7 @@ interface BuildFrame {
138
148
  indices: number[];
139
149
  children: GroupNode[];
140
150
  nextChildIdx: number;
151
+ claimed: Set<string>;
141
152
  }
142
153
 
143
154
  const makeChildNodeKey = (parent: BuildFrame): string => {
@@ -145,13 +156,25 @@ const makeChildNodeKey = (parent: BuildFrame): string => {
145
156
  return parent.nodeKey === "" ? String(idx) : `${parent.nodeKey}.${idx}`;
146
157
  };
147
158
 
159
+ const claimIdKey = (
160
+ frame: BuildFrame,
161
+ id: string | undefined,
162
+ ): string | undefined => {
163
+ if (id === undefined || frame.claimed.has(id)) return undefined;
164
+ frame.claimed.add(id);
165
+ return `id:${id}`;
166
+ };
167
+
148
168
  /**
149
169
  * Build the group tree from an array of normalized group paths.
150
170
  * `paths[i]` is the path for part `i`. The output tree contains one
151
171
  * `part` node per part and one `group` node per coalesced run.
172
+ * `partIds[i]` optionally carries a stable identity for part `i` (e.g. a
173
+ * tool call id), from which nodes derive an `idKey`.
152
174
  */
153
175
  export const buildGroupTree = (
154
176
  paths: readonly (readonly string[])[],
177
+ partIds?: readonly (string | undefined)[],
155
178
  ): readonly GroupNode[] => {
156
179
  const root: BuildFrame = {
157
180
  key: "",
@@ -159,6 +182,7 @@ export const buildGroupTree = (
159
182
  indices: [],
160
183
  children: [],
161
184
  nextChildIdx: 0,
185
+ claimed: new Set(),
162
186
  };
163
187
  const stack: BuildFrame[] = [root];
164
188
 
@@ -169,6 +193,7 @@ export const buildGroupTree = (
169
193
  type: "group",
170
194
  key: closing.key,
171
195
  nodeKey: closing.nodeKey,
196
+ idKey: claimIdKey(parent, partIds?.[closing.indices[0]!]),
172
197
  indices: closing.indices,
173
198
  children: closing.children,
174
199
  });
@@ -202,6 +227,7 @@ export const buildGroupTree = (
202
227
  indices: [],
203
228
  children: [],
204
229
  nextChildIdx: 0,
230
+ claimed: new Set(),
205
231
  });
206
232
  }
207
233
 
@@ -211,6 +237,7 @@ export const buildGroupTree = (
211
237
  type: "part",
212
238
  index: i,
213
239
  nodeKey: makeChildNodeKey(top),
240
+ idKey: claimIdKey(top, partIds?.[i]),
214
241
  });
215
242
 
216
243
  // Record the part index in every open ancestor group.
@@ -42,5 +42,6 @@ export type ThreadListItemState = {
42
42
  readonly externalId: string | undefined;
43
43
  readonly status: import("../interfaces/thread-list-runtime-core").ThreadListItemStatus;
44
44
  readonly title?: string | undefined;
45
+ readonly lastMessageAt?: Date | undefined;
45
46
  readonly custom?: Record<string, unknown> | undefined;
46
47
  };
@@ -1,8 +1,10 @@
1
1
  import type {
2
2
  ThreadAssistantMessagePart,
3
3
  ThreadUserMessagePart,
4
+ ToolApprovalResponse,
4
5
  ToolCallMessagePartStatus,
5
6
  } from "../../types/message";
7
+ import { resolveToolApprovalResponse } from "../utils/resolveToolApprovalResponse";
6
8
  import type { Unsubscribe } from "../../types/unsubscribe";
7
9
  import type { MessagePartStatus } from "../../types/message";
8
10
  import type { SubscribableWithState } from "../../subscribable/subscribable";
@@ -26,7 +28,7 @@ type MessagePartSnapshotBinding = SubscribableWithState<
26
28
  export type MessagePartRuntime = {
27
29
  addToolResult(result: any | ToolResponse<any>): void;
28
30
  resumeToolCall(payload: unknown): void;
29
- respondToToolApproval(response: { approved: boolean; reason?: string }): void;
31
+ respondToToolApproval(response: ToolApprovalResponse): void;
30
32
 
31
33
  readonly path: MessagePartRuntimePath;
32
34
  getState(): MessagePartState;
@@ -104,10 +106,7 @@ export class MessagePartRuntimeImpl implements MessagePartRuntime {
104
106
  });
105
107
  }
106
108
 
107
- public respondToToolApproval(response: {
108
- approved: boolean;
109
- reason?: string;
110
- }) {
109
+ public respondToToolApproval(response: ToolApprovalResponse) {
111
110
  const state = this.contentBinding.getState();
112
111
  if (!state) throw new Error("Message part is not available");
113
112
 
@@ -116,16 +115,20 @@ export class MessagePartRuntimeImpl implements MessagePartRuntime {
116
115
  "Tried to respond to tool approval on non-tool message part",
117
116
  );
118
117
 
119
- if (!state.approval || state.approval.approved !== undefined)
118
+ if (
119
+ !state.approval ||
120
+ state.approval.approved !== undefined ||
121
+ state.approval.resolution !== undefined
122
+ )
120
123
  throw new Error("Tool call has no pending approval");
121
124
 
122
125
  if (!this.threadApi) throw new Error("Thread API is not available");
123
126
 
124
- this.threadApi.getState().respondToToolApproval({
125
- approvalId: state.approval.id,
126
- approved: response.approved,
127
- ...(response.reason != null && { reason: response.reason }),
128
- });
127
+ this.threadApi
128
+ .getState()
129
+ .respondToToolApproval(
130
+ resolveToolApprovalResponse(state.approval, response),
131
+ );
129
132
  }
130
133
 
131
134
  public subscribe(callback: () => void) {
@@ -101,6 +101,7 @@ export type MessageRuntime = {
101
101
  readonly composer: EditComposerRuntime;
102
102
 
103
103
  getState(): MessageState;
104
+ delete(): void | Promise<void>;
104
105
  reload(config?: ReloadConfig): void;
105
106
  /**
106
107
  * @deprecated This API is still under active development and might change without notice.
@@ -155,6 +156,7 @@ export class MessageRuntimeImpl implements MessageRuntime {
155
156
 
156
157
  protected __internal_bindMethods() {
157
158
  this.reload = this.reload.bind(this);
159
+ this.delete = this.delete.bind(this);
158
160
  this.getState = this.getState.bind(this);
159
161
  this.subscribe = this.subscribe.bind(this);
160
162
  this.getMessagePartByIndex = this.getMessagePartByIndex.bind(this);
@@ -180,6 +182,11 @@ export class MessageRuntimeImpl implements MessageRuntime {
180
182
  return this._core.getState();
181
183
  }
182
184
 
185
+ public delete() {
186
+ const state = this._core.getState();
187
+ return this._threadBinding.getState().deleteMessage(state.id);
188
+ }
189
+
183
190
  public reload(reloadConfig: ReloadConfig = {}) {
184
191
  const editComposerRuntimeCore = this._getEditComposerRuntimeCore();
185
192
  const composerRuntimeCore =
@@ -88,6 +88,7 @@ const getThreadListItemState = (
88
88
  externalId: threadData.externalId,
89
89
  title: threadData.title,
90
90
  status: threadData.status,
91
+ lastMessageAt: threadData.lastMessageAt,
91
92
  custom: threadData.custom,
92
93
  isMain: threadData.id === threadList.mainThreadId,
93
94
  };
@@ -252,6 +252,8 @@ export type ThreadRuntime = {
252
252
  */
253
253
  append(message: CreateAppendMessage): void;
254
254
 
255
+ deleteMessage(messageId: string): void | Promise<void>;
256
+
255
257
  /**
256
258
  * Start a new run with the given configuration.
257
259
  * @param config The configuration for starting the run
@@ -374,6 +376,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
374
376
 
375
377
  protected __internal_bindMethods() {
376
378
  this.append = this.append.bind(this);
379
+ this.deleteMessage = this.deleteMessage.bind(this);
377
380
  this.resumeRun = this.resumeRun.bind(this);
378
381
  this.importExternalState = this.importExternalState.bind(this);
379
382
  this.exportExternalState = this.exportExternalState.bind(this);
@@ -411,6 +414,10 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
411
414
  );
412
415
  }
413
416
 
417
+ public deleteMessage(messageId: string) {
418
+ return this._threadBinding.getState().deleteMessage(messageId);
419
+ }
420
+
414
421
  public subscribe(callback: () => void) {
415
422
  return this._threadBinding.subscribe(callback);
416
423
  }
@@ -56,6 +56,7 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
56
56
 
57
57
  public abstract get capabilities(): RuntimeCapabilities;
58
58
  public abstract append(message: AppendMessage): void;
59
+ public abstract deleteMessage(messageId: string): void | Promise<void>;
59
60
  public abstract startRun(config: StartRunConfig): void;
60
61
  public abstract resumeRun(config: ResumeRunConfig): void;
61
62
  public abstract addToolResult(options: AddToolResultOptions): void;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The branch surface a runtime exposes so the branch picker can navigate
3
+ * between sibling variants of a message. Read during render; recreate the
4
+ * adapter object when branch data changes.
5
+ *
6
+ * Editing a message creates a branch only if the `onEdit` handler creates a
7
+ * sibling and `getBranches` reports it. Note that `ExternalThread`'s edit
8
+ * payload carries the edited message's own id as both `parentId` and
9
+ * `sourceId`.
10
+ */
11
+ export type ExternalThreadBranchAdapter = {
12
+ /**
13
+ * Returns the sibling branch ids for a message in display order, including
14
+ * the message's own id. Return an empty array for messages without
15
+ * alternative branches.
16
+ */
17
+ getBranches: (messageId: string) => readonly string[];
18
+ /**
19
+ * Makes the given branch the visible one. The runtime is expected to swap
20
+ * the `messages` array to the selected branch. May be invoked
21
+ * programmatically while a run is in progress; pending queue items are not
22
+ * cleared, and reconciling them with the new branch is the runtime's
23
+ * responsibility.
24
+ */
25
+ switchToBranch: (branchId: string) => void;
26
+ };
@@ -10,6 +10,7 @@ export type ThreadListItemCoreState = {
10
10
 
11
11
  readonly status: ThreadListItemStatus;
12
12
  readonly title?: string | undefined;
13
+ readonly lastMessageAt?: Date | undefined;
13
14
  readonly custom?: Record<string, unknown> | undefined;
14
15
 
15
16
  readonly runtime?: ThreadRuntimeCore | undefined;
@@ -23,6 +23,7 @@ export type RuntimeCapabilities = {
23
23
  readonly switchBranchDuringRun: boolean;
24
24
  readonly edit: boolean;
25
25
  readonly reload: boolean;
26
+ readonly delete: boolean;
26
27
  readonly cancel: boolean;
27
28
  readonly unstable_copy: boolean;
28
29
  readonly speech: boolean;
@@ -57,6 +58,8 @@ export type ResumeToolCallOptions = {
57
58
  export type RespondToToolApprovalOptions = {
58
59
  approvalId: string;
59
60
  approved: boolean;
61
+ /** The approval option that produced this decision, when the request carried options. */
62
+ optionId?: string;
60
63
  reason?: string;
61
64
  };
62
65
 
@@ -146,6 +149,7 @@ export type ThreadRuntimeCore = Readonly<{
146
149
  switchToBranch: (branchId: string) => void;
147
150
 
148
151
  append: (message: AppendMessage) => void;
152
+ deleteMessage: (messageId: string) => void | Promise<void>;
149
153
  startRun: (config: StartRunConfig) => void;
150
154
  resumeRun: (config: ResumeRunConfig) => void;
151
155
  cancelRun: () => void;