@assistant-ui/core 0.2.9 → 0.2.11

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 (437) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/attachment.js +22 -12
  3. package/dist/adapters/attachment.js.map +1 -1
  4. package/dist/adapters/directive-formatter.js.map +1 -1
  5. package/dist/adapters/speech.js.map +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal.js +1 -1
  10. package/dist/model-context/frame/host.js.map +1 -1
  11. package/dist/model-context/frame/provider.js.map +1 -1
  12. package/dist/model-context/registry.js.map +1 -1
  13. package/dist/model-context/tool.d.ts +1 -1
  14. package/dist/model-context/tool.js +1 -1
  15. package/dist/model-context/tool.js.map +1 -1
  16. package/dist/model-context/types.js +17 -2
  17. package/dist/model-context/types.js.map +1 -1
  18. package/dist/react/AssistantProvider.js +1 -1
  19. package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
  20. package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
  21. package/dist/react/AssistantRuntimeProvider.js +1 -1
  22. package/dist/react/RuntimeAdapter.js +4 -2
  23. package/dist/react/RuntimeAdapter.js.map +1 -1
  24. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  25. package/dist/react/adapters/LocalStorageThreadListAdapter.js +13 -3
  26. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  27. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  28. package/dist/react/client/DataRenderers.js +6 -5
  29. package/dist/react/client/DataRenderers.js.map +1 -1
  30. package/dist/react/client/Interactables.d.ts.map +1 -1
  31. package/dist/react/client/Interactables.js +30 -29
  32. package/dist/react/client/Interactables.js.map +1 -1
  33. package/dist/react/client/Tools.d.ts.map +1 -1
  34. package/dist/react/client/Tools.js +19 -12
  35. package/dist/react/client/Tools.js.map +1 -1
  36. package/dist/react/index.d.ts +10 -5
  37. package/dist/react/index.js +7 -2
  38. package/dist/react/model-context/define-mcp-toolkit.d.ts +12 -0
  39. package/dist/react/model-context/define-mcp-toolkit.d.ts.map +1 -0
  40. package/dist/react/model-context/define-mcp-toolkit.js +14 -0
  41. package/dist/react/model-context/define-mcp-toolkit.js.map +1 -0
  42. package/dist/react/model-context/define-toolkit.d.ts +10 -12
  43. package/dist/react/model-context/define-toolkit.d.ts.map +1 -1
  44. package/dist/react/model-context/define-toolkit.js +2 -15
  45. package/dist/react/model-context/define-toolkit.js.map +1 -1
  46. package/dist/react/model-context/external-tool.d.ts +14 -0
  47. package/dist/react/model-context/external-tool.d.ts.map +1 -0
  48. package/dist/react/model-context/external-tool.js +17 -0
  49. package/dist/react/model-context/external-tool.js.map +1 -0
  50. package/dist/react/model-context/human-tool.d.ts +27 -0
  51. package/dist/react/model-context/human-tool.d.ts.map +1 -0
  52. package/dist/react/model-context/human-tool.js +30 -0
  53. package/dist/react/model-context/human-tool.js.map +1 -0
  54. package/dist/react/model-context/makeAssistantTool.d.ts +8 -0
  55. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  56. package/dist/react/model-context/makeAssistantTool.js +4 -0
  57. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  58. package/dist/react/model-context/makeAssistantToolUI.d.ts +8 -0
  59. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  60. package/dist/react/model-context/makeAssistantToolUI.js +4 -0
  61. package/dist/react/model-context/makeAssistantToolUI.js.map +1 -1
  62. package/dist/react/model-context/provider-tool.d.ts +15 -0
  63. package/dist/react/model-context/provider-tool.d.ts.map +1 -0
  64. package/dist/react/model-context/provider-tool.js +12 -0
  65. package/dist/react/model-context/provider-tool.js.map +1 -0
  66. package/dist/react/model-context/stub-tool.d.ts +12 -0
  67. package/dist/react/model-context/stub-tool.d.ts.map +1 -0
  68. package/dist/react/model-context/stub-tool.js +15 -0
  69. package/dist/react/model-context/stub-tool.js.map +1 -0
  70. package/dist/react/model-context/toolbox.d.ts +64 -17
  71. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  72. package/dist/react/model-context/toolbox.js +19 -1
  73. package/dist/react/model-context/toolbox.js.map +1 -1
  74. package/dist/react/model-context/useAssistantContext.js +1 -1
  75. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  76. package/dist/react/model-context/useAssistantDataUI.js +1 -1
  77. package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
  78. package/dist/react/model-context/useAssistantInstructions.js +1 -1
  79. package/dist/react/model-context/useAssistantInstructions.js.map +1 -1
  80. package/dist/react/model-context/useAssistantInteractable.js +1 -1
  81. package/dist/react/model-context/useAssistantInteractable.js.map +1 -1
  82. package/dist/react/model-context/useAssistantTool.d.ts +11 -1
  83. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  84. package/dist/react/model-context/useAssistantTool.js +12 -6
  85. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  86. package/dist/react/model-context/useAssistantToolUI.d.ts +13 -4
  87. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  88. package/dist/react/model-context/useAssistantToolUI.js +7 -4
  89. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  90. package/dist/react/model-context/useAuiToolOverrides.d.ts +22 -0
  91. package/dist/react/model-context/useAuiToolOverrides.d.ts.map +1 -0
  92. package/dist/react/model-context/useAuiToolOverrides.js +31 -0
  93. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -0
  94. package/dist/react/model-context/useInlineRender.js +1 -1
  95. package/dist/react/model-context/useInlineRender.js.map +1 -1
  96. package/dist/react/model-context/useInteractableState.js +1 -1
  97. package/dist/react/model-context/useInteractableState.js.map +1 -1
  98. package/dist/react/model-context/useToolArgsStatus.js +1 -1
  99. package/dist/react/primitive-hooks/useActionBarCopy.js +1 -1
  100. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  101. package/dist/react/primitive-hooks/useActionBarEdit.js +1 -1
  102. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  103. package/dist/react/primitive-hooks/useActionBarFeedback.js +1 -1
  104. package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
  105. package/dist/react/primitive-hooks/useActionBarReload.js +1 -1
  106. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  107. package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -1
  108. package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
  109. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -1
  110. package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
  111. package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -1
  112. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  113. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -1
  114. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  115. package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -1
  116. package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
  117. package/dist/react/primitive-hooks/useComposerCancel.js +1 -1
  118. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  119. package/dist/react/primitive-hooks/useComposerDictate.js +1 -1
  120. package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
  121. package/dist/react/primitive-hooks/useComposerSend.js +1 -1
  122. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  123. package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -1
  124. package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
  125. package/dist/react/primitive-hooks/useEditComposerSend.js +1 -1
  126. package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
  127. package/dist/react/primitive-hooks/useMessageBranching.js +1 -1
  128. package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
  129. package/dist/react/primitive-hooks/useMessageReload.js +1 -1
  130. package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
  131. package/dist/react/primitive-hooks/useSuggestionTrigger.js +1 -1
  132. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  133. package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -1
  134. package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
  135. package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -1
  136. package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
  137. package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -1
  138. package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
  139. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -1
  140. package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
  141. package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -1
  142. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  143. package/dist/react/primitive-hooks/useThreadListNew.js +1 -1
  144. package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
  145. package/dist/react/primitive-hooks/useVoice.js +1 -1
  146. package/dist/react/primitive-hooks/useVoice.js.map +1 -1
  147. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts +1 -1
  148. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
  149. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  150. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  151. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  152. package/dist/react/primitives/composer/ComposerQueue.js +1 -1
  153. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  154. package/dist/react/primitives/generativeUI/GenerativeUI.js +1 -1
  155. package/dist/react/primitives/generativeUI/GenerativeUI.js.map +1 -1
  156. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  157. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  158. package/dist/react/primitives/message/MessageGroupedParts.js +1 -1
  159. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  160. package/dist/react/primitives/message/MessageParts.d.ts +1 -1
  161. package/dist/react/primitives/message/MessageParts.js +1 -1
  162. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  163. package/dist/react/primitives/message/MessageQuote.js +1 -1
  164. package/dist/react/primitives/part/PartMessages.d.ts +12 -10
  165. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  166. package/dist/react/primitives/part/PartMessages.js +13 -11
  167. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  168. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  169. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  170. package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
  171. package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
  172. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  173. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  174. package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
  175. package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
  176. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
  177. package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
  178. package/dist/react/providers/PartByIndexProvider.js.map +1 -1
  179. package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
  180. package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
  181. package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
  182. package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
  183. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  184. package/dist/react/providers/TextMessagePartProvider.js +4 -3
  185. package/dist/react/providers/TextMessagePartProvider.js.map +1 -1
  186. package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
  187. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +7 -0
  188. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  189. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +1 -1
  190. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  191. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -0
  192. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  193. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +29 -1
  194. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  195. package/dist/react/runtimes/RuntimeAdapterProvider.js +1 -1
  196. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +1 -1
  197. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  198. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  199. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +10 -3
  200. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  201. package/dist/react/runtimes/createMessageConverter.d.ts +2 -2
  202. package/dist/react/runtimes/createMessageConverter.d.ts.map +1 -1
  203. package/dist/react/runtimes/createMessageConverter.js.map +1 -1
  204. package/dist/react/runtimes/external-message-converter.d.ts +4 -3
  205. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  206. package/dist/react/runtimes/external-message-converter.js +1 -1
  207. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  208. package/dist/react/runtimes/useExternalStoreRuntime.js +1 -1
  209. package/dist/react/runtimes/useExternalStoreSharedOptions.js +1 -1
  210. package/dist/react/runtimes/useLocalRuntime.d.ts +2 -1
  211. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  212. package/dist/react/runtimes/useLocalRuntime.js +4 -3
  213. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  214. package/dist/react/runtimes/useRemoteThreadListRuntime.js +1 -1
  215. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  216. package/dist/react/utils/groupParts.d.ts +1 -1
  217. package/dist/react/utils/groupParts.js.map +1 -1
  218. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  219. package/dist/runtime/api/composer-runtime.d.ts +8 -2
  220. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  221. package/dist/runtime/api/composer-runtime.js +14 -0
  222. package/dist/runtime/api/composer-runtime.js.map +1 -1
  223. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  224. package/dist/runtime/api/message-runtime.js +1 -1
  225. package/dist/runtime/api/message-runtime.js.map +1 -1
  226. package/dist/runtime/api/thread-list-item-runtime.d.ts +2 -0
  227. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  228. package/dist/runtime/api/thread-list-item-runtime.js +6 -0
  229. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  230. package/dist/runtime/api/thread-runtime.d.ts +7 -0
  231. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  232. package/dist/runtime/api/thread-runtime.js.map +1 -1
  233. package/dist/runtime/base/base-composer-runtime-core.d.ts +4 -0
  234. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  235. package/dist/runtime/base/base-composer-runtime-core.js +7 -1
  236. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  237. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  238. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +4 -0
  239. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  240. package/dist/runtime/base/default-thread-composer-runtime-core.js +17 -1
  241. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  242. package/dist/runtime/interfaces/composer-runtime-core.d.ts +6 -1
  243. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  244. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
  245. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  246. package/dist/runtime/interfaces/thread-runtime-core.d.ts +4 -0
  247. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  248. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +20 -0
  249. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -0
  250. package/dist/runtime/queue/external-thread-queue-adapter.js +0 -0
  251. package/dist/runtime/queue/message-queue.d.ts +20 -0
  252. package/dist/runtime/queue/message-queue.d.ts.map +1 -0
  253. package/dist/runtime/queue/message-queue.js +97 -0
  254. package/dist/runtime/queue/message-queue.js.map +1 -0
  255. package/dist/runtime/utils/message-repository.js.map +1 -1
  256. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  257. package/dist/runtimes/external-store/external-store-adapter.d.ts +5 -1
  258. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  259. package/dist/runtimes/external-store/external-store-runtime-core.js.map +1 -1
  260. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -0
  261. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  262. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +5 -0
  263. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  264. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +4 -0
  265. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  266. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +20 -2
  267. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  268. package/dist/runtimes/local/local-runtime-core.js.map +1 -1
  269. package/dist/runtimes/local/local-runtime-options.d.ts +5 -0
  270. package/dist/runtimes/local/local-runtime-options.d.ts.map +1 -1
  271. package/dist/runtimes/local/local-thread-runtime-core.d.ts +7 -0
  272. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  273. package/dist/runtimes/local/local-thread-runtime-core.js +45 -0
  274. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  275. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +3 -0
  276. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  277. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  278. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  279. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +1 -0
  280. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  281. package/dist/runtimes/remote-thread-list/adapter/in-memory.js +3 -0
  282. package/dist/runtimes/remote-thread-list/adapter/in-memory.js.map +1 -1
  283. package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
  284. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  285. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  286. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  287. package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
  288. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  289. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  290. package/dist/store/clients/chain-of-thought-client.d.ts.map +1 -1
  291. package/dist/store/clients/chain-of-thought-client.js +6 -5
  292. package/dist/store/clients/chain-of-thought-client.js.map +1 -1
  293. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  294. package/dist/store/clients/model-context-client.js +6 -5
  295. package/dist/store/clients/model-context-client.js.map +1 -1
  296. package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
  297. package/dist/store/clients/no-op-composer-client.js +4 -3
  298. package/dist/store/clients/no-op-composer-client.js.map +1 -1
  299. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  300. package/dist/store/clients/runtime-adapter.js +7 -6
  301. package/dist/store/clients/runtime-adapter.js.map +1 -1
  302. package/dist/store/clients/suggestions.d.ts.map +1 -1
  303. package/dist/store/clients/suggestions.js +7 -6
  304. package/dist/store/clients/suggestions.js.map +1 -1
  305. package/dist/store/clients/thread-message-client.d.ts.map +1 -1
  306. package/dist/store/clients/thread-message-client.js +13 -12
  307. package/dist/store/clients/thread-message-client.js.map +1 -1
  308. package/dist/store/index.d.ts +1 -1
  309. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  310. package/dist/store/runtime-clients/attachment-runtime-client.js +3 -3
  311. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  312. package/dist/store/runtime-clients/composer-runtime-client.d.ts +12 -5
  313. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  314. package/dist/store/runtime-clients/composer-runtime-client.js +32 -16
  315. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  316. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  317. package/dist/store/runtime-clients/message-part-runtime-client.js +3 -3
  318. package/dist/store/runtime-clients/message-part-runtime-client.js.map +1 -1
  319. package/dist/store/runtime-clients/message-runtime-client.d.ts +6 -3
  320. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  321. package/dist/store/runtime-clients/message-runtime-client.js +17 -16
  322. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  323. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  324. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +9 -7
  325. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  326. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  327. package/dist/store/runtime-clients/thread-list-runtime-client.js +11 -10
  328. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  329. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  330. package/dist/store/runtime-clients/thread-runtime-client.js +15 -14
  331. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  332. package/dist/store/runtime-clients/useSubscribable.d.ts +7 -0
  333. package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -0
  334. package/dist/store/runtime-clients/useSubscribable.js +16 -0
  335. package/dist/store/runtime-clients/useSubscribable.js.map +1 -0
  336. package/dist/store/scope-registration.d.ts +1 -1
  337. package/dist/store/scopes/composer.d.ts +1 -1
  338. package/dist/store/scopes/queue-item.d.ts +2 -1
  339. package/dist/store/scopes/queue-item.d.ts.map +1 -1
  340. package/dist/store/scopes/queue-item.js +6 -0
  341. package/dist/store/scopes/queue-item.js.map +1 -0
  342. package/dist/store/scopes/thread-list-item.d.ts +1 -0
  343. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  344. package/dist/store/scopes/thread.d.ts +1 -1
  345. package/dist/store/scopes/threads.d.ts +1 -1
  346. package/dist/types/message.d.ts +2 -1
  347. package/dist/types/message.d.ts.map +1 -1
  348. package/dist/types/message.js.map +1 -1
  349. package/dist/utils/composite-context-provider.d.ts +1 -1
  350. package/dist/utils/composite-context-provider.js +3 -1
  351. package/dist/utils/composite-context-provider.js.map +1 -1
  352. package/dist/utils/json/is-json.js.map +1 -1
  353. package/dist/utils/text.js.map +1 -1
  354. package/package.json +15 -11
  355. package/src/adapters/attachment.ts +24 -4
  356. package/src/index.ts +8 -0
  357. package/src/model-context/tool.ts +1 -1
  358. package/src/model-context/types.ts +21 -3
  359. package/src/react/RuntimeAdapter.ts +6 -4
  360. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +15 -2
  361. package/src/react/client/DataRenderers.ts +48 -42
  362. package/src/react/client/Interactables.ts +263 -267
  363. package/src/react/client/Tools.ts +123 -115
  364. package/src/react/index.ts +16 -3
  365. package/src/react/model-context/define-mcp-toolkit.ts +16 -0
  366. package/src/react/model-context/define-toolkit.test.ts +101 -6
  367. package/src/react/model-context/define-toolkit.ts +35 -18
  368. package/src/react/model-context/external-tool.ts +16 -0
  369. package/src/react/model-context/human-tool.ts +32 -0
  370. package/src/react/model-context/makeAssistantTool.ts +8 -0
  371. package/src/react/model-context/makeAssistantToolUI.ts +8 -0
  372. package/src/react/model-context/provider-tool.ts +30 -0
  373. package/src/react/model-context/stub-tool.ts +14 -0
  374. package/src/react/model-context/toolbox.test.ts +182 -0
  375. package/src/react/model-context/toolbox.ts +191 -23
  376. package/src/react/model-context/useAssistantTool.ts +28 -8
  377. package/src/react/model-context/useAssistantToolUI.ts +13 -4
  378. package/src/react/model-context/useAuiToolOverrides.ts +38 -0
  379. package/src/react/primitives/message/MessageGroupedParts.tsx +1 -1
  380. package/src/react/primitives/part/PartMessages.tsx +12 -10
  381. package/src/react/providers/TextMessagePartProvider.tsx +31 -32
  382. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +43 -0
  383. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +9 -0
  384. package/src/react/runtimes/createMessageConverter.ts +2 -1
  385. package/src/react/runtimes/external-message-converter.ts +5 -3
  386. package/src/react/runtimes/useLocalRuntime.ts +2 -0
  387. package/src/runtime/api/composer-runtime.ts +26 -0
  388. package/src/runtime/api/thread-list-item-runtime.ts +15 -0
  389. package/src/runtime/base/base-composer-runtime-core.ts +11 -0
  390. package/src/runtime/base/default-thread-composer-runtime-core.ts +22 -0
  391. package/src/runtime/interfaces/composer-runtime-core.ts +7 -0
  392. package/src/runtime/interfaces/thread-list-runtime-core.ts +4 -0
  393. package/src/runtime/interfaces/thread-runtime-core.ts +5 -0
  394. package/src/runtime/queue/external-thread-queue-adapter.ts +14 -0
  395. package/src/runtime/queue/message-queue.ts +128 -0
  396. package/src/runtimes/external-store/external-store-adapter.ts +10 -0
  397. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +13 -0
  398. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -2
  399. package/src/runtimes/local/local-runtime-options.ts +6 -0
  400. package/src/runtimes/local/local-thread-runtime-core.ts +70 -0
  401. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  402. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +4 -0
  403. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  404. package/src/runtimes/remote-thread-list/types.ts +4 -0
  405. package/src/store/clients/chain-of-thought-client.ts +24 -25
  406. package/src/store/clients/model-context-client.test.ts +87 -2
  407. package/src/store/clients/model-context-client.ts +22 -19
  408. package/src/store/clients/no-op-composer-client.ts +69 -66
  409. package/src/store/clients/runtime-adapter.ts +9 -6
  410. package/src/store/clients/suggestions.ts +41 -40
  411. package/src/store/clients/thread-message-client.ts +127 -132
  412. package/src/store/runtime-clients/attachment-runtime-client.ts +7 -3
  413. package/src/store/runtime-clients/composer-runtime-client.ts +142 -113
  414. package/src/store/runtime-clients/message-part-runtime-client.ts +16 -14
  415. package/src/store/runtime-clients/message-runtime-client.ts +124 -122
  416. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +44 -44
  417. package/src/store/runtime-clients/thread-list-runtime-client.ts +83 -80
  418. package/src/store/runtime-clients/thread-runtime-client.ts +113 -119
  419. package/src/store/runtime-clients/{tap-subscribable.ts → useSubscribable.ts} +4 -4
  420. package/src/store/scopes/queue-item.ts +2 -0
  421. package/src/store/scopes/thread-list-item.ts +1 -0
  422. package/src/tests/RemoteThreadListThreadListRuntimeCore-custom-metadata.test.ts +69 -1
  423. package/src/tests/attachment-adapters.test.ts +86 -0
  424. package/src/tests/external-store-thread-runtime-core.test.ts +125 -0
  425. package/src/tests/message-queue.test.ts +168 -0
  426. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  427. package/src/types/message.ts +2 -0
  428. package/src/utils/composite-context-provider.ts +3 -1
  429. package/dist/react/model-context/hitl.d.ts +0 -19
  430. package/dist/react/model-context/hitl.d.ts.map +0 -1
  431. package/dist/react/model-context/hitl.js +0 -22
  432. package/dist/react/model-context/hitl.js.map +0 -1
  433. package/dist/store/runtime-clients/tap-subscribable.d.ts +0 -7
  434. package/dist/store/runtime-clients/tap-subscribable.d.ts.map +0 -1
  435. package/dist/store/runtime-clients/tap-subscribable.js +0 -16
  436. package/dist/store/runtime-clients/tap-subscribable.js.map +0 -1
  437. package/src/react/model-context/hitl.ts +0 -22
