@assistant-ui/core 0.1.14 → 0.1.15

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 (324) hide show
  1. package/dist/adapters/attachment.d.ts +6 -0
  2. package/dist/adapters/attachment.d.ts.map +1 -1
  3. package/dist/adapters/attachment.js +54 -9
  4. package/dist/adapters/attachment.js.map +1 -1
  5. package/dist/adapters/{mention.d.ts → directive-formatter.d.ts} +2 -4
  6. package/dist/adapters/directive-formatter.d.ts.map +1 -0
  7. package/dist/adapters/{mention.js → directive-formatter.js} +4 -9
  8. package/dist/adapters/directive-formatter.js.map +1 -0
  9. package/dist/adapters/index.d.ts +1 -3
  10. package/dist/adapters/index.d.ts.map +1 -1
  11. package/dist/adapters/index.js +2 -1
  12. package/dist/adapters/index.js.map +1 -1
  13. package/dist/adapters/speech.d.ts.map +1 -1
  14. package/dist/adapters/speech.js +1 -3
  15. package/dist/adapters/speech.js.map +1 -1
  16. package/dist/adapters/thread-history.d.ts +1 -0
  17. package/dist/adapters/thread-history.d.ts.map +1 -1
  18. package/dist/adapters/trigger.d.ts +1 -18
  19. package/dist/adapters/trigger.d.ts.map +1 -1
  20. package/dist/index.d.ts +2 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/model-context/frame/host.d.ts +1 -1
  25. package/dist/model-context/frame/host.d.ts.map +1 -1
  26. package/dist/model-context/frame/host.js +1 -0
  27. package/dist/model-context/frame/host.js.map +1 -1
  28. package/dist/model-context/frame/provider.d.ts +1 -1
  29. package/dist/model-context/frame/provider.d.ts.map +1 -1
  30. package/dist/model-context/frame/provider.js +1 -0
  31. package/dist/model-context/frame/provider.js.map +1 -1
  32. package/dist/model-context/registry.d.ts +2 -2
  33. package/dist/model-context/registry.d.ts.map +1 -1
  34. package/dist/model-context/tool.d.ts +1 -1
  35. package/dist/model-context/tool.d.ts.map +1 -1
  36. package/dist/model-context/types.d.ts +1 -1
  37. package/dist/model-context/types.d.ts.map +1 -1
  38. package/dist/model-context/types.js +0 -3
  39. package/dist/model-context/types.js.map +1 -1
  40. package/dist/react/AssistantRuntimeProvider.d.ts +1 -1
  41. package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
  42. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  43. package/dist/react/client/DataRenderers.d.ts +1 -1
  44. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  45. package/dist/react/client/DataRenderers.js +14 -0
  46. package/dist/react/client/DataRenderers.js.map +1 -1
  47. package/dist/react/client/Tools.d.ts +1 -1
  48. package/dist/react/client/Tools.d.ts.map +1 -1
  49. package/dist/react/client/Tools.js +1 -0
  50. package/dist/react/client/Tools.js.map +1 -1
  51. package/dist/react/model-context/makeAssistantTool.d.ts +1 -1
  52. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  53. package/dist/react/model-context/makeAssistantToolUI.d.ts +1 -1
  54. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  55. package/dist/react/model-context/useInlineRender.d.ts +2 -2
  56. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  57. package/dist/react/model-context/useInlineRender.js +1 -0
  58. package/dist/react/model-context/useInlineRender.js.map +1 -1
  59. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts.map +1 -1
  60. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -0
  61. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  62. package/dist/react/primitives/composer/ComposerAttachments.d.ts +1 -1
  63. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  64. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  65. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  66. package/dist/react/primitives/message/MessageAttachments.d.ts +1 -1
  67. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  68. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  69. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  70. package/dist/react/primitives/message/MessageParts.d.ts +1 -1
  71. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  72. package/dist/react/primitives/message/MessageParts.js +16 -17
  73. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  74. package/dist/react/primitives/part/PartMessages.d.ts +1 -1
  75. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  76. package/dist/react/primitives/thread/ThreadMessages.d.ts +1 -1
  77. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  78. package/dist/react/primitives/thread/ThreadMessages.js +2 -1
  79. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  80. package/dist/react/primitives/threadList/ThreadListItems.d.ts +1 -1
  81. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  82. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  83. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  84. package/dist/react/providers/AttachmentByIndexProvider.d.ts +1 -1
  85. package/dist/react/providers/AttachmentByIndexProvider.d.ts.map +1 -1
  86. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts +1 -1
  87. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts.map +1 -1
  88. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts +1 -1
  89. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
  90. package/dist/react/providers/MessageByIndexProvider.d.ts +1 -1
  91. package/dist/react/providers/MessageByIndexProvider.d.ts.map +1 -1
  92. package/dist/react/providers/PartByIndexProvider.d.ts +1 -1
  93. package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
  94. package/dist/react/providers/QueueItemByIndexProvider.d.ts +1 -1
  95. package/dist/react/providers/QueueItemByIndexProvider.d.ts.map +1 -1
  96. package/dist/react/providers/SuggestionByIndexProvider.d.ts +1 -1
  97. package/dist/react/providers/SuggestionByIndexProvider.d.ts.map +1 -1
  98. package/dist/react/providers/TextMessagePartProvider.d.ts +1 -1
  99. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  100. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts +1 -1
  101. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts.map +1 -1
  102. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts +1 -1
  103. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +3 -1
  105. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  106. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +2 -1
  107. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  108. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
  109. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  110. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +21 -4
  111. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  112. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +1 -1
  113. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  114. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  115. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +2 -2
  116. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  117. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  118. package/dist/react/runtimes/cloud/auiV0.d.ts +2 -2
  119. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  120. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  121. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  122. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +4 -1
  123. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  124. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  125. package/dist/react/runtimes/useLocalRuntime.js +10 -0
  126. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  127. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  128. package/dist/react/runtimes/useRemoteThreadListRuntime.js +6 -0
  129. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  130. package/dist/react/runtimes/useToolInvocations.d.ts.map +1 -1
  131. package/dist/react/runtimes/useToolInvocations.js +2 -0
  132. package/dist/react/runtimes/useToolInvocations.js.map +1 -1
  133. package/dist/react/types/MessagePartComponentTypes.d.ts +1 -1
  134. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  135. package/dist/react/types/scopes/dataRenderers.d.ts +2 -0
  136. package/dist/react/types/scopes/dataRenderers.d.ts.map +1 -1
  137. package/dist/runtime/api/assistant-runtime.d.ts +1 -1
  138. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  139. package/dist/runtime/api/attachment-runtime.d.ts +0 -1
  140. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  141. package/dist/runtime/api/attachment-runtime.js +0 -3
  142. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  143. package/dist/runtime/api/message-runtime.d.ts +6 -6
  144. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  145. package/dist/runtime/api/thread-list-runtime.d.ts +4 -2
  146. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  147. package/dist/runtime/api/thread-list-runtime.js +5 -0
  148. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  149. package/dist/runtime/api/thread-runtime.d.ts +10 -9
  150. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  151. package/dist/runtime/api/thread-runtime.js +4 -3
  152. package/dist/runtime/api/thread-runtime.js.map +1 -1
  153. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  154. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -1
  155. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  156. package/dist/runtime/base/default-edit-composer-runtime-core.js +26 -5
  157. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  158. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
  159. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  160. package/dist/runtime/interfaces/thread-runtime-core.d.ts +7 -0
  161. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  162. package/dist/runtime/internal.d.ts.map +1 -1
  163. package/dist/runtime/internal.js +1 -4
  164. package/dist/runtime/internal.js.map +1 -1
  165. package/dist/runtime/utils/auto-status.d.ts +1 -1
  166. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  167. package/dist/runtime/utils/chat-model-adapter.d.ts +1 -1
  168. package/dist/runtime/utils/chat-model-adapter.d.ts.map +1 -1
  169. package/dist/runtime/utils/thread-message-like.d.ts +1 -1
  170. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  171. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  172. package/dist/runtimes/assistant-transport/utils.d.ts +1 -1
  173. package/dist/runtimes/assistant-transport/utils.d.ts.map +1 -1
  174. package/dist/runtimes/assistant-transport/utils.js +1 -1
  175. package/dist/runtimes/assistant-transport/utils.js.map +1 -1
  176. package/dist/runtimes/external-store/external-store-adapter.d.ts +8 -0
  177. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  178. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
  179. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  180. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +27 -25
  181. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  182. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +1 -0
  183. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  184. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +4 -0
  185. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  186. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +2 -2
  187. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  188. package/dist/runtimes/remote-thread-list/types.d.ts +1 -1
  189. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  190. package/dist/store/runtime-clients/attachment-runtime-client.d.ts +2 -2
  191. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  192. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -1
  193. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  194. package/dist/store/runtime-clients/message-part-runtime-client.d.ts +2 -2
  195. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  196. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -1
  197. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  198. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +1 -1
  199. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  200. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +2 -2
  201. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  202. package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
  203. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  204. package/dist/store/runtime-clients/thread-runtime-client.d.ts +1 -1
  205. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  206. package/dist/store/scopes/threads.d.ts +1 -0
  207. package/dist/store/scopes/threads.d.ts.map +1 -1
  208. package/dist/subscribable/subscribable.d.ts.map +1 -1
  209. package/dist/subscribable/subscribable.js +1 -15
  210. package/dist/subscribable/subscribable.js.map +1 -1
  211. package/dist/tests/remote-thread-list-test-helpers.d.ts +12 -0
  212. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -0
  213. package/dist/tests/remote-thread-list-test-helpers.js +48 -0
  214. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -0
  215. package/dist/types/directive.d.ts +19 -0
  216. package/dist/types/directive.d.ts.map +1 -0
  217. package/dist/types/directive.js +2 -0
  218. package/dist/types/directive.js.map +1 -0
  219. package/dist/types/index.d.ts +1 -1
  220. package/dist/types/index.d.ts.map +1 -1
  221. package/dist/types/message.d.ts.map +1 -1
  222. package/dist/types/trigger.d.ts +2 -2
  223. package/dist/types/trigger.d.ts.map +1 -1
  224. package/dist/utils/json/is-json.d.ts +1 -1
  225. package/dist/utils/json/is-json.d.ts.map +1 -1
  226. package/package.json +11 -11
  227. package/src/adapters/attachment.ts +68 -16
  228. package/src/adapters/{mention.ts → directive-formatter.ts} +8 -20
  229. package/src/adapters/index.ts +2 -9
  230. package/src/adapters/speech.ts +1 -16
  231. package/src/adapters/thread-history.ts +1 -8
  232. package/src/adapters/trigger.ts +1 -37
  233. package/src/index.ts +3 -24
  234. package/src/model-context/frame/host.ts +6 -5
  235. package/src/model-context/frame/provider.ts +6 -5
  236. package/src/model-context/registry.ts +6 -6
  237. package/src/model-context/tool.ts +1 -1
  238. package/src/model-context/types.ts +1 -17
  239. package/src/react/AssistantRuntimeProvider.tsx +1 -1
  240. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -1
  241. package/src/react/client/DataRenderers.ts +19 -3
  242. package/src/react/client/Tools.ts +4 -3
  243. package/src/react/model-context/makeAssistantTool.ts +1 -1
  244. package/src/react/model-context/makeAssistantToolUI.ts +1 -1
  245. package/src/react/model-context/useInlineRender.ts +3 -2
  246. package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -0
  247. package/src/react/primitives/composer/ComposerAttachments.tsx +7 -1
  248. package/src/react/primitives/message/MessageAttachments.tsx +7 -1
  249. package/src/react/primitives/message/MessageParts.tsx +27 -17
  250. package/src/react/primitives/part/PartMessages.tsx +1 -1
  251. package/src/react/primitives/thread/ThreadMessages.tsx +3 -2
  252. package/src/react/primitives/threadList/ThreadListItems.tsx +7 -1
  253. package/src/react/providers/AttachmentByIndexProvider.tsx +1 -1
  254. package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
  255. package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +1 -1
  256. package/src/react/providers/MessageByIndexProvider.tsx +1 -1
  257. package/src/react/providers/PartByIndexProvider.tsx +1 -1
  258. package/src/react/providers/QueueItemByIndexProvider.tsx +1 -1
  259. package/src/react/providers/SuggestionByIndexProvider.tsx +1 -1
  260. package/src/react/providers/TextMessagePartProvider.tsx +1 -1
  261. package/src/react/providers/ThreadListItemByIndexProvider.tsx +1 -1
  262. package/src/react/providers/ThreadListItemRuntimeProvider.tsx +1 -1
  263. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +7 -8
  264. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +28 -8
  265. package/src/react/runtimes/RuntimeAdapterProvider.tsx +1 -1
  266. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +3 -3
  267. package/src/react/runtimes/cloud/auiV0.ts +5 -2
  268. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +6 -3
  269. package/src/react/runtimes/useLocalRuntime.ts +10 -0
  270. package/src/react/runtimes/useRemoteThreadListRuntime.ts +6 -0
  271. package/src/react/runtimes/useToolInvocations.ts +2 -0
  272. package/src/react/types/MessagePartComponentTypes.ts +1 -1
  273. package/src/react/types/scopes/dataRenderers.ts +2 -0
  274. package/src/runtime/api/assistant-runtime.ts +1 -1
  275. package/src/runtime/api/attachment-runtime.ts +0 -4
  276. package/src/runtime/api/message-runtime.ts +8 -8
  277. package/src/runtime/api/thread-list-runtime.ts +13 -5
  278. package/src/runtime/api/thread-runtime.ts +13 -12
  279. package/src/runtime/base/base-thread-runtime-core.ts +1 -1
  280. package/src/runtime/base/default-edit-composer-runtime-core.ts +35 -5
  281. package/src/runtime/interfaces/thread-list-runtime-core.ts +1 -0
  282. package/src/runtime/interfaces/thread-runtime-core.ts +7 -0
  283. package/src/runtime/internal.ts +1 -4
  284. package/src/runtime/utils/auto-status.ts +1 -1
  285. package/src/runtime/utils/chat-model-adapter.ts +1 -1
  286. package/src/runtime/utils/thread-message-like.ts +4 -1
  287. package/src/runtimes/assistant-transport/utils.ts +5 -1
  288. package/src/runtimes/external-store/external-store-adapter.ts +8 -0
  289. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +35 -29
  290. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +4 -0
  291. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +2 -2
  292. package/src/runtimes/remote-thread-list/types.ts +1 -1
  293. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -2
  294. package/src/store/runtime-clients/composer-runtime-client.ts +2 -2
  295. package/src/store/runtime-clients/message-part-runtime-client.ts +2 -2
  296. package/src/store/runtime-clients/message-runtime-client.ts +2 -2
  297. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +1 -1
  298. package/src/store/runtime-clients/thread-list-runtime-client.ts +4 -3
  299. package/src/store/runtime-clients/thread-runtime-client.ts +3 -3
  300. package/src/store/scopes/threads.ts +1 -0
  301. package/src/subscribable/subscribable.ts +1 -24
  302. package/src/tests/OptimisticState-list-race.test.ts +5 -9
  303. package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +209 -0
  304. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-dedupe.test.ts +139 -0
  305. package/src/tests/attachment.test.ts +180 -0
  306. package/src/tests/default-edit-composer-runtime-core.test.ts +312 -0
  307. package/src/tests/{mention-formatter.test.ts → directive-formatter.test.ts} +26 -1
  308. package/src/tests/external-store-thread-list-runtime-core.test.ts +212 -0
  309. package/src/tests/get-thread-state-isRunning.test.ts +93 -0
  310. package/src/tests/remote-thread-list-isLoading.test.ts +6 -10
  311. package/src/tests/remote-thread-list-test-helpers.ts +70 -0
  312. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +17 -1
  313. package/src/types/directive.ts +19 -0
  314. package/src/types/index.ts +1 -3
  315. package/src/types/message.ts +0 -12
  316. package/src/types/trigger.ts +2 -10
  317. package/src/utils/json/is-json.ts +1 -1
  318. package/dist/adapters/mention.d.ts.map +0 -1
  319. package/dist/adapters/mention.js.map +0 -1
  320. package/dist/types/mention.d.ts +0 -21
  321. package/dist/types/mention.d.ts.map +0 -1
  322. package/dist/types/mention.js +0 -2
  323. package/dist/types/mention.js.map +0 -1
  324. package/src/types/mention.ts +0 -39
@@ -0,0 +1,209 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import type { RemoteThreadListResponse } from "../runtimes/remote-thread-list/types";
3
+ import {
4
+ createCore,
5
+ deferred,
6
+ makeAdapter,
7
+ } from "./remote-thread-list-test-helpers";
8
+
9
+ describe("RemoteThreadListThreadListRuntimeCore.reload", () => {
10
+ it("refetches list() after a successful empty load", async () => {
11
+ const listFn = vi
12
+ .fn<() => Promise<RemoteThreadListResponse>>()
13
+ .mockResolvedValueOnce({ threads: [] })
14
+ .mockResolvedValueOnce({
15
+ threads: [
16
+ {
17
+ status: "regular",
18
+ remoteId: "t-1",
19
+ externalId: "t-1",
20
+ title: "After auth",
21
+ },
22
+ ],
23
+ });
24
+ const adapter = makeAdapter({ list: listFn });
25
+ const core = createCore(adapter);
26
+
27
+ await core.getLoadThreadsPromise();
28
+ expect(listFn).toHaveBeenCalledTimes(1);
29
+ expect(core.threadIds).toEqual([]);
30
+
31
+ await core.reload();
32
+ expect(listFn).toHaveBeenCalledTimes(2);
33
+ expect(core.threadIds).toEqual(["t-1"]);
34
+ });
35
+
36
+ it("returns the same cached promise from getLoadThreadsPromise when reload is not called", async () => {
37
+ const adapter = makeAdapter({
38
+ list: vi.fn(async () => ({ threads: [] })),
39
+ });
40
+ const core = createCore(adapter);
41
+
42
+ const p1 = core.getLoadThreadsPromise();
43
+ const p2 = core.getLoadThreadsPromise();
44
+ await p1;
45
+ await p2;
46
+
47
+ expect(adapter.list).toHaveBeenCalledTimes(1);
48
+ });
49
+
50
+ it("drops stale responses when a reload is triggered mid-flight", async () => {
51
+ const first = deferred<RemoteThreadListResponse>();
52
+ const second = deferred<RemoteThreadListResponse>();
53
+ const listFn = vi
54
+ .fn<() => Promise<RemoteThreadListResponse>>()
55
+ .mockReturnValueOnce(first.promise)
56
+ .mockReturnValueOnce(second.promise);
57
+
58
+ const adapter = makeAdapter({ list: listFn });
59
+ const core = createCore(adapter);
60
+
61
+ core.getLoadThreadsPromise();
62
+ const reloaded = core.reload();
63
+
64
+ second.resolve({
65
+ threads: [
66
+ {
67
+ status: "regular",
68
+ remoteId: "fresh",
69
+ externalId: "fresh",
70
+ title: "Fresh",
71
+ },
72
+ ],
73
+ });
74
+ await reloaded;
75
+
76
+ first.resolve({
77
+ threads: [
78
+ {
79
+ status: "regular",
80
+ remoteId: "stale",
81
+ externalId: "stale",
82
+ title: "Stale",
83
+ },
84
+ ],
85
+ });
86
+ // flush microtasks so the stale then() reducer runs and its generation
87
+ // guard has a chance to discard the result
88
+ await Promise.resolve();
89
+
90
+ expect(core.threadIds).toEqual(["fresh"]);
91
+ expect(core.threadIds).not.toContain("stale");
92
+ });
93
+
94
+ it("recovers after a failed initial load", async () => {
95
+ const listFn = vi
96
+ .fn<() => Promise<RemoteThreadListResponse>>()
97
+ .mockRejectedValueOnce(new Error("401"))
98
+ .mockResolvedValueOnce({
99
+ threads: [
100
+ {
101
+ status: "regular",
102
+ remoteId: "t-1",
103
+ externalId: "t-1",
104
+ title: "Authed",
105
+ },
106
+ ],
107
+ });
108
+ const adapter = makeAdapter({ list: listFn });
109
+ const core = createCore(adapter);
110
+
111
+ await core.getLoadThreadsPromise();
112
+ expect(core.threadIds).toEqual([]);
113
+ expect(core.isLoading).toBe(false);
114
+
115
+ await core.reload();
116
+ expect(listFn).toHaveBeenCalledTimes(2);
117
+ expect(core.threadIds).toEqual(["t-1"]);
118
+ });
119
+
120
+ it("does not clear the active reload's promise when a stale load rejects", async () => {
121
+ const first = deferred<RemoteThreadListResponse>();
122
+ const second = deferred<RemoteThreadListResponse>();
123
+ const listFn = vi
124
+ .fn<() => Promise<RemoteThreadListResponse>>()
125
+ .mockReturnValueOnce(first.promise)
126
+ .mockReturnValueOnce(second.promise);
127
+
128
+ const adapter = makeAdapter({ list: listFn });
129
+ const core = createCore(adapter);
130
+
131
+ core.getLoadThreadsPromise();
132
+ const reloaded = core.reload();
133
+
134
+ first.reject(new Error("stale 401"));
135
+ await Promise.resolve();
136
+
137
+ second.resolve({
138
+ threads: [
139
+ {
140
+ status: "regular",
141
+ remoteId: "fresh",
142
+ externalId: "fresh",
143
+ title: "Fresh",
144
+ },
145
+ ],
146
+ });
147
+
148
+ await reloaded;
149
+ expect(core.threadIds).toEqual(["fresh"]);
150
+ expect(core.isLoading).toBe(false);
151
+ });
152
+
153
+ it("only the last of several overlapping reloads wins", async () => {
154
+ const deferreds = [
155
+ deferred<RemoteThreadListResponse>(),
156
+ deferred<RemoteThreadListResponse>(),
157
+ deferred<RemoteThreadListResponse>(),
158
+ ];
159
+ const listFn = vi
160
+ .fn<() => Promise<RemoteThreadListResponse>>()
161
+ .mockImplementationOnce(() => deferreds[0]!.promise)
162
+ .mockImplementationOnce(() => deferreds[1]!.promise)
163
+ .mockImplementationOnce(() => deferreds[2]!.promise);
164
+
165
+ const adapter = makeAdapter({ list: listFn });
166
+ const core = createCore(adapter);
167
+
168
+ const r1 = core.getLoadThreadsPromise();
169
+ const r2 = core.reload();
170
+ const r3 = core.reload();
171
+
172
+ deferreds[2]!.resolve({
173
+ threads: [
174
+ {
175
+ status: "regular",
176
+ remoteId: "c",
177
+ externalId: "c",
178
+ title: "c",
179
+ },
180
+ ],
181
+ });
182
+ await r3;
183
+
184
+ deferreds[0]!.resolve({
185
+ threads: [
186
+ {
187
+ status: "regular",
188
+ remoteId: "a",
189
+ externalId: "a",
190
+ title: "a",
191
+ },
192
+ ],
193
+ });
194
+ deferreds[1]!.resolve({
195
+ threads: [
196
+ {
197
+ status: "regular",
198
+ remoteId: "b",
199
+ externalId: "b",
200
+ title: "b",
201
+ },
202
+ ],
203
+ });
204
+ await r1;
205
+ await r2;
206
+
207
+ expect(core.threadIds).toEqual(["c"]);
208
+ });
209
+ });
@@ -0,0 +1,139 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import type {
3
+ RemoteThreadListResponse,
4
+ RemoteThreadMetadata,
5
+ } from "../runtimes/remote-thread-list/types";
6
+ import {
7
+ createCore,
8
+ deferred,
9
+ makeAdapter,
10
+ } from "./remote-thread-list-test-helpers";
11
+
12
+ describe("RemoteThreadListThreadListRuntimeCore.switchToThread dedupe", () => {
13
+ it("does not duplicate threadIds when list() resolves during fetch()", async () => {
14
+ const THREAD_ID = "thread-1";
15
+ const listDeferred = deferred<RemoteThreadListResponse>();
16
+ const fetchDeferred = deferred<RemoteThreadMetadata>();
17
+
18
+ const adapter = makeAdapter({
19
+ list: vi.fn(() => listDeferred.promise),
20
+ fetch: vi.fn(() => fetchDeferred.promise),
21
+ });
22
+
23
+ const core = createCore(adapter, THREAD_ID);
24
+
25
+ const loadPromise = core.getLoadThreadsPromise();
26
+ const switchPromise = core.switchToThread(THREAD_ID);
27
+
28
+ // Commit `list()` before resolving `fetch()` so `switchToThread` reads a
29
+ // state that already contains THREAD_ID.
30
+ listDeferred.resolve({
31
+ threads: [
32
+ {
33
+ status: "regular",
34
+ remoteId: THREAD_ID,
35
+ externalId: THREAD_ID,
36
+ title: "Test",
37
+ },
38
+ ],
39
+ });
40
+ await loadPromise;
41
+
42
+ fetchDeferred.resolve({
43
+ status: "regular",
44
+ remoteId: THREAD_ID,
45
+ externalId: THREAD_ID,
46
+ title: "Test",
47
+ });
48
+ await switchPromise;
49
+
50
+ expect(core.threadIds.filter((id) => id === THREAD_ID)).toEqual([
51
+ THREAD_ID,
52
+ ]);
53
+ });
54
+
55
+ it("does not duplicate archivedThreadIds when list() resolves during fetch()", async () => {
56
+ const THREAD_ID = "archived-1";
57
+ const listDeferred = deferred<RemoteThreadListResponse>();
58
+ const fetchDeferred = deferred<RemoteThreadMetadata>();
59
+
60
+ const adapter = makeAdapter({
61
+ list: vi.fn(() => listDeferred.promise),
62
+ fetch: vi.fn(() => fetchDeferred.promise),
63
+ });
64
+
65
+ const core = createCore(adapter, THREAD_ID);
66
+ // Without this stub, auto-unarchive would filter `archivedThreadIds` via
67
+ // `updateStatusReducer`, hiding any duplicate written by `switchToThread`.
68
+ (
69
+ core as unknown as { unarchive: (id: string) => Promise<void> }
70
+ ).unarchive = async () => {};
71
+
72
+ const loadPromise = core.getLoadThreadsPromise();
73
+ const switchPromise = core.switchToThread(THREAD_ID);
74
+
75
+ listDeferred.resolve({
76
+ threads: [
77
+ {
78
+ status: "archived",
79
+ remoteId: THREAD_ID,
80
+ externalId: THREAD_ID,
81
+ title: "Archived",
82
+ },
83
+ ],
84
+ });
85
+ await loadPromise;
86
+
87
+ fetchDeferred.resolve({
88
+ status: "archived",
89
+ remoteId: THREAD_ID,
90
+ externalId: THREAD_ID,
91
+ title: "Archived",
92
+ });
93
+ await switchPromise;
94
+
95
+ expect(core.archivedThreadIds.filter((id) => id === THREAD_ID)).toEqual([
96
+ THREAD_ID,
97
+ ]);
98
+ });
99
+
100
+ it("moves the id to the correct array when list() and fetch() disagree on status", async () => {
101
+ const THREAD_ID = "flipped-1";
102
+ const listDeferred = deferred<RemoteThreadListResponse>();
103
+ const fetchDeferred = deferred<RemoteThreadMetadata>();
104
+
105
+ const adapter = makeAdapter({
106
+ list: vi.fn(() => listDeferred.promise),
107
+ fetch: vi.fn(() => fetchDeferred.promise),
108
+ });
109
+
110
+ const core = createCore(adapter, THREAD_ID);
111
+
112
+ const loadPromise = core.getLoadThreadsPromise();
113
+ const switchPromise = core.switchToThread(THREAD_ID);
114
+
115
+ // A concurrent unarchive between `list()` and `fetch()` flips the status.
116
+ listDeferred.resolve({
117
+ threads: [
118
+ {
119
+ status: "archived",
120
+ remoteId: THREAD_ID,
121
+ externalId: THREAD_ID,
122
+ title: "Flipped",
123
+ },
124
+ ],
125
+ });
126
+ await loadPromise;
127
+
128
+ fetchDeferred.resolve({
129
+ status: "regular",
130
+ remoteId: THREAD_ID,
131
+ externalId: THREAD_ID,
132
+ title: "Flipped",
133
+ });
134
+ await switchPromise;
135
+
136
+ expect(core.threadIds).toContain(THREAD_ID);
137
+ expect(core.archivedThreadIds).not.toContain(THREAD_ID);
138
+ });
139
+ });
@@ -0,0 +1,180 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ attachmentsEqual,
4
+ liftNonTextParts,
5
+ partToCompleteAttachment,
6
+ } from "../adapters/attachment";
7
+ import type { CompleteAttachment } from "../types/attachment";
8
+
9
+ const makeAttachment = (id: string): CompleteAttachment => ({
10
+ id,
11
+ type: "document",
12
+ name: "file.pdf",
13
+ content: [
14
+ { type: "file", data: "data", mimeType: "application/pdf", filename: id },
15
+ ],
16
+ status: { type: "complete" },
17
+ });
18
+
19
+ describe("attachmentsEqual", () => {
20
+ it("returns true for two empty arrays", () => {
21
+ expect(attachmentsEqual([], [])).toBe(true);
22
+ });
23
+
24
+ it("returns false when lengths differ", () => {
25
+ expect(attachmentsEqual([makeAttachment("a")], [])).toBe(false);
26
+ });
27
+
28
+ it("returns true when all ids match in order", () => {
29
+ const a = makeAttachment("a");
30
+ const b = makeAttachment("b");
31
+ expect(attachmentsEqual([a, b], [a, b])).toBe(true);
32
+ });
33
+
34
+ it("returns false when ids differ at the same length", () => {
35
+ expect(attachmentsEqual([makeAttachment("a")], [makeAttachment("b")])).toBe(
36
+ false,
37
+ );
38
+ });
39
+ });
40
+
41
+ describe("partToCompleteAttachment", () => {
42
+ it("converts an image part using the filename as name", () => {
43
+ const result = partToCompleteAttachment({
44
+ type: "image",
45
+ image: "https://example.com/x.png",
46
+ filename: "x.png",
47
+ });
48
+ expect(result).toMatchObject({
49
+ type: "image",
50
+ name: "x.png",
51
+ status: { type: "complete" },
52
+ });
53
+ expect(result.content).toEqual([
54
+ {
55
+ type: "image",
56
+ image: "https://example.com/x.png",
57
+ filename: "x.png",
58
+ },
59
+ ]);
60
+ });
61
+
62
+ it("falls back to 'image' when the image part has no filename", () => {
63
+ const result = partToCompleteAttachment({
64
+ type: "image",
65
+ image: "blob",
66
+ });
67
+ expect(result.name).toBe("image");
68
+ });
69
+
70
+ it("converts a file part to a document attachment with contentType", () => {
71
+ const result = partToCompleteAttachment({
72
+ type: "file",
73
+ data: "blob",
74
+ mimeType: "application/pdf",
75
+ filename: "report.pdf",
76
+ });
77
+ expect(result).toMatchObject({
78
+ type: "document",
79
+ name: "report.pdf",
80
+ contentType: "application/pdf",
81
+ });
82
+ });
83
+
84
+ it("falls back to 'document' when the file part has no filename", () => {
85
+ const result = partToCompleteAttachment({
86
+ type: "file",
87
+ data: "blob",
88
+ mimeType: "application/pdf",
89
+ });
90
+ expect(result.name).toBe("document");
91
+ });
92
+
93
+ it("converts an audio part with derived name and contentType", () => {
94
+ const mp3 = partToCompleteAttachment({
95
+ type: "audio",
96
+ audio: { data: "blob", format: "mp3" },
97
+ });
98
+ expect(mp3).toMatchObject({
99
+ type: "audio",
100
+ name: "audio.mp3",
101
+ contentType: "audio/mp3",
102
+ });
103
+
104
+ const wav = partToCompleteAttachment({
105
+ type: "audio",
106
+ audio: { data: "blob", format: "wav" },
107
+ });
108
+ expect(wav.name).toBe("audio.wav");
109
+ expect(wav.contentType).toBe("audio/wav");
110
+ });
111
+
112
+ it("converts a data part using its name", () => {
113
+ const result = partToCompleteAttachment({
114
+ type: "data",
115
+ name: "weather-widget",
116
+ data: { temp: 20 },
117
+ });
118
+ expect(result).toMatchObject({
119
+ type: "data",
120
+ name: "weather-widget",
121
+ });
122
+ expect(result.contentType).toBeUndefined();
123
+ });
124
+
125
+ it("generates a unique id for each call", () => {
126
+ const a = partToCompleteAttachment({
127
+ type: "file",
128
+ data: "x",
129
+ mimeType: "application/pdf",
130
+ });
131
+ const b = partToCompleteAttachment({
132
+ type: "file",
133
+ data: "x",
134
+ mimeType: "application/pdf",
135
+ });
136
+ expect(a.id).not.toBe(b.id);
137
+ });
138
+ });
139
+
140
+ describe("liftNonTextParts", () => {
141
+ it("returns an empty array for content of only text parts", () => {
142
+ expect(
143
+ liftNonTextParts([
144
+ { type: "text", text: "hello" },
145
+ { type: "text", text: "world" },
146
+ ]),
147
+ ).toEqual([]);
148
+ });
149
+
150
+ it("lifts mixed non-text types preserving order", () => {
151
+ const result = liftNonTextParts([
152
+ { type: "text", text: "mix" },
153
+ {
154
+ type: "image",
155
+ image: "url",
156
+ filename: "pic.png",
157
+ },
158
+ {
159
+ type: "file",
160
+ data: "d",
161
+ mimeType: "application/pdf",
162
+ filename: "doc.pdf",
163
+ },
164
+ { type: "audio", audio: { data: "a", format: "mp3" } },
165
+ { type: "data", name: "widget", data: {} },
166
+ ]);
167
+ expect(result.map((a) => a.type)).toEqual([
168
+ "image",
169
+ "document",
170
+ "audio",
171
+ "data",
172
+ ]);
173
+ expect(result.map((a) => a.name)).toEqual([
174
+ "pic.png",
175
+ "doc.pdf",
176
+ "audio.mp3",
177
+ "widget",
178
+ ]);
179
+ });
180
+ });