@assistant-ui/core 0.2.20 → 0.2.21

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 (509) hide show
  1. package/dist/adapters/attachment.d.ts +2 -2
  2. package/dist/adapters/attachment.d.ts.map +1 -1
  3. package/dist/adapters/attachment.js +14 -7
  4. package/dist/adapters/attachment.js.map +1 -1
  5. package/dist/adapters/directive-formatter.d.ts +0 -1
  6. package/dist/adapters/directive-formatter.d.ts.map +1 -1
  7. package/dist/adapters/feedback.d.ts +0 -1
  8. package/dist/adapters/feedback.d.ts.map +1 -1
  9. package/dist/adapters/index.d.ts +2 -2
  10. package/dist/adapters/index.js +2 -1
  11. package/dist/adapters/speech.d.ts +0 -1
  12. package/dist/adapters/speech.d.ts.map +1 -1
  13. package/dist/adapters/suggestion.d.ts +16 -2
  14. package/dist/adapters/suggestion.d.ts.map +1 -1
  15. package/dist/adapters/suggestion.js +36 -0
  16. package/dist/adapters/suggestion.js.map +1 -0
  17. package/dist/adapters/thread-history.d.ts +2 -2
  18. package/dist/adapters/thread-history.d.ts.map +1 -1
  19. package/dist/adapters/trigger.d.ts +5 -3
  20. package/dist/adapters/trigger.d.ts.map +1 -1
  21. package/dist/adapters/voice.d.ts +0 -1
  22. package/dist/adapters/voice.d.ts.map +1 -1
  23. package/dist/index.d.ts +4 -3
  24. package/dist/index.js +3 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal/duplicate-detection.d.ts.map +1 -1
  27. package/dist/internal.d.ts +7 -1
  28. package/dist/internal.js +6 -2
  29. package/dist/model-context/frame/host.d.ts +0 -1
  30. package/dist/model-context/frame/host.d.ts.map +1 -1
  31. package/dist/model-context/frame/provider.d.ts +0 -1
  32. package/dist/model-context/frame/provider.d.ts.map +1 -1
  33. package/dist/model-context/frame/types.d.ts.map +1 -1
  34. package/dist/model-context/interactable-composer-metadata.d.ts +4 -2
  35. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  36. package/dist/model-context/registry-handles.d.ts +0 -1
  37. package/dist/model-context/registry-handles.d.ts.map +1 -1
  38. package/dist/model-context/registry.d.ts +0 -1
  39. package/dist/model-context/registry.d.ts.map +1 -1
  40. package/dist/model-context/tool.d.ts +23 -9
  41. package/dist/model-context/tool.d.ts.map +1 -1
  42. package/dist/model-context/tool.js +0 -25
  43. package/dist/model-context/tool.js.map +1 -1
  44. package/dist/model-context/types.d.ts +0 -1
  45. package/dist/model-context/types.d.ts.map +1 -1
  46. package/dist/react/AssistantProvider.d.ts +0 -1
  47. package/dist/react/AssistantProvider.d.ts.map +1 -1
  48. package/dist/react/AssistantRuntimeProvider.d.ts +1 -6
  49. package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
  50. package/dist/react/RuntimeAdapter.d.ts +1 -0
  51. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  52. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts +13 -2
  53. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  54. package/dist/react/adapters/LocalStorageThreadListAdapter.js +122 -7
  55. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  56. package/dist/react/adapters/TitleGenerationAdapter.d.ts +0 -1
  57. package/dist/react/adapters/TitleGenerationAdapter.d.ts.map +1 -1
  58. package/dist/react/client/DataRenderers.d.ts +0 -1
  59. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  60. package/dist/react/client/Interactables.d.ts +0 -1
  61. package/dist/react/client/Interactables.d.ts.map +1 -1
  62. package/dist/react/client/Tools.d.ts +3 -2
  63. package/dist/react/client/Tools.d.ts.map +1 -1
  64. package/dist/react/client/interactable-model-context.d.ts +0 -1
  65. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  66. package/dist/react/index.d.ts +2 -2
  67. package/dist/react/interactables-legacy/Interactables.d.ts +0 -1
  68. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  69. package/dist/react/interactables-legacy/interactable-model-context.d.ts +0 -1
  70. package/dist/react/interactables-legacy/interactable-model-context.d.ts.map +1 -1
  71. package/dist/react/interactables-legacy/scopes.d.ts +4 -2
  72. package/dist/react/interactables-legacy/scopes.d.ts.map +1 -1
  73. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts +0 -1
  74. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
  75. package/dist/react/interactables-legacy/useInteractableState.d.ts.map +1 -1
  76. package/dist/react/model-context/define-mcp-toolkit.d.ts +19 -4
  77. package/dist/react/model-context/define-mcp-toolkit.d.ts.map +1 -1
  78. package/dist/react/model-context/define-mcp-toolkit.js +17 -5
  79. package/dist/react/model-context/define-mcp-toolkit.js.map +1 -1
  80. package/dist/react/model-context/define-toolkit.d.ts +1 -2
  81. package/dist/react/model-context/define-toolkit.d.ts.map +1 -1
  82. package/dist/react/model-context/external-tool.d.ts.map +1 -1
  83. package/dist/react/model-context/human-tool.d.ts.map +1 -1
  84. package/dist/react/model-context/interactableTool.d.ts +2 -2
  85. package/dist/react/model-context/interactableTool.d.ts.map +1 -1
  86. package/dist/react/model-context/makeAssistantDataUI.d.ts +2 -2
  87. package/dist/react/model-context/makeAssistantDataUI.d.ts.map +1 -1
  88. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  89. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  90. package/dist/react/model-context/makeAssistantToolUI.d.ts +2 -2
  91. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  92. package/dist/react/model-context/provider-tool.d.ts +0 -1
  93. package/dist/react/model-context/provider-tool.d.ts.map +1 -1
  94. package/dist/react/model-context/stub-tool.d.ts.map +1 -1
  95. package/dist/react/model-context/toolbox.d.ts +5 -5
  96. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  97. package/dist/react/model-context/useAssistantContext.d.ts +1 -0
  98. package/dist/react/model-context/useAssistantContext.d.ts.map +1 -1
  99. package/dist/react/model-context/useAssistantDataUI.d.ts +3 -2
  100. package/dist/react/model-context/useAssistantDataUI.d.ts.map +1 -1
  101. package/dist/react/model-context/useAssistantInstructions.d.ts +1 -0
  102. package/dist/react/model-context/useAssistantInstructions.d.ts.map +1 -1
  103. package/dist/react/model-context/useAssistantTool.d.ts +4 -2
  104. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  105. package/dist/react/model-context/useAssistantToolUI.d.ts +3 -2
  106. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  107. package/dist/react/model-context/useAuiToolOverrides.d.ts +0 -1
  108. package/dist/react/model-context/useAuiToolOverrides.d.ts.map +1 -1
  109. package/dist/react/model-context/useInlineRender.d.ts +0 -1
  110. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  111. package/dist/react/model-context/useInteractable.d.ts +7 -4
  112. package/dist/react/model-context/useInteractable.d.ts.map +1 -1
  113. package/dist/react/model-context/useInteractableState.d.ts.map +1 -1
  114. package/dist/react/model-context/useInteractableVersions.d.ts +0 -1
  115. package/dist/react/model-context/useInteractableVersions.d.ts.map +1 -1
  116. package/dist/react/model-context/useToolArgsStatus.d.ts +3 -1
  117. package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
  118. package/dist/react/primitive-hooks/useActionBarCopy.d.ts +1 -4
  119. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  120. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  121. package/dist/react/primitive-hooks/useActionBarFeedback.d.ts.map +1 -1
  122. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  123. package/dist/react/primitive-hooks/useActionBarSpeak.d.ts.map +1 -1
  124. package/dist/react/primitive-hooks/useActionBarStopSpeaking.d.ts.map +1 -1
  125. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  126. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  127. package/dist/react/primitive-hooks/useComposerAddAttachment.d.ts +0 -1
  128. package/dist/react/primitive-hooks/useComposerAddAttachment.d.ts.map +1 -1
  129. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  130. package/dist/react/primitive-hooks/useComposerDictate.d.ts.map +1 -1
  131. package/dist/react/primitive-hooks/useComposerSend.d.ts +0 -1
  132. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  133. package/dist/react/primitive-hooks/useEditComposerCancel.d.ts.map +1 -1
  134. package/dist/react/primitive-hooks/useEditComposerSend.d.ts.map +1 -1
  135. package/dist/react/primitive-hooks/useMessageBranching.d.ts.map +1 -1
  136. package/dist/react/primitive-hooks/useMessageError.d.ts.map +1 -1
  137. package/dist/react/primitive-hooks/useMessageError.js +5 -1
  138. package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
  139. package/dist/react/primitive-hooks/useMessageReload.d.ts.map +1 -1
  140. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts +1 -5
  141. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  142. package/dist/react/primitive-hooks/useThreadIsEmpty.d.ts.map +1 -1
  143. package/dist/react/primitive-hooks/useThreadIsRunning.d.ts.map +1 -1
  144. package/dist/react/primitive-hooks/useThreadListItemArchive.d.ts.map +1 -1
  145. package/dist/react/primitive-hooks/useThreadListItemDelete.d.ts.map +1 -1
  146. package/dist/react/primitive-hooks/useThreadListItemTrigger.d.ts.map +1 -1
  147. package/dist/react/primitive-hooks/useThreadListItemUnarchive.d.ts.map +1 -1
  148. package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
  149. package/dist/react/primitive-hooks/useThreadListNew.d.ts.map +1 -1
  150. package/dist/react/primitive-hooks/useThreadMessageIds.d.ts.map +1 -1
  151. package/dist/react/primitive-hooks/useThreadMessages.d.ts +0 -1
  152. package/dist/react/primitive-hooks/useThreadMessages.d.ts.map +1 -1
  153. package/dist/react/primitive-hooks/useVoice.d.ts +0 -1
  154. package/dist/react/primitive-hooks/useVoice.d.ts.map +1 -1
  155. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts +7 -4
  156. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts.map +1 -1
  157. package/dist/react/primitives/composer/ComposerAttachments.d.ts +4 -3
  158. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  159. package/dist/react/primitives/composer/ComposerIf.d.ts +4 -3
  160. package/dist/react/primitives/composer/ComposerIf.d.ts.map +1 -1
  161. package/dist/react/primitives/composer/ComposerQueue.d.ts +2 -2
  162. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  163. package/dist/react/primitives/generativeUI/GenerativeUI.d.ts +2 -2
  164. package/dist/react/primitives/generativeUI/GenerativeUI.d.ts.map +1 -1
  165. package/dist/react/primitives/message/MessageAttachments.d.ts +4 -3
  166. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  167. package/dist/react/primitives/message/MessageGroupedParts.d.ts +1 -6
  168. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  169. package/dist/react/primitives/message/MessageParts.d.ts +42 -24
  170. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  171. package/dist/react/primitives/message/MessageParts.js +2 -1
  172. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  173. package/dist/react/primitives/message/MessageQuote.d.ts +2 -2
  174. package/dist/react/primitives/message/MessageQuote.d.ts.map +1 -1
  175. package/dist/react/primitives/messagePart/MessagePartInProgress.d.ts +0 -1
  176. package/dist/react/primitives/messagePart/MessagePartInProgress.d.ts.map +1 -1
  177. package/dist/react/primitives/part/PartMessages.d.ts +2 -2
  178. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  179. package/dist/react/primitives/thread/ThreadMessages.d.ts +35 -17
  180. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  181. package/dist/react/primitives/thread/ThreadSuggestions.d.ts +6 -4
  182. package/dist/react/primitives/thread/ThreadSuggestions.d.ts.map +1 -1
  183. package/dist/react/primitives/threadList/ThreadListItems.d.ts +4 -3
  184. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  185. package/dist/react/primitives/threadListItem/ThreadListItemTitle.d.ts +0 -1
  186. package/dist/react/primitives/threadListItem/ThreadListItemTitle.d.ts.map +1 -1
  187. package/dist/react/providers/AttachmentByIndexProvider.d.ts +0 -1
  188. package/dist/react/providers/AttachmentByIndexProvider.d.ts.map +1 -1
  189. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts +0 -1
  190. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts.map +1 -1
  191. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts +0 -1
  192. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
  193. package/dist/react/providers/MessageByIdProvider.d.ts +0 -1
  194. package/dist/react/providers/MessageByIdProvider.d.ts.map +1 -1
  195. package/dist/react/providers/MessageByIndexProvider.d.ts +0 -1
  196. package/dist/react/providers/MessageByIndexProvider.d.ts.map +1 -1
  197. package/dist/react/providers/PartByIndexProvider.d.ts +0 -1
  198. package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
  199. package/dist/react/providers/QueueItemByIndexProvider.d.ts +0 -1
  200. package/dist/react/providers/QueueItemByIndexProvider.d.ts.map +1 -1
  201. package/dist/react/providers/ReadonlyThreadProvider.d.ts +0 -1
  202. package/dist/react/providers/ReadonlyThreadProvider.d.ts.map +1 -1
  203. package/dist/react/providers/SuggestionByIndexProvider.d.ts +0 -1
  204. package/dist/react/providers/SuggestionByIndexProvider.d.ts.map +1 -1
  205. package/dist/react/providers/TextMessagePartProvider.d.ts +0 -1
  206. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  207. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts +0 -1
  208. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts.map +1 -1
  209. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts +1 -1
  210. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts.map +1 -1
  211. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -1
  212. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  213. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
  214. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  215. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +3 -1
  216. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  217. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +21 -19
  218. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  219. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +0 -1
  220. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  221. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +0 -1
  222. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  223. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -4
  224. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  225. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +6 -3
  226. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  227. package/dist/react/runtimes/cloud/auiV0.d.ts +12 -2
  228. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  229. package/dist/react/runtimes/cloud/auiV0.js +30 -1
  230. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  231. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +0 -1
  232. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  233. package/dist/react/runtimes/createMessageConverter.d.ts +1 -7
  234. package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
  235. package/dist/react/runtimes/createRuntimeExtras.d.ts +0 -1
  236. package/dist/react/runtimes/createRuntimeExtras.d.ts.map +1 -1
  237. package/dist/react/runtimes/external-message-converter.d.ts +1 -8
  238. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  239. package/dist/react/runtimes/external-message-converter.js +42 -44
  240. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  241. package/dist/react/runtimes/useExternalStoreRuntime.d.ts +0 -1
  242. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  243. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts +0 -1
  244. package/dist/react/runtimes/useExternalStoreSharedOptions.d.ts.map +1 -1
  245. package/dist/react/runtimes/useLocalRuntime.d.ts +2 -5
  246. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  247. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts +0 -1
  248. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  249. package/dist/react/runtimes/useStreamingTiming.d.ts +0 -1
  250. package/dist/react/runtimes/useStreamingTiming.d.ts.map +1 -1
  251. package/dist/react/types/MessagePartComponentTypes.d.ts +6 -3
  252. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  253. package/dist/react/types/scopes/dataRenderers.d.ts +1 -1
  254. package/dist/react/types/scopes/dataRenderers.d.ts.map +1 -1
  255. package/dist/react/types/scopes/interactables.d.ts +4 -2
  256. package/dist/react/types/scopes/interactables.d.ts.map +1 -1
  257. package/dist/react/types/scopes/tools.d.ts +5 -3
  258. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  259. package/dist/react/types/store-augmentation.d.ts +1 -2
  260. package/dist/react/types/store-augmentation.d.ts.map +1 -1
  261. package/dist/react/utils/getMessageQuote.d.ts +0 -1
  262. package/dist/react/utils/getMessageQuote.d.ts.map +1 -1
  263. package/dist/react/utils/groupParts.d.ts +2 -2
  264. package/dist/react/utils/groupParts.d.ts.map +1 -1
  265. package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
  266. package/dist/runtime/api/assistant-runtime.d.ts +0 -1
  267. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  268. package/dist/runtime/api/attachment-runtime.d.ts +0 -1
  269. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  270. package/dist/runtime/api/bindings.d.ts +0 -1
  271. package/dist/runtime/api/bindings.d.ts.map +1 -1
  272. package/dist/runtime/api/composer-runtime.d.ts +6 -4
  273. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  274. package/dist/runtime/api/message-part-runtime.d.ts +0 -1
  275. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  276. package/dist/runtime/api/message-runtime.d.ts +6 -16
  277. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  278. package/dist/runtime/api/message-runtime.js +1 -1
  279. package/dist/runtime/api/paths.d.ts.map +1 -1
  280. package/dist/runtime/api/thread-list-item-runtime.d.ts +0 -1
  281. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  282. package/dist/runtime/api/thread-list-runtime.d.ts +0 -1
  283. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  284. package/dist/runtime/api/thread-runtime.d.ts +3 -1
  285. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  286. package/dist/runtime/base/base-assistant-runtime-core.d.ts +0 -1
  287. package/dist/runtime/base/base-assistant-runtime-core.d.ts.map +1 -1
  288. package/dist/runtime/base/base-composer-runtime-core.d.ts +0 -1
  289. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  290. package/dist/runtime/base/base-composer-runtime-core.js +17 -3
  291. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  292. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -4
  293. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  294. package/dist/runtime/base/base-thread-runtime-core.js +1 -1
  295. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +1 -5
  296. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  297. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -0
  298. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  299. package/dist/runtime/branch/external-thread-branch-adapter.d.ts.map +1 -1
  300. package/dist/runtime/interfaces/assistant-runtime-core.d.ts +0 -1
  301. package/dist/runtime/interfaces/assistant-runtime-core.d.ts.map +1 -1
  302. package/dist/runtime/interfaces/composer-runtime-core.d.ts +2 -2
  303. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  304. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +0 -1
  305. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  306. package/dist/runtime/interfaces/thread-runtime-core.d.ts +2 -2
  307. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  308. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +0 -1
  309. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  310. package/dist/runtime/queue/message-queue.d.ts +6 -4
  311. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  312. package/dist/runtime/queue/message-queue.js +1 -1
  313. package/dist/runtime/utils/auto-status.d.ts +0 -1
  314. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  315. package/dist/runtime/utils/chat-model-adapter.d.ts +0 -1
  316. package/dist/runtime/utils/chat-model-adapter.d.ts.map +1 -1
  317. package/dist/runtime/utils/external-store-message.d.ts +0 -1
  318. package/dist/runtime/utils/external-store-message.d.ts.map +1 -1
  319. package/dist/runtime/utils/message-repository.d.ts +1 -5
  320. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  321. package/dist/runtime/utils/message-repository.js +3 -1
  322. package/dist/runtime/utils/message-repository.js.map +1 -1
  323. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +0 -1
  324. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
  325. package/dist/runtime/utils/streaming-timing.d.ts +5 -3
  326. package/dist/runtime/utils/streaming-timing.d.ts.map +1 -1
  327. package/dist/runtime/utils/thread-message-like.d.ts +2 -2
  328. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  329. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  330. package/dist/runtimes/assistant-transport/utils.d.ts.map +1 -1
  331. package/dist/runtimes/external-store/external-store-adapter.d.ts +2 -2
  332. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  333. package/dist/runtimes/external-store/external-store-runtime-core.d.ts +0 -1
  334. package/dist/runtimes/external-store/external-store-runtime-core.d.ts.map +1 -1
  335. package/dist/runtimes/external-store/external-store-shared-options.d.ts +0 -1
  336. package/dist/runtimes/external-store/external-store-shared-options.d.ts.map +1 -1
  337. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +0 -1
  338. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  339. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -0
  340. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  341. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +1 -1
  342. package/dist/runtimes/external-store/thread-message-converter.d.ts +0 -1
  343. package/dist/runtimes/external-store/thread-message-converter.d.ts.map +1 -1
  344. package/dist/runtimes/local/local-runtime-core.d.ts +0 -1
  345. package/dist/runtimes/local/local-runtime-core.d.ts.map +1 -1
  346. package/dist/runtimes/local/local-runtime-options.d.ts +0 -1
  347. package/dist/runtimes/local/local-runtime-options.d.ts.map +1 -1
  348. package/dist/runtimes/local/local-thread-list-runtime-core.d.ts +0 -1
  349. package/dist/runtimes/local/local-thread-list-runtime-core.d.ts.map +1 -1
  350. package/dist/runtimes/local/local-thread-runtime-core.d.ts +5 -21
  351. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  352. package/dist/runtimes/local/local-thread-runtime-core.js +24 -15
  353. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  354. package/dist/runtimes/local/should-continue.d.ts +0 -1
  355. package/dist/runtimes/local/should-continue.d.ts.map +1 -1
  356. package/dist/runtimes/local/should-continue.js +2 -2
  357. package/dist/runtimes/local/should-continue.js.map +1 -1
  358. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +0 -1
  359. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  360. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +1 -2
  361. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  362. package/dist/runtimes/remote-thread-list/adapter/in-memory.js +5 -3
  363. package/dist/runtimes/remote-thread-list/adapter/in-memory.js.map +1 -1
  364. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts +0 -1
  365. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  366. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts +6 -4
  367. package/dist/runtimes/remote-thread-list/optimistic-state.d.ts.map +1 -1
  368. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +0 -1
  369. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  370. package/dist/runtimes/remote-thread-list/types.d.ts +0 -1
  371. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  372. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +2 -2
  373. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  374. package/dist/store/clients/chain-of-thought-client.d.ts +0 -1
  375. package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
  376. package/dist/store/clients/model-context-client.d.ts +0 -1
  377. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  378. package/dist/store/clients/no-op-composer-client.d.ts +0 -1
  379. package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
  380. package/dist/store/clients/runtime-adapter.d.ts +0 -1
  381. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  382. package/dist/store/clients/suggestions.d.ts +0 -1
  383. package/dist/store/clients/suggestions.d.ts.map +1 -1
  384. package/dist/store/clients/thread-message-client.d.ts +0 -1
  385. package/dist/store/clients/thread-message-client.d.ts.map +1 -1
  386. package/dist/store/runtime-clients/attachment-runtime-client.d.ts +0 -1
  387. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  388. package/dist/store/runtime-clients/composer-runtime-client.d.ts +0 -1
  389. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  390. package/dist/store/runtime-clients/liveRef.d.ts.map +1 -1
  391. package/dist/store/runtime-clients/message-part-runtime-client.d.ts +0 -1
  392. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  393. package/dist/store/runtime-clients/message-runtime-client.d.ts +0 -1
  394. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  395. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +0 -1
  396. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  397. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +0 -1
  398. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  399. package/dist/store/runtime-clients/thread-runtime-client.d.ts +0 -1
  400. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  401. package/dist/store/runtime-clients/useSubscribable.d.ts +0 -1
  402. package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
  403. package/dist/store/scope-registration.d.ts +1 -2
  404. package/dist/store/scope-registration.d.ts.map +1 -1
  405. package/dist/store/scopes/attachment.d.ts +0 -1
  406. package/dist/store/scopes/attachment.d.ts.map +1 -1
  407. package/dist/store/scopes/chain-of-thought.d.ts +0 -1
  408. package/dist/store/scopes/chain-of-thought.d.ts.map +1 -1
  409. package/dist/store/scopes/composer.d.ts +0 -1
  410. package/dist/store/scopes/composer.d.ts.map +1 -1
  411. package/dist/store/scopes/message.d.ts +6 -4
  412. package/dist/store/scopes/message.d.ts.map +1 -1
  413. package/dist/store/scopes/model-context.d.ts +0 -1
  414. package/dist/store/scopes/model-context.d.ts.map +1 -1
  415. package/dist/store/scopes/part.d.ts +0 -1
  416. package/dist/store/scopes/part.d.ts.map +1 -1
  417. package/dist/store/scopes/queue-item.d.ts.map +1 -1
  418. package/dist/store/scopes/suggestion.d.ts.map +1 -1
  419. package/dist/store/scopes/suggestions.d.ts +0 -1
  420. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  421. package/dist/store/scopes/thread-list-item.d.ts +0 -1
  422. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  423. package/dist/store/scopes/thread.d.ts +4 -3
  424. package/dist/store/scopes/thread.d.ts.map +1 -1
  425. package/dist/store/scopes/threads.d.ts +0 -1
  426. package/dist/store/scopes/threads.d.ts.map +1 -1
  427. package/dist/subscribable/subscribable.d.ts +0 -1
  428. package/dist/subscribable/subscribable.d.ts.map +1 -1
  429. package/dist/tests/remote-thread-list-test-helpers.d.ts +0 -1
  430. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -1
  431. package/dist/types/attachment.d.ts +1 -1
  432. package/dist/types/attachment.d.ts.map +1 -1
  433. package/dist/types/directive.d.ts +3 -2
  434. package/dist/types/directive.d.ts.map +1 -1
  435. package/dist/types/error.d.ts +15 -0
  436. package/dist/types/error.d.ts.map +1 -0
  437. package/dist/types/error.js +46 -0
  438. package/dist/types/error.js.map +1 -0
  439. package/dist/types/index.d.ts +2 -2
  440. package/dist/types/message.d.ts +70 -33
  441. package/dist/types/message.d.ts.map +1 -1
  442. package/dist/types/message.js.map +1 -1
  443. package/dist/types/quote.d.ts.map +1 -1
  444. package/dist/types/trigger.d.ts +0 -1
  445. package/dist/types/trigger.d.ts.map +1 -1
  446. package/dist/types/unsubscribe.d.ts.map +1 -1
  447. package/dist/utils/composite-context-provider.d.ts +1 -0
  448. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  449. package/dist/utils/id.d.ts.map +1 -1
  450. package/dist/utils/json/is-json-equal.d.ts.map +1 -1
  451. package/dist/utils/json/is-json.d.ts +0 -1
  452. package/dist/utils/json/is-json.d.ts.map +1 -1
  453. package/dist/utils/json/is-json.js +1 -1
  454. package/dist/utils/json/is-json.js.map +1 -1
  455. package/dist/utils/json/stable-stringify-tool-args.d.ts +7 -0
  456. package/dist/utils/json/stable-stringify-tool-args.d.ts.map +1 -0
  457. package/dist/utils/json/stable-stringify-tool-args.js +32 -0
  458. package/dist/utils/json/stable-stringify-tool-args.js.map +1 -0
  459. package/dist/utils/text.d.ts +0 -1
  460. package/dist/utils/text.d.ts.map +1 -1
  461. package/package.json +12 -9
  462. package/src/adapters/attachment.test.ts +107 -0
  463. package/src/adapters/attachment.ts +20 -10
  464. package/src/adapters/index.ts +6 -1
  465. package/src/adapters/suggestion.test.ts +187 -0
  466. package/src/adapters/suggestion.ts +75 -1
  467. package/src/index.ts +15 -1
  468. package/src/internal.ts +16 -0
  469. package/src/model-context/tool.test.ts +110 -0
  470. package/src/model-context/tool.ts +31 -9
  471. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +222 -0
  472. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +214 -7
  473. package/src/react/index.ts +2 -0
  474. package/src/react/model-context/define-mcp-toolkit.ts +39 -6
  475. package/src/react/model-context/define-toolkit.test.ts +107 -0
  476. package/src/react/primitive-hooks/useMessageError.test.ts +64 -0
  477. package/src/react/primitive-hooks/useMessageError.ts +19 -6
  478. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +3 -1
  479. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +48 -19
  480. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +111 -0
  481. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +13 -3
  482. package/src/react/runtimes/cloud/auiV0.ts +71 -2
  483. package/src/react/runtimes/external-message-converter.test.tsx +102 -0
  484. package/src/react/runtimes/external-message-converter.ts +35 -10
  485. package/src/runtime/base/base-composer-runtime-core.ts +26 -7
  486. package/src/runtime/utils/message-repository.ts +8 -3
  487. package/src/runtime/utils/thread-message-like.ts +2 -0
  488. package/src/runtimes/local/local-thread-runtime-core.test.ts +127 -3
  489. package/src/runtimes/local/local-thread-runtime-core.ts +25 -23
  490. package/src/runtimes/local/should-continue.ts +5 -2
  491. package/src/runtimes/remote-thread-list/adapter/in-memory.test.ts +14 -0
  492. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +13 -5
  493. package/src/tests/MessageRepository.test.ts +26 -0
  494. package/src/tests/RemoteThreadListThreadListRuntimeCore-errors.test.ts +42 -0
  495. package/src/tests/attachment-adapters.test.ts +14 -2
  496. package/src/tests/auiV0Encode.test.ts +134 -1
  497. package/src/tests/base-composer-runtime-core-addAttachment.test.ts +79 -5
  498. package/src/tests/base-composer-runtime-core-send.test.ts +145 -0
  499. package/src/tests/thread-message-like.test.ts +40 -0
  500. package/src/types/attachment.ts +1 -0
  501. package/src/types/error.test.ts +122 -0
  502. package/src/types/error.ts +74 -0
  503. package/src/types/index.ts +1 -0
  504. package/src/types/message.ts +11 -3
  505. package/src/utils/json/is-json-equal.test.ts +84 -0
  506. package/src/utils/json/is-json.test.ts +123 -0
  507. package/src/utils/json/is-json.ts +1 -1
  508. package/src/utils/json/stable-stringify-tool-args.test.ts +105 -0
  509. package/src/utils/json/stable-stringify-tool-args.ts +70 -0
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect, expectTypeOf } from "vitest";
2
2
  import type { AsyncIterableStream } from "assistant-stream/utils";