@@ -197,6 +197,19 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
197
197
  await onRename(threadId, newTitle);
198
198
  }
199
199
 
200
+ public async updateCustom(
201
+ threadId: string,
202
+ custom: Record<string, unknown> | undefined,
203
+ ): Promise<void> {
204
+ const onUpdateCustom = this.adapter.onUpdateCustom;
205
+ if (!onUpdateCustom)
206
+ throw new Error(
207
+ "External store adapter does not support updating custom metadata",
208
+ );
209
+
210
+ await onUpdateCustom(threadId, custom);
211
+ }
212
+
200
213
  public async detach(): Promise<void> {
201
214
  // no-op
202
215
  }
@@ -32,6 +32,7 @@ import {
32
32
  } from "../../runtime/utils/message-repository";
33
33
  import { generateId } from "../../utils/id";
34
34
  import { ToolInvocationTracker } from "../tool-invocations/ToolInvocationTracker";
35
+ import { EMPTY_QUEUE_ITEMS } from "../../store/scopes/queue-item";
35
36
 
36
37
  const EMPTY_ARRAY: readonly ThreadSuggestion[] = Object.freeze([]);
37
38
 
@@ -155,7 +156,7 @@ export class ExternalStoreThreadRuntimeCore
155
156
  unstable_copy: this._store.unstable_capabilities?.copy !== false,
156
157
  attachments: !!this._store.adapters?.attachments,
157
158
  feedback: !!this._store.adapters?.feedback,
158
- queue: false,
159
+ queue: this._store.queue !== undefined,
159
160
  };
160
161
  if (!shallowEqual(this._capabilities, newCapabilities)) {
161
162
  this._capabilities = newCapabilities;
@@ -389,6 +390,15 @@ export class ExternalStoreThreadRuntimeCore
389
390
  }
390
391
 
391
392
  public async append(message: AppendMessage): Promise<void> {
393
+ const isEdit = message.parentId !== (this.messages.at(-1)?.id ?? null);
394
+
395
+ // Buffering does not start a run, so the tool-abort below must wait until
396
+ // the queue flushes. By then the prior run (and its tools) has settled.
397
+ if (!isEdit && this._store.queue) {
398
+ this._store.queue.enqueue(message, { steer: message.steer ?? false });
399
+ return;
400
+ }
401
+
392
402
  // Auto-abort in-flight client-side tool executions when a new run is
393
403
  // about to start. Without this, a tool that finishes after the new turn
394
404
  // begins would feed a stale result into `onAddToolResult`, racing with
@@ -399,19 +409,36 @@ export class ExternalStoreThreadRuntimeCore
399
409
  await this._toolInvocations?.abort();
400
410
  }
401
411
 
402
- if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
412
+ if (isEdit) {
403
413
  if (!this._store.onEdit)
404
414
  throw new Error("Runtime does not support editing messages.");
415
+ this._store.queue?.clear("edit");
405
416
  await this._store.onEdit(message);
406
417
  } else {
407
418
  await this._store.onNew(message);
408
419
  }
409
420
  }
410
421
 
422
+ public getQueueItems() {
423
+ // The composer reads this during base-thread construction, before the
424
+ // constructor assigns `_store`, so guard against the unset field.
425
+ return this._store?.queue?.items ?? EMPTY_QUEUE_ITEMS;
426
+ }
427
+
428
+ public steerQueueItem(queueItemId: string) {
429
+ this._store?.queue?.steer(queueItemId);
430
+ }
431
+
432
+ public removeQueueItem(queueItemId: string) {
433
+ this._store?.queue?.remove(queueItemId);
434
+ }
435
+
411
436
  public async startRun(config: StartRunConfig): Promise<void> {
412
437
  if (!this._store.onReload)
413
438
  throw new Error("Runtime does not support reloading messages.");
414
439
 
440
+ this._store.queue?.clear("reload");
441
+
415
442
  // Auto-abort in-flight client-side tool executions when a run reloads;
416
443
  // any results that land afterward would target a turn that no longer
417
444
  // exists. See `append` above for full rationale.
@@ -457,6 +484,8 @@ export class ExternalStoreThreadRuntimeCore
457
484
  if (!this._store.onCancel)
458
485
  throw new Error("Runtime does not support cancelling runs.");
459
486
 
487
+ this._store.queue?.clear("cancel-run");
488
+
460
489
  // Abort any in-flight client-side tool executions. Fire-and-forget —
461
490
  // the abort resolves once executions settle, but we don't gate the
462
491
  // cancel on it.
@@ -26,4 +26,10 @@ export type LocalRuntimeOptionsBase = {
26
26
  * Names of tools that are allowed to interrupt the run in order to wait for human/external approval.
27
27
  */
28
28
  unstable_humanToolNames?: string[] | undefined;
29
+
30
+ /**
31
+ * Opt in to message queuing: a message sent during a run is held in
32
+ * `composer.queue` and sent once the run settles. Steering runs it next.
33
+ */
34
+ unstable_enableMessageQueue?: boolean | undefined;
29
35
  };
@@ -22,6 +22,14 @@ import type {
22
22
  } from "../../types/message";
23
23
  import type { RunConfig } from "../../types/message";
24
24
  import type { ModelContextProvider } from "../../model-context/types";
25
+ import {
26
+ createMessageQueue,
27
+ type MessageQueueController,
28
+ } from "../../runtime/queue/message-queue";
29
+ import {
30
+ EMPTY_QUEUE_ITEMS,
31
+ type QueueItemState,
32
+ } from "../../store/scopes/queue-item";
25
33
 
26
34
  class AbortError extends Error {
27
35
  override name = "AbortError";
@@ -54,6 +62,9 @@ export class LocalThreadRuntimeCore
54
62
 
55
63
  private abortController: AbortController | null = null;
56
64
 
65
+ private _queue: MessageQueueController | null = null;
66
+ private _queueRunInFlight = false;
67
+
57
68
  public readonly isDisabled = false;
58
69
  public readonly isSendDisabled = false;
59
70
 
@@ -139,6 +150,31 @@ export class LocalThreadRuntimeCore
139
150
  hasUpdates = true;
140
151
  }
141
152
 
153
+ const canQueue = options.unstable_enableMessageQueue === true;
154
+ if (canQueue && !this._queue) {
155
+ this._queue = createMessageQueue({
156
+ run: (message) => {
157
+ // release the queue when the dispatch settles, even if it rejects
158
+ // before reaching startRun's finally, so a failure can't deadlock it
159
+ this._queueRunInFlight = true;
160
+ void this._runAppend(message)
161
+ .finally(() => {
162
+ this._queueRunInFlight = false;
163
+ this._queue?.notifyIdle();
164
+ })
165
+ .catch(() => {});
166
+ },
167
+ });
168
+ this._queue.subscribe(() => this._notifySubscribers());
169
+ } else if (!canQueue && this._queue) {
170
+ this._queue.adapter.clear("cancel-run");
171
+ this._queue = null;
172
+ }
173
+ if (this.capabilities.queue !== canQueue) {
174
+ this.capabilities.queue = canQueue;
175
+ hasUpdates = true;
176
+ }
177
+
142
178
  if (hasUpdates) this._notifySubscribers();
143
179
  }
144
180
 
@@ -183,6 +219,31 @@ export class LocalThreadRuntimeCore
183
219
  }
184
220
 
185
221
  public async append(message: AppendMessage): Promise<void> {
222
+ const isTail = message.parentId === (this.messages.at(-1)?.id ?? null);
223
+ const willRun = message.startRun ?? message.role === "user";
224
+ if (this._queue && willRun && isTail) {
225
+ this._queue.adapter.enqueue(message, { steer: message.steer ?? false });
226
+ return;
227
+ }
228
+ if (this._queue && !isTail) this._queue.adapter.clear("edit");
229
+ return this._runAppend(message);
230
+ }
231
+
232
+ public getQueueItems(): readonly QueueItemState[] {
233
+ // Reads can arrive during base-thread construction, before the queue field
234
+ // is assigned, so guard against the unset field.
235
+ return this._queue?.adapter.items ?? EMPTY_QUEUE_ITEMS;
236
+ }
237
+
238
+ public steerQueueItem(queueItemId: string): void {
239
+ this._queue?.adapter.steer(queueItemId);
240
+ }
241
+
242
+ public removeQueueItem(queueItemId: string): void {
243
+ this._queue?.adapter.remove(queueItemId);
244
+ }
245
+
246
+ private async _runAppend(message: AppendMessage): Promise<void> {
186
247
  this.ensureInitialized();
187
248
 
188
249
  const initPromise = this._getInitializePromise?.();
@@ -254,6 +315,8 @@ export class LocalThreadRuntimeCore
254
315
  this._notifyEventSubscribers("runStart", {});
255
316
 
256
317
  try {
318
+ // mark busy for runs not started through the queue (regenerate, resume)
319
+ this._queue?.notifyBusy();
257
320
  this._suggestions = [];
258
321
  this._suggestionsController?.abort();
259
322
  this._suggestionsController = null;
@@ -270,6 +333,11 @@ export class LocalThreadRuntimeCore
270
333
  } while (shouldContinue(message, this._options.unstable_humanToolNames));
271
334
  } finally {
272
335
  this._notifyEventSubscribers("runEnd", {});
336
+ // queue-driven runs release from the driver settle handler; a direct
337
+ // run (regenerate, resume) releases here
338
+ if (!this._queueRunInFlight) {
339
+ queueMicrotask(() => this._queue?.notifyIdle());
340
+ }
273
341
  }
274
342
 
275
343
  this._suggestionsController = new AbortController();
@@ -474,12 +542,14 @@ export class LocalThreadRuntimeCore
474
542
  }
475
543
 
476
544
  public detach() {
545
+ this._queue?.adapter.clear("cancel-run");
477
546
  const error = new AbortError(true);
478
547
  this.abortController?.abort(error);
479
548
  this.abortController = null;
480
549
  }
481
550
 
482
551
  public cancelRun() {
552
+ this._queue?.adapter.clear("cancel-run");
483
553
  const error = new AbortError(false);
484
554
  this.abortController?.abort(error);
485
555
  this.abortController = null;
@@ -158,6 +158,10 @@ export class ReadonlyThreadRuntimeCore
158
158
  // noop
159
159
  },
160
160
 
161
+ queue: [] as never[],
162
+ steerQueueItem() {},
163
+ removeQueueItem() {},
164
+
161
165
  dictation: undefined,
162
166
 
163
167
  startDictation() {
@@ -17,6 +17,10 @@ export class InMemoryThreadListAdapter implements RemoteThreadListAdapter {
17
17
  return Promise.resolve();
18
18
  }
19
19
 
20
+ updateCustom(): Promise<void> {
21
+ return Promise.resolve();
22
+ }
23
+
20
24
  archive(): Promise<void> {
21
25
  return Promise.resolve();
22
26
  }
@@ -139,6 +139,10 @@ export const EMPTY_THREAD_CORE: ThreadRuntimeCore = {
139
139
  // noop
140
140
  },
141
141
 
142
+ queue: [] as never[],
143
+ steerQueueItem() {},
144
+ removeQueueItem() {},
145
+
142
146
  dictation: undefined,
143
147
 
144
148
  startDictation() {
@@ -29,6 +29,10 @@ export type RemoteThreadListAdapter = {
29
29
  list(params?: RemoteThreadListPageOptions): Promise<RemoteThreadListResponse>;
30
30
 
31
31
  rename(remoteId: string, newTitle: string): Promise<void>;
32
+ updateCustom?(
33
+ remoteId: string,
34
+ custom: Record<string, unknown> | undefined,
35
+ ): Promise<void>;
32
36
  archive(remoteId: string): Promise<void>;
33
37
  unarchive(remoteId: string): Promise<void>;
34
38
  delete(remoteId: string): Promise<void>;
@@ -1,4 +1,5 @@
1
- import { resource, tapMemo, tapState } from "@assistant-ui/tap";
1
+ import { useMemo, useState } from "react";
2
+ import { resource } from "@assistant-ui/tap";
2
3
  import type { ClientOutput } from "@assistant-ui/store";
3
4
  import type {
4
5
  ChainOfThoughtState,
@@ -11,30 +12,28 @@ const COMPLETE_STATUS: MessagePartStatus = Object.freeze({
11
12
  type: "complete",
12
13
  });
13
14
 
14
- export const ChainOfThoughtClient = resource(
15
- ({
16
- parts,
17
- getMessagePart,
18
- }: {
19
- parts: readonly ChainOfThoughtPart[];
20
- getMessagePart: (selector: { index: number }) => PartMethods;
21
- }): ClientOutput<"chainOfThought"> => {
22
- const [collapsed, setCollapsed] = tapState(true);
15
+ export const ChainOfThoughtClient = resource(function ChainOfThoughtClient({
16
+ parts,
17
+ getMessagePart,
18
+ }: {
19
+ parts: readonly ChainOfThoughtPart[];
20
+ getMessagePart: (selector: { index: number }) => PartMethods;
21
+ }): ClientOutput<"chainOfThought"> {
22
+ const [collapsed, setCollapsed] = useState(true);
23
23
 
24
- const status = tapMemo(() => {
25
- const lastPart = parts[parts.length - 1];
26
- return lastPart?.status ?? COMPLETE_STATUS;
27
- }, [parts]);
24
+ const status = useMemo(() => {
25
+ const lastPart = parts[parts.length - 1];
26
+ return lastPart?.status ?? COMPLETE_STATUS;
27
+ }, [parts]);
28
28
 
29
- const state = tapMemo<ChainOfThoughtState>(
30
- () => ({ parts, collapsed, status }),
31
- [parts, collapsed, status],
32
- );
29
+ const state = useMemo<ChainOfThoughtState>(
30
+ () => ({ parts, collapsed, status }),
31
+ [parts, collapsed, status],
32
+ );
33
33
 
34
- return {
35
- getState: () => state,
36
- setCollapsed,
37
- part: getMessagePart,
38
- };
39
- },
40
- );
34
+ return {
35
+ getState: () => state,
36
+ setCollapsed,
37
+ part: getMessagePart,
38
+ };
39
+ });
@@ -6,6 +6,7 @@ import type {
6
6
  ModelContext as ModelContextValue,
7
7
  ModelContextProvider,
8
8
  } from "../../model-context/types";
9
+ import { mergeModelContexts } from "../../model-context/types";
9
10
 
10
11
  const tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0));
11
12
 
@@ -13,7 +14,7 @@ const provider = (ctx: ModelContextValue): ModelContextProvider => ({
13
14
  getModelContext: () => ctx,
14
15
  });
15
16
 
16
- const stubTool = (): Tool<any, any> =>
17
+ const toolFixture = (): Tool<any, any> =>
17
18
  ({ description: "", parameters: {} as any }) as unknown as Tool<any, any>;
18
19
 
19
20
  const render = () => {
@@ -51,7 +52,9 @@ describe("ModelContext", () => {
51
52
  try {
52
53
  sub
53
54
  .getValue()
54
- .register(provider({ tools: { foo: stubTool(), bar: stubTool() } }));
55
+ .register(
56
+ provider({ tools: { foo: toolFixture(), bar: toolFixture() } }),
57
+ );
55
58
  await tick();
56
59
 
57
60
  expect(sub.getValue().getState().toolNames).toEqual(["bar", "foo"]);
@@ -106,3 +109,85 @@ describe("ModelContext", () => {
106
109
  }
107
110
  });
108
111
  });
112
+
113
+ describe("mergeModelContexts", () => {
114
+ it("merges a higher-priority tool override into an existing tool", () => {
115
+ const execute = async () => ({ ok: true });
116
+ const merged = mergeModelContexts(
117
+ new Set([
118
+ provider({
119
+ priority: 0,
120
+ tools: {
121
+ add_task: {
122
+ type: "frontend",
123
+ description: "Add a task",
124
+ parameters: { type: "object", properties: {} } as any,
125
+ renderText: { running: "Adding task" },
126
+ } as Tool<any, any>,
127
+ },
128
+ }),
129
+ provider({
130
+ priority: 1000,
131
+ tools: {
132
+ add_task: {
133
+ execute,
134
+ } as unknown as Tool<any, any>,
135
+ },
136
+ }),
137
+ ]),
138
+ );
139
+
140
+ expect(merged.tools?.add_task).toMatchObject({
141
+ type: "frontend",
142
+ description: "Add a task",
143
+ });
144
+ expect(merged.tools?.add_task?.execute).toBe(execute);
145
+ expect(merged.tools?.add_task?.parameters).toEqual({
146
+ type: "object",
147
+ properties: {},
148
+ });
149
+ });
150
+
151
+ it("still rejects duplicate tools at the same priority", () => {
152
+ expect(() =>
153
+ mergeModelContexts(
154
+ new Set([
155
+ provider({ tools: { duplicate: toolFixture() } }),
156
+ provider({ tools: { duplicate: toolFixture() } }),
157
+ ]),
158
+ ),
159
+ ).toThrow(/already exists/);
160
+ });
161
+
162
+ it("preserves the highest priority when a lower-priority provider reuses the same tool object", () => {
163
+ const shared = {
164
+ ...toolFixture(),
165
+ description: "high priority",
166
+ } as Tool<any, any>;
167
+ const execute = async () => ({ ok: true });
168
+ const merged = mergeModelContexts(
169
+ new Set([
170
+ provider({
171
+ priority: 1000,
172
+ tools: { shared },
173
+ }),
174
+ provider({
175
+ priority: 0,
176
+ tools: { shared },
177
+ }),
178
+ provider({
179
+ priority: 500,
180
+ tools: {
181
+ shared: {
182
+ description: "medium priority",
183
+ execute,
184
+ } as unknown as Tool<any, any>,
185
+ },
186
+ }),
187
+ ]),
188
+ );
189
+
190
+ expect(merged.tools?.shared?.description).toBe("high priority");
191
+ expect(merged.tools?.shared?.execute).toBe(execute);
192
+ });
193
+ });
@@ -1,4 +1,5 @@
1
- import { resource, tapEffect, tapMemo, tapState } from "@assistant-ui/tap";
1
+ import { useEffect, useMemo, useState } from "react";
2
+ import { resource } from "@assistant-ui/tap";
2
3
  import type { ClientOutput } from "@assistant-ui/store";
3
4
  import { CompositeContextProvider } from "../../utils/composite-context-provider";
4
5
  import type { ModelContextState } from "../scopes/model-context";
@@ -28,23 +29,25 @@ const deriveState = (
28
29
  return { modelName, toolNames };
29
30
  };
30
31
 
31
- export const ModelContext = resource((): ClientOutput<"modelContext"> => {
32
- const composite = tapMemo(() => new CompositeContextProvider(), []);
33
- const [state, setState] = tapState<ModelContextState>(() =>
34
- deriveState(composite, INITIAL_STATE),
35
- );
32
+ export const ModelContext = resource(
33
+ function ModelContext(): ClientOutput<"modelContext"> {
34
+ const composite = useMemo(() => new CompositeContextProvider(), []);
35
+ const [state, setState] = useState<ModelContextState>(() =>
36
+ deriveState(composite, INITIAL_STATE),
37
+ );
36
38
 
37
- tapEffect(() => {
38
- setState((prev) => deriveState(composite, prev));
39
- return composite.subscribe(() => {
39
+ useEffect(() => {
40
40
  setState((prev) => deriveState(composite, prev));
41
- });
42
- }, [composite]);
43
-
44
- return {
45
- getState: () => deriveState(composite, state),
46
- getModelContext: () => composite.getModelContext(),
47
- subscribe: (callback) => composite.subscribe(callback),
48
- register: (provider) => composite.registerModelContextProvider(provider),
49
- };
50
- });
41
+ return composite.subscribe(() => {
42
+ setState((prev) => deriveState(composite, prev));
43
+ });
44
+ }, [composite]);
45
+
46
+ return {
47
+ getState: () => deriveState(composite, state),
48
+ getModelContext: () => composite.getModelContext(),
49
+ subscribe: (callback) => composite.subscribe(callback),
50
+ register: (provider) => composite.registerModelContextProvider(provider),
51
+ };
52
+ },
53
+ );
@@ -1,71 +1,74 @@
1
- import { resource, tapMemo } from "@assistant-ui/tap";
1
+ import { useMemo } from "react";
2
+ import { resource } from "@assistant-ui/tap";
2
3
  import type { ClientOutput } from "@assistant-ui/store";
3
4
  import type { ComposerState } from "../scopes/composer";
4
5
 
5
- export const NoOpComposerClient = resource(
6
- ({ type }: { type: "edit" | "thread" }): ClientOutput<"composer"> => {
7
- const state = tapMemo<ComposerState>(() => {
8
- return {
9
- isEditing: false,
10
- isEmpty: true,
11
- text: "",
12
- attachmentAccept: "*",
13
- attachments: [],
14
- role: "user",
15
- runConfig: {},
16
- canCancel: false,
17
- canSend: false,
18
- type: type,
19
- dictation: undefined,
20
- quote: undefined,
21
- queue: [],
22
- };
23
- }, [type]);
24
-
6
+ export const NoOpComposerClient = resource(function NoOpComposerClient({
7
+ type,
8
+ }: {
9
+ type: "edit" | "thread";
10
+ }): ClientOutput<"composer"> {
11
+ const state = useMemo<ComposerState>(() => {
25
12
  return {
26
- getState: () => state,
27
- setText: () => {
28
- throw new Error("Not supported");
29
- },
30
- setRole: () => {
31
- throw new Error("Not supported");
32
- },
33
- setRunConfig: () => {
34
- throw new Error("Not supported");
35
- },
36
- addAttachment: () => {
37
- throw new Error("Not supported");
38
- },
39
- clearAttachments: () => {
40
- throw new Error("Not supported");
41
- },
42
- attachment: () => {
43
- throw new Error("Not supported");
44
- },
45
- reset: () => {
46
- throw new Error("Not supported");
47
- },
48
- send: () => {
49
- throw new Error("Not supported");
50
- },
51
- cancel: () => {
52
- throw new Error("Not supported");
53
- },
54
- startDictation: () => {
55
- throw new Error("Not supported");
56
- },
57
- stopDictation: () => {
58
- throw new Error("Not supported");
59
- },
60
- beginEdit: () => {
61
- throw new Error("Not supported");
62
- },
63
- setQuote: () => {
64
- throw new Error("Not supported");
65
- },
66
- queueItem: () => {
67
- throw new Error("Not supported");
68
- },
13
+ isEditing: false,
14
+ isEmpty: true,
15
+ text: "",
16
+ attachmentAccept: "*",
17
+ attachments: [],
18
+ role: "user",
19
+ runConfig: {},
20
+ canCancel: false,
21
+ canSend: false,
22
+ type: type,
23
+ dictation: undefined,
24
+ quote: undefined,
25
+ queue: [],
69
26
  };
70
- },
71
- );
27
+ }, [type]);
28
+
29
+ return {
30
+ getState: () => state,
31
+ setText: () => {
32
+ throw new Error("Not supported");
33
+ },
34
+ setRole: () => {
35
+ throw new Error("Not supported");
36
+ },
37
+ setRunConfig: () => {
38
+ throw new Error("Not supported");
39
+ },
40
+ addAttachment: () => {
41
+ throw new Error("Not supported");
42
+ },
43
+ clearAttachments: () => {
44
+ throw new Error("Not supported");
45
+ },
46
+ attachment: () => {
47
+ throw new Error("Not supported");
48
+ },
49
+ reset: () => {
50
+ throw new Error("Not supported");
51
+ },
52
+ send: () => {
53
+ throw new Error("Not supported");
54
+ },
55
+ cancel: () => {
56
+ throw new Error("Not supported");
57
+ },
58
+ startDictation: () => {
59
+ throw new Error("Not supported");
60
+ },
61
+ stopDictation: () => {
62
+ throw new Error("Not supported");
63
+ },
64
+ beginEdit: () => {
65
+ throw new Error("Not supported");
66
+ },
67
+ setQuote: () => {
68
+ throw new Error("Not supported");
69
+ },
70
+ queueItem: () => {
71
+ throw new Error("Not supported");
72
+ },
73
+ };
74
+ });
@@ -1,8 +1,9 @@
1
- import { resource, tapEffect, tapResource } from "@assistant-ui/tap";
1
+ import { useEffect } from "react";
2
+ import { useResource, resource } from "@assistant-ui/tap";
2
3
  import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
3
4
  import { ThreadListClient } from "../runtime-clients/thread-list-runtime-client";
4
5
  import {
5
- tapAssistantClientRef,
6
+ useAssistantClientRef,
6
7
  Derived,
7
8
  type ScopesConfig,
8
9
  type AssistantClient,
@@ -10,16 +11,18 @@ import {
10
11
  import { ModelContext } from "./model-context-client";
11
12
  import { Suggestions } from "./suggestions";
12
13
 
13
- export const RuntimeAdapterResource = resource((runtime: AssistantRuntime) => {
14
- const clientRef = tapAssistantClientRef();
14
+ export const RuntimeAdapterResource = resource(function RuntimeAdapterResource(
15
+ runtime: AssistantRuntime,
16
+ ) {
17
+ const clientRef = useAssistantClientRef();
15
18
 
16
- tapEffect(() => {
19
+ useEffect(() => {
17
20
  return runtime.registerModelContextProvider(
18
21
  clientRef.current!.modelContext(),
19
22
  );
20
23
  }, [runtime, clientRef]);
21
24
 
22
- return tapResource(
25
+ return useResource(
23
26
  ThreadListClient({
24
27
  runtime: runtime.threads,
25
28
  __internal_assistantRuntime: runtime,