@assistant-ui/core 0.3.12 → 0.3.14

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 (452) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +9 -15
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +2 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/adapters/voice.d.ts.map +1 -1
  7. package/dist/adapters/voice.js +27 -15
  8. package/dist/adapters/voice.js.map +1 -1
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +2 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/internal.d.ts +1 -1
  13. package/dist/internal.js +6 -6
  14. package/dist/model-context/frame/host.d.ts.map +1 -1
  15. package/dist/model-context/frame/host.js +2 -1
  16. package/dist/model-context/frame/host.js.map +1 -1
  17. package/dist/model-context/registry.d.ts.map +1 -1
  18. package/dist/model-context/registry.js +16 -4
  19. package/dist/model-context/registry.js.map +1 -1
  20. package/dist/react/RuntimeAdapter.d.ts +8 -1
  21. package/dist/react/RuntimeAdapter.d.ts.map +1 -1
  22. package/dist/react/RuntimeAdapter.js +23 -18
  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 +28 -12
  26. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  27. package/dist/react/client/AdaptedRemoteThread.d.ts +11 -0
  28. package/dist/react/client/AdaptedRemoteThread.d.ts.map +1 -0
  29. package/dist/react/client/AdaptedRemoteThread.js +27 -0
  30. package/dist/react/client/AdaptedRemoteThread.js.map +1 -0
  31. package/dist/react/client/InMemoryThreadList.d.ts +19 -0
  32. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -0
  33. package/dist/react/client/InMemoryThreadList.js +418 -0
  34. package/dist/react/client/InMemoryThreadList.js.map +1 -0
  35. package/dist/react/client/Interactables.d.ts.map +1 -1
  36. package/dist/react/client/Interactables.js +159 -102
  37. package/dist/react/client/Interactables.js.map +1 -1
  38. package/dist/react/client/RemoteThreadList.d.ts +34 -0
  39. package/dist/react/client/RemoteThreadList.d.ts.map +1 -0
  40. package/dist/react/client/RemoteThreadList.js +826 -0
  41. package/dist/react/client/RemoteThreadList.js.map +1 -0
  42. package/dist/react/client/Tools.d.ts.map +1 -1
  43. package/dist/react/client/Tools.js +38 -27
  44. package/dist/react/client/Tools.js.map +1 -1
  45. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  46. package/dist/react/client/interactable-model-context.js +5 -1
  47. package/dist/react/client/interactable-model-context.js.map +1 -1
  48. package/dist/react/index.d.ts +7 -2
  49. package/dist/react/index.js +5 -2
  50. package/dist/react/interactables-legacy/Interactables.d.ts.map +1 -1
  51. package/dist/react/interactables-legacy/Interactables.js +145 -110
  52. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  53. package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
  54. package/dist/react/primitive-hooks/useActionBarCopy.js +13 -18
  55. package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
  56. package/dist/react/primitive-hooks/useActionBarEdit.d.ts.map +1 -1
  57. package/dist/react/primitive-hooks/useActionBarEdit.js +2 -4
  58. package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
  59. package/dist/react/primitive-hooks/useActionBarReload.d.ts.map +1 -1
  60. package/dist/react/primitive-hooks/useActionBarReload.js +2 -4
  61. package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
  62. package/dist/react/primitive-hooks/useBranchPickerNext.d.ts.map +1 -1
  63. package/dist/react/primitive-hooks/useBranchPickerNext.js +2 -6
  64. package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
  65. package/dist/react/primitive-hooks/useBranchPickerPrevious.d.ts.map +1 -1
  66. package/dist/react/primitive-hooks/useBranchPickerPrevious.js +2 -6
  67. package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
  68. package/dist/react/primitive-hooks/useComposerCancel.d.ts.map +1 -1
  69. package/dist/react/primitive-hooks/useComposerCancel.js +2 -4
  70. package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
  71. package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
  72. package/dist/react/primitive-hooks/useComposerSend.js +2 -4
  73. package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
  74. package/dist/react/primitive-hooks/useSuggestionTrigger.d.ts.map +1 -1
  75. package/dist/react/primitive-hooks/useSuggestionTrigger.js +6 -2
  76. package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
  77. package/dist/react/primitives/message/MessageParts.d.ts +13 -0
  78. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  79. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  80. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  81. package/dist/react/primitives/thread/ThreadMessages.js +1 -1
  82. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  83. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +22 -10
  84. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +109 -71
  86. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  87. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +8 -2
  88. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  89. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +40 -13
  90. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  91. package/dist/react/runtimes/RemoteThreadResource.d.ts +30 -0
  92. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -0
  93. package/dist/react/runtimes/RemoteThreadResource.js +134 -0
  94. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -0
  95. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +3 -10
  96. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  97. package/dist/react/runtimes/RuntimeAdapterProvider.js +3 -6
  98. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  99. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts +17 -0
  100. package/dist/react/runtimes/assistant-transport/commandQueue.d.ts.map +1 -0
  101. package/dist/react/runtimes/assistant-transport/commandQueue.js +55 -0
  102. package/dist/react/runtimes/assistant-transport/commandQueue.js.map +1 -0
  103. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts +11 -0
  104. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.d.ts.map +1 -0
  105. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js +165 -0
  106. package/dist/react/runtimes/assistant-transport/replayBoundaryStream.js.map +1 -0
  107. package/dist/react/runtimes/assistant-transport/runManager.d.ts +15 -0
  108. package/dist/react/runtimes/assistant-transport/runManager.d.ts.map +1 -0
  109. package/dist/react/runtimes/assistant-transport/runManager.js +86 -0
  110. package/dist/react/runtimes/assistant-transport/runManager.js.map +1 -0
  111. package/dist/react/runtimes/assistant-transport/types.d.ts +130 -0
  112. package/dist/react/runtimes/assistant-transport/types.d.ts.map +1 -0
  113. package/dist/react/runtimes/assistant-transport/types.js +0 -0
  114. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts +14 -0
  115. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -0
  116. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js +296 -0
  117. package/dist/react/runtimes/assistant-transport/useAssistantTransportRuntime.js.map +1 -0
  118. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts +7 -0
  119. package/dist/react/runtimes/assistant-transport/useConvertedState.d.ts.map +1 -0
  120. package/dist/react/runtimes/assistant-transport/useConvertedState.js +25 -0
  121. package/dist/react/runtimes/assistant-transport/useConvertedState.js.map +1 -0
  122. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts +7 -0
  123. package/dist/react/runtimes/assistant-transport/useLatestRef.d.ts.map +1 -0
  124. package/dist/react/runtimes/assistant-transport/useLatestRef.js +27 -0
  125. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -0
  126. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  127. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +39 -13
  128. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  129. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +2 -1
  130. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  131. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +3 -3
  132. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  133. package/dist/react/runtimes/cloud/auiV0.d.ts +4 -0
  134. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  135. package/dist/react/runtimes/cloud/auiV0.js +7 -0
  136. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  137. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  138. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +22 -12
  139. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  140. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts +16 -0
  141. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.d.ts.map +1 -0
  142. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js +36 -0
  143. package/dist/react/runtimes/cloud/useCloudThreadListRuntime.js.map +1 -0
  144. package/dist/react/runtimes/external-message-converter.js +14 -14
  145. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  146. package/dist/react/runtimes/useExternalStoreRuntime.d.ts.map +1 -1
  147. package/dist/react/runtimes/useExternalStoreRuntime.js +44 -28
  148. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  149. package/dist/react/runtimes/useExternalStoreSharedOptions.js.map +1 -1
  150. package/dist/react/runtimes/useLocalRuntime.js +1 -1
  151. package/dist/react/runtimes/useRuntimeAdapters.d.ts +9 -0
  152. package/dist/react/runtimes/useRuntimeAdapters.d.ts.map +1 -0
  153. package/dist/react/runtimes/useRuntimeAdapters.js +20 -0
  154. package/dist/react/runtimes/useRuntimeAdapters.js.map +1 -0
  155. package/dist/runtime/api/composer-runtime.d.ts +5 -0
  156. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/composer-runtime.js.map +1 -1
  158. package/dist/runtime/api/message-runtime.js +1 -1
  159. package/dist/runtime/api/thread-list-runtime.d.ts +1 -0
  160. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  161. package/dist/runtime/api/thread-list-runtime.js +4 -2
  162. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  163. package/dist/runtime/api/thread-runtime.d.ts +12 -2
  164. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  165. package/dist/runtime/api/thread-runtime.js +13 -3
  166. package/dist/runtime/api/thread-runtime.js.map +1 -1
  167. package/dist/runtime/base/base-composer-runtime-core.d.ts +25 -0
  168. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  169. package/dist/runtime/base/base-composer-runtime-core.js +72 -18
  170. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  171. package/dist/runtime/base/base-thread-runtime-core.d.ts +15 -0
  172. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  173. package/dist/runtime/base/base-thread-runtime-core.js +34 -3
  174. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  175. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  176. package/dist/runtime/base/default-edit-composer-runtime-core.js +1 -6
  177. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  178. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +0 -1
  179. package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
  180. package/dist/runtime/base/default-thread-composer-runtime-core.js +11 -8
  181. package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
  182. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  183. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  184. package/dist/runtime/internal.js +5 -5
  185. package/dist/runtime/queue/external-thread-queue-adapter.d.ts +15 -0
  186. package/dist/runtime/queue/external-thread-queue-adapter.d.ts.map +1 -1
  187. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  188. package/dist/runtime/queue/message-queue.js +25 -11
  189. package/dist/runtime/queue/message-queue.js.map +1 -1
  190. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts +8 -0
  191. package/dist/runtime/utils/thread-runtime-lifecycle.d.ts.map +1 -0
  192. package/dist/runtime/utils/thread-runtime-lifecycle.js +11 -0
  193. package/dist/runtime/utils/thread-runtime-lifecycle.js.map +1 -0
  194. package/dist/runtimes/external-store/external-store-adapter.d.ts +7 -0
  195. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  196. package/dist/runtimes/external-store/external-store-shared-options.js.map +1 -1
  197. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  198. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +4 -1
  199. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  200. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +11 -1
  201. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  202. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +78 -20
  203. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  204. package/dist/runtimes/internal.d.ts +1 -1
  205. package/dist/runtimes/local/local-thread-runtime-core.d.ts +3 -0
  206. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  207. package/dist/runtimes/local/local-thread-runtime-core.js +55 -14
  208. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  209. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +1 -0
  210. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
  211. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +3 -0
  212. package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
  213. package/dist/runtimes/remote-thread-list/empty-thread-core.js +3 -0
  214. package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
  215. package/dist/runtimes/remote-thread-list/types.d.ts +29 -1
  216. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  217. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +1 -12
  218. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  219. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +67 -38
  220. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  221. package/dist/store/clients/external-thread.d.ts +7 -0
  222. package/dist/store/clients/external-thread.d.ts.map +1 -1
  223. package/dist/store/clients/external-thread.js +460 -369
  224. package/dist/store/clients/external-thread.js.map +1 -1
  225. package/dist/store/clients/runtime-adapter.d.ts.map +1 -1
  226. package/dist/store/clients/runtime-adapter.js +5 -2
  227. package/dist/store/clients/runtime-adapter.js.map +1 -1
  228. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  229. package/dist/store/clients/single-thread-list.js +31 -27
  230. package/dist/store/clients/single-thread-list.js.map +1 -1
  231. package/dist/store/clients/suggestions.d.ts +3 -1
  232. package/dist/store/clients/suggestions.d.ts.map +1 -1
  233. package/dist/store/clients/suggestions.js +65 -37
  234. package/dist/store/clients/suggestions.js.map +1 -1
  235. package/dist/store/clients/thread-selection-events.d.ts +10 -0
  236. package/dist/store/clients/thread-selection-events.d.ts.map +1 -0
  237. package/dist/store/clients/thread-selection-events.js +40 -0
  238. package/dist/store/clients/thread-selection-events.js.map +1 -0
  239. package/dist/store/env.d.ts +5 -0
  240. package/dist/store/env.d.ts.map +1 -0
  241. package/dist/store/env.js +12 -0
  242. package/dist/store/env.js.map +1 -0
  243. package/dist/store/index.d.ts +6 -4
  244. package/dist/store/index.js +5 -3
  245. package/dist/store/internal.d.ts +4 -1
  246. package/dist/store/internal.js +4 -1
  247. package/dist/store/primitive-predicates.d.ts +19 -0
  248. package/dist/store/primitive-predicates.d.ts.map +1 -0
  249. package/dist/store/primitive-predicates.js +19 -0
  250. package/dist/store/primitive-predicates.js.map +1 -0
  251. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  252. package/dist/store/runtime-clients/attachment-runtime-client.js +18 -11
  253. package/dist/store/runtime-clients/attachment-runtime-client.js.map +1 -1
  254. package/dist/store/runtime-clients/handle-runtime-action.d.ts +5 -0
  255. package/dist/store/runtime-clients/handle-runtime-action.d.ts.map +1 -0
  256. package/dist/store/runtime-clients/handle-runtime-action.js +12 -0
  257. package/dist/store/runtime-clients/handle-runtime-action.js.map +1 -0
  258. package/dist/store/runtime-clients/handle-thread-list-action.d.ts +5 -0
  259. package/dist/store/runtime-clients/handle-thread-list-action.d.ts.map +1 -0
  260. package/dist/store/runtime-clients/handle-thread-list-action.js +7 -0
  261. package/dist/store/runtime-clients/handle-thread-list-action.js.map +1 -0
  262. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +104 -57
  264. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  266. package/dist/store/runtime-clients/thread-list-runtime-client.js +5 -6
  267. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  268. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  269. package/dist/store/runtime-clients/thread-runtime-client.js +98 -82
  270. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  271. package/dist/store/scope-registration.d.ts +2 -2
  272. package/dist/store/scopes/composer.d.ts +9 -4
  273. package/dist/store/scopes/composer.d.ts.map +1 -1
  274. package/dist/store/scopes/suggestions.d.ts +6 -1
  275. package/dist/store/scopes/suggestions.d.ts.map +1 -1
  276. package/dist/store/scopes/thread-list-item.d.ts +7 -6
  277. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  278. package/dist/store/scopes/thread.d.ts +25 -7
  279. package/dist/store/scopes/thread.d.ts.map +1 -1
  280. package/dist/store/scopes/threads.d.ts +17 -1
  281. package/dist/store/scopes/threads.d.ts.map +1 -1
  282. package/dist/subscribable/subscribable.d.ts +2 -1
  283. package/dist/subscribable/subscribable.d.ts.map +1 -1
  284. package/dist/subscribable/subscribable.js +23 -18
  285. package/dist/subscribable/subscribable.js.map +1 -1
  286. package/dist/types/error.d.ts +15 -1
  287. package/dist/types/error.d.ts.map +1 -1
  288. package/dist/types/error.js +18 -1
  289. package/dist/types/error.js.map +1 -1
  290. package/dist/types/message.d.ts +2 -0
  291. package/dist/types/message.d.ts.map +1 -1
  292. package/dist/types/message.js.map +1 -1
  293. package/dist/utils/composite-context-provider.d.ts +1 -0
  294. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  295. package/dist/utils/composite-context-provider.js +25 -9
  296. package/dist/utils/composite-context-provider.js.map +1 -1
  297. package/dist/utils/notify-event-listeners.d.ts +2 -2
  298. package/dist/utils/notify-event-listeners.d.ts.map +1 -1
  299. package/dist/utils/notify-event-listeners.js +2 -2
  300. package/dist/utils/notify-event-listeners.js.map +1 -1
  301. package/package.json +7 -7
  302. package/src/adapters/speech.test.ts +118 -1
  303. package/src/adapters/speech.ts +21 -22
  304. package/src/adapters/thread-history.ts +2 -0
  305. package/src/adapters/voice.test.ts +69 -0
  306. package/src/adapters/voice.ts +27 -27
  307. package/src/index.ts +2 -0
  308. package/src/model-context/frame/host.test.ts +23 -0
  309. package/src/model-context/frame/host.ts +2 -1
  310. package/src/model-context/registry.test.ts +131 -0
  311. package/src/model-context/registry.ts +16 -6
  312. package/src/react/RuntimeAdapter.test.ts +2 -0
  313. package/src/react/RuntimeAdapter.ts +20 -8
  314. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +34 -17
  315. package/src/react/client/AdaptedRemoteThread.ts +41 -0
  316. package/src/react/client/InMemoryThreadList.test.tsx +148 -0
  317. package/src/react/client/InMemoryThreadList.ts +290 -0
  318. package/src/react/client/Interactables.test.ts +326 -2
  319. package/src/react/client/Interactables.ts +227 -110
  320. package/src/react/client/RemoteThreadList.test.ts +1026 -0
  321. package/src/react/client/RemoteThreadList.ts +1067 -0
  322. package/src/react/client/Tools.ts +36 -29
  323. package/src/react/client/interactable-model-context.ts +6 -1
  324. package/src/react/index.ts +13 -0
  325. package/src/react/interactables-legacy/Interactables.test.ts +317 -0
  326. package/src/react/interactables-legacy/Interactables.ts +204 -128
  327. package/src/react/primitive-hooks/useActionBarCopy.ts +2 -7
  328. package/src/react/primitive-hooks/useActionBarEdit.ts +2 -1
  329. package/src/react/primitive-hooks/useActionBarReload.ts +2 -6
  330. package/src/react/primitive-hooks/useBranchPickerNext.ts +2 -7
  331. package/src/react/primitive-hooks/useBranchPickerPrevious.ts +2 -7
  332. package/src/react/primitive-hooks/useComposerCancel.ts +2 -1
  333. package/src/react/primitive-hooks/useComposerSend.ts +2 -5
  334. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +11 -0
  335. package/src/react/primitive-hooks/useSuggestionTrigger.ts +4 -5
  336. package/src/react/primitives/message/MessageParts.tsx +0 -1
  337. package/src/react/primitives/thread/ThreadMessages.tsx +2 -1
  338. package/src/react/runtimes/RemoteThreadListHookInstanceManager.retry.test.tsx +116 -0
  339. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +1 -1
  340. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +57 -6
  341. package/src/react/runtimes/RemoteThreadListHookInstanceManager.title.test.tsx +272 -0
  342. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +159 -124
  343. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +59 -20
  344. package/src/react/runtimes/RemoteThreadResource.test.ts +141 -0
  345. package/src/react/runtimes/RemoteThreadResource.ts +231 -0
  346. package/src/react/runtimes/RuntimeAdapterProvider.tsx +8 -20
  347. package/src/react/runtimes/assistant-transport/commandQueue.ts +68 -0
  348. package/src/react/runtimes/assistant-transport/replayBoundaryStream.test.ts +455 -0
  349. package/src/react/runtimes/assistant-transport/replayBoundaryStream.ts +172 -0
  350. package/src/react/runtimes/assistant-transport/runManager.ts +124 -0
  351. package/src/react/runtimes/assistant-transport/transport-delivery.test.tsx +79 -0
  352. package/src/react/runtimes/assistant-transport/transport-parentid.test.tsx +97 -0
  353. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +414 -0
  354. package/src/react/runtimes/assistant-transport/types.ts +170 -0
  355. package/src/react/runtimes/assistant-transport/useAssistantTransport.spec.md +141 -0
  356. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.test.tsx +625 -0
  357. package/src/react/runtimes/assistant-transport/useAssistantTransportRuntime.ts +481 -0
  358. package/src/react/runtimes/assistant-transport/useConvertedState.ts +20 -0
  359. package/src/react/runtimes/assistant-transport/useLatestRef.ts +9 -0
  360. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +131 -6
  361. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +61 -15
  362. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +6 -4
  363. package/src/react/runtimes/cloud/auiV0.ts +17 -1
  364. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +36 -21
  365. package/src/react/runtimes/cloud/useCloudThreadListRuntime.test.tsx +56 -0
  366. package/src/react/runtimes/cloud/useCloudThreadListRuntime.ts +31 -0
  367. package/src/react/runtimes/external-message-converter.test.ts +143 -0
  368. package/src/react/runtimes/external-message-converter.ts +41 -41
  369. package/src/react/runtimes/remote-thread-hook-on-tap.test.ts +58 -0
  370. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +83 -0
  371. package/src/react/runtimes/useExternalStoreRuntime.suggestions.test.tsx +124 -0
  372. package/src/react/runtimes/useExternalStoreRuntime.ts +7 -0
  373. package/src/react/runtimes/useExternalStoreSharedOptions.ts +3 -1
  374. package/src/react/runtimes/useLocalRuntime.test.tsx +130 -4
  375. package/src/react/runtimes/useRuntimeAdapters.test.tsx +62 -0
  376. package/src/react/runtimes/useRuntimeAdapters.ts +28 -0
  377. package/src/runtime/api/composer-runtime.ts +5 -0
  378. package/src/runtime/api/thread-list-runtime.ts +3 -1
  379. package/src/runtime/api/thread-runtime.ts +28 -3
  380. package/src/runtime/base/base-composer-runtime-core.ts +106 -13
  381. package/src/runtime/base/base-thread-runtime-core.test.ts +191 -0
  382. package/src/runtime/base/base-thread-runtime-core.ts +47 -2
  383. package/src/runtime/base/default-edit-composer-runtime-core.ts +1 -15
  384. package/src/runtime/base/default-thread-composer-runtime-core.ts +13 -15
  385. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  386. package/src/runtime/queue/external-thread-queue-adapter.ts +17 -0
  387. package/src/runtime/queue/message-queue.ts +28 -10
  388. package/src/runtime/utils/thread-runtime-lifecycle.ts +18 -0
  389. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  390. package/src/runtimes/external-store/external-store-shared-options.ts +3 -1
  391. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +4 -1
  392. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +187 -48
  393. package/src/runtimes/local/local-thread-runtime-core.test.ts +373 -4
  394. package/src/runtimes/local/local-thread-runtime-core.ts +83 -15
  395. package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +4 -0
  396. package/src/runtimes/remote-thread-list/empty-thread-core.ts +4 -0
  397. package/src/runtimes/remote-thread-list/types.ts +30 -0
  398. package/src/runtimes/tool-invocations/EDGE_CASES.md +17 -6
  399. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +243 -0
  400. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +127 -61
  401. package/src/store/clients/external-thread.ts +119 -16
  402. package/src/store/clients/model-context-client.test.ts +16 -8
  403. package/src/store/clients/runtime-adapter.ts +5 -2
  404. package/src/store/clients/single-thread-list.ts +2 -1
  405. package/src/store/clients/suggestions.ts +39 -13
  406. package/src/store/clients/thread-selection-events.ts +21 -0
  407. package/src/store/env.ts +11 -0
  408. package/src/store/index.ts +14 -1
  409. package/src/store/internal.ts +13 -0
  410. package/src/store/primitive-predicates.test.ts +184 -0
  411. package/src/store/primitive-predicates.ts +43 -0
  412. package/src/store/runtime-clients/attachment-runtime-client.test.ts +41 -0
  413. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -1
  414. package/src/store/runtime-clients/handle-runtime-action.ts +11 -0
  415. package/src/store/runtime-clients/handle-thread-list-action.test.ts +69 -0
  416. package/src/store/runtime-clients/handle-thread-list-action.ts +6 -0
  417. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +28 -35
  418. package/src/store/runtime-clients/thread-list-runtime-client.ts +9 -6
  419. package/src/store/runtime-clients/thread-runtime-client.ts +5 -0
  420. package/src/store/scopes/composer.ts +9 -4
  421. package/src/store/scopes/suggestions.ts +6 -0
  422. package/src/store/scopes/thread-list-item.ts +7 -6
  423. package/src/store/scopes/thread.ts +25 -7
  424. package/src/store/scopes/threads.ts +14 -0
  425. package/src/subscribable/subscribable.test.ts +77 -1
  426. package/src/subscribable/subscribable.ts +38 -23
  427. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-unarchive.test.ts +25 -0
  428. package/src/tests/append-interactable-snapshots.test.ts +350 -0
  429. package/src/tests/auiV0Encode.test.ts +66 -0
  430. package/src/tests/base-composer-runtime-core-send.test.ts +156 -0
  431. package/src/tests/base-composer-runtime-core.test.ts +136 -1
  432. package/src/tests/composer-can-cancel.test.ts +101 -0
  433. package/src/tests/default-edit-composer-runtime-core.test.ts +0 -68
  434. package/src/tests/external-store-thread-list-runtime-core.test.ts +101 -0
  435. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +491 -1
  436. package/src/tests/external-store-thread-runtime-core.test.ts +124 -0
  437. package/src/tests/external-thread-attachments.test.tsx +214 -0
  438. package/src/tests/external-thread-parity.test.tsx +54 -0
  439. package/src/tests/external-thread-refetch.test.tsx +117 -0
  440. package/src/tests/external-thread-suggestions.test.tsx +59 -0
  441. package/src/tests/interactables-toolui-migration.test.tsx +66 -0
  442. package/src/tests/message-queue.test.ts +54 -0
  443. package/src/tests/session-reset-notification.test.ts +145 -0
  444. package/src/tests/thread-message-like.test.ts +39 -0
  445. package/src/tests/thread-switch-events.test.tsx +234 -0
  446. package/src/tests/tools-scope-migration.test.tsx +58 -0
  447. package/src/types/error.ts +24 -0
  448. package/src/types/message.ts +2 -0
  449. package/src/utils/composite-context-provider.test.ts +139 -0
  450. package/src/utils/composite-context-provider.ts +26 -8
  451. package/src/utils/notify-event-listeners.ts +10 -5
  452. package/src/tests/default-thread-composer-runtime-core.test.ts +0 -82
@@ -0,0 +1,131 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ModelContextRegistry } from "./registry";
3
+
4
+ describe("ModelContextRegistry", () => {
5
+ it("notifies every subscriber and rethrows when a registration subscriber throws", () => {
6
+ const registry = new ModelContextRegistry();
7
+ const error = new Error("subscriber failed");
8
+ const laterSubscriber = vi.fn();
9
+
10
+ registry.subscribe(() => {
11
+ throw error;
12
+ });
13
+ registry.subscribe(laterSubscriber);
14
+
15
+ expect(() => registry.addTool({ toolName: "search" })).toThrow(error);
16
+
17
+ expect(registry.getModelContext().tools).toHaveProperty("search");
18
+ expect(laterSubscriber).toHaveBeenCalledTimes(1);
19
+ });
20
+
21
+ it("keeps a provider registered when a registration subscriber throws", () => {
22
+ const registry = new ModelContextRegistry();
23
+ const error = new Error("subscriber failed");
24
+ const laterSubscriber = vi.fn();
25
+
26
+ registry.subscribe(() => {
27
+ throw error;
28
+ });
29
+ registry.subscribe(laterSubscriber);
30
+
31
+ expect(() =>
32
+ registry.addProvider({
33
+ getModelContext: () => ({ system: "provider instructions" }),
34
+ }),
35
+ ).toThrow(error);
36
+
37
+ expect(registry.getModelContext().system).toBe("provider instructions");
38
+ expect(laterSubscriber).toHaveBeenCalledTimes(1);
39
+ });
40
+
41
+ it("notifies every subscriber and rethrows when registering instructions", () => {
42
+ const registry = new ModelContextRegistry();
43
+ const error = new Error("subscriber failed");
44
+ const laterSubscriber = vi.fn();
45
+
46
+ registry.subscribe(() => {
47
+ throw error;
48
+ });
49
+ registry.subscribe(laterSubscriber);
50
+
51
+ expect(() => registry.addInstruction("be concise")).toThrow(error);
52
+
53
+ expect(registry.getModelContext().system).toContain("be concise");
54
+ expect(laterSubscriber).toHaveBeenCalledTimes(1);
55
+ });
56
+
57
+ it("rethrows the provider subscription failure when a rollback subscriber throws", () => {
58
+ const registry = new ModelContextRegistry();
59
+ const subscriptionError = new Error("subscription failed");
60
+ const subscriberError = new Error("subscriber failed");
61
+ const consoleError = vi
62
+ .spyOn(console, "error")
63
+ .mockImplementation(() => {});
64
+
65
+ registry.subscribe(() => {
66
+ throw subscriberError;
67
+ });
68
+
69
+ try {
70
+ expect(() =>
71
+ registry.addProvider({
72
+ getModelContext: () => ({ system: "provider instructions" }),
73
+ subscribe: () => {
74
+ throw subscriptionError;
75
+ },
76
+ }),
77
+ ).toThrow(subscriptionError);
78
+
79
+ expect(registry.getModelContext().system).toBeUndefined();
80
+ expect(consoleError).toHaveBeenCalledWith(subscriberError);
81
+ } finally {
82
+ consoleError.mockRestore();
83
+ }
84
+ });
85
+
86
+ it("rolls back providers that fail to subscribe", () => {
87
+ const registry = new ModelContextRegistry();
88
+ const error = new Error("subscription failed");
89
+ const observedSystems: Array<string | undefined> = [];
90
+
91
+ registry.subscribe(() => {
92
+ observedSystems.push(registry.getModelContext().system);
93
+ });
94
+
95
+ expect(() =>
96
+ registry.addProvider({
97
+ getModelContext: () => ({ system: "provider instructions" }),
98
+ subscribe: (callback) => {
99
+ callback();
100
+ throw error;
101
+ },
102
+ }),
103
+ ).toThrow(error);
104
+
105
+ expect(registry.getModelContext().system).toBeUndefined();
106
+ expect(observedSystems).toEqual(["provider instructions", undefined]);
107
+ });
108
+
109
+ it("notifies every subscriber and rethrows on provider updates", () => {
110
+ const registry = new ModelContextRegistry();
111
+ const error = new Error("subscriber failed");
112
+ const laterSubscriber = vi.fn();
113
+ let publishUpdate = () => {};
114
+
115
+ registry.addProvider({
116
+ getModelContext: () => ({ system: "provider instructions" }),
117
+ subscribe: (callback) => {
118
+ publishUpdate = callback;
119
+ return () => {};
120
+ },
121
+ });
122
+
123
+ registry.subscribe(() => {
124
+ throw error;
125
+ });
126
+ registry.subscribe(laterSubscriber);
127
+
128
+ expect(() => publishUpdate()).toThrow(error);
129
+ expect(laterSubscriber).toHaveBeenCalledTimes(1);
130
+ });
131
+ });
@@ -7,6 +7,7 @@ import {
7
7
  type AssistantInstructionsConfig,
8
8
  } from "./types";
9
9
  import type { Unsubscribe } from "../types/unsubscribe";
10
+ import { notifySubscribers as notifyStateSubscribers } from "../subscribable/subscribable";
10
11
  import type {
11
12
  ModelContextRegistryToolHandle,
12
13
  ModelContextRegistryInstructionHandle,
@@ -75,9 +76,7 @@ export class ModelContextRegistry implements ModelContextProvider {
75
76
  }
76
77
 
77
78
  private notifySubscribers(): void {
78
- for (const callback of this._subscribers) {
79
- callback();
80
- }
79
+ notifyStateSubscribers(this._subscribers);
81
80
  }
82
81
 
83
82
  addTool<TArgs extends Record<string, unknown>, TResult>(
@@ -144,9 +143,20 @@ export class ModelContextRegistry implements ModelContextProvider {
144
143
 
145
144
  this._providers.set(id, provider);
146
145
 
147
- const unsubscribe = provider.subscribe?.(() => {
148
- this.notifySubscribers();
149
- });
146
+ let unsubscribe: Unsubscribe | undefined;
147
+ try {
148
+ unsubscribe = provider.subscribe?.(() => {
149
+ this.notifySubscribers();
150
+ });
151
+ } catch (error) {
152
+ this._providers.delete(id);
153
+ try {
154
+ this.notifySubscribers();
155
+ } catch (notifyError) {
156
+ console.error(notifyError);
157
+ }
158
+ throw error;
159
+ }
150
160
  this._providerUnsubscribes.set(id, unsubscribe);
151
161
 
152
162
  this.notifySubscribers();
@@ -54,6 +54,7 @@ describe("RuntimeAdapter via the neutral store entry", () => {
54
54
  const handle = createAssistantClient(
55
55
  AuiConfig({ threads: RuntimeAdapter(runtime) }),
56
56
  );
57
+ handle.subscribe(() => {});
57
58
  const aui = handle.getClient();
58
59
 
59
60
  flushTapSync(() => aui.composer.setText("hello"));
@@ -75,6 +76,7 @@ describe("RuntimeAdapter via the neutral store entry", () => {
75
76
  const handle = createAssistantClient(
76
77
  AuiConfig({ threads: RuntimeAdapter(runtime) }),
77
78
  );
79
+ handle.subscribe(() => {});
78
80
 
79
81
  // Dev mode double-mounts the root (StrictMode emulation), so assert
80
82
  // presence rather than an exact count
@@ -1,5 +1,5 @@
1
- import { useEffect } from "react";
2
1
  import { useResource, resource } from "@assistant-ui/tap";
2
+ import type { AssistantClient, ScopesConfig } from "@assistant-ui/store";
3
3
  import type { AssistantRuntime } from "..";
4
4
  import {
5
5
  baseRuntimeAdapterTransformScopes,
@@ -8,6 +8,7 @@ import {
8
8
  import {
9
9
  attachTransformScopes,
10
10
  useAssistantClientRef,
11
+ useAssistantScopeEffect,
11
12
  } from "@assistant-ui/store/client";
12
13
  import { DataRenderers } from "./client/DataRenderers";
13
14
  import { Tools } from "./client/Tools";
@@ -15,11 +16,12 @@ import { Tools } from "./client/Tools";
15
16
  const useRuntimeAdapter = (runtime: AssistantRuntime) => {
16
17
  const clientRef = useAssistantClientRef();
17
18
 
18
- useEffect(() => {
19
- return runtime.registerModelContextProvider(
20
- clientRef.current!.modelContext(),
21
- );
22
- }, [runtime, clientRef]);
19
+ useAssistantScopeEffect(
20
+ "modelContext",
21
+ () =>
22
+ runtime.registerModelContextProvider(clientRef.current!.modelContext()),
23
+ [runtime],
24
+ );
23
25
 
24
26
  return useResource(
25
27
  ThreadListClient({
@@ -31,7 +33,15 @@ const useRuntimeAdapter = (runtime: AssistantRuntime) => {
31
33
 
32
34
  export const RuntimeAdapter = resource(useRuntimeAdapter);
33
35
 
34
- attachTransformScopes(useRuntimeAdapter, (scopes, parent) => {
36
+ /**
37
+ * The scope defaults `RuntimeAdapter` installs when it is used as the `threads`
38
+ * config entry. Adapter packages that wrap a runtime in their own config entry
39
+ * attach this to the wrapping resource for scope parity with `RuntimeAdapter`.
40
+ */
41
+ export const runtimeAdapterTransformScopes = (
42
+ scopes: ScopesConfig,
43
+ parent: AssistantClient,
44
+ ): void => {
35
45
  baseRuntimeAdapterTransformScopes(scopes, parent);
36
46
 
37
47
  if (!scopes.tools && parent.tools.source === null) {
@@ -41,4 +51,6 @@ attachTransformScopes(useRuntimeAdapter, (scopes, parent) => {
41
51
  if (!scopes.dataRenderers && parent.dataRenderers.source === null) {
42
52
  scopes.dataRenderers = DataRenderers();
43
53
  }
44
- });
54
+ };
55
+
56
+ attachTransformScopes(useRuntimeAdapter, runtimeAdapterTransformScopes);
@@ -21,7 +21,10 @@ import type {
21
21
  ExportedMessageRepository,
22
22
  ExportedMessageRepositoryItem,
23
23
  } from "../../internal";
24
- import { RuntimeAdapterProvider } from "../runtimes/RuntimeAdapterProvider";
24
+ import {
25
+ RuntimeAdapterProvider,
26
+ type RuntimeAdapters,
27
+ } from "../runtimes/RuntimeAdapterProvider";
25
28
  import type { TitleGenerationAdapter } from "./TitleGenerationAdapter";
26
29
 
27
30
  export type AsyncStorageLike = {
@@ -338,29 +341,40 @@ class AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {
338
341
  }
339
342
  }
340
343
 
344
+ const useLocalStorageThreadAdapters = (
345
+ storage: AsyncStorageLike,
346
+ prefix: string,
347
+ mutationQueue: KeyedMutationQueue,
348
+ ): RuntimeAdapters => {
349
+ const aui = useAui();
350
+ // Not useEffectEvent: history adapter methods run during render (SSR load).
351
+ const auiRef = useRef(aui);
352
+ useEffect(() => {
353
+ auiRef.current = aui;
354
+ });
355
+ const [history] = useState(
356
+ () =>
357
+ new AsyncStorageHistoryAdapter(
358
+ storage,
359
+ () => auiRef.current,
360
+ prefix,
361
+ mutationQueue,
362
+ ),
363
+ );
364
+ return useMemo(() => ({ history }), [history]);
365
+ };
366
+
341
367
  const createHistoryProvider = (
342
368
  storage: AsyncStorageLike,
343
369
  prefix: string,
344
370
  mutationQueue: KeyedMutationQueue,
345
371
  ): FC<PropsWithChildren> => {
346
372
  const Provider: FC<PropsWithChildren> = ({ children }) => {
347
- const aui = useAui();
348
- // Not useEffectEvent: history adapter methods run during render (SSR load).
349
- const auiRef = useRef(aui);
350
- useEffect(() => {
351
- auiRef.current = aui;
352
- });
353
- const [history] = useState(
354
- () =>
355
- new AsyncStorageHistoryAdapter(
356
- storage,
357
- () => auiRef.current,
358
- prefix,
359
- mutationQueue,
360
- ),
373
+ const adapters = useLocalStorageThreadAdapters(
374
+ storage,
375
+ prefix,
376
+ mutationQueue,
361
377
  );
362
- const adapters = useMemo(() => ({ history }), [history]);
363
-
364
378
  return (
365
379
  <RuntimeAdapterProvider adapters={adapters}>
366
380
  {children}
@@ -406,6 +420,9 @@ export const createLocalStorageAdapter = (
406
420
 
407
421
  const adapter: RemoteThreadListAdapter = {
408
422
  unstable_Provider: createHistoryProvider(storage, prefix, mutationQueue),
423
+ unstable_useAdapters: function useLocalStorageAdapters() {
424
+ return useLocalStorageThreadAdapters(storage, prefix, mutationQueue);
425
+ },
409
426
 
410
427
  async list(): Promise<RemoteThreadListResponse> {
411
428
  const threads = await loadThreadMetadata();
@@ -0,0 +1,41 @@
1
+ import { useEffect, useMemo } from "react";
2
+ import { resource, type ResourceElement } from "@assistant-ui/tap";
3
+ import { useClientResource } from "@assistant-ui/store/client";
4
+ import type { ClientOutput } from "@assistant-ui/store";
5
+ import type { RuntimeAdapters } from "../../runtimes/remote-thread-list/types";
6
+ import { isDevelopment } from "../../store/internal";
7
+ import {
8
+ useRuntimeAdapters,
9
+ useRuntimeAdaptersProvider,
10
+ useStableRuntimeAdapters,
11
+ } from "../runtimes/useRuntimeAdapters";
12
+
13
+ const useAdaptedRemoteThread = ({
14
+ useAdapters,
15
+ thread,
16
+ }: {
17
+ useAdapters: () => RuntimeAdapters | null | undefined;
18
+ thread: ResourceElement<ClientOutput<"thread">>;
19
+ }): ClientOutput<"thread"> => {
20
+ const parent = useRuntimeAdapters();
21
+ const stableAdapters = useStableRuntimeAdapters(useAdapters());
22
+
23
+ const unkeyedHistory =
24
+ stableAdapters?.history != null && thread.key === undefined;
25
+ useEffect(() => {
26
+ if (!isDevelopment || !unkeyedHistory) return;
27
+ console.warn(
28
+ "[assistant-ui] RemoteThreadList received a history adapter, but the thread factory is unkeyed. Key the thread resource by thread id (withKey) so switching threads reloads history.",
29
+ );
30
+ }, [unkeyedHistory]);
31
+
32
+ const merged = useMemo(
33
+ () => (stableAdapters == null ? parent : { ...parent, ...stableAdapters }),
34
+ [parent, stableAdapters],
35
+ );
36
+ return useRuntimeAdaptersProvider(merged, function useBoundRemoteThread() {
37
+ return useClientResource(thread).methods;
38
+ });
39
+ };
40
+
41
+ export const AdaptedRemoteThread = resource(useAdaptedRemoteThread);
@@ -0,0 +1,148 @@
1
+ // @vitest-environment jsdom
2
+
3
+ import { act, render } from "@testing-library/react";
4
+ import { describe, expect, it, vi } from "vitest";
5
+ import { resource } from "@assistant-ui/tap";
6
+ import { AuiProvider, useAui, useAuiEvent } from "@assistant-ui/store";
7
+ import { InMemoryThreadList } from "./InMemoryThreadList";
8
+
9
+ const stubComposer = { getState: () => ({}) };
10
+ const stubSuggestions = { getState: () => ({ suggestions: [] }) };
11
+ const useStubThread = (_props: { threadId: string }) => ({
12
+ getState: () => ({ isRunning: false }),
13
+ composer: () => stubComposer,
14
+ suggestions: () => stubSuggestions,
15
+ });
16
+ const StubThread = resource(useStubThread);
17
+
18
+ const setup = () => {
19
+ const selectionChanged = vi.fn();
20
+ let aui!: ReturnType<typeof useAui>;
21
+ const Consumer = () => {
22
+ useAuiEvent("threads.selectionChanged" as never, selectionChanged as never);
23
+ return null;
24
+ };
25
+ const Harness = () => {
26
+ aui = useAui({
27
+ threads: InMemoryThreadList({
28
+ thread: (threadId) => StubThread({ threadId }) as never,
29
+ }),
30
+ } as never);
31
+ return (
32
+ <AuiProvider value={aui}>
33
+ <Consumer />
34
+ </AuiProvider>
35
+ );
36
+ };
37
+ render(<Harness />);
38
+ return { getAui: () => aui, selectionChanged };
39
+ };
40
+
41
+ describe("InMemoryThreadList selection events", () => {
42
+ it("does not emit for the initially selected thread on mount", async () => {
43
+ const { selectionChanged } = setup();
44
+ await act(async () => {});
45
+ expect(selectionChanged).not.toHaveBeenCalled();
46
+ });
47
+
48
+ it("emits on switchToNewThread and on switching back", async () => {
49
+ const { getAui, selectionChanged } = setup();
50
+ await act(async () => {});
51
+
52
+ await act(async () => {
53
+ getAui().threads.switchToNewThread();
54
+ });
55
+ await act(async () => {});
56
+
57
+ const newThreadId = getAui().threads.getState().mainThreadId;
58
+ expect(newThreadId).not.toBe("main");
59
+ expect(selectionChanged).toHaveBeenCalledExactlyOnceWith({
60
+ threadId: newThreadId,
61
+ previousThreadId: "main",
62
+ });
63
+
64
+ await act(async () => {
65
+ getAui().threads.switchToThread("main");
66
+ });
67
+ await act(async () => {});
68
+
69
+ expect(selectionChanged).toHaveBeenCalledTimes(2);
70
+ expect(selectionChanged).toHaveBeenLastCalledWith({
71
+ threadId: "main",
72
+ previousThreadId: newThreadId,
73
+ });
74
+ });
75
+
76
+ it("emits when deleting the selected thread falls back to another", async () => {
77
+ const { getAui, selectionChanged } = setup();
78
+ await act(async () => {});
79
+
80
+ await act(async () => {
81
+ getAui().threads.switchToNewThread();
82
+ });
83
+ await act(async () => {});
84
+
85
+ const newThreadId = getAui().threads.getState().mainThreadId;
86
+ selectionChanged.mockClear();
87
+
88
+ await act(async () => {
89
+ getAui().threads.item({ id: newThreadId }).delete();
90
+ });
91
+ await act(async () => {});
92
+
93
+ expect(getAui().threads.getState().mainThreadId).toBe("main");
94
+ expect(selectionChanged).toHaveBeenCalledExactlyOnceWith({
95
+ threadId: "main",
96
+ previousThreadId: newThreadId,
97
+ });
98
+ });
99
+ });
100
+
101
+ describe("InMemoryThreadList delete", () => {
102
+ it("notifies onDelete with the removed thread id", async () => {
103
+ const onDelete = vi.fn();
104
+ let aui!: ReturnType<typeof useAui>;
105
+ const Harness = () => {
106
+ aui = useAui({
107
+ threads: InMemoryThreadList({
108
+ thread: (threadId) => StubThread({ threadId }) as never,
109
+ onDelete,
110
+ }),
111
+ } as never);
112
+ return <AuiProvider value={aui}>{null}</AuiProvider>;
113
+ };
114
+ render(<Harness />);
115
+ await act(async () => {});
116
+
117
+ await act(async () => {
118
+ aui.threads.switchToNewThread();
119
+ });
120
+ const doomed = aui.threads.getState().mainThreadId;
121
+ await act(async () => {
122
+ aui.threads.item({ id: doomed }).delete();
123
+ });
124
+ expect(onDelete).toHaveBeenCalledExactlyOnceWith(doomed);
125
+ });
126
+
127
+ it("starts a fresh thread when the last one is deleted", async () => {
128
+ let aui!: ReturnType<typeof useAui>;
129
+ const Harness = () => {
130
+ aui = useAui({
131
+ threads: InMemoryThreadList({
132
+ thread: (threadId) => StubThread({ threadId }) as never,
133
+ }),
134
+ } as never);
135
+ return <AuiProvider value={aui}>{null}</AuiProvider>;
136
+ };
137
+ render(<Harness />);
138
+ await act(async () => {});
139
+
140
+ await act(async () => {
141
+ aui.threads.item({ id: "main" }).delete();
142
+ });
143
+ const state = aui.threads.getState();
144
+ expect(state.threadIds).toHaveLength(1);
145
+ expect(state.mainThreadId).toBe(state.threadIds[0]);
146
+ expect(state.mainThreadId).not.toBe("main");
147
+ });
148
+ });