3
+ import { defineMcpToolkit } from "./define-mcp-toolkit";
3
4
  import { defineToolkit } from "./define-toolkit";
4
5
  import { hitl, hitlTool, humanTool } from "./human-tool";
5
6
  import { providerTool } from "./provider-tool";
@@ -74,12 +75,118 @@ const checkToolkitDefinitionTypes = () => {
74
75
  };
75
76
  expectTypeOf(checkToolkitDefinitionTypes).toEqualTypeOf<() => void>();
76
77
 
78
+ const checkDefineMcpToolkitTypes = () => {
79
+ defineMcpToolkit({
80
+ docs: {
81
+ type: "http",
82
+ url: "https://example.com/mcp",
83
+ },
84
+ prefixedDocs: {
85
+ server: {
86
+ type: "http",
87
+ url: "https://example.com/prefixed-mcp",
88
+ },
89
+ disabled: true,
90
+ prefix: "docs_",
91
+ },
92
+ gatedDocs: {
93
+ server: {
94
+ type: "http",
95
+ url: "https://example.com/gated-mcp",
96
+ },
97
+ disabled: true,
98
+ tools: {
99
+ privateSearch: {
100
+ disabled: true,
101
+ },
102
+ },
103
+ },
104
+ });
105
+ };
106
+ expectTypeOf(checkDefineMcpToolkitTypes).toEqualTypeOf<() => void>();
107
+
77
108
  describe("use-generative markers", () => {
78
109
  it("defineToolkit returns the toolkit at runtime", () => {
79
110
  const toolkit = {};
80
111
  expect(defineToolkit(toolkit)).toBe(toolkit);
81
112
  });
82
113
 
114
+ it("defineMcpToolkit supports prefixed and disabled MCP entries", () => {
115
+ expect(
116
+ defineMcpToolkit({
117
+ docs: {
118
+ server: { type: "http", url: "https://example.com/mcp" },
119
+ disabled: true,
120
+ prefix: "docs_",
121
+ },
122
+ }),
123
+ ).toEqual({
124
+ docs: {
125
+ type: "mcp",
126
+ server: { type: "http", url: "https://example.com/mcp" },
127
+ disabled: true,
128
+ prefix: "docs_",
129
+ },
130
+ });
131
+ });
132
+
133
+ it("defineMcpToolkit supports disabled server entries", () => {
134
+ expect(
135
+ defineMcpToolkit({
136
+ docs: {
137
+ type: "http",
138
+ url: "https://example.com/mcp",
139
+ },
140
+ gatedDocs: {
141
+ server: {
142
+ type: "http",
143
+ url: "https://example.com/gated-mcp",
144
+ },
145
+ disabled: true,
146
+ tools: {
147
+ privateSearch: {
148
+ disabled: true,
149
+ },
150
+ },
151
+ },
152
+ }),
153
+ ).toEqual({
154
+ docs: {
155
+ type: "mcp",
156
+ server: {
157
+ type: "http",
158
+ url: "https://example.com/mcp",
159
+ },
160
+ },
161
+ gatedDocs: {
162
+ type: "mcp",
163
+ server: {
164
+ type: "http",
165
+ url: "https://example.com/gated-mcp",
166
+ },
167
+ disabled: true,
168
+ tools: {
169
+ privateSearch: {
170
+ disabled: true,
171
+ },
172
+ },
173
+ },
174
+ });
175
+ });
176
+
177
+ it("defineMcpToolkit supports raw MCP server configs", () => {
178
+ expect(
179
+ defineMcpToolkit({
180
+ docs: { type: "http", url: "https://example.com/mcp" },
181
+ }),
182
+ ).toEqual({
183
+ docs: {
184
+ type: "mcp",
185
+ server: { type: "http", url: "https://example.com/mcp" },
186
+ },
187
+ });
188
+ });
189
+
83
190
  it("humanTool throws at runtime — it must be stripped by the compiler, never called", () => {
84
191
  expect(() => humanTool()).toThrow(/no runtime implementation/);
85
192
  });
@@ -0,0 +1,64 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+
3
+ const { mockUseAuiState } = vi.hoisted(() => ({ mockUseAuiState: vi.fn() }));
4
+
5
+ vi.mock("@assistant-ui/store", async (importOriginal) => ({
6
+ ...(await importOriginal<typeof import("@assistant-ui/store")>()),
7
+ useAuiState: ((selector: (s: unknown) => unknown) =>
8
+ mockUseAuiState(
9
+ selector,
10
+ )) as typeof import("@assistant-ui/store").useAuiState,
11
+ }));
12
+
13
+ import { useMessageError } from "./useMessageError";
14
+
15
+ const against = (message: unknown) =>
16
+ mockUseAuiState.mockImplementationOnce((selector: (s: unknown) => unknown) =>
17
+ selector({ message }),
18
+ );
19
+
20
+ describe("useMessageError", () => {
21
+ it("returns the message from a structured AssistantError", () => {
22
+ against({
23
+ status: {
24
+ type: "incomplete",
25
+ reason: "error",
26
+ error: { code: "network", message: "offline" },
27
+ },
28
+ });
29
+ expect(useMessageError()).toBe("offline");
30
+ });
31
+
32
+ it("passes a legacy string error through", () => {
33
+ against({
34
+ status: {
35
+ type: "incomplete",
36
+ reason: "error",
37
+ error: "legacy failure",
38
+ },
39
+ });
40
+ expect(useMessageError()).toBe("legacy failure");
41
+ });
42
+
43
+ it("returns message from an object that fails the full guard", () => {
44
+ against({
45
+ status: {
46
+ type: "incomplete",
47
+ reason: "error",
48
+ error: {
49
+ code: "unknown",
50
+ message: "foreign severity stream",
51
+ severity: "fatal",
52
+ },
53
+ },
54
+ });
55
+ expect(useMessageError()).toBe("foreign severity stream");
56
+ });
57
+
58
+ it("returns undefined when there is no error status", () => {
59
+ against({
60
+ status: { type: "complete", reason: "stop" },
61
+ });
62
+ expect(useMessageError()).toBeUndefined();
63
+ });
64
+ });
@@ -1,10 +1,23 @@
1
1
  import { useAuiState } from "@assistant-ui/store";
2
2
 
3
3
  export const useMessageError = () => {
4
- return useAuiState((s) =>
5
- s.message.status?.type === "incomplete" &&
6
- s.message.status.reason === "error"
7
- ? (s.message.status.error ?? "An error occurred")
8
- : undefined,
9
- );
4
+ return useAuiState((s) => {
5
+ if (
6
+ s.message.status?.type !== "incomplete" ||
7
+ s.message.status.reason !== "error"
8
+ ) {
9
+ return undefined;
10
+ }
11
+ const error = s.message.status.error;
12
+ if (typeof error === "string") return error;
13
+ if (
14
+ typeof error === "object" &&
15
+ error !== null &&
16
+ "message" in error &&
17
+ typeof error.message === "string"
18
+ ) {
19
+ return error.message;
20
+ }
21
+ return error ?? "An error occurred";
22
+ });
10
23
  };
@@ -109,7 +109,9 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
109
109
  const updateRuntime = useCallback(() => {
110
110
  const aliveThread = this.instances.get(threadId);
111
111
  if (!aliveThread)
112
- throw new Error("Thread not found. This is a bug in assistant-ui.");
112
+ throw new Error(
113
+ `Thread "${threadId}" runtime binding not found. This is a bug in assistant-ui.`,
114
+ );
113
115
 
114
116
  aliveThread.runtime = threadBinding.getState();
115
117
  this._notifySubscribers();
@@ -22,6 +22,18 @@ import { AssistantMessageStream } from "assistant-stream";
22
22
  import type { ModelContextProvider } from "../../model-context/types";
23
23
  import { RuntimeAdapterProvider } from "./RuntimeAdapterProvider";
24
24
 
25
+ const threadNotFoundError = (threadIdOrRemoteId: string, action: string) =>
26
+ new Error(`Thread "${threadIdOrRemoteId}" not found while ${action}.`);
27
+
28
+ const threadStatusError = (
29
+ threadIdOrRemoteId: string,
30
+ status: RemoteThreadData["status"],
31
+ action: string,
32
+ ) =>
33
+ new Error(
34
+ `Thread "${threadIdOrRemoteId}" has status "${status}", so it cannot ${action}.`,
35
+ );
36
+
25
37
  export class RemoteThreadListThreadListRuntimeCore
26
38
  extends BaseSubscribable
27
39
  implements ThreadListRuntimeCore
@@ -280,10 +292,14 @@ export class RemoteThreadListThreadListRuntimeCore
280
292
 
281
293
  public getThreadRuntimeCore(threadIdOrRemoteId: string) {
282
294
  const data = this.getItemById(threadIdOrRemoteId);
283
- if (!data) throw new Error("Thread not found");
295
+ if (!data)
296
+ throw threadNotFoundError(threadIdOrRemoteId, "getting its runtime");
284
297
 
285
298
  const result = this._hookManager.getThreadRuntimeCore(data.id);
286
- if (!result) throw new Error("Thread not found");
299
+ if (!result)
300
+ throw new Error(
301
+ `Runtime for thread "${threadIdOrRemoteId}" not found while getting its runtime.`,
302
+ );
287
303
  return result;
288
304
  }
289
305
 
@@ -354,7 +370,7 @@ export class RemoteThreadListThreadListRuntimeCore
354
370
  data = this.getItemById(threadIdOrRemoteId);
355
371
  }
356
372
 
357
- if (!data) throw new Error("Thread not found");
373
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "switching to it");
358
374
  if (this._mainThreadId === data.id) return;
359
375
 
360
376
  const task = this._hookManager.startThreadRuntime(data.id);
@@ -417,8 +433,9 @@ export class RemoteThreadListThreadListRuntimeCore
417
433
  public initialize = async (threadId: string) => {
418
434
  if (this._state.value.newThreadId !== threadId) {
419
435
  const data = this.getItemById(threadId);
420
- if (!data) throw new Error("Thread not found");
421
- if (data.status === "new") throw new Error("Unexpected new state");
436
+ if (!data) throw threadNotFoundError(threadId, "initializing it");
437
+ if (data.status === "new")
438
+ throw threadStatusError(threadId, data.status, "be initialized here");
422
439
  return data.initializeTask;
423
440
  }
424
441
 
@@ -469,8 +486,9 @@ export class RemoteThreadListThreadListRuntimeCore
469
486
 
470
487
  public generateTitle = async (threadId: string) => {
471
488
  const data = this.getItemById(threadId);
472
- if (!data) throw new Error("Thread not found");
473
- if (data.status === "new") throw new Error("Thread is not yet initialized");
489
+ if (!data) throw threadNotFoundError(threadId, "generating its title");
490
+ if (data.status === "new")
491
+ throw threadStatusError(threadId, data.status, "generate a title");
474
492
 
475
493
  const { remoteId } = await data.initializeTask;
476
494
 
@@ -503,8 +521,9 @@ export class RemoteThreadListThreadListRuntimeCore
503
521
 
504
522
  public rename(threadIdOrRemoteId: string, newTitle: string): Promise<void> {
505
523
  const data = this.getItemById(threadIdOrRemoteId);
506
- if (!data) throw new Error("Thread not found");
507
- if (data.status === "new") throw new Error("Thread is not yet initialized");
524
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "renaming it");
525
+ if (data.status === "new")
526
+ throw threadStatusError(threadIdOrRemoteId, data.status, "be renamed");
508
527
 
509
528
  return this._state.optimisticUpdate({
510
529
  execute: async () => {
@@ -534,8 +553,17 @@ export class RemoteThreadListThreadListRuntimeCore
534
553
  custom: Record<string, unknown> | undefined,
535
554
  ): Promise<void> {
536
555
  const data = this.getItemById(threadIdOrRemoteId);
537
- if (!data) throw new Error("Thread not found");
538
- if (data.status === "new") throw new Error("Thread is not yet initialized");
556
+ if (!data)
557
+ throw threadNotFoundError(
558
+ threadIdOrRemoteId,
559
+ "updating its custom metadata",
560
+ );
561
+ if (data.status === "new")
562
+ throw threadStatusError(
563
+ threadIdOrRemoteId,
564
+ data.status,
565
+ "update custom metadata",
566
+ );
539
567
 
540
568
  if (!this._options.adapter.updateCustom) {
541
569
  throw new Error(
@@ -583,9 +611,9 @@ export class RemoteThreadListThreadListRuntimeCore
583
611
 
584
612
  public async archive(threadIdOrRemoteId: string) {
585
613
  const data = this.getItemById(threadIdOrRemoteId);
586
- if (!data) throw new Error("Thread not found");
614
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "archiving it");
587
615
  if (data.status !== "regular")
588
- throw new Error("Thread is not yet initialized or already archived");
616
+ throw threadStatusError(threadIdOrRemoteId, data.status, "be archived");
589
617
 
590
618
  await this._ensureThreadIsNotMain(data.id);
591
619
 
@@ -602,8 +630,9 @@ export class RemoteThreadListThreadListRuntimeCore
602
630
 
603
631
  public unarchive(threadIdOrRemoteId: string): Promise<void> {
604
632
  const data = this.getItemById(threadIdOrRemoteId);
605
- if (!data) throw new Error("Thread not found");
606
- if (data.status !== "archived") throw new Error("Thread is not archived");
633
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "unarchiving it");
634
+ if (data.status !== "archived")
635
+ throw threadStatusError(threadIdOrRemoteId, data.status, "be unarchived");
607
636
 
608
637
  return this._state.optimisticUpdate({
609
638
  execute: async () => {
@@ -623,9 +652,9 @@ export class RemoteThreadListThreadListRuntimeCore
623
652
 
624
653
  public async delete(threadIdOrRemoteId: string) {
625
654
  const data = this.getItemById(threadIdOrRemoteId);
626
- if (!data) throw new Error("Thread not found");
655
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "deleting it");
627
656
  if (data.status !== "regular" && data.status !== "archived")
628
- throw new Error("Thread is not yet initialized");
657
+ throw threadStatusError(threadIdOrRemoteId, data.status, "be deleted");
629
658
 
630
659
  await this._ensureThreadIsNotMain(data.id);
631
660
  this._hookManager.stopThreadRuntime(data.id);
@@ -643,9 +672,9 @@ export class RemoteThreadListThreadListRuntimeCore
643
672
 
644
673
  public async detach(threadIdOrRemoteId: string): Promise<void> {
645
674
  const data = this.getItemById(threadIdOrRemoteId);
646
- if (!data) throw new Error("Thread not found");
675
+ if (!data) throw threadNotFoundError(threadIdOrRemoteId, "detaching it");
647
676
  if (data.status !== "regular" && data.status !== "archived")
648
- throw new Error("Thread is not yet initialized");
677
+ throw threadStatusError(threadIdOrRemoteId, data.status, "be detached");
649
678
 
650
679
  await this._ensureThreadIsNotMain(data.id);
651
680
  this._hookManager.stopThreadRuntime(data.id);
@@ -0,0 +1,111 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import type { AssistantCloud } from "assistant-cloud";
3
+ import type { PendingAttachment } from "../../../types/attachment";
4
+ import { CloudFileAttachmentAdapter } from "./CloudFileAttachmentAdapter";
5
+
6
+ const makeCloud = () =>
7
+ ({
8
+ files: {
9
+ generatePresignedUploadUrl: vi.fn().mockResolvedValue({
10
+ signedUrl: "https://storage.example/upload",
11
+ publicUrl: "https://cdn.example/file.png",
12
+ }),
13
+ },
14
+ }) as unknown as AssistantCloud;
15
+
16
+ const makeFile = () =>
17
+ new File([new Uint8Array([1, 2, 3])], "pixel.png", { type: "image/png" });
18
+
19
+ const drain = async (adapter: CloudFileAttachmentAdapter) => {
20
+ const yields: PendingAttachment[] = [];
21
+ for await (const value of adapter.add({ file: makeFile() })) {
22
+ yields.push(value);
23
+ }
24
+ return yields;
25
+ };
26
+
27
+ describe("CloudFileAttachmentAdapter", () => {
28
+ afterEach(() => {
29
+ vi.unstubAllGlobals();
30
+ vi.restoreAllMocks();
31
+ });
32
+
33
+ it("marks the attachment ready when the upload succeeds", async () => {
34
+ vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: true }));
35
+ const adapter = new CloudFileAttachmentAdapter(makeCloud());
36
+
37
+ const yields = await drain(adapter);
38
+
39
+ expect(yields.at(0)?.status).toEqual({
40
+ type: "running",
41
+ reason: "uploading",
42
+ progress: 0,
43
+ });
44
+ expect(yields.at(-1)?.status).toEqual({
45
+ type: "requires-action",
46
+ reason: "composer-send",
47
+ });
48
+
49
+ const complete = await adapter.send(yields.at(-1)!);
50
+ expect(complete.status).toEqual({ type: "complete" });
51
+ expect(complete.content).toEqual([
52
+ {
53
+ type: "image",
54
+ image: "https://cdn.example/file.png",
55
+ filename: "pixel.png",
56
+ },
57
+ ]);
58
+ });
59
+
60
+ it("marks the attachment incomplete when the upload returns an HTTP error", async () => {
61
+ const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
62
+ vi.stubGlobal(
63
+ "fetch",
64
+ vi.fn().mockResolvedValue({
65
+ ok: false,
66
+ status: 403,
67
+ statusText: "Forbidden",
68
+ }),
69
+ );
70
+ const adapter = new CloudFileAttachmentAdapter(makeCloud());
71
+
72
+ const yields = await drain(adapter);
73
+
74
+ expect(yields.at(-1)?.status).toEqual({
75
+ type: "incomplete",
76
+ reason: "error",
77
+ message: "Failed to upload file: 403 Forbidden",
78
+ });
79
+ expect(errorSpy).toHaveBeenCalledWith(
80
+ "[assistant-ui] Failed to upload attachment:",
81
+ expect.objectContaining({
82
+ message: "Failed to upload file: 403 Forbidden",
83
+ }),
84
+ );
85
+ await expect(adapter.send(yields.at(-1)!)).rejects.toThrow(
86
+ "Attachment not uploaded",
87
+ );
88
+ });
89
+
90
+ it("marks the attachment incomplete when the upload throws", async () => {
91
+ const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
92
+ const uploadError = new Error("network down");
93
+ vi.stubGlobal("fetch", vi.fn().mockRejectedValue(uploadError));
94
+ const adapter = new CloudFileAttachmentAdapter(makeCloud());
95
+
96
+ const yields = await drain(adapter);
97
+
98
+ expect(yields.at(-1)?.status).toEqual({
99
+ type: "incomplete",
100
+ reason: "error",
101
+ message: "network down",
102
+ });
103
+ expect(errorSpy).toHaveBeenCalledWith(
104
+ "[assistant-ui] Failed to upload attachment:",
105
+ uploadError,
106
+ );
107
+ await expect(adapter.send(yields.at(-1)!)).rejects.toThrow(
108
+ "Attachment not uploaded",
109
+ );
110
+ });
111
+ });
@@ -44,7 +44,7 @@ export class CloudFileAttachmentAdapter implements AttachmentAdapter {
44
44
  await this.cloud.files.generatePresignedUploadUrl({
45
45
  filename: file.name,
46
46
  });
47
- await fetch(signedUrl, {
47
+ const res = await fetch(signedUrl, {
48
48
  method: "PUT",
49
49
  body: file,
50
50
  headers: {
@@ -52,16 +52,26 @@ export class CloudFileAttachmentAdapter implements AttachmentAdapter {
52
52
  },
53
53
  mode: "cors",
54
54
  });
55
+ if (!res.ok) {
56
+ throw new Error(
57
+ `Failed to upload file: ${res.status} ${res.statusText}`,
58
+ );
59
+ }
55
60
  this.uploadedUrls.set(id, publicUrl);
56
61
  attachment = {
57
62
  ...attachment,
58
63
  status: { type: "requires-action", reason: "composer-send" },
59
64
  };
60
65
  yield attachment;
61
- } catch {
66
+ } catch (error) {
67
+ console.error("[assistant-ui] Failed to upload attachment:", error);
62
68
  attachment = {
63
69
  ...attachment,
64
- status: { type: "incomplete", reason: "error" },
70
+ status: {
71
+ type: "incomplete",
72
+ reason: "error",
73
+ message: error instanceof Error ? error.message : String(error),
74
+ },
65
75
  };
66
76
  yield attachment;
67
77
  }
@@ -1,8 +1,14 @@
1
1
  import type {
2
+ DataMessagePart,
3
+ FileMessagePart,
4
+ ImageMessagePart,
2
5
  MessageStatus,
3
6
  SourceProviderMetadata,
4
7
  ThreadMessage,
8
+ TextMessagePart,
9
+ Unstable_AudioMessagePart,
5
10
  } from "../../../types/message";
11
+ import type { CompleteAttachment } from "../../../types/attachment";
6
12
  import { fromThreadMessageLike } from "../../../runtime/utils/thread-message-like";
7
13
  import type { CloudMessage } from "assistant-cloud";
8
14
  import { isJSONValue } from "../../../utils/json/is-json";
@@ -65,10 +71,27 @@ type AuiV0MessagePart =
65
71
  readonly filename?: string;
66
72
  };
67
73
 
74
+ type AuiV0AttachmentPart =
75
+ | TextMessagePart
76
+ | ImageMessagePart
77
+ | FileMessagePart
78
+ | Unstable_AudioMessagePart
79
+ | DataMessagePart<ReadonlyJSONValue>;
80
+
81
+ type AuiV0Attachment = {
82
+ readonly id: string;
83
+ readonly type: CompleteAttachment["type"];
84
+ readonly name: string;
85
+ readonly contentType?: string;
86
+ readonly status: CompleteAttachment["status"];
87
+ readonly content: readonly AuiV0AttachmentPart[];
88
+ };
89
+
68
90
  type AuiV0Message = {
69
91
  readonly role: "assistant" | "user" | "system";
70
92
  readonly status?: MessageStatus;
71
93
  readonly content: readonly AuiV0MessagePart[];
94
+ readonly attachments?: readonly AuiV0Attachment[];
72
95
  readonly metadata: {
73
96
  readonly unstable_state?: ReadonlyJSONValue;
74
97
  readonly unstable_annotations: readonly ReadonlyJSONValue[];
@@ -83,14 +106,59 @@ type AuiV0Message = {
83
106
  };
84
107
  };
85
108
 
109
+ const encodeAttachmentPart = (
110
+ part: CompleteAttachment["content"][number],
111
+ ): AuiV0AttachmentPart => {
112
+ const type = part.type;
113
+ switch (type) {
114
+ case "text":
115
+ case "image":
116
+ case "file":
117
+ case "audio":
118
+ return part;
119
+
120
+ case "data": {
121
+ if (!isJSONValue(part.data)) {
122
+ console.warn(`attachment data is not JSON! ${JSON.stringify(part)}`);
123
+ }
124
+ return { ...part, data: part.data as ReadonlyJSONValue };
125
+ }
126
+
127
+ default: {
128
+ const unhandledType: never = type;
129
+ throw new Error(
130
+ `Attachment part type not supported by aui/v0: ${unhandledType}`,
131
+ );
132
+ }
133
+ }
134
+ };
135
+
136
+ const encodeAttachments = (
137
+ message: ThreadMessage,
138
+ ): readonly AuiV0Attachment[] | undefined => {
139
+ if (message.role !== "user" || message.attachments.length === 0) {
140
+ return undefined;
141
+ }
142
+
143
+ return message.attachments.map(
144
+ ({ id, type, name, contentType, status, content }) => ({
145
+ id,
146
+ type,
147
+ name,
148
+ status,
149
+ ...(contentType != null ? { contentType } : undefined),
150
+ content: content.map(encodeAttachmentPart),
151
+ }),
152
+ );
153
+ };
154
+
86
155
  export function auiV0Encode(message: ThreadMessage): AuiV0Message {
87
- // TODO attachments are currently intentionally ignored
88
156
  // info: ID and createdAt are ignored (we use the server value instead)
89
-
90
157
  const status: MessageStatus | undefined =
91
158
  message.status?.type === "running"
92
159
  ? { type: "incomplete", reason: "cancelled" }
93
160
  : message.status;
161
+ const attachments = encodeAttachments(message);
94
162
 
95
163
  return {
96
164
  role: message.role,
@@ -172,6 +240,7 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
172
240
  }),
173
241
  metadata: message.metadata as AuiV0Message["metadata"],
174
242
  ...(status ? { status } : undefined),
243
+ ...(attachments ? { attachments } : undefined),
175
244
  };
176
245
  }
177
246