@assistant-ui/core 0.1.14 → 0.1.16

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 (345) 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.d.ts.map +1 -1
  43. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  44. package/dist/react/client/DataRenderers.d.ts +1 -1
  45. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  46. package/dist/react/client/DataRenderers.js +14 -0
  47. package/dist/react/client/DataRenderers.js.map +1 -1
  48. package/dist/react/client/Tools.d.ts +1 -1
  49. package/dist/react/client/Tools.d.ts.map +1 -1
  50. package/dist/react/client/Tools.js +1 -0
  51. package/dist/react/client/Tools.js.map +1 -1
  52. package/dist/react/model-context/makeAssistantTool.d.ts +1 -1
  53. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  54. package/dist/react/model-context/makeAssistantToolUI.d.ts +1 -1
  55. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  56. package/dist/react/model-context/useInlineRender.d.ts +2 -2
  57. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  58. package/dist/react/model-context/useInlineRender.js +1 -0
  59. package/dist/react/model-context/useInlineRender.js.map +1 -1
  60. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.d.ts.map +1 -1
  61. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -0
  62. package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
  63. package/dist/react/primitives/composer/ComposerAttachments.d.ts +1 -1
  64. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  65. package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
  66. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  67. package/dist/react/primitives/message/MessageAttachments.d.ts +1 -1
  68. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  69. package/dist/react/primitives/message/MessageAttachments.js +1 -1
  70. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  71. package/dist/react/primitives/message/MessageParts.d.ts +7 -1
  72. package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
  73. package/dist/react/primitives/message/MessageParts.js +60 -44
  74. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  75. package/dist/react/primitives/part/PartMessages.d.ts +1 -1
  76. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  77. package/dist/react/primitives/thread/ThreadMessages.d.ts +1 -1
  78. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  79. package/dist/react/primitives/thread/ThreadMessages.js +2 -1
  80. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  81. package/dist/react/primitives/threadList/ThreadListItems.d.ts +1 -1
  82. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  83. package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
  84. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  85. package/dist/react/providers/AttachmentByIndexProvider.d.ts +1 -1
  86. package/dist/react/providers/AttachmentByIndexProvider.d.ts.map +1 -1
  87. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts +1 -1
  88. package/dist/react/providers/ChainOfThoughtByIndicesProvider.d.ts.map +1 -1
  89. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts +1 -1
  90. package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
  91. package/dist/react/providers/MessageByIndexProvider.d.ts +1 -1
  92. package/dist/react/providers/MessageByIndexProvider.d.ts.map +1 -1
  93. package/dist/react/providers/PartByIndexProvider.d.ts +1 -1
  94. package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
  95. package/dist/react/providers/QueueItemByIndexProvider.d.ts +1 -1
  96. package/dist/react/providers/QueueItemByIndexProvider.d.ts.map +1 -1
  97. package/dist/react/providers/SuggestionByIndexProvider.d.ts +1 -1
  98. package/dist/react/providers/SuggestionByIndexProvider.d.ts.map +1 -1
  99. package/dist/react/providers/TextMessagePartProvider.d.ts +1 -1
  100. package/dist/react/providers/TextMessagePartProvider.d.ts.map +1 -1
  101. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts +1 -1
  102. package/dist/react/providers/ThreadListItemByIndexProvider.d.ts.map +1 -1
  103. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts +1 -1
  104. package/dist/react/providers/ThreadListItemRuntimeProvider.d.ts.map +1 -1
  105. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +4 -2
  106. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  107. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +28 -6
  108. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  109. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
  110. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  111. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +27 -9
  112. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  113. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts +1 -1
  114. package/dist/react/runtimes/RuntimeAdapterProvider.d.ts.map +1 -1
  115. package/dist/react/runtimes/RuntimeAdapterProvider.js.map +1 -1
  116. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +2 -2
  117. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  118. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  119. package/dist/react/runtimes/cloud/auiV0.d.ts +2 -2
  120. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  121. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  122. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +4 -1
  124. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  125. package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
  126. package/dist/react/runtimes/useLocalRuntime.js +10 -0
  127. package/dist/react/runtimes/useLocalRuntime.js.map +1 -1
  128. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  129. package/dist/react/runtimes/useRemoteThreadListRuntime.js +6 -0
  130. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  131. package/dist/react/runtimes/useToolInvocations.d.ts.map +1 -1
  132. package/dist/react/runtimes/useToolInvocations.js +2 -0
  133. package/dist/react/runtimes/useToolInvocations.js.map +1 -1
  134. package/dist/react/types/MessagePartComponentTypes.d.ts +1 -1
  135. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  136. package/dist/react/types/scopes/dataRenderers.d.ts +2 -0
  137. package/dist/react/types/scopes/dataRenderers.d.ts.map +1 -1
  138. package/dist/runtime/api/assistant-runtime.d.ts +1 -1
  139. package/dist/runtime/api/assistant-runtime.d.ts.map +1 -1
  140. package/dist/runtime/api/attachment-runtime.d.ts +0 -1
  141. package/dist/runtime/api/attachment-runtime.d.ts.map +1 -1
  142. package/dist/runtime/api/attachment-runtime.js +0 -3
  143. package/dist/runtime/api/attachment-runtime.js.map +1 -1
  144. package/dist/runtime/api/bindings.d.ts +1 -0
  145. package/dist/runtime/api/bindings.d.ts.map +1 -1
  146. package/dist/runtime/api/composer-runtime.d.ts +4 -2
  147. package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
  148. package/dist/runtime/api/composer-runtime.js.map +1 -1
  149. package/dist/runtime/api/message-runtime.d.ts +6 -6
  150. package/dist/runtime/api/message-runtime.d.ts.map +1 -1
  151. package/dist/runtime/api/thread-list-runtime.d.ts +4 -2
  152. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  153. package/dist/runtime/api/thread-list-runtime.js +6 -0
  154. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  155. package/dist/runtime/api/thread-runtime.d.ts +10 -9
  156. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  157. package/dist/runtime/api/thread-runtime.js +4 -3
  158. package/dist/runtime/api/thread-runtime.js.map +1 -1
  159. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  160. package/dist/runtime/base/base-composer-runtime-core.js +22 -8
  161. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  162. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  163. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +2 -1
  164. package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
  165. package/dist/runtime/base/default-edit-composer-runtime-core.js +26 -5
  166. package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
  167. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +2 -0
  168. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  169. package/dist/runtime/interfaces/thread-runtime-core.d.ts +7 -0
  170. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  171. package/dist/runtime/internal.d.ts.map +1 -1
  172. package/dist/runtime/internal.js +1 -4
  173. package/dist/runtime/internal.js.map +1 -1
  174. package/dist/runtime/utils/auto-status.d.ts +1 -1
  175. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  176. package/dist/runtime/utils/chat-model-adapter.d.ts +1 -1
  177. package/dist/runtime/utils/chat-model-adapter.d.ts.map +1 -1
  178. package/dist/runtime/utils/thread-message-like.d.ts +1 -1
  179. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  180. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  181. package/dist/runtimes/assistant-transport/utils.d.ts +1 -1
  182. package/dist/runtimes/assistant-transport/utils.d.ts.map +1 -1
  183. package/dist/runtimes/assistant-transport/utils.js +1 -1
  184. package/dist/runtimes/assistant-transport/utils.js.map +1 -1
  185. package/dist/runtimes/external-store/external-store-adapter.d.ts +8 -0
  186. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  187. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
  188. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  189. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +27 -25
  190. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  191. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +1 -0
  192. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  193. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +4 -0
  194. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  195. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +2 -2
  196. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  197. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +3 -0
  198. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  199. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  200. package/dist/runtimes/remote-thread-list/types.d.ts +14 -2
  201. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  202. package/dist/store/runtime-clients/attachment-runtime-client.d.ts +2 -2
  203. package/dist/store/runtime-clients/attachment-runtime-client.d.ts.map +1 -1
  204. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -1
  205. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  206. package/dist/store/runtime-clients/message-part-runtime-client.d.ts +2 -2
  207. package/dist/store/runtime-clients/message-part-runtime-client.d.ts.map +1 -1
  208. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -1
  209. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  210. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts +1 -1
  211. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  212. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts +2 -2
  213. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  214. package/dist/store/runtime-clients/thread-list-runtime-client.js +1 -0
  215. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  216. package/dist/store/runtime-clients/thread-runtime-client.d.ts +1 -1
  217. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  218. package/dist/store/scopes/thread-list-item.d.ts +1 -0
  219. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  220. package/dist/store/scopes/threads.d.ts +1 -0
  221. package/dist/store/scopes/threads.d.ts.map +1 -1
  222. package/dist/subscribable/subscribable.d.ts.map +1 -1
  223. package/dist/subscribable/subscribable.js +1 -15
  224. package/dist/subscribable/subscribable.js.map +1 -1
  225. package/dist/tests/remote-thread-list-test-helpers.d.ts +12 -0
  226. package/dist/tests/remote-thread-list-test-helpers.d.ts.map +1 -0
  227. package/dist/tests/remote-thread-list-test-helpers.js +48 -0
  228. package/dist/tests/remote-thread-list-test-helpers.js.map +1 -0
  229. package/dist/types/directive.d.ts +19 -0
  230. package/dist/types/directive.d.ts.map +1 -0
  231. package/dist/types/directive.js +2 -0
  232. package/dist/types/directive.js.map +1 -0
  233. package/dist/types/index.d.ts +1 -1
  234. package/dist/types/index.d.ts.map +1 -1
  235. package/dist/types/message.d.ts.map +1 -1
  236. package/dist/types/trigger.d.ts +2 -2
  237. package/dist/types/trigger.d.ts.map +1 -1
  238. package/dist/utils/json/is-json.d.ts +1 -1
  239. package/dist/utils/json/is-json.d.ts.map +1 -1
  240. package/package.json +11 -11
  241. package/src/adapters/attachment.ts +68 -16
  242. package/src/adapters/{mention.ts → directive-formatter.ts} +8 -20
  243. package/src/adapters/index.ts +2 -9
  244. package/src/adapters/speech.ts +1 -16
  245. package/src/adapters/thread-history.ts +1 -8
  246. package/src/adapters/trigger.ts +1 -37
  247. package/src/index.ts +3 -24
  248. package/src/model-context/frame/host.ts +6 -5
  249. package/src/model-context/frame/provider.ts +6 -5
  250. package/src/model-context/registry.ts +6 -6
  251. package/src/model-context/tool.ts +1 -1
  252. package/src/model-context/types.ts +1 -17
  253. package/src/react/AssistantRuntimeProvider.tsx +1 -1
  254. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +3 -1
  255. package/src/react/client/DataRenderers.ts +19 -3
  256. package/src/react/client/Tools.ts +4 -3
  257. package/src/react/model-context/makeAssistantTool.ts +1 -1
  258. package/src/react/model-context/makeAssistantToolUI.ts +1 -1
  259. package/src/react/model-context/useInlineRender.ts +3 -2
  260. package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -0
  261. package/src/react/primitives/composer/ComposerAttachments.tsx +7 -1
  262. package/src/react/primitives/message/MessageAttachments.tsx +7 -1
  263. package/src/react/primitives/message/MessageParts.tsx +94 -57
  264. package/src/react/primitives/part/PartMessages.tsx +1 -1
  265. package/src/react/primitives/thread/ThreadMessages.tsx +3 -2
  266. package/src/react/primitives/threadList/ThreadListItems.tsx +7 -1
  267. package/src/react/providers/AttachmentByIndexProvider.tsx +1 -1
  268. package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
  269. package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +1 -1
  270. package/src/react/providers/MessageByIndexProvider.tsx +1 -1
  271. package/src/react/providers/PartByIndexProvider.tsx +1 -1
  272. package/src/react/providers/QueueItemByIndexProvider.tsx +1 -1
  273. package/src/react/providers/SuggestionByIndexProvider.tsx +1 -1
  274. package/src/react/providers/TextMessagePartProvider.tsx +1 -1
  275. package/src/react/providers/ThreadListItemByIndexProvider.tsx +1 -1
  276. package/src/react/providers/ThreadListItemRuntimeProvider.tsx +1 -1
  277. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +47 -15
  278. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +31 -17
  279. package/src/react/runtimes/RuntimeAdapterProvider.tsx +1 -1
  280. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +3 -3
  281. package/src/react/runtimes/cloud/auiV0.ts +5 -2
  282. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +6 -3
  283. package/src/react/runtimes/useLocalRuntime.ts +10 -0
  284. package/src/react/runtimes/useRemoteThreadListRuntime.ts +6 -0
  285. package/src/react/runtimes/useToolInvocations.ts +2 -0
  286. package/src/react/types/MessagePartComponentTypes.ts +1 -1
  287. package/src/react/types/scopes/dataRenderers.ts +2 -0
  288. package/src/runtime/api/assistant-runtime.ts +1 -1
  289. package/src/runtime/api/attachment-runtime.ts +0 -4
  290. package/src/runtime/api/bindings.ts +1 -0
  291. package/src/runtime/api/composer-runtime.ts +4 -2
  292. package/src/runtime/api/message-runtime.ts +8 -8
  293. package/src/runtime/api/thread-list-runtime.ts +14 -5
  294. package/src/runtime/api/thread-runtime.ts +13 -12
  295. package/src/runtime/base/base-composer-runtime-core.ts +37 -16
  296. package/src/runtime/base/base-thread-runtime-core.ts +1 -1
  297. package/src/runtime/base/default-edit-composer-runtime-core.ts +35 -5
  298. package/src/runtime/interfaces/thread-list-runtime-core.ts +2 -0
  299. package/src/runtime/interfaces/thread-runtime-core.ts +7 -0
  300. package/src/runtime/internal.ts +1 -4
  301. package/src/runtime/utils/auto-status.ts +1 -1
  302. package/src/runtime/utils/chat-model-adapter.ts +1 -1
  303. package/src/runtime/utils/thread-message-like.ts +4 -1
  304. package/src/runtimes/assistant-transport/utils.ts +5 -1
  305. package/src/runtimes/external-store/external-store-adapter.ts +8 -0
  306. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +35 -29
  307. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +4 -0
  308. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +2 -2
  309. package/src/runtimes/remote-thread-list/remote-thread-state.ts +3 -0
  310. package/src/runtimes/remote-thread-list/types.ts +14 -2
  311. package/src/store/runtime-clients/attachment-runtime-client.ts +2 -2
  312. package/src/store/runtime-clients/composer-runtime-client.ts +2 -2
  313. package/src/store/runtime-clients/message-part-runtime-client.ts +2 -2
  314. package/src/store/runtime-clients/message-runtime-client.ts +2 -2
  315. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +1 -1
  316. package/src/store/runtime-clients/thread-list-runtime-client.ts +4 -3
  317. package/src/store/runtime-clients/thread-runtime-client.ts +3 -3
  318. package/src/store/scopes/thread-list-item.ts +1 -0
  319. package/src/store/scopes/threads.ts +1 -0
  320. package/src/subscribable/subscribable.ts +1 -24
  321. package/src/tests/OptimisticState-list-race.test.ts +5 -9
  322. package/src/tests/RemoteThreadListThreadListRuntimeCore-custom-metadata.test.ts +123 -0
  323. package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +209 -0
  324. package/src/tests/RemoteThreadListThreadListRuntimeCore-switchToThread-dedupe.test.ts +139 -0
  325. package/src/tests/attachment.test.ts +180 -0
  326. package/src/tests/base-composer-runtime-core-addAttachment.test.ts +154 -0
  327. package/src/tests/default-edit-composer-runtime-core.test.ts +312 -0
  328. package/src/tests/{mention-formatter.test.ts → directive-formatter.test.ts} +26 -1
  329. package/src/tests/external-store-thread-list-runtime-core.test.ts +212 -0
  330. package/src/tests/get-thread-state-isRunning.test.ts +93 -0
  331. package/src/tests/remote-thread-list-isLoading.test.ts +6 -10
  332. package/src/tests/remote-thread-list-test-helpers.ts +70 -0
  333. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +17 -1
  334. package/src/types/directive.ts +19 -0
  335. package/src/types/index.ts +1 -3
  336. package/src/types/message.ts +0 -12
  337. package/src/types/trigger.ts +2 -10
  338. package/src/utils/json/is-json.ts +1 -1
  339. package/dist/adapters/mention.d.ts.map +0 -1
  340. package/dist/adapters/mention.js.map +0 -1
  341. package/dist/types/mention.d.ts +0 -21
  342. package/dist/types/mention.d.ts.map +0 -1
  343. package/dist/types/mention.js +0 -2
  344. package/dist/types/mention.js.map +0 -1
  345. package/src/types/mention.ts +0 -39
@@ -1,8 +1,8 @@
1
1
  declare const process: { env: Record<string, string | undefined> };
2
2
 
3
3
  import {
4
- FC,
5
- PropsWithChildren,
4
+ type FC,
5
+ type PropsWithChildren,
6
6
  useCallback,
7
7
  useEffect,
8
8
  useMemo,
@@ -28,7 +28,7 @@ type CloudThreadListAdapterOptions = {
28
28
 
29
29
  const baseUrl =
30
30
  typeof process !== "undefined" &&
31
- process?.env?.["NEXT_PUBLIC_ASSISTANT_BASE_URL"];
31
+ process?.env?.NEXT_PUBLIC_ASSISTANT_BASE_URL;
32
32
  const autoCloud = baseUrl
33
33
  ? new AssistantCloud({ baseUrl, anonymous: true })
34
34
  : undefined;
@@ -43,17 +43,20 @@ export const useCloudThreadListAdapter = (
43
43
 
44
44
  const unstable_Provider = useCallback<FC<PropsWithChildren>>(
45
45
  function Provider({ children }) {
46
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
46
47
  const history = useAssistantCloudThreadHistoryAdapter({
47
48
  get current() {
48
49
  return adapterRef.current.cloud ?? autoCloud!;
49
50
  },
50
51
  });
51
52
  const cloudInstance = adapterRef.current.cloud ?? autoCloud!;
53
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
52
54
  const attachments = useMemo(
53
55
  () => new CloudFileAttachmentAdapter(cloudInstance),
54
56
  [cloudInstance],
55
57
  );
56
58
 
59
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
57
60
  const adapters = useMemo(
58
61
  () => ({
59
62
  history,
@@ -22,6 +22,7 @@ const useLocalThreadRuntime = (
22
22
  chatModel: ChatModelAdapter,
23
23
  { initialMessages, ...options }: LocalRuntimeOptions,
24
24
  ): AssistantRuntime => {
25
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
25
26
  const { modelContext, ...threadListAdapters } = useRuntimeAdapters() ?? {};
26
27
  const opt = {
27
28
  ...options,
@@ -32,33 +33,41 @@ const useLocalThreadRuntime = (
32
33
  },
33
34
  };
34
35
 
36
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
35
37
  const [runtime] = useState(() => new LocalRuntimeCore(opt, initialMessages));
36
38
 
39
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
37
40
  const threadIdRef = useRef<string | undefined>(undefined);
41
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
38
42
  threadIdRef.current = useAuiState((s) => s.threadListItem.remoteId);
39
43
 
44
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
40
45
  useEffect(() => {
41
46
  runtime.threads
42
47
  .getMainThreadRuntimeCore()
43
48
  .__internal_setGetThreadId(() => threadIdRef.current);
44
49
  }, [runtime]);
45
50
 
51
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
46
52
  useEffect(() => {
47
53
  return () => {
48
54
  runtime.threads.getMainThreadRuntimeCore().detach();
49
55
  };
50
56
  }, [runtime]);
51
57
 
58
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
52
59
  useEffect(() => {
53
60
  runtime.threads.getMainThreadRuntimeCore().__internal_setOptions(opt);
54
61
  runtime.threads.getMainThreadRuntimeCore().__internal_load();
55
62
  });
56
63
 
64
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
57
65
  useEffect(() => {
58
66
  if (!modelContext) return undefined;
59
67
  return runtime.registerModelContextProvider(modelContext);
60
68
  }, [modelContext, runtime]);
61
69
 
70
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
62
71
  return useMemo(() => new AssistantRuntimeImpl(runtime), [runtime]);
63
72
  };
64
73
 
@@ -93,6 +102,7 @@ export const useLocalRuntime = (
93
102
  const cloudAdapter = useCloudThreadListAdapter({ cloud });
94
103
  return useRemoteThreadListRuntime({
95
104
  runtimeHook: function RuntimeHook() {
105
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
96
106
  return useLocalThreadRuntime(chatModel, options);
97
107
  },
98
108
  adapter: cloudAdapter,
@@ -29,12 +29,15 @@ class RemoteThreadListRuntimeCore
29
29
  const useRemoteThreadListRuntimeImpl = (
30
30
  options: RemoteThreadListOptions,
31
31
  ): AssistantRuntime => {
32
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
32
33
  const [runtime] = useState(() => new RemoteThreadListRuntimeCore(options));
34
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
33
35
  useEffect(() => {
34
36
  runtime.threads.__internal_setOptions(options);
35
37
  runtime.threads.__internal_load();
36
38
  }, [runtime, options]);
37
39
 
40
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
38
41
  return useMemo(() => new AssistantRuntimeImpl(runtime), [runtime]);
39
42
  };
40
43
 
@@ -77,9 +80,12 @@ export const useRemoteThreadListRuntime = (
77
80
  return stableRuntimeHook();
78
81
  }
79
82
 
83
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
80
84
  const runtime = useRemoteThreadListRuntimeImpl(stableOptions);
81
85
 
86
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
82
87
  const prevThreadIdRef = useRef(options.threadId);
88
+ // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
83
89
  useEffect(() => {
84
90
  if (options.threadId === prevThreadIdRef.current) return;
85
91
  prevThreadIdRef.current = options.threadId;
@@ -197,6 +197,7 @@ export function useToolInvocations({
197
197
  if (wasStarted) {
198
198
  executingCountRef.current--;
199
199
  if (executingCountRef.current === 0) {
200
+ // biome-ignore lint/suspicious/useIterableCallbackReturn: forEach callback intentionally has no return
200
201
  settledResolversRef.current.forEach((resolve) => resolve());
201
202
  settledResolversRef.current = [];
202
203
  }
@@ -215,6 +216,7 @@ export function useToolInvocations({
215
216
  });
216
217
  // Resolve any waiting abort promises when all tools have settled
217
218
  if (executingCountRef.current === 0) {
219
+ // biome-ignore lint/suspicious/useIterableCallbackReturn: forEach callback intentionally has no return
218
220
  settledResolversRef.current.forEach((resolve) => resolve());
219
221
  settledResolversRef.current = [];
220
222
  }
@@ -12,7 +12,7 @@ import type {
12
12
  QuoteInfo,
13
13
  } from "../..";
14
14
  import type { MessagePartState } from "../..";
15
- import { ToolResponse } from "assistant-stream";
15
+ import type { ToolResponse } from "assistant-stream";
16
16
 
17
17
  export type EmptyMessagePartProps = {
18
18
  status: MessagePartStatus;
@@ -3,11 +3,13 @@ import type { Unsubscribe } from "../../..";
3
3
 
4
4
  export type DataRenderersState = {
5
5
  renderers: Record<string, DataMessagePartComponent[]>;
6
+ fallbacks: DataMessagePartComponent[];
6
7
  };
7
8
 
8
9
  export type DataRenderersMethods = {
9
10
  getState(): DataRenderersState;
10
11
  setDataUI(name: string, render: DataMessagePartComponent): Unsubscribe;
12
+ setFallbackDataUI(render: DataMessagePartComponent): Unsubscribe;
11
13
  };
12
14
 
13
15
  export type DataRenderersClientSchema = {
@@ -3,7 +3,7 @@ import type { ModelContextProvider } from "../../model-context/types";
3
3
  import type { AssistantRuntimeCore } from "../interfaces/assistant-runtime-core";
4
4
  import type { ThreadRuntime } from "./thread-runtime";
5
5
  import {
6
- ThreadListRuntime,
6
+ type ThreadListRuntime,
7
7
  ThreadListRuntimeImpl,
8
8
  } from "./thread-list-runtime";
9
9
  import { ExportedMessageRepository } from "../utils/message-repository";
@@ -105,10 +105,6 @@ export class MessageAttachmentRuntimeImpl extends AttachmentRuntimeImpl<"message
105
105
  return "message";
106
106
  }
107
107
 
108
- constructor(core: AttachmentSnapshotBinding<"message">) {
109
- super(core);
110
- }
111
-
112
108
  public remove(): never {
113
109
  throw new Error("Message attachments cannot be removed");
114
110
  }
@@ -47,4 +47,5 @@ export type ThreadListItemState = {
47
47
  readonly externalId: string | undefined;
48
48
  readonly status: import("../interfaces/thread-list-runtime-core").ThreadListItemStatus;
49
49
  readonly title?: string | undefined;
50
+ readonly custom?: Record<string, unknown> | undefined;
50
51
  };
@@ -136,8 +136,10 @@ export type ComposerRuntime = {
136
136
  /**
137
137
  * Add an attachment to the composer. Accepts either a standard File object
138
138
  * (processed through the AttachmentAdapter) or a CreateAttachment descriptor
139
- * for external-source attachments (URLs, API data, CMS references) that
140
- * bypasses the adapter entirely.
139
+ * for external-source attachments (URLs, API data, CMS references). External
140
+ * descriptors bypass the adapter's `add()` step but still respect
141
+ * `adapter.accept` when an adapter is configured; without an adapter they
142
+ * are added as-is.
141
143
  * @param fileOrAttachment The file or attachment descriptor to add.
142
144
  */
143
145
  addAttachment(fileOrAttachment: File | CreateAttachment): Promise<void>;
@@ -1,4 +1,4 @@
1
- import {
1
+ import type {
2
2
  SpeechState,
3
3
  SubmittedFeedback,
4
4
  } from "../interfaces/thread-runtime-core";
@@ -18,21 +18,21 @@ import {
18
18
  ShallowMemoizeSubject,
19
19
  } from "../../subscribable/subscribable";
20
20
  import {
21
- AttachmentRuntime,
22
- AttachmentState,
21
+ type AttachmentRuntime,
22
+ type AttachmentState,
23
23
  MessageAttachmentRuntimeImpl,
24
24
  } from "./attachment-runtime";
25
25
  import {
26
- EditComposerRuntime,
26
+ type EditComposerRuntime,
27
27
  EditComposerRuntimeImpl,
28
28
  } from "./composer-runtime";
29
29
  import {
30
- MessagePartRuntime,
30
+ type MessagePartRuntime,
31
31
  MessagePartRuntimeImpl,
32
- MessagePartState,
32
+ type MessagePartState,
33
33
  } from "./message-part-runtime";
34
- import { MessageRuntimePath } from "./paths";
35
- import { ThreadRuntimeCoreBinding } from "./thread-runtime";
34
+ import type { MessageRuntimePath } from "./paths";
35
+ import type { ThreadRuntimeCoreBinding } from "./thread-runtime";
36
36
  import type { MessageStateBinding } from "./bindings";
37
37
 
38
38
  const COMPLETE_STATUS: MessagePartStatus = Object.freeze({
@@ -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 = (
@@ -77,6 +80,7 @@ const getThreadListItemState = (
77
80
  externalId: threadData.externalId,
78
81
  title: threadData.title,
79
82
  status: threadData.status,
83
+ custom: threadData.custom,
80
84
  isMain: threadData.id === threadList.mainThreadId,
81
85
  };
82
86
  };
@@ -133,6 +137,7 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
133
137
  this.switchToThread = this.switchToThread.bind(this);
134
138
  this.switchToNewThread = this.switchToNewThread.bind(this);
135
139
  this.getLoadThreadsPromise = this.getLoadThreadsPromise.bind(this);
140
+ this.reload = this.reload.bind(this);
136
141
  this.getState = this.getState.bind(this);
137
142
  this.subscribe = this.subscribe.bind(this);
138
143
  this.getById = this.getById.bind(this);
@@ -153,6 +158,10 @@ export class ThreadListRuntimeImpl implements ThreadListRuntime {
153
158
  return this._core.getLoadThreadsPromise();
154
159
  }
155
160
 
161
+ public reload(): Promise<void> {
162
+ return this._core.reload?.() ?? RESOLVED_PROMISE;
163
+ }
164
+
156
165
  public getState(): ThreadListState {
157
166
  return this._getState();
158
167
  }
@@ -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,
@@ -204,6 +204,27 @@ export abstract class BaseComposerRuntimeCore
204
204
 
205
205
  async addAttachment(fileOrAttachment: File | CreateAttachment) {
206
206
  if (!(fileOrAttachment instanceof File)) {
207
+ const adapter = this.getAttachmentAdapter();
208
+ if (
209
+ adapter &&
210
+ !fileMatchesAccept(
211
+ {
212
+ name: fileOrAttachment.name,
213
+ type: fileOrAttachment.contentType ?? "",
214
+ },
215
+ adapter.accept,
216
+ )
217
+ ) {
218
+ try {
219
+ this._notifyEventSubscribers("attachmentAddError");
220
+ } catch {
221
+ // prevent subscriber errors from masking the original error
222
+ }
223
+ throw new Error(
224
+ `File type ${fileOrAttachment.contentType || "unknown"} is not accepted. Accepted types: ${adapter.accept}`,
225
+ );
226
+ }
227
+
207
228
  const a: CompleteAttachment = {
208
229
  id: fileOrAttachment.id ?? generateId(),
209
230
  type: fileOrAttachment.type ?? "document",
@@ -213,25 +234,11 @@ export abstract class BaseComposerRuntimeCore
213
234
  status: { type: "complete" },
214
235
  };
215
236
  this._attachments = [...this._attachments, a];
216
- this._notifyEventSubscribers("attachmentAdd");
217
237
  this._notifySubscribers();
238
+ this._notifyEventSubscribers("attachmentAdd");
218
239
  return;
219
240
  }
220
241
 
221
- const adapter = this.getAttachmentAdapter();
222
- if (!adapter) throw new Error("Attachments are not supported");
223
-
224
- if (
225
- !fileMatchesAccept(
226
- { name: fileOrAttachment.name, type: fileOrAttachment.type },
227
- adapter.accept,
228
- )
229
- ) {
230
- throw new Error(
231
- `File type ${fileOrAttachment.type || "unknown"} is not accepted. Accepted types: ${adapter.accept}`,
232
- );
233
- }
234
-
235
242
  const upsertAttachment = (a: PendingAttachment) => {
236
243
  const idx = this._attachments.findIndex(
237
244
  (attachment) => attachment.id === a.id,
@@ -251,6 +258,20 @@ export abstract class BaseComposerRuntimeCore
251
258
 
252
259
  let lastAttachment: PendingAttachment | undefined;
253
260
  try {
261
+ const adapter = this.getAttachmentAdapter();
262
+ if (!adapter) throw new Error("Attachments are not supported");
263
+
264
+ if (
265
+ !fileMatchesAccept(
266
+ { name: fileOrAttachment.name, type: fileOrAttachment.type },
267
+ adapter.accept,
268
+ )
269
+ ) {
270
+ throw new Error(
271
+ `File type ${fileOrAttachment.type || "unknown"} is not accepted. Accepted types: ${adapter.accept}`,
272
+ );
273
+ }
274
+
254
275
  const promiseOrGenerator = adapter.add({ file: fileOrAttachment });
255
276
  if (Symbol.asyncIterator in promiseOrGenerator) {
256
277
  for await (const r of promiseOrGenerator) {
@@ -271,7 +292,7 @@ export abstract class BaseComposerRuntimeCore
271
292
  try {
272
293
  this._notifyEventSubscribers("attachmentAddError");
273
294
  } catch {
274
- // prevent subscriber errors from masking the adapter error
295
+ // prevent subscriber errors from masking the original error
275
296
  }
276
297
  throw e;
277
298
  }
@@ -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,
@@ -10,6 +10,7 @@ export type ThreadListItemCoreState = {
10
10
 
11
11
  readonly status: ThreadListItemStatus;
12
12
  readonly title?: string | undefined;
13
+ readonly custom?: Record<string, unknown> | undefined;
13
14
 
14
15
  readonly runtime?: ThreadRuntimeCore | undefined;
15
16
  };
@@ -33,6 +34,7 @@ export type ThreadListRuntimeCore = {
33
34
  switchToNewThread(): Promise<void>;
34
35
 
35
36
  getLoadThreadsPromise(): Promise<void>;
37
+ reload?(): Promise<void>;
36
38
 
37
39
  detach(threadId: string): Promise<void>;
38
40
  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[];