@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
@@ -9,17 +9,19 @@ import {
9
9
  } from "../../subscribable/subscribable";
10
10
  import type { ThreadListRuntimeCore } from "../interfaces/thread-list-runtime-core";
11
11
  import {
12
- ThreadListItemRuntime,
12
+ type ThreadListItemRuntime,
13
13
  ThreadListItemRuntimeImpl,
14
- ThreadListItemState,
14
+ type ThreadListItemState,
15
15
  } from "./thread-list-item-runtime";
16
16
  import {
17
- ThreadListItemRuntimeBinding,
18
- ThreadRuntime,
19
- ThreadRuntimeCoreBinding,
17
+ type ThreadListItemRuntimeBinding,
18
+ type ThreadRuntime,
19
+ type ThreadRuntimeCoreBinding,
20
20
  ThreadRuntimeImpl,
21
21
  } from "./thread-runtime";
22
22
 
23
+ const RESOLVED_PROMISE = Promise.resolve();
24
+
23
25
  export type ThreadListState = {
24
26
  readonly mainThreadId: string;
25
27
  readonly newThreadId: string | undefined;
@@ -48,6 +50,7 @@ export type ThreadListRuntime = {
48
50
  switchToNewThread(): Promise<void>;
49
51
 
50
52
  getLoadThreadsPromise(): Promise<void>;
53
+ reload(): Promise<void>;
51
54
  };
52
55
 
53
56
  const getThreadListState = (
@@ -133,6 +136,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
133
136
  this.switchToThread = this.switchToThread.bind(this);
134
137
  this.switchToNewThread = this.switchToNewThread.bind(this);
135
138
  this.getLoadThreadsPromise = this.getLoadThreadsPromise.bind(this);
139
+ this.reload = this.reload.bind(this);
136
140
  this.getState = this.getState.bind(this);
137
141
  this.subscribe = this.subscribe.bind(this);
138
142
  this.getById = this.getById.bind(this);
@@ -153,6 +157,10 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
153
157
  return this._core.getLoadThreadsPromise();
154
158
  }
155
159
 
160
+ public reload(): Promise<void> {
161
+ return this._core.reload?.() ?? RESOLVED_PROMISE;
162
+ }
163
+
156
164
  public getState(): ThreadListState {
157
165
  return this._getState();
158
166
  }
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  ThreadSuggestion,
3
3
  RuntimeCapabilities,
4
4
  ThreadRuntimeCore,
@@ -8,12 +8,12 @@ import {
8
8
  StartRunConfig,
9
9
  ResumeRunConfig,
10
10
  } from "../interfaces/thread-runtime-core";
11
- import { ExportedMessageRepository } from "../utils/message-repository";
12
- import { ThreadMessageLike } from "../utils/thread-message-like";
11
+ import type { ExportedMessageRepository } from "../utils/message-repository";
12
+ import type { ThreadMessageLike } from "../utils/thread-message-like";
13
13
  import {
14
- MessageRuntime,
14
+ type MessageRuntime,
15
15
  MessageRuntimeImpl,
16
- MessageState,
16
+ type MessageState,
17
17
  } from "./message-runtime";
18
18
  import { NestedSubscriptionSubject } from "../../subscribable/subscribable";
19
19
  import {
@@ -22,10 +22,10 @@ import {
22
22
  } from "../../subscribable/subscribable";
23
23
  import type { SubscribableWithState } from "../../subscribable/subscribable";
24
24
  import {
25
- ThreadComposerRuntime,
25
+ type ThreadComposerRuntime,
26
26
  ThreadComposerRuntimeImpl,
27
27
  } from "./composer-runtime";
28
- import {
28
+ import type {
29
29
  MessageRuntimePath,
30
30
  ThreadListItemRuntimePath,
31
31
  ThreadRuntimePath,
@@ -36,12 +36,12 @@ import type { Unsubscribe } from "../../types/unsubscribe";
36
36
  import type { RunConfig } from "../../types/message";
37
37
  import { EventSubscriptionSubject } from "../../subscribable/subscribable";
38
38
  import { symbolInnerMessage } from "../utils/external-store-message";
39
- import { ModelContext } from "../../model-context/types";
40
- import {
39
+ import type { ModelContext } from "../../model-context/types";
40
+ import type {
41
41
  ChatModelRunOptions,
42
42
  ChatModelRunResult,
43
43
  } from "../utils/chat-model-adapter";
44
- import { ReadonlyJSONValue } from "assistant-stream/utils";
44
+ import type { ReadonlyJSONValue } from "assistant-stream/utils";
45
45
 
46
46
  export type CreateStartRunConfig = {
47
47
  parentId: string | null;
@@ -204,9 +204,10 @@ export const getThreadState = (
204
204
  isDisabled: runtime.isDisabled,
205
205
  isLoading: runtime.isLoading,
206
206
  isRunning:
207
- lastMessage?.role !== "assistant"
207
+ runtime.isRunning ??
208
+ (lastMessage?.role !== "assistant"
208
209
  ? false
209
- : lastMessage.status.type === "running",
210
+ : lastMessage.status.type === "running"),
210
211
  messages: runtime.messages,
211
212
  state: runtime.state,
212
213
  suggestions: runtime.suggestions,
@@ -93,7 +93,7 @@ export abstract class BaseThreadRuntimeCore implements ThreadRuntimeCore {
93
93
  }
94
94
 
95
95
  public get state() {
96
- let mostRecentAssistantMessage;
96
+ let mostRecentAssistantMessage: (typeof this.messages)[number] | undefined;
97
97
  for (const message of this.messages) {
98
98
  if (message.role === "assistant") {
99
99
  mostRecentAssistantMessage = message;
@@ -1,5 +1,7 @@
1
1
  import type { AppendMessage, ThreadMessage } from "../../types/message";
2
+ import type { CompleteAttachment } from "../../types/attachment";
2
3
  import { getThreadMessageText } from "../../utils/text";
4
+ import { attachmentsEqual, liftNonTextParts } from "../../adapters/attachment";
3
5
  import type { AttachmentAdapter } from "../../adapters/attachment";
4
6
  import type { DictationAdapter } from "../../adapters/speech";
5
7
  import type { SendOptions } from "../interfaces/composer-runtime-core";
@@ -19,8 +21,9 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
19
21
  return this.runtime.adapters?.dictation;
20
22
  }
21
23
 
22
- private _nonTextParts;
23
24
  private _previousText;
25
+ private _previousAttachments: readonly CompleteAttachment[];
26
+ private _nonTextPassthrough: readonly ThreadMessage["content"][number][];
24
27
  private _parentId: string | null;
25
28
  private _sourceId: string | null;
26
29
  constructor(
@@ -42,9 +45,20 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
42
45
  this.setText(this._previousText);
43
46
 
44
47
  this.setRole(message.role);
45
- this.setAttachments(message.attachments ?? []);
46
48
 
47
- this._nonTextParts = message.content.filter((part) => part.type !== "text");
49
+ if (message.role === "user") {
50
+ this._previousAttachments = [
51
+ ...(message.attachments ?? []),
52
+ ...liftNonTextParts(message.content),
53
+ ];
54
+ this._nonTextPassthrough = [];
55
+ } else {
56
+ this._previousAttachments = message.attachments ?? [];
57
+ this._nonTextPassthrough = message.content.filter(
58
+ (p) => p.type !== "text",
59
+ );
60
+ }
61
+ this.setAttachments(this._previousAttachments);
48
62
 
49
63
  this.setRunConfig({ ...runtime.composer.runConfig });
50
64
  }
@@ -62,10 +76,26 @@ export class DefaultEditComposerRuntimeCore extends BaseComposerRuntimeCore {
62
76
  options?: SendOptions,
63
77
  ) {
64
78
  const text = getThreadMessageText(message as AppendMessage);
65
- if (text !== this._previousText || options?.startRun) {
79
+ const attachmentsChanged = !attachmentsEqual(
80
+ message.attachments ?? [],
81
+ this._previousAttachments,
82
+ );
83
+
84
+ if (
85
+ text !== this._previousText ||
86
+ attachmentsChanged ||
87
+ options?.startRun
88
+ ) {
89
+ const content =
90
+ this._nonTextPassthrough.length > 0
91
+ ? ([
92
+ ...message.content,
93
+ ...this._nonTextPassthrough,
94
+ ] as AppendMessage["content"])
95
+ : message.content;
66
96
  this.runtime.append({
67
97
  ...message,
68
- content: [...message.content, ...this._nonTextParts] as any,
98
+ content,
69
99
  parentId: this._parentId,
70
100
  sourceId: this._sourceId,
71
101
  startRun: options?.startRun,
@@ -33,6 +33,7 @@ export type ThreadListRuntimeCore = {
33
33
  switchToNewThread(): Promise<void>;
34
34
 
35
35
  getLoadThreadsPromise(): Promise<void>;
36
+ reload?(): Promise<void>;
36
37
 
37
38
  detach(threadId: string): Promise<void>;
38
39
  rename(threadId: string, newTitle: string): Promise<void>;
@@ -129,6 +129,13 @@ export type ThreadRuntimeCore = Readonly<{
129
129
  capabilities: Readonly<RuntimeCapabilities>;
130
130
  isDisabled: boolean;
131
131
  isLoading: boolean;
132
+ /**
133
+ * Optional explicit thread-level running flag. When provided, takes
134
+ * precedence over the last-message-status heuristic. When omitted, falls
135
+ * back to the legacy behavior. External-store runtimes surface this via
136
+ * `ExternalStoreAdapter.isRunning`.
137
+ */
138
+ isRunning?: boolean | undefined;
132
139
  messages: readonly ThreadMessage[];
133
140
  state: ReadonlyJSONValue;
134
141
  suggestions: readonly ThreadSuggestion[];
@@ -1,7 +1,4 @@
1
- // =============================================================================
2
- // Internal API — implementation details used by framework bindings
3
- // Not part of the public API surface.
4
- // =============================================================================
1
+ // Internal API — implementation details used by framework bindings, not part of the public API surface.
5
2
 
6
3
  // Binding Types
7
4
  export type {
@@ -1,5 +1,5 @@
1
1
  import type { MessageStatus } from "../../types/message";
2
- import { ReadonlyJSONValue } from "assistant-stream/utils";
2
+ import type { ReadonlyJSONValue } from "assistant-stream/utils";
3
3
 
4
4
  const symbolAutoStatus = Symbol("autoStatus");
5
5
 
@@ -14,7 +14,7 @@ import type {
14
14
  TextMessagePart,
15
15
  } from "../../types/message";
16
16
  import type { ModelContext } from "../../model-context/types";
17
- import { ReadonlyJSONValue } from "assistant-stream/utils";
17
+ import type { ReadonlyJSONValue } from "assistant-stream/utils";
18
18
 
19
19
  export type ChatModelRunUpdate = {
20
20
  readonly content: readonly ThreadAssistantMessagePart[];
@@ -18,7 +18,10 @@ import type {
18
18
  } from "../../types/message";
19
19
  import type { CompleteAttachment } from "../../types/attachment";
20
20
  import type { MessageTiming, TextMessagePart } from "../../types/message";
21
- import { ReadonlyJSONObject, ReadonlyJSONValue } from "assistant-stream/utils";
21
+ import type {
22
+ ReadonlyJSONObject,
23
+ ReadonlyJSONValue,
24
+ } from "assistant-stream/utils";
22
25
 
23
26
  type DataPrefixedPart = {
24
27
  readonly type: `data-${string}`;
@@ -1,4 +1,8 @@
1
- import { Tool, toToolsJSONSchema, type ToolJSONSchema } from "assistant-stream";
1
+ import {
2
+ type Tool,
3
+ toToolsJSONSchema,
4
+ type ToolJSONSchema,
5
+ } from "assistant-stream";
2
6
 
3
7
  /**
4
8
  * @deprecated Use `toToolsJSONSchema` from `assistant-stream` instead.
@@ -60,6 +60,14 @@ type ExternalStoreMessageConverterAdapter<T> = {
60
60
 
61
61
  type ExternalStoreAdapterBase<T> = {
62
62
  isDisabled?: boolean | undefined;
63
+ /**
64
+ * Whether the thread is running. When provided, this value flows directly
65
+ * to `thread.isRunning`, letting the application keep the thread in a
66
+ * running state even after the last assistant message has completed (for
67
+ * example while non-message stream chunks like suggestions or metadata
68
+ * updates are still arriving). When omitted, `thread.isRunning` falls back
69
+ * to the last-message-status heuristic.
70
+ */
63
71
  isRunning?: boolean | undefined;
64
72
  isLoading?: boolean | undefined;
65
73
  messages?: readonly T[];
@@ -30,6 +30,7 @@ export class ExternalStoreThreadListRuntimeCore
30
30
  private _archivedThreads: readonly string[] = EMPTY_ARRAY;
31
31
  private _threadData: Readonly<Record<string, ThreadListItemCoreState>> =
32
32
  DEFAULT_THREAD_DATA;
33
+ private adapter: ExternalStoreThreadListAdapter = {};
33
34
 
34
35
  public get isLoading() {
35
36
  return this.adapter.isLoading ?? false;
@@ -55,17 +56,16 @@ export class ExternalStoreThreadListRuntimeCore
55
56
  return RESOLVED_PROMISE;
56
57
  }
57
58
 
58
- private _mainThread: ExternalStoreThreadRuntimeCore;
59
+ private _mainThread!: ExternalStoreThreadRuntimeCore;
59
60
 
60
61
  public get mainThreadId() {
61
62
  return this._mainThreadId;
62
63
  }
63
64
 
64
65
  constructor(
65
- private adapter: ExternalStoreThreadListAdapter = {},
66
+ adapter: ExternalStoreThreadListAdapter = {},
66
67
  private threadFactory: ExternalStoreThreadFactory,
67
68
  ) {
68
- this._mainThread = this.threadFactory();
69
69
  this.__internal_setAdapter(adapter, true);
70
70
  }
71
71
 
@@ -113,31 +113,36 @@ export class ExternalStoreThreadListRuntimeCore
113
113
  return;
114
114
  }
115
115
 
116
- this._threadData = {
117
- ...DEFAULT_THREAD_DATA,
118
- ...Object.fromEntries(
119
- adapter.threads?.map((t) => [
120
- t.id,
121
- {
122
- ...t,
123
- remoteId: t.remoteId,
124
- externalId: t.externalId,
125
- status: "regular",
126
- },
127
- ]) ?? [],
128
- ),
129
- ...Object.fromEntries(
130
- adapter.archivedThreads?.map((t) => [
131
- t.id,
132
- {
133
- ...t,
134
- remoteId: t.remoteId,
135
- externalId: t.externalId,
136
- status: "archived",
137
- },
138
- ]) ?? [],
139
- ),
140
- };
116
+ if (
117
+ previousThreads !== newThreads ||
118
+ previousArchivedThreads !== newArchivedThreads
119
+ ) {
120
+ this._threadData = {
121
+ ...DEFAULT_THREAD_DATA,
122
+ ...Object.fromEntries(
123
+ adapter.threads?.map((t) => [
124
+ t.id,
125
+ {
126
+ ...t,
127
+ remoteId: t.remoteId,
128
+ externalId: t.externalId,
129
+ status: "regular",
130
+ },
131
+ ]) ?? [],
132
+ ),
133
+ ...Object.fromEntries(
134
+ adapter.archivedThreads?.map((t) => [
135
+ t.id,
136
+ {
137
+ ...t,
138
+ remoteId: t.remoteId,
139
+ externalId: t.externalId,
140
+ status: "archived",
141
+ },
142
+ ]) ?? [],
143
+ ),
144
+ };
145
+ }
141
146
 
142
147
  if (previousThreads !== newThreads) {
143
148
  this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;
@@ -148,7 +153,8 @@ export class ExternalStoreThreadListRuntimeCore
148
153
  this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;
149
154
  }
150
155
 
151
- if (previousThreadId !== newThreadId) {
156
+ // `initialLoad ||`: `_mainThread!` must be assigned on construction.
157
+ if (initialLoad || previousThreadId !== newThreadId) {
152
158
  this._mainThreadId = newThreadId;
153
159
  this._mainThread = this.threadFactory();
154
160
  }
@@ -78,6 +78,10 @@ export class ExternalStoreThreadRuntimeCore
78
78
  public get isLoading() {
79
79
  return this._store.isLoading ?? false;
80
80
  }
81
+ // Unlike `isLoading`: pass `undefined` through to preserve the `getThreadState` fallback.
82
+ public get isRunning(): boolean | undefined {
83
+ return this._store.isRunning;
84
+ }
81
85
 
82
86
  protected override _getBaseMessages(): readonly ThreadMessage[] {
83
87
  return this._messages;
@@ -1,5 +1,5 @@
1
- import { AssistantStream, AssistantStreamChunk } from "assistant-stream";
2
- import {
1
+ import type { AssistantStream, AssistantStreamChunk } from "assistant-stream";
2
+ import type {
3
3
  RemoteThreadInitializeResponse,
4
4
  RemoteThreadListAdapter,
5
5
  RemoteThreadListResponse,
@@ -1,6 +1,6 @@
1
1
  import type { ThreadMessage } from "../../types/message";
2
2
  import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
3
- import { AssistantStream } from "assistant-stream";
3
+ import type { AssistantStream } from "assistant-stream";
4
4
 
5
5
  export type RemoteThreadInitializeResponse = {
6
6
  remoteId: string;
@@ -1,6 +1,6 @@
1
1
  import { resource } from "@assistant-ui/tap";
2
- import { type ClientOutput } from "@assistant-ui/store";
3
- import { AttachmentRuntime } from "../../runtime/api/attachment-runtime";
2
+ import type { ClientOutput } from "@assistant-ui/store";
3
+ import type { AttachmentRuntime } from "../../runtime/api/attachment-runtime";
4
4
  import { tapSubscribable } from "./tap-subscribable";
5
5
 
6
6
  export const AttachmentRuntimeClient = resource(
@@ -12,11 +12,11 @@ import {
12
12
  tapAssistantEmit,
13
13
  tapClientLookup,
14
14
  } from "@assistant-ui/store";
15
- import {
15
+ import type {
16
16
  ComposerRuntime,
17
17
  EditComposerRuntime,
18
18
  } from "../../runtime/api/composer-runtime";
19
- import { ComposerState } from "../scopes/composer";
19
+ import type { ComposerState } from "../scopes/composer";
20
20
  import { AttachmentRuntimeClient } from "./attachment-runtime-client";
21
21
  import { tapSubscribable } from "./tap-subscribable";
22
22
 
@@ -1,6 +1,6 @@
1
1
  import { resource } from "@assistant-ui/tap";
2
- import { type ClientOutput } from "@assistant-ui/store";
3
- import { MessagePartRuntime } from "../../runtime/api/message-part-runtime";
2
+ import type { ClientOutput } from "@assistant-ui/store";
3
+ import type { MessagePartRuntime } from "../../runtime/api/message-part-runtime";
4
4
  import { tapSubscribable } from "./tap-subscribable";
5
5
 
6
6
  export const MessagePartClient = resource(
@@ -11,11 +11,11 @@ import {
11
11
  tapClientLookup,
12
12
  tapClientResource,
13
13
  } from "@assistant-ui/store";
14
- import { MessageRuntime } from "../../runtime/api/message-runtime";
14
+ import type { MessageRuntime } from "../../runtime/api/message-runtime";
15
15
  import { tapSubscribable } from "./tap-subscribable";
16
16
  import { ComposerClient } from "./composer-runtime-client";
17
17
  import { MessagePartClient } from "./message-part-runtime-client";
18
- import { MessageState } from "../scopes/message";
18
+ import type { MessageState } from "../scopes/message";
19
19
  import { AttachmentRuntimeClient } from "./attachment-runtime-client";
20
20
 
21
21
  const MessageAttachmentClientByIndex = resource(
@@ -1,7 +1,7 @@
1
1
  import type { Unsubscribe } from "../../types/unsubscribe";
2
2
  import { resource, tapEffect } from "@assistant-ui/tap";
3
3
  import { type ClientOutput, tapAssistantEmit } from "@assistant-ui/store";
4
- import {
4
+ import type {
5
5
  ThreadListItemEventType,
6
6
  ThreadListItemRuntime,
7
7
  } from "../../runtime/api/thread-list-item-runtime";
@@ -4,12 +4,12 @@ import {
4
4
  tapClientLookup,
5
5
  tapClientResource,
6
6
  } from "@assistant-ui/store";
7
- import { ThreadListRuntime } from "../../runtime/api/thread-list-runtime";
8
- import { AssistantRuntime } from "../../runtime/api/assistant-runtime";
7
+ import type { ThreadListRuntime } from "../../runtime/api/thread-list-runtime";
8
+ import type { AssistantRuntime } from "../../runtime/api/assistant-runtime";
9
9
  import { tapSubscribable } from "./tap-subscribable";
10
10
  import { ThreadListItemClient } from "./thread-list-item-runtime-client";
11
11
  import { ThreadClient } from "./thread-runtime-client";
12
- import { ThreadsState } from "../scopes/threads";
12
+ import type { ThreadsState } from "../scopes/threads";
13
13
 
14
14
  const ThreadListItemClientById = resource(
15
15
  ({ runtime, id }: { runtime: ThreadListRuntime; id: string }) => {
@@ -86,6 +86,7 @@ export const ThreadListClient = resource(
86
86
  await runtime.switchToNewThread();
87
87
  },
88
88
  getLoadThreadsPromise: () => runtime.getLoadThreadsPromise(),
89
+ reload: () => runtime.reload(),
89
90
  __internal_getAssistantRuntime: () => __internal_assistantRuntime,
90
91
  };
91
92
  },
@@ -1,6 +1,6 @@
1
1
  import type { Unsubscribe } from "../../types/unsubscribe";
2
- import { ThreadRuntimeEventType } from "../../runtime/interfaces/thread-runtime-core";
3
- import { ThreadRuntime } from "../../runtime/api/thread-runtime";
2
+ import type { ThreadRuntimeEventType } from "../../runtime/interfaces/thread-runtime-core";
3
+ import type { ThreadRuntime } from "../../runtime/api/thread-runtime";
4
4
  import {
5
5
  resource,
6
6
  tapResource,
@@ -18,7 +18,7 @@ import {
18
18
  import { ComposerClient } from "./composer-runtime-client";
19
19
  import { MessageClient } from "./message-runtime-client";
20
20
  import { tapSubscribable } from "./tap-subscribable";
21
- import { ThreadState } from "../scopes/thread";
21
+ import type { ThreadState } from "../scopes/thread";
22
22
 
23
23
  const MessageClientById = resource(
24
24
  ({
@@ -27,6 +27,7 @@ export type ThreadsMethods = {
27
27
  ): ThreadListItemMethods;
28
28
  thread(selector: "main"): ThreadMethods;
29
29
  getLoadThreadsPromise(): Promise<void>;
30
+ reload(): Promise<void>;
30
31
  __internal_getAssistantRuntime?(): AssistantRuntime;
31
32
  };
32
33
 
@@ -1,16 +1,8 @@
1
1
  import type { Unsubscribe } from "../types/unsubscribe";
2
2
 
3
- // =============================================================================
4
- // Sentinel
5
- // =============================================================================
6
-
7
3
  export const SKIP_UPDATE = Symbol("skip-update");
8
4
  export type SKIP_UPDATE = typeof SKIP_UPDATE;
9
5
 
10
- // =============================================================================
11
- // Types
12
- // =============================================================================
13
-
14
6
  export type Subscribable = {
15
7
  subscribe: (callback: () => void) => Unsubscribe;
16
8
  };
@@ -36,10 +28,6 @@ export type EventSubscribable<TEvent extends string> = {
36
28
  >;
37
29
  };
38
30
 
39
- // =============================================================================
40
- // Utilities
41
- // =============================================================================
42
-
43
31
  function shallowEqual<T extends object>(
44
32
  objA: T | undefined,
45
33
  objB: T | undefined,
@@ -57,10 +45,6 @@ function shallowEqual<T extends object>(
57
45
  return true;
58
46
  }
59
47
 
60
- // =============================================================================
61
- // Base Subscribable (simple pub-sub)
62
- // =============================================================================
63
-
64
48
  export class BaseSubscribable {
65
49
  private _subscribers = new Set<() => void>();
66
50
 
@@ -101,10 +85,7 @@ export class BaseSubscribable {
101
85
  }
102
86
  }
103
87
 
104
- // =============================================================================
105
- // Base Subject (lazy connect/disconnect)
106
- // =============================================================================
107
-
88
+ // lazy connect/disconnect: only opens upstream subscription while it has subscribers
108
89
  export abstract class BaseSubject {
109
90
  private _subscriptions = new Set<() => void>();
110
91
  private _connection: Unsubscribe | undefined;
@@ -140,10 +121,6 @@ export abstract class BaseSubject {
140
121
  }
141
122
  }
142
123
 
143
- // =============================================================================
144
- // Subject Implementations
145
- // =============================================================================
146
-
147
124
  export class ShallowMemoizeSubject<TState extends object, TPath>
148
125
  extends BaseSubject
149
126
  implements SubscribableWithState<TState, TPath>
@@ -7,6 +7,7 @@ import {
7
7
  createThreadMappingId,
8
8
  updateStatusReducer,
9
9
  } from "../runtimes/remote-thread-list/remote-thread-state";
10
+ import { deferred } from "./remote-thread-list-test-helpers";
10
11
 
11
12
  /**
12
13
  * Reproduces the race condition where a stale list() response
@@ -75,15 +76,6 @@ const applyListResult = (
75
76
  };
76
77
  };
77
78
 
78
- /** Creates a deferred promise for controlling resolution order. */
79
- function deferred<T>() {
80
- let resolve!: (v: T) => void;
81
- const promise = new Promise<T>((r) => {
82
- resolve = r;
83
- });
84
- return { promise, resolve };
85
- }
86
-
87
79
  describe("list + delete race condition", () => {
88
80
  it("stale list() does not re-add a thread deleted while list was in flight", async () => {
89
81
  const state = new OptimisticState<RemoteThreadState>(EMPTY_STATE);
@@ -95,6 +87,7 @@ describe("list + delete race condition", () => {
95
87
  const listPromise = state.optimisticUpdate({
96
88
  execute: () => listDeferred.promise,
97
89
  loading: (s) => ({ ...s, isLoading: true }),
90
+ // biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
98
91
  then: applyListResult,
99
92
  });
100
93
 
@@ -152,6 +145,7 @@ describe("list + delete race condition", () => {
152
145
  const listPromise = state.optimisticUpdate({
153
146
  execute: () => listDeferred.promise,
154
147
  loading: (s) => ({ ...s, isLoading: true }),
148
+ // biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
155
149
  then: applyListResult,
156
150
  });
157
151
 
@@ -189,6 +183,7 @@ describe("list + delete race condition", () => {
189
183
  const listPromise = state.optimisticUpdate({
190
184
  execute: () => listDeferred.promise,
191
185
  loading: (s) => ({ ...s, isLoading: true }),
186
+ // biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
192
187
  then: applyListResult,
193
188
  });
194
189
 
@@ -226,6 +221,7 @@ describe("list + delete race condition", () => {
226
221
  const listPromise = state.optimisticUpdate({
227
222
  execute: () => listDeferred.promise,
228
223
  loading: (s) => ({ ...s, isLoading: true }),
224
+ // biome-ignore lint/suspicious/noThenProperty: OptimisticState reducer pattern
229
225
  then: applyListResult,
230
226
  });
231
227