@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,184 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ actionBarCopyDisabled,
4
+ actionBarEditDisabled,
5
+ actionBarReloadDisabled,
6
+ branchPickerNextDisabled,
7
+ branchPickerPreviousDisabled,
8
+ composerCancelDisabled,
9
+ composerInputDisabled,
10
+ composerSendDisabled,
11
+ suggestionTriggerDisabled,
12
+ } from "./primitive-predicates";
13
+
14
+ const state = (partial: Record<string, unknown>) => partial as never;
15
+
16
+ describe("primitive predicates", () => {
17
+ it("composerSendDisabled requires canSend and either an idle thread or a queue", () => {
18
+ const composer = { canSend: true };
19
+ expect(
20
+ composerSendDisabled(
21
+ state({
22
+ composer,
23
+ thread: { isRunning: false, capabilities: { queue: false } },
24
+ }),
25
+ ),
26
+ ).toBe(false);
27
+ expect(
28
+ composerSendDisabled(
29
+ state({
30
+ composer,
31
+ thread: { isRunning: true, capabilities: { queue: true } },
32
+ }),
33
+ ),
34
+ ).toBe(false);
35
+ expect(
36
+ composerSendDisabled(
37
+ state({
38
+ composer,
39
+ thread: { isRunning: true, capabilities: { queue: false } },
40
+ }),
41
+ ),
42
+ ).toBe(true);
43
+ expect(
44
+ composerSendDisabled(
45
+ state({
46
+ composer: { canSend: false },
47
+ thread: { isRunning: false, capabilities: { queue: false } },
48
+ }),
49
+ ),
50
+ ).toBe(true);
51
+ });
52
+
53
+ it("actionBarReloadDisabled rejects user messages and busy threads", () => {
54
+ const thread = { isRunning: false, isDisabled: false };
55
+ expect(
56
+ actionBarReloadDisabled(
57
+ state({ thread, message: { role: "assistant" } }),
58
+ ),
59
+ ).toBe(false);
60
+ expect(
61
+ actionBarReloadDisabled(state({ thread, message: { role: "user" } })),
62
+ ).toBe(true);
63
+ expect(
64
+ actionBarReloadDisabled(
65
+ state({
66
+ thread: { ...thread, isRunning: true },
67
+ message: { role: "assistant" },
68
+ }),
69
+ ),
70
+ ).toBe(true);
71
+ });
72
+
73
+ it("actionBarCopyDisabled requires settled content with non-empty text", () => {
74
+ expect(
75
+ actionBarCopyDisabled(
76
+ state({
77
+ message: {
78
+ role: "assistant",
79
+ status: { type: "complete" },
80
+ parts: [{ type: "text", text: "hi" }],
81
+ },
82
+ }),
83
+ ),
84
+ ).toBe(false);
85
+ expect(
86
+ actionBarCopyDisabled(
87
+ state({
88
+ message: {
89
+ role: "assistant",
90
+ status: { type: "running" },
91
+ parts: [{ type: "text", text: "hi" }],
92
+ },
93
+ }),
94
+ ),
95
+ ).toBe(true);
96
+ expect(
97
+ actionBarCopyDisabled(
98
+ state({
99
+ message: {
100
+ role: "user",
101
+ status: undefined,
102
+ parts: [{ type: "text", text: "" }],
103
+ },
104
+ }),
105
+ ),
106
+ ).toBe(true);
107
+ });
108
+
109
+ it("branch picker predicates respect bounds and run capabilities", () => {
110
+ const thread = {
111
+ isRunning: false,
112
+ capabilities: { switchBranchDuringRun: false },
113
+ };
114
+ const message = { branchNumber: 2, branchCount: 3 };
115
+ expect(branchPickerPreviousDisabled(state({ thread, message }))).toBe(
116
+ false,
117
+ );
118
+ expect(branchPickerNextDisabled(state({ thread, message }))).toBe(false);
119
+ expect(
120
+ branchPickerPreviousDisabled(
121
+ state({ thread, message: { ...message, branchNumber: 1 } }),
122
+ ),
123
+ ).toBe(true);
124
+ expect(
125
+ branchPickerNextDisabled(
126
+ state({ thread, message: { ...message, branchNumber: 3 } }),
127
+ ),
128
+ ).toBe(true);
129
+ expect(
130
+ branchPickerNextDisabled(
131
+ state({ thread: { ...thread, isRunning: true }, message }),
132
+ ),
133
+ ).toBe(true);
134
+ });
135
+
136
+ it("suggestionTriggerDisabled gates on send only for queueless runs", () => {
137
+ const thread = {
138
+ isDisabled: false,
139
+ isRunning: true,
140
+ capabilities: { queue: false },
141
+ };
142
+ expect(suggestionTriggerDisabled(state({ thread }), false)).toBe(false);
143
+ expect(suggestionTriggerDisabled(state({ thread }), true)).toBe(true);
144
+ expect(
145
+ suggestionTriggerDisabled(
146
+ state({ thread: { ...thread, capabilities: { queue: true } } }),
147
+ true,
148
+ ),
149
+ ).toBe(false);
150
+ });
151
+ it("composerCancelDisabled, composerInputDisabled, and actionBarEditDisabled mirror their fields", () => {
152
+ expect(
153
+ composerCancelDisabled(state({ composer: { canCancel: true } })),
154
+ ).toBe(false);
155
+ expect(
156
+ composerCancelDisabled(state({ composer: { canCancel: false } })),
157
+ ).toBe(true);
158
+
159
+ const enabledThread = { isDisabled: false };
160
+ expect(
161
+ composerInputDisabled(state({ thread: enabledThread, composer: {} })),
162
+ ).toBe(false);
163
+ expect(
164
+ composerInputDisabled(
165
+ state({
166
+ thread: enabledThread,
167
+ composer: { dictation: { inputDisabled: true } },
168
+ }),
169
+ ),
170
+ ).toBe(true);
171
+ expect(
172
+ composerInputDisabled(
173
+ state({ thread: { isDisabled: true }, composer: {} }),
174
+ ),
175
+ ).toBe(true);
176
+
177
+ expect(
178
+ actionBarEditDisabled(state({ composer: { isEditing: false } })),
179
+ ).toBe(false);
180
+ expect(
181
+ actionBarEditDisabled(state({ composer: { isEditing: true } })),
182
+ ).toBe(true);
183
+ });
184
+ });
@@ -0,0 +1,43 @@
1
+ import type { AssistantState } from "@assistant-ui/store";
2
+
3
+ /**
4
+ * Disabled predicates shared by every binding's primitive layer. Each binding
5
+ * consumes these as state selectors so the disabled semantics of a primitive
6
+ * cannot drift between frameworks.
7
+ */
8
+
9
+ export const composerSendDisabled = (s: AssistantState): boolean =>
10
+ !s.composer.canSend || (s.thread.isRunning && !s.thread.capabilities.queue);
11
+
12
+ export const composerCancelDisabled = (s: AssistantState): boolean =>
13
+ !s.composer.canCancel;
14
+
15
+ export const composerInputDisabled = (s: AssistantState): boolean =>
16
+ s.thread.isDisabled || s.composer.dictation?.inputDisabled === true;
17
+
18
+ export const actionBarEditDisabled = (s: AssistantState): boolean =>
19
+ s.composer.isEditing;
20
+
21
+ export const actionBarReloadDisabled = (s: AssistantState): boolean =>
22
+ s.thread.isRunning || s.thread.isDisabled || s.message.role !== "assistant";
23
+
24
+ export const actionBarCopyDisabled = (s: AssistantState): boolean =>
25
+ !(
26
+ (s.message.role !== "assistant" || s.message.status?.type !== "running") &&
27
+ s.message.parts.some((part) => part.type === "text" && part.text.length > 0)
28
+ );
29
+
30
+ export const branchPickerPreviousDisabled = (s: AssistantState): boolean =>
31
+ s.message.branchNumber <= 1 ||
32
+ (s.thread.isRunning && !s.thread.capabilities.switchBranchDuringRun);
33
+
34
+ export const branchPickerNextDisabled = (s: AssistantState): boolean =>
35
+ s.message.branchNumber >= s.message.branchCount ||
36
+ (s.thread.isRunning && !s.thread.capabilities.switchBranchDuringRun);
37
+
38
+ export const suggestionTriggerDisabled = (
39
+ s: AssistantState,
40
+ send: boolean,
41
+ ): boolean =>
42
+ s.thread.isDisabled ||
43
+ (send && s.thread.isRunning && !s.thread.capabilities.queue);
@@ -0,0 +1,41 @@
1
+ import { createTapRoot, useResource } from "@assistant-ui/tap";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import type { AttachmentRuntime } from "../../runtime/api/attachment-runtime";
4
+ import { AttachmentRuntimeClient } from "./attachment-runtime-client";
5
+
6
+ describe("AttachmentRuntimeClient", () => {
7
+ afterEach(() => {
8
+ vi.restoreAllMocks();
9
+ });
10
+
11
+ it("reports attachment removal failures", async () => {
12
+ const error = new Error("storage unavailable");
13
+ const consoleError = vi
14
+ .spyOn(console, "error")
15
+ .mockImplementation(() => {});
16
+ const state = {
17
+ id: "attachment-1",
18
+ type: "file",
19
+ name: "notes.txt",
20
+ status: { type: "complete" },
21
+ content: [],
22
+ source: "thread-composer",
23
+ };
24
+ const runtime = {
25
+ getState: () => state,
26
+ subscribe: () => () => {},
27
+ remove: () => Promise.reject(error),
28
+ } as unknown as AttachmentRuntime;
29
+ const root = createTapRoot(function AttachmentClientRoot() {
30
+ return useResource(AttachmentRuntimeClient({ runtime }));
31
+ });
32
+
33
+ await expect(root.getValue().remove()).rejects.toBe(error);
34
+
35
+ expect(consoleError).toHaveBeenCalledWith(
36
+ "[assistant-ui] attachment remove failed:",
37
+ error,
38
+ );
39
+ root.unmount();
40
+ });
41
+ });
@@ -1,6 +1,7 @@
1
1
  import { resource } from "@assistant-ui/tap";
2
2
  import type { ClientOutput } from "@assistant-ui/store";
3
3
  import type { AttachmentRuntime } from "../../runtime/api/attachment-runtime";
4
+ import { handleRuntimeAction } from "./handle-runtime-action";
4
5
  import { useSubscribable } from "./useSubscribable";
5
6
 
6
7
  const useAttachmentRuntimeClient = ({
@@ -12,7 +13,7 @@ const useAttachmentRuntimeClient = ({
12
13
 
13
14
  return {
14
15
  getState: () => state,
15
- remove: runtime.remove,
16
+ remove: () => handleRuntimeAction("attachment remove", runtime.remove),
16
17
  __internal_getRuntime: () => runtime,
17
18
  };
18
19
  };
@@ -0,0 +1,11 @@
1
+ export const handleRuntimeAction = (
2
+ label: string,
3
+ execute: () => Promise<void>,
4
+ ): Promise<void> => {
5
+ const task = execute();
6
+
7
+ void task.catch((error: unknown) => {
8
+ console.error(`[assistant-ui] ${label} failed:`, error);
9
+ });
10
+ return task;
11
+ };
@@ -0,0 +1,69 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { handleThreadListAction } from "./handle-thread-list-action";
3
+
4
+ describe("handleThreadListAction", () => {
5
+ afterEach(() => {
6
+ vi.restoreAllMocks();
7
+ });
8
+
9
+ it("reports a rejected task", async () => {
10
+ const error = new Error("unavailable");
11
+ const task = Promise.reject(error);
12
+ const consoleError = vi
13
+ .spyOn(console, "error")
14
+ .mockImplementation(() => {});
15
+
16
+ const result = handleThreadListAction("delete", () => task);
17
+
18
+ expect(result).toBe(task);
19
+ await expect(result).rejects.toBe(error);
20
+ expect(consoleError).toHaveBeenCalledWith(
21
+ "[assistant-ui] thread list delete failed:",
22
+ error,
23
+ );
24
+ });
25
+
26
+ it("preserves synchronous failures", () => {
27
+ const error = new Error("invalid thread");
28
+ const consoleError = vi
29
+ .spyOn(console, "error")
30
+ .mockImplementation(() => {});
31
+
32
+ expect(() =>
33
+ handleThreadListAction("switch", () => {
34
+ throw error;
35
+ }),
36
+ ).toThrow(error);
37
+ expect(consoleError).not.toHaveBeenCalled();
38
+ });
39
+
40
+ it("does not leak an ignored action as an unhandled rejection", async () => {
41
+ const error = new Error("delete failed");
42
+ const consoleError = vi
43
+ .spyOn(console, "error")
44
+ .mockImplementation(() => {});
45
+ const rejections: unknown[] = [];
46
+ const onUnhandledRejection = (reason: unknown) => {
47
+ rejections.push(reason);
48
+ };
49
+ const priorListeners = process.listeners("unhandledRejection");
50
+ process.removeAllListeners("unhandledRejection");
51
+ process.on("unhandledRejection", onUnhandledRejection);
52
+
53
+ try {
54
+ handleThreadListAction("delete", () => Promise.reject(error));
55
+ await new Promise((resolve) => setTimeout(resolve, 20));
56
+ } finally {
57
+ process.removeListener("unhandledRejection", onUnhandledRejection);
58
+ for (const listener of priorListeners) {
59
+ process.on("unhandledRejection", listener);
60
+ }
61
+ }
62
+
63
+ expect(rejections).toEqual([]);
64
+ expect(consoleError).toHaveBeenCalledWith(
65
+ "[assistant-ui] thread list delete failed:",
66
+ error,
67
+ );
68
+ });
69
+ });
@@ -0,0 +1,6 @@
1
+ import { handleRuntimeAction } from "./handle-runtime-action";
2
+
3
+ export const handleThreadListAction = (
4
+ action: string,
5
+ execute: () => Promise<void>,
6
+ ): Promise<void> => handleRuntimeAction(`thread list ${action}`, execute);
@@ -1,13 +1,10 @@
1
- import type { Unsubscribe } from "../../types/unsubscribe";
2
- import { useEffect, useMemo } from "react";
1
+ import { useEffect, useMemo, useRef } from "react";
3
2
  import { resource } from "@assistant-ui/tap";
4
3
  import type { ClientOutput } from "@assistant-ui/store";
5
4
  import { useAssistantEmit } from "@assistant-ui/store/client";
6
- import type {
7
- ThreadListItemEventType,
8
- ThreadListItemRuntime,
9
- } from "../../runtime/api/thread-list-item-runtime";
5
+ import type { ThreadListItemRuntime } from "../../runtime/api/thread-list-item-runtime";
10
6
  import { useSubscribable } from "./useSubscribable";
7
+ import { handleThreadListAction } from "./handle-thread-list-action";
11
8
 
12
9
  const useThreadListItemClient = ({
13
10
  runtime,
@@ -28,39 +25,35 @@ const useThreadListItemClient = ({
28
25
  }, [runtimeState, mainThreadIsRunning]);
29
26
  const emit = useAssistantEmit();
30
27
 
31
- // Bind thread list item events to event manager
28
+ // Emitted after the flush that rebinds the derived scopes; the runtime's own
29
+ // synchronous notification would be delivered against the pre-switch binding.
30
+ const { isMain, id: threadId } = runtimeState;
31
+ const selectionRef = useRef({ isMain, threadId });
32
32
  useEffect(() => {
33
- const unsubscribers: Unsubscribe[] = [];
34
-
35
- // Subscribe to thread list item events
36
- const threadListItemEvents: ThreadListItemEventType[] = [
37
- "switchedTo",
38
- "switchedAway",
39
- ];
40
-
41
- for (const event of threadListItemEvents) {
42
- const unsubscribe = runtime.unstable_on(event, () => {
43
- emit(`threadListItem.${event}`, {
44
- threadId: runtime.getState()!.id,
45
- });
46
- });
47
- unsubscribers.push(unsubscribe);
48
- }
49
-
50
- return () => {
51
- for (const unsub of unsubscribers) unsub();
52
- };
53
- }, [runtime, emit]);
33
+ const previous = selectionRef.current;
34
+ if (previous.isMain === isMain && previous.threadId === threadId) return;
35
+ selectionRef.current = { isMain, threadId };
36
+ emit(isMain ? "threadListItem.switchedTo" : "threadListItem.switchedAway", {
37
+ threadId,
38
+ });
39
+ }, [isMain, threadId, emit]);
54
40
 
55
41
  return {
56
42
  getState: () => state,
57
- switchTo: runtime.switchTo,
58
- rename: runtime.rename,
59
- updateCustom: runtime.updateCustom,
60
- archive: runtime.archive,
61
- unarchive: runtime.unarchive,
62
- delete: runtime.delete,
63
- generateTitle: runtime.generateTitle,
43
+ switchTo: (options) =>
44
+ handleThreadListAction("switch", () => runtime.switchTo(options)),
45
+ rename: (newTitle) =>
46
+ handleThreadListAction("rename", () => runtime.rename(newTitle)),
47
+ updateCustom: (custom) =>
48
+ handleThreadListAction("update custom metadata", () =>
49
+ runtime.updateCustom(custom),
50
+ ),
51
+ archive: () => handleThreadListAction("archive", () => runtime.archive()),
52
+ unarchive: () =>
53
+ handleThreadListAction("unarchive", () => runtime.unarchive()),
54
+ delete: () => handleThreadListAction("delete", () => runtime.delete()),
55
+ generateTitle: () =>
56
+ handleThreadListAction("generate title", () => runtime.generateTitle()),
64
57
  initialize: runtime.initialize,
65
58
  detach: runtime.detach,
66
59
  __internal_getRuntime: () => runtime,
@@ -2,12 +2,14 @@ import { useMemo } from "react";
2
2
  import { useResource, withKey, resource } from "@assistant-ui/tap";
3
3
  import type { ClientOutput } from "@assistant-ui/store";
4
4
  import { useClientLookup, useClientResource } from "@assistant-ui/store/client";
5
+ import { useThreadSelectionEvents } from "../clients/thread-selection-events";
5
6
  import type { ThreadListRuntime } from "../../runtime/api/thread-list-runtime";
6
7
  import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
7
8
  import { useSubscribable } from "./useSubscribable";
8
9
  import { ThreadListItemClient } from "./thread-list-item-runtime-client";
9
10
  import { ThreadClient } from "./thread-runtime-client";
10
11
  import type { ThreadsState } from "../scopes/threads";
12
+ import { handleThreadListAction } from "./handle-thread-list-action";
11
13
 
12
14
  const useThreadListItemClientById = ({
13
15
  runtime,
@@ -40,6 +42,7 @@ const useThreadListClient = ({
40
42
  __internal_assistantRuntime: AssistantRuntime;
41
43
  }): ClientOutput<"threads"> => {
42
44
  const runtimeState = useSubscribable(runtime);
45
+ useThreadSelectionEvents(runtimeState.mainThreadId);
43
46
 
44
47
  const main = useClientResource(
45
48
  ThreadClient({
@@ -93,12 +96,12 @@ const useThreadListClient = ({
93
96
  : state.threadIds[index]!;
94
97
  return threadItems.get({ key: id });
95
98
  },
96
- switchToThread: async (threadId, options) => {
97
- await runtime.switchToThread(threadId, options);
98
- },
99
- switchToNewThread: async () => {
100
- await runtime.switchToNewThread();
101
- },
99
+ switchToThread: (threadId, options) =>
100
+ handleThreadListAction("switch", () =>
101
+ runtime.switchToThread(threadId, options),
102
+ ),
103
+ switchToNewThread: () =>
104
+ handleThreadListAction("create", () => runtime.switchToNewThread()),
102
105
  getLoadThreadsPromise: () => runtime.getLoadThreadsPromise(),
103
106
  reload: () => runtime.reload(),
104
107
  reloadMainThread: () => runtime.reloadMainThread(),
@@ -12,6 +12,7 @@ import {
12
12
  } from "@assistant-ui/store/client";
13
13
  import { ComposerClient } from "./composer-runtime-client";
14
14
  import { MessageClient } from "./message-runtime-client";
15
+ import { ThreadSuggestions } from "../clients/suggestions";
15
16
  import { useSubscribable } from "./useSubscribable";
16
17
  import type { ThreadState } from "../scopes/thread";
17
18
 
@@ -78,6 +79,9 @@ const useThreadClient = ({
78
79
  threadIdRef,
79
80
  }),
80
81
  );
82
+ const suggestions = useClientResource(
83
+ ThreadSuggestions(runtimeState.suggestions),
84
+ );
81
85
  const messages = useClientLookup(
82
86
  runtimeState.messages.map((m) =>
83
87
  withKey(m.id, MessageClientById({ runtime, id: m.id, threadIdRef }), [
@@ -109,6 +113,7 @@ const useThreadClient = ({
109
113
  return {
110
114
  getState: () => state,
111
115
  composer: () => composer.methods,
116
+ suggestions: () => suggestions.methods,
112
117
  append: runtime.append,
113
118
  deleteMessage: runtime.deleteMessage,
114
119
  startRun: runtime.startRun,
@@ -27,6 +27,11 @@ export type ComposerState = {
27
27
  readonly attachments: readonly Attachment[];
28
28
  readonly runConfig: RunConfig;
29
29
  readonly isEditing: boolean;
30
+ /**
31
+ * Whether the composer can cancel the current run. `true` when the runtime
32
+ * supports cancel and a run is in flight, not merely when cancel is a
33
+ * capability.
34
+ */
30
35
  readonly canCancel: boolean;
31
36
  /**
32
37
  * Whether the composer is currently willing to send. `true` when the
@@ -104,13 +109,13 @@ export type ComposerMeta = {
104
109
 
105
110
  export type ComposerEvents = {
106
111
  /**
107
- * @deprecated State-derivable. Observe composer `text` clearing via
108
- * `useAuiState` instead. Kept for backward compatibility.
112
+ * The user sent the composer contents. `messageId` is set when the send
113
+ * came from an edit composer.
109
114
  */
110
115
  "composer.send": { threadId: string; messageId?: string };
111
116
  /**
112
- * @deprecated State-derivable. Observe composer `attachments` via
113
- * `useAuiState` instead. Kept for backward compatibility.
117
+ * An attachment was added to the composer. `messageId` is set when the
118
+ * attachment was added to an edit composer.
114
119
  */
115
120
  "composer.attachmentAdd": { threadId: string; messageId?: string };
116
121
  "composer.attachmentAddError": {
@@ -15,6 +15,12 @@ export type SuggestionsMethods = {
15
15
  suggestion(query: { index: number }): SuggestionMethods;
16
16
  };
17
17
 
18
+ export type SuggestionsMeta = {
19
+ source: "thread";
20
+ query: Record<string, never>;
21
+ };
22
+
18
23
  export type SuggestionsClientSchema = {
19
24
  methods: SuggestionsMethods;
25
+ meta: SuggestionsMeta;
20
26
  };
@@ -42,15 +42,16 @@ export type ThreadListItemMeta = {
42
42
 
43
43
  export type ThreadListItemEvents = {
44
44
  /**
45
- * @deprecated State-derivable. Compare `s.threads.mainThreadId` against the
46
- * item's `s.threadListItem.id` via `useAuiState` instead. Kept for backward
47
- * compatibility.
45
+ * @deprecated Use `threads.selectionChanged` instead; its `threadId` is the
46
+ * newly selected thread. Inside a per-item `threadListItem` scope, filter by
47
+ * `threadId === threadListItem.id` to reproduce the per-item delivery. Kept
48
+ * for backward compatibility.
48
49
  */
49
50
  "threadListItem.switchedTo": { threadId: string };
50
51
  /**
51
- * @deprecated State-derivable. Compare `s.threads.mainThreadId` against the
52
- * item's `s.threadListItem.id` via `useAuiState` instead. Kept for backward
53
- * compatibility.
52
+ * @deprecated Use `threads.selectionChanged` instead; its
53
+ * `previousThreadId` is the thread that was switched away from. Kept for
54
+ * backward compatibility.
54
55
  */
55
56
  "threadListItem.switchedAway": { threadId: string };
56
57
  };
@@ -17,6 +17,7 @@ import type {
17
17
  import type { ModelContext } from "../../model-context/types";
18
18
  import type { MessageMethods, MessageState } from "./message";
19
19
  import type { ComposerMethods, ComposerState } from "./composer";
20
+ import type { SuggestionsMethods } from "./suggestions";
20
21
 
21
22
  export type ThreadState = {
22
23
  /**
@@ -71,6 +72,10 @@ export type ThreadMethods = {
71
72
  * The thread composer runtime.
72
73
  */
73
74
  composer(): ComposerMethods;
75
+ /**
76
+ * The suggestions shown for this thread.
77
+ */
78
+ suggestions(): SuggestionsMethods;
74
79
  /**
75
80
  * Append a new message to the thread.
76
81
  *
@@ -100,6 +105,18 @@ export type ThreadMethods = {
100
105
  */
101
106
  resumeRun(config: CreateResumeRunConfig): void;
102
107
  cancelRun(): void;
108
+ /**
109
+ * Re-fetch this thread's state from its backing store, in place: the tap
110
+ * thread's refetch hook, which `threads.reloadMainThread()` prefers and
111
+ * whose rejection it propagates. `capabilities.refetchThread` is the
112
+ * portable feature-detection signal; a legacy-bridged thread reports it
113
+ * there while routing the refetch through its runtime, not this method.
114
+ * The method-shorthand optionality is load-bearing: an explicit
115
+ * `| undefined` stops `ThreadMethods` satisfying `ClientMethods` and
116
+ * collapses the client schema, which only a workspace-level app typecheck
117
+ * surfaces.
118
+ */
119
+ unstable_refetchThread?(): Promise<void>;
103
120
  getModelContext(): ModelContext;
104
121
  export(): ExportedMessageRepository;
105
122
  import(repository: ExportedMessageRepository): void;
@@ -128,19 +145,20 @@ export type ThreadMeta = {
128
145
 
129
146
  export type ThreadEvents = {
130
147
  /**
131
- * @deprecated State-derivable. Observe `isRunning` flipping to `true` via
132
- * `useAuiState` instead. Kept for backward compatibility.
148
+ * A run started on this thread. Also observable as `isRunning` flipping to
149
+ * `true` in thread state.
133
150
  */
134
151
  "thread.runStart": { threadId: string };
135
152
  /**
136
- * @deprecated State-derivable. Observe `isRunning` flipping to `false` via
137
- * `useAuiState` instead. Kept for backward compatibility.
153
+ * A run on this thread ended, whether it completed, errored, or was
154
+ * cancelled. Also observable as `isRunning` flipping to `false` in thread
155
+ * state.
138
156
  */
139
157
  "thread.runEnd": { threadId: string };
140
158
  /**
141
- * @deprecated State-derivable. This event fires before the first message is
142
- * added; observe `messages` becoming non-empty via `useAuiState` instead of
143
- * reading state inside this event handler. Kept for backward compatibility.
159
+ * The thread transitioned from new to initialized. Fires before the first
160
+ * message is added, so read thread state via `useAuiState` rather than
161
+ * inside this event handler.
144
162
  */
145
163
  "thread.initialize": { threadId: string };
146
164
  /**