@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
@@ -0,0 +1,107 @@
1
+ import { afterEach, describe, expect, it } from "vitest";
2
+ import { getFileDataURL, SimpleImageAttachmentAdapter } from "./attachment";
3
+
4
+ const originalFileReader = globalThis.FileReader;
5
+ const originalBuffer = globalThis.Buffer;
6
+
7
+ afterEach(() => {
8
+ globalThis.FileReader = originalFileReader;
9
+ globalThis.Buffer = originalBuffer;
10
+ });
11
+
12
+ describe("getFileDataURL", () => {
13
+ it("uses FileReader when available", async () => {
14
+ class FakeFileReader {
15
+ result: string | null = null;
16
+ onload: (() => void) | null = null;
17
+ onerror: ((error: unknown) => void) | null = null;
18
+ readAsDataURL(file: File) {
19
+ file
20
+ .arrayBuffer()
21
+ .then((buf) => {
22
+ this.result = `data:${file.type};base64,${originalBuffer.from(buf).toString("base64")}`;
23
+ this.onload?.();
24
+ })
25
+ .catch((error) => this.onerror?.(error));
26
+ }
27
+ }
28
+ globalThis.FileReader = FakeFileReader as unknown as typeof FileReader;
29
+
30
+ const file = new File(["hello"], "a.txt", { type: "text/plain" });
31
+ expect(await getFileDataURL(file)).toBe(
32
+ `data:text/plain;base64,${originalBuffer.from("hello").toString("base64")}`,
33
+ );
34
+ });
35
+
36
+ it("falls back to Buffer when FileReader is absent", async () => {
37
+ globalThis.FileReader = undefined as unknown as typeof FileReader;
38
+
39
+ const file = new File(["hello"], "a.txt", { type: "text/plain" });
40
+ expect(await getFileDataURL(file)).toBe(
41
+ `data:text/plain;base64,${originalBuffer.from("hello").toString("base64")}`,
42
+ );
43
+ });
44
+
45
+ it("defaults to application/octet-stream when the file has no type", async () => {
46
+ globalThis.FileReader = undefined as unknown as typeof FileReader;
47
+
48
+ const file = new File(["hello"], "a.bin", { type: "" });
49
+ expect(await getFileDataURL(file)).toBe(
50
+ `data:application/octet-stream;base64,${originalBuffer.from("hello").toString("base64")}`,
51
+ );
52
+ });
53
+
54
+ it("falls back to chunked btoa when neither FileReader nor Buffer exist", async () => {
55
+ globalThis.FileReader = undefined as unknown as typeof FileReader;
56
+ globalThis.Buffer = undefined as unknown as typeof Buffer;
57
+
58
+ const file = new File(["hello"], "a.txt", { type: "text/plain" });
59
+ expect(await getFileDataURL(file)).toBe(
60
+ `data:text/plain;base64,${originalBuffer.from("hello").toString("base64")}`,
61
+ );
62
+ });
63
+
64
+ it("encodes large inputs without RangeError on the btoa path", async () => {
65
+ globalThis.FileReader = undefined as unknown as typeof FileReader;
66
+ globalThis.Buffer = undefined as unknown as typeof Buffer;
67
+
68
+ const bytes = new Uint8Array(100_000);
69
+ for (let i = 0; i < bytes.length; i++) bytes[i] = i % 256;
70
+ const file = new File([bytes], "big.bin", {
71
+ type: "application/octet-stream",
72
+ });
73
+
74
+ expect(await getFileDataURL(file)).toBe(
75
+ `data:application/octet-stream;base64,${originalBuffer.from(bytes).toString("base64")}`,
76
+ );
77
+ });
78
+ });
79
+
80
+ describe("SimpleImageAttachmentAdapter", () => {
81
+ it("assigns unique IDs to files with the same name", async () => {
82
+ const adapter = new SimpleImageAttachmentAdapter();
83
+ const first = await adapter.add({
84
+ file: new File(["first"], "image.png", { type: "image/png" }),
85
+ });
86
+ const second = await adapter.add({
87
+ file: new File(["second"], "image.png", { type: "image/png" }),
88
+ });
89
+
90
+ expect(first.id).not.toBe(second.id);
91
+ expect(first.name).toBe("image.png");
92
+ expect(second.name).toBe("image.png");
93
+ });
94
+
95
+ it("sends an image as a data URL", async () => {
96
+ globalThis.FileReader = undefined as unknown as typeof FileReader;
97
+
98
+ const file = new File(["img"], "a.png", { type: "image/png" });
99
+ const adapter = new SimpleImageAttachmentAdapter();
100
+ const result = await adapter.send(await adapter.add({ file }));
101
+ const part = result.content[0];
102
+ if (part?.type !== "image") throw new Error("expected image content part");
103
+ expect(part.image).toBe(
104
+ `data:image/png;base64,${originalBuffer.from("img").toString("base64")}`,
105
+ );
106
+ });
107
+ });
@@ -20,7 +20,7 @@ export class SimpleImageAttachmentAdapter implements AttachmentAdapter {
20
20
 
21
21
  public async add(state: { file: File }): Promise<PendingAttachment> {
22
22
  return {
23
- id: state.file.name,
23
+ id: generateId(),
24
24
  type: "image",
25
25
  name: state.file.name,
26
26
  contentType: state.file.type,
@@ -49,21 +49,31 @@ export class SimpleImageAttachmentAdapter implements AttachmentAdapter {
49
49
  }
50
50
  }
51
51
 
52
- const bytesToBase64 = (bytes: Uint8Array): string =>
53
- (
52
+ const bytesToBase64 = (bytes: Uint8Array): string => {
53
+ const nodeBuffer = (
54
54
  globalThis as {
55
- Buffer: {
55
+ Buffer?: {
56
56
  from(bytes: Uint8Array): { toString(encoding: string): string };
57
57
  };
58
58
  }
59
- ).Buffer.from(bytes).toString("base64");
59
+ ).Buffer;
60
+ if (nodeBuffer) {
61
+ return nodeBuffer.from(bytes).toString("base64");
62
+ }
63
+ let binary = "";
64
+ const chunkSize = 0x8000;
65
+ for (let i = 0; i < bytes.length; i += chunkSize) {
66
+ binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
67
+ }
68
+ return btoa(binary);
69
+ };
60
70
 
61
71
  // React Native's Blob polyfill has FileReader but not file.text()/arrayBuffer(); Node has
62
72
  // the reverse. Prefer FileReader when present, falling back to the Blob methods otherwise.
63
- const getFileDataURL = async (file: File): Promise<string> => {
73
+ export const getFileDataURL = async (file: File): Promise<string> => {
64
74
  if (typeof FileReader === "undefined") {
65
75
  const buffer = await file.arrayBuffer();
66
- return `data:${file.type};base64,${bytesToBase64(new Uint8Array(buffer))}`;
76
+ return `data:${file.type || "application/octet-stream"};base64,${bytesToBase64(new Uint8Array(buffer))}`;
67
77
  }
68
78
  return new Promise<string>((resolve, reject) => {
69
79
  const reader = new FileReader();
@@ -75,11 +85,11 @@ const getFileDataURL = async (file: File): Promise<string> => {
75
85
 
76
86
  export class SimpleTextAttachmentAdapter implements AttachmentAdapter {
77
87
  public accept =
78
- "text/plain,text/html,text/markdown,text/csv,text/xml,text/json,text/css";
88
+ "text/plain,text/html,text/markdown,text/csv,text/xml,text/json,application/json,text/css";
79
89
 
80
90
  public async add(state: { file: File }): Promise<PendingAttachment> {
81
91
  return {
82
- id: state.file.name,
92
+ id: generateId(),
83
93
  type: "document",
84
94
  name: state.file.name,
85
95
  contentType: state.file.type,
@@ -133,7 +143,7 @@ export function fileMatchesAccept(
133
143
  .map((type) => type.trim().toLowerCase());
134
144
 
135
145
  const fileExtension = `.${file.name.split(".").pop()!.toLowerCase()}`;
136
- const fileMimeType = file.type.toLowerCase();
146
+ const fileMimeType = file.type.split(";", 1)[0]!.trim().toLowerCase();
137
147
 
138
148
  for (const type of allowedTypes) {
139
149
  if (type.startsWith(".") && type === fileExtension) {
@@ -19,7 +19,12 @@ export type { VoiceSessionControls, VoiceSessionHelpers } from "./voice";
19
19
  export type { FeedbackAdapter } from "./feedback";
20
20
 
21
21
  // Suggestion adapter
22
- export type { SuggestionAdapter } from "./suggestion";
22
+ export type {
23
+ SuggestionAdapter,
24
+ SuggestionAdapterGenerateOptions,
25
+ CreateSuggestionAdapterOptions,
26
+ } from "./suggestion";
27
+ export { createSuggestionAdapter } from "./suggestion";
23
28
 
24
29
  // Trigger adapter (generic)
25
30
  export type { Unstable_TriggerAdapter } from "./trigger";
@@ -0,0 +1,187 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { consumeSuggestionResult, createSuggestionAdapter } from "./suggestion";
3
+ import type { ThreadMessage } from "../types/message";
4
+ import type { ThreadSuggestion } from "../runtime/interfaces/thread-runtime-core";
5
+
6
+ const message = (
7
+ role: "user" | "assistant" | "system",
8
+ text: string,
9
+ id = `${role}-${text}`,
10
+ ): ThreadMessage =>
11
+ ({
12
+ id,
13
+ role,
14
+ content: text ? [{ type: "text", text }] : [],
15
+ createdAt: new Date(),
16
+ status:
17
+ role === "assistant" ? { type: "complete", reason: "stop" } : undefined,
18
+ metadata: {
19
+ unstable_state: null,
20
+ unstable_annotations: [],
21
+ unstable_data: [],
22
+ custom: {},
23
+ },
24
+ }) as unknown as ThreadMessage;
25
+
26
+ describe("createSuggestionAdapter", () => {
27
+ it("builds a role-labeled transcript from recent messages and honors maxMessages", async () => {
28
+ const complete = vi.fn().mockResolvedValue(["follow up"]);
29
+ const adapter = createSuggestionAdapter({ complete, maxMessages: 2 });
30
+
31
+ await adapter.generate({
32
+ messages: [
33
+ message("user", "first"),
34
+ message("assistant", "second"),
35
+ message("user", "third"),
36
+ message("assistant", "fourth"),
37
+ ],
38
+ });
39
+
40
+ expect(complete).toHaveBeenCalledTimes(1);
41
+ const prompt = complete.mock.calls[0]![0].prompt as string;
42
+ expect(prompt).toContain("user: third");
43
+ expect(prompt).toContain("assistant: fourth");
44
+ expect(prompt).not.toContain("user: first");
45
+ expect(prompt).not.toContain("assistant: second");
46
+ });
47
+
48
+ it("skips messages with empty text in the transcript", async () => {
49
+ const complete = vi.fn().mockResolvedValue(["follow up"]);
50
+ const adapter = createSuggestionAdapter({ complete });
51
+
52
+ await adapter.generate({
53
+ messages: [
54
+ message("user", "hello"),
55
+ message("assistant", ""),
56
+ message("user", "again"),
57
+ ],
58
+ });
59
+
60
+ const prompt = complete.mock.calls[0]![0].prompt as string;
61
+ expect(prompt).toContain("user: hello");
62
+ expect(prompt).toContain("user: again");
63
+ expect(prompt).not.toMatch(/^assistant:/m);
64
+ });
65
+
66
+ it("includes count and instructions in the prompt", async () => {
67
+ const complete = vi.fn().mockResolvedValue(["a", "b", "c", "d", "e"]);
68
+ const adapter = createSuggestionAdapter({
69
+ complete,
70
+ count: 5,
71
+ instructions: "Prefer short product questions",
72
+ });
73
+
74
+ await adapter.generate({
75
+ messages: [message("user", "hello")],
76
+ });
77
+
78
+ const prompt = complete.mock.calls[0]![0].prompt as string;
79
+ expect(prompt).toContain("exactly 5");
80
+ expect(prompt).toContain("Prefer short product questions");
81
+ });
82
+
83
+ it("trims, drops empties, and clamps results to count", async () => {
84
+ const complete = vi
85
+ .fn()
86
+ .mockResolvedValue([" one ", "", " ", "two", "three", "four"]);
87
+ const adapter = createSuggestionAdapter({ complete, count: 2 });
88
+
89
+ const result = await adapter.generate({
90
+ messages: [message("user", "hello")],
91
+ });
92
+
93
+ expect(result).toEqual([{ prompt: "one" }, { prompt: "two" }]);
94
+ });
95
+
96
+ it("forwards the generate signal to complete when defined", async () => {
97
+ const complete = vi.fn().mockResolvedValue(["ok"]);
98
+ const adapter = createSuggestionAdapter({ complete });
99
+ const controller = new AbortController();
100
+
101
+ await adapter.generate({
102
+ messages: [message("user", "hello")],
103
+ signal: controller.signal,
104
+ });
105
+
106
+ expect(complete).toHaveBeenCalledWith({
107
+ prompt: expect.any(String),
108
+ signal: controller.signal,
109
+ });
110
+ });
111
+
112
+ it("omits signal from complete options when generate has no signal", async () => {
113
+ const complete = vi.fn().mockResolvedValue(["ok"]);
114
+ const adapter = createSuggestionAdapter({ complete });
115
+
116
+ await adapter.generate({
117
+ messages: [message("user", "hello")],
118
+ });
119
+
120
+ expect(complete).toHaveBeenCalledWith({
121
+ prompt: expect.any(String),
122
+ });
123
+ expect(complete.mock.calls[0]![0]).not.toHaveProperty("signal");
124
+ });
125
+
126
+ it("treats maxMessages 0 as an empty transcript while still calling complete", async () => {
127
+ const complete = vi.fn().mockResolvedValue(["follow up"]);
128
+ const adapter = createSuggestionAdapter({ complete, maxMessages: 0 });
129
+
130
+ await adapter.generate({
131
+ messages: [message("user", "first"), message("assistant", "second")],
132
+ });
133
+
134
+ expect(complete).toHaveBeenCalledTimes(1);
135
+ const prompt = complete.mock.calls[0]![0].prompt as string;
136
+ expect(prompt).toContain("Conversation:\n");
137
+ expect(prompt).not.toContain("user: first");
138
+ expect(prompt).not.toContain("assistant: second");
139
+ expect(prompt).toContain("exactly 3");
140
+ });
141
+ });
142
+
143
+ describe("consumeSuggestionResult", () => {
144
+ it("calls onUpdate for each yield and stops after abort mid-stream", async () => {
145
+ const controller = new AbortController();
146
+ const updates: ThreadSuggestion[][] = [];
147
+ const onUpdate = vi.fn((s: readonly ThreadSuggestion[]) => {
148
+ updates.push([...s]);
149
+ });
150
+
151
+ async function* generate() {
152
+ yield [{ prompt: "one" }];
153
+ yield [{ prompt: "two" }];
154
+ controller.abort();
155
+ yield [{ prompt: "three" }];
156
+ yield [{ prompt: "four" }];
157
+ }
158
+
159
+ await consumeSuggestionResult(generate(), {
160
+ signal: controller.signal,
161
+ onUpdate,
162
+ });
163
+
164
+ expect(onUpdate).toHaveBeenCalledTimes(2);
165
+ expect(updates).toEqual([[{ prompt: "one" }], [{ prompt: "two" }]]);
166
+ });
167
+
168
+ it("drops the promise result when aborted before resolve", async () => {
169
+ const controller = new AbortController();
170
+ const onUpdate = vi.fn();
171
+ let resolve!: (value: readonly ThreadSuggestion[]) => void;
172
+ const promise = new Promise<readonly ThreadSuggestion[]>((r) => {
173
+ resolve = r;
174
+ });
175
+
176
+ const consumption = consumeSuggestionResult(promise, {
177
+ signal: controller.signal,
178
+ onUpdate,
179
+ });
180
+
181
+ controller.abort();
182
+ resolve([{ prompt: "late" }]);
183
+ await consumption;
184
+
185
+ expect(onUpdate).not.toHaveBeenCalled();
186
+ });
187
+ });
@@ -1,8 +1,10 @@
1
1
  import type { ThreadMessage } from "../types/message";
2
2
  import type { ThreadSuggestion } from "../runtime/interfaces/thread-runtime-core";
3
+ import { getThreadMessageText } from "../utils/text";
3
4
 
4
- type SuggestionAdapterGenerateOptions = {
5
+ export type SuggestionAdapterGenerateOptions = {
5
6
  messages: readonly ThreadMessage[];
7
+ signal?: AbortSignal;
6
8
  };
7
9
 
8
10
  export type SuggestionAdapter = {
@@ -12,3 +14,75 @@ export type SuggestionAdapter = {
12
14
  | Promise<readonly ThreadSuggestion[]>
13
15
  | AsyncGenerator<readonly ThreadSuggestion[], void>;
14
16
  };
17
+
18
+ export const consumeSuggestionResult = async (
19
+ result: ReturnType<SuggestionAdapter["generate"]>,
20
+ options: {
21
+ signal: AbortSignal;
22
+ onUpdate: (suggestions: readonly ThreadSuggestion[]) => void;
23
+ },
24
+ ): Promise<void> => {
25
+ const { signal, onUpdate } = options;
26
+ if (Symbol.asyncIterator in result) {
27
+ for await (const r of result) {
28
+ if (signal.aborted) break;
29
+ onUpdate(r);
30
+ }
31
+ } else {
32
+ const suggestions = await result;
33
+ if (signal.aborted) return;
34
+ onUpdate(suggestions);
35
+ }
36
+ };
37
+
38
+ export type CreateSuggestionAdapterOptions = {
39
+ complete: (options: {
40
+ prompt: string;
41
+ signal?: AbortSignal;
42
+ }) => Promise<readonly string[]>;
43
+ count?: number | undefined;
44
+ instructions?: string | undefined;
45
+ maxMessages?: number | undefined;
46
+ };
47
+
48
+ export const createSuggestionAdapter = (
49
+ options: CreateSuggestionAdapterOptions,
50
+ ): SuggestionAdapter => {
51
+ const count = options.count ?? 3;
52
+ const maxMessages = options.maxMessages ?? 10;
53
+
54
+ return {
55
+ async generate({ messages, signal }) {
56
+ const limit = Math.max(0, Math.floor(maxMessages));
57
+ const recent = limit === 0 ? [] : messages.slice(-limit);
58
+ const transcript = recent
59
+ .map((message) => {
60
+ const text = getThreadMessageText(message).trim();
61
+ if (!text) return null;
62
+ return `${message.role}: ${text}`;
63
+ })
64
+ .filter((line): line is string => line != null)
65
+ .join("\n");
66
+
67
+ let prompt =
68
+ `Based on the following conversation, suggest exactly ${count} short follow-up prompts that the USER would plausibly send next. ` +
69
+ `Write each prompt in the user's voice as something they would type. ` +
70
+ `Return only the prompts, one per line, with no numbering or extra commentary.\n\n` +
71
+ `Conversation:\n${transcript}`;
72
+
73
+ if (options.instructions) {
74
+ prompt += `\n\nAdditional instructions:\n${options.instructions}`;
75
+ }
76
+
77
+ const results = await options.complete({
78
+ prompt,
79
+ ...(signal !== undefined && { signal }),
80
+ });
81
+ return results
82
+ .map((s) => s.trim())
83
+ .filter((s) => s.length > 0)
84
+ .slice(0, count)
85
+ .map((text) => ({ prompt: text }));
86
+ },
87
+ };
88
+ };
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export type {
12
12
  // Message parts
13
13
  TextMessagePart,
14
14
  ReasoningMessagePart,
15
+ PartProviderMetadata,
15
16
  SourceProviderMetadata,
16
17
  SourceMessagePart,
17
18
  ImageMessagePart,
@@ -149,7 +150,12 @@ export type {
149
150
  export type { FeedbackAdapter } from "./adapters/feedback";
150
151
 
151
152
  // Suggestion adapter
152
- export type { SuggestionAdapter } from "./adapters/suggestion";
153
+ export type {
154
+ SuggestionAdapter,
155
+ SuggestionAdapterGenerateOptions,
156
+ CreateSuggestionAdapterOptions,
157
+ } from "./adapters/suggestion";
158
+ export { createSuggestionAdapter } from "./adapters/suggestion";
153
159
 
154
160
  // Directive formatter
155
161
  export { unstable_defaultDirectiveFormatter } from "./adapters/directive-formatter";
@@ -188,6 +194,14 @@ export type {
188
194
  ThreadComposerRuntimeCore,
189
195
  } from "./runtime/interfaces/composer-runtime-core";
190
196
 
197
+ export type {
198
+ ErrorSeverity,
199
+ ErrorDisplay,
200
+ AssistantErrorCode,
201
+ AssistantError,
202
+ } from "./types/error";
203
+ export { toAssistantError, isAssistantError } from "./types/error";
204
+
191
205
  export type {
192
206
  RuntimeCapabilities,
193
207
  AddToolResultOptions,
package/src/internal.ts CHANGED
@@ -33,10 +33,26 @@ export {
33
33
  // Message utilities
34
34
  export { getThreadMessageText } from "./utils/text";
35
35
  export { resolveToolApprovalResponse } from "./runtime/utils/resolveToolApprovalResponse";
36
+ export { consumeSuggestionResult } from "./adapters/suggestion";
36
37
 
37
38
  // Composite context provider
38
39
  export { CompositeContextProvider } from "./utils/composite-context-provider";
39
40
 
41
+ // Shared attachment data-URL encoder, reused by framework adapters so the
42
+ // FileReader fallback lives in one place.
43
+ export { getFileDataURL } from "./adapters/attachment";
44
+
45
+ // Streaming-stable tool-args stringifier, reused by framework adapters so the
46
+ // key-order stabilization lives in one place.
47
+ export {
48
+ stableStringifyToolArgs,
49
+ trackToolArgsKeyOrder,
50
+ } from "./utils/json/stable-stringify-tool-args";
51
+
52
+ // JSON type guards, reused by framework bindings so the depth-guarded
53
+ // validation lives in one place.
54
+ export { isJSONValue, isRecord } from "./utils/json/is-json";
55
+
40
56
  // Runtime extras helper for external-store adapters. Internal because the
41
57
  // tap-native runtime path replaces the `thread.extras` side-channel it wraps.
42
58
  export {
@@ -0,0 +1,110 @@
1
+ import { describe, expect, expectTypeOf, it } from "vitest";
2
+ import type { Tool } from "assistant-stream";
3
+ import type { AsyncIterableStream } from "assistant-stream/utils";
4
+ import { tool } from "./tool";
5
+
6
+ type TestStandardSchema<TInput> = {
7
+ readonly "~standard": {
8
+ readonly version: 1;
9
+ readonly vendor: "test";
10
+ readonly types?: {
11
+ readonly input: TInput;
12
+ readonly output: TInput;
13
+ };
14
+ readonly validate: (value: unknown) => { readonly value: TInput };
15
+ };
16
+ };
17
+
18
+ const checkStandardSchemaInference = () => {
19
+ const weatherSchema = {} as TestStandardSchema<{
20
+ city: string;
21
+ unit?: "c" | "f";
22
+ tags: string[];
23
+ }>;
24
+
25
+ const getWeather = tool({
26
+ type: "frontend",
27
+ parameters: weatherSchema,
28
+ execute: async (args) => {
29
+ expectTypeOf(args.city).toEqualTypeOf<string>();
30
+ expectTypeOf(args.unit).toEqualTypeOf<"c" | "f" | undefined>();
31
+ expectTypeOf(args.tags).toEqualTypeOf<string[]>();
32
+ // @ts-expect-error unknown schema fields should not be accepted
33
+ void args.missing;
34
+
35
+ return `Weather in ${args.city}`;
36
+ },
37
+ streamCall: async (reader) => {
38
+ const city = await reader.args.get("city");
39
+ expectTypeOf(city).toEqualTypeOf<string>();
40
+ expectTypeOf(reader.args.forEach("tags")).toEqualTypeOf<
41
+ AsyncIterableStream<string>
42
+ >();
43
+ // @ts-expect-error unknown argument paths should not be accepted
44
+ reader.args.get("missing");
45
+ },
46
+ toModelOutput: ({ input }) => {
47
+ expectTypeOf(input.city).toEqualTypeOf<string>();
48
+ expectTypeOf(input.unit).toEqualTypeOf<"c" | "f" | undefined>();
49
+ return [{ type: "text", text: input.city }];
50
+ },
51
+ });
52
+
53
+ expectTypeOf(getWeather).toEqualTypeOf<
54
+ Tool<
55
+ {
56
+ city: string;
57
+ unit?: "c" | "f";
58
+ tags: string[];
59
+ },
60
+ string
61
+ >
62
+ >();
63
+ };
64
+ expectTypeOf(checkStandardSchemaInference).toEqualTypeOf<() => void>();
65
+
66
+ const checkUnknownStandardSchemaInputFallsBackToRecord = () => {
67
+ const unknownSchema = {} as TestStandardSchema<unknown>;
68
+
69
+ const passthrough = tool({
70
+ type: "frontend",
71
+ parameters: unknownSchema,
72
+ execute: async (args) => {
73
+ expectTypeOf(args).toEqualTypeOf<Record<string, unknown>>();
74
+ return args;
75
+ },
76
+ });
77
+
78
+ expectTypeOf(passthrough).toEqualTypeOf<
79
+ Tool<Record<string, unknown>, Record<string, unknown>>
80
+ >();
81
+ };
82
+ expectTypeOf(checkUnknownStandardSchemaInputFallsBackToRecord).toEqualTypeOf<
83
+ () => void
84
+ >();
85
+
86
+ const checkExplicitJsonSchemaTypesStillWork = () => {
87
+ const getWeather = tool<{ city: string }, string>({
88
+ type: "frontend",
89
+ parameters: {
90
+ type: "object",
91
+ properties: { city: { type: "string" } },
92
+ required: ["city"],
93
+ },
94
+ execute: async ({ city }) => city,
95
+ });
96
+
97
+ expectTypeOf(getWeather).toEqualTypeOf<Tool<{ city: string }, string>>();
98
+ };
99
+ expectTypeOf(checkExplicitJsonSchemaTypesStillWork).toEqualTypeOf<() => void>();
100
+
101
+ describe("tool", () => {
102
+ it("returns the tool definition at runtime", () => {
103
+ const definition = {
104
+ type: "frontend" as const,
105
+ parameters: { type: "object" as const, properties: {} },
106
+ };
107
+
108
+ expect(tool(definition)).toBe(definition);
109
+ });
110
+ });