@assistant-ui/core 0.3.17 → 0.3.18

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 (284) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/attachment.js +5 -4
  3. package/dist/adapters/attachment.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal.d.ts +3 -2
  7. package/dist/internal.js +3 -2
  8. package/dist/model-context/frame/host.d.ts.map +1 -1
  9. package/dist/model-context/frame/host.js +10 -4
  10. package/dist/model-context/frame/host.js.map +1 -1
  11. package/dist/model-context/frame/provider.d.ts +2 -0
  12. package/dist/model-context/frame/provider.d.ts.map +1 -1
  13. package/dist/model-context/frame/provider.js +30 -7
  14. package/dist/model-context/frame/provider.js.map +1 -1
  15. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  16. package/dist/model-context/interactable-composer-metadata.js +16 -9
  17. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  18. package/dist/model-context/registry.d.ts.map +1 -1
  19. package/dist/model-context/registry.js +3 -5
  20. package/dist/model-context/registry.js.map +1 -1
  21. package/dist/model-context/types.d.ts.map +1 -1
  22. package/dist/model-context/types.js +5 -4
  23. package/dist/model-context/types.js.map +1 -1
  24. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  25. package/dist/react/client/InMemoryThreadList.js +62 -56
  26. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  27. package/dist/react/client/Interactables.d.ts.map +1 -1
  28. package/dist/react/client/Interactables.js +24 -27
  29. package/dist/react/client/Interactables.js.map +1 -1
  30. package/dist/react/client/RemoteThreadList.d.ts +1 -0
  31. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  32. package/dist/react/client/RemoteThreadList.js +151 -141
  33. package/dist/react/client/RemoteThreadList.js.map +1 -1
  34. package/dist/react/client/Tools.d.ts.map +1 -1
  35. package/dist/react/client/Tools.js +18 -16
  36. package/dist/react/client/Tools.js.map +1 -1
  37. package/dist/react/interactables-legacy/Interactables.js +242 -121
  38. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  39. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
  40. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
  41. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
  42. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  43. package/dist/react/model-context/makeAssistantTool.js +1 -1
  44. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  45. package/dist/react/model-context/useAssistantTool.d.ts +2 -2
  46. package/dist/react/model-context/useAssistantTool.js +1 -1
  47. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  48. package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
  49. package/dist/react/model-context/useToolArgsStatus.js +2 -1
  50. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  51. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  52. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
  53. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  54. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
  55. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  56. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +103 -103
  57. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  58. package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
  59. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  60. package/dist/react/runtimes/RemoteThreadResource.js +13 -11
  61. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  62. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +4 -1
  63. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  64. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +401 -34
  65. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  66. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
  67. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +2 -1
  68. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
  69. package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
  70. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  71. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  72. package/dist/react/runtimes/useRemoteThreadListRuntime.js +63 -23
  73. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  74. package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
  75. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  76. package/dist/runtime/api/thread-list-item-runtime.js +2 -2
  77. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  78. package/dist/runtime/api/thread-list-runtime.d.ts +3 -0
  79. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  80. package/dist/runtime/api/thread-list-runtime.js +18 -14
  81. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  82. package/dist/runtime/api/thread-runtime.d.ts +4 -0
  83. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  84. package/dist/runtime/api/thread-runtime.js +1 -1
  85. package/dist/runtime/api/thread-runtime.js.map +1 -1
  86. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  87. package/dist/runtime/base/base-composer-runtime-core.js +16 -12
  88. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  89. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  90. package/dist/runtime/base/base-thread-runtime-core.js +6 -5
  91. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  92. package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
  93. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  94. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +4 -1
  95. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  96. package/dist/runtime/utils/external-message-conversion.js +1 -1
  97. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  98. package/dist/runtime/utils/message-repository.d.ts +1 -0
  99. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  100. package/dist/runtime/utils/message-repository.js +15 -6
  101. package/dist/runtime/utils/message-repository.js.map +1 -1
  102. package/dist/runtime/utils/thread-message-like.js +1 -1
  103. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  104. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  105. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
  106. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  107. package/dist/runtimes/internal.d.ts +2 -2
  108. package/dist/runtimes/internal.js +2 -2
  109. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
  110. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  111. package/dist/runtimes/remote-thread-list/remote-thread-state.js +130 -42
  112. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  113. package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
  114. package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
  115. package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
  116. package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
  117. package/dist/runtimes/remote-thread-list/title.d.ts +3 -1
  118. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
  119. package/dist/runtimes/remote-thread-list/title.js +9 -1
  120. package/dist/runtimes/remote-thread-list/title.js.map +1 -1
  121. package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
  122. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  123. package/dist/store/clients/external-thread.d.ts.map +1 -1
  124. package/dist/store/clients/external-thread.js +19 -3
  125. package/dist/store/clients/external-thread.js.map +1 -1
  126. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  127. package/dist/store/clients/model-context-client.js +2 -1
  128. package/dist/store/clients/model-context-client.js.map +1 -1
  129. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  130. package/dist/store/clients/single-thread-list.js +1 -0
  131. package/dist/store/clients/single-thread-list.js.map +1 -1
  132. package/dist/store/clients/suggestions.d.ts.map +1 -1
  133. package/dist/store/clients/suggestions.js +5 -4
  134. package/dist/store/clients/suggestions.js.map +1 -1
  135. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
  136. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  137. package/dist/store/runtime-clients/composer-runtime-client.js +97 -61
  138. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  139. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
  140. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  141. package/dist/store/runtime-clients/message-runtime-client.js +221 -144
  142. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  143. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  144. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  145. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  146. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  147. package/dist/store/runtime-clients/thread-list-runtime-client.js +54 -52
  148. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  149. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  150. package/dist/store/runtime-clients/thread-runtime-client.js +193 -121
  151. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  152. package/dist/store/scopes/composer.d.ts +10 -2
  153. package/dist/store/scopes/composer.d.ts.map +1 -1
  154. package/dist/store/scopes/message.d.ts +30 -1
  155. package/dist/store/scopes/message.d.ts.map +1 -1
  156. package/dist/store/scopes/thread-list-item.d.ts +2 -2
  157. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  158. package/dist/store/scopes/thread.d.ts +8 -0
  159. package/dist/store/scopes/thread.d.ts.map +1 -1
  160. package/dist/store/scopes/threads.d.ts +1 -0
  161. package/dist/store/scopes/threads.d.ts.map +1 -1
  162. package/dist/types/attachment.d.ts +2 -1
  163. package/dist/types/attachment.d.ts.map +1 -1
  164. package/dist/types/attachment.js +2 -1
  165. package/dist/types/attachment.js.map +1 -1
  166. package/dist/utils/abortable-iterable.d.ts +19 -0
  167. package/dist/utils/abortable-iterable.d.ts.map +1 -0
  168. package/dist/utils/abortable-iterable.js +72 -0
  169. package/dist/utils/abortable-iterable.js.map +1 -0
  170. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  171. package/dist/utils/composite-context-provider.js +20 -2
  172. package/dist/utils/composite-context-provider.js.map +1 -1
  173. package/dist/utils/record.d.ts +11 -0
  174. package/dist/utils/record.d.ts.map +1 -0
  175. package/dist/utils/record.js +12 -0
  176. package/dist/utils/record.js.map +1 -0
  177. package/package.json +10 -10
  178. package/src/adapters/attachment.test.ts +50 -1
  179. package/src/adapters/attachment.ts +7 -4
  180. package/src/index.ts +1 -0
  181. package/src/internal.ts +4 -0
  182. package/src/model-context/frame/host.test.ts +24 -0
  183. package/src/model-context/frame/host.ts +10 -4
  184. package/src/model-context/frame/provider.test.ts +71 -0
  185. package/src/model-context/frame/provider.ts +37 -7
  186. package/src/model-context/interactable-composer-metadata.test.ts +28 -0
  187. package/src/model-context/interactable-composer-metadata.ts +9 -3
  188. package/src/model-context/registry.test.ts +12 -0
  189. package/src/model-context/registry.ts +3 -2
  190. package/src/model-context/types.test.ts +25 -0
  191. package/src/model-context/types.ts +9 -4
  192. package/src/react/RuntimeAdapter.test.ts +34 -0
  193. package/src/react/client/InMemoryThreadList.ts +1 -0
  194. package/src/react/client/Interactables.test.ts +28 -0
  195. package/src/react/client/Interactables.ts +15 -13
  196. package/src/react/client/RemoteThreadList.background.test.ts +148 -6
  197. package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
  198. package/src/react/client/RemoteThreadList.test.ts +345 -3
  199. package/src/react/client/RemoteThreadList.ts +166 -110
  200. package/src/react/client/Tools.ts +22 -11
  201. package/src/react/interactables-legacy/Interactables.ts +16 -16
  202. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
  203. package/src/react/model-context/makeAssistantTool.ts +2 -2
  204. package/src/react/model-context/useAssistantTool.ts +2 -2
  205. package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
  206. package/src/react/model-context/useToolArgsStatus.ts +2 -1
  207. package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
  208. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
  209. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
  210. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
  211. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
  212. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
  213. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +136 -111
  214. package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
  215. package/src/react/runtimes/RemoteThreadResource.ts +19 -12
  216. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +483 -6
  217. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +504 -68
  218. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +15 -0
  219. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +1 -0
  220. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
  221. package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
  222. package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
  223. package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
  224. package/src/react/runtimes/useRemoteThreadListRuntime.ts +33 -0
  225. package/src/runtime/api/message-runtime.test.ts +75 -0
  226. package/src/runtime/api/thread-list-item-runtime.ts +10 -3
  227. package/src/runtime/api/thread-list-runtime.ts +21 -11
  228. package/src/runtime/api/thread-runtime.test.ts +78 -0
  229. package/src/runtime/api/thread-runtime.ts +8 -1
  230. package/src/runtime/base/base-composer-runtime-core.ts +36 -8
  231. package/src/runtime/base/base-thread-runtime-core.test.ts +55 -1
  232. package/src/runtime/base/base-thread-runtime-core.ts +6 -4
  233. package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
  234. package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
  235. package/src/runtime/utils/external-message-conversion.test.ts +68 -0
  236. package/src/runtime/utils/external-message-conversion.ts +1 -1
  237. package/src/runtime/utils/message-repository.ts +29 -17
  238. package/src/runtime/utils/thread-message-like.ts +1 -1
  239. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
  240. package/src/runtimes/internal.ts +1 -0
  241. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
  242. package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
  243. package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
  244. package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
  245. package/src/runtimes/remote-thread-list/title.test.ts +62 -0
  246. package/src/runtimes/remote-thread-list/title.ts +13 -0
  247. package/src/runtimes/remote-thread-list/types.ts +10 -0
  248. package/src/store/clients/external-thread.ts +48 -3
  249. package/src/store/clients/model-context-client.ts +5 -1
  250. package/src/store/clients/single-thread-list.ts +1 -0
  251. package/src/store/clients/suggestions.test.ts +40 -0
  252. package/src/store/clients/suggestions.ts +13 -10
  253. package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
  254. package/src/store/runtime-clients/message-runtime-client.ts +54 -6
  255. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
  256. package/src/store/runtime-clients/thread-list-runtime-client.ts +1 -0
  257. package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
  258. package/src/store/scopes/composer.ts +16 -4
  259. package/src/store/scopes/message.ts +14 -0
  260. package/src/store/scopes/thread-list-item.ts +5 -2
  261. package/src/store/scopes/thread.ts +4 -0
  262. package/src/store/scopes/threads.ts +1 -0
  263. package/src/tests/MessageRepository.test.ts +116 -0
  264. package/src/tests/OptimisticState-list-race.test.ts +1 -0
  265. package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
  266. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +47 -0
  267. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
  268. package/src/tests/attachment-adapters.test.ts +14 -0
  269. package/src/tests/base-composer-runtime-core.test.ts +39 -0
  270. package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
  271. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +27 -18
  272. package/src/tests/external-thread-attachments.test.tsx +139 -0
  273. package/src/tests/external-thread-parity.test.tsx +23 -0
  274. package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
  275. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  276. package/src/tests/thread-switch-events.test.tsx +78 -0
  277. package/src/tests/tools-scope-migration.test.tsx +28 -0
  278. package/src/types/attachment.ts +4 -0
  279. package/src/utils/abortable-iterable.test.ts +213 -0
  280. package/src/utils/abortable-iterable.ts +93 -0
  281. package/src/utils/composite-context-provider.test.ts +25 -0
  282. package/src/utils/composite-context-provider.ts +23 -2
  283. package/src/utils/record.test.ts +48 -0
  284. package/src/utils/record.ts +11 -0
@@ -1 +1 @@
1
- {"version":3,"file":"external-message-conversion.js","names":["ReadonlyJSONValue","ToolExecutionStatus","ThreadAssistantMessage","ThreadMessage","ToolCallMessagePart","MessageTiming","generateErrorMessageId","isJSONValueEqual","getAutoStatus","isAutoStatus","isInterruptedToolCall","isPendingToolCall","bindExternalStoreMessage","FALLBACK_ID_PREFIX","getExternalStoreMessages","symbolInnerMessage","fromThreadMessageLike","ThreadMessageLike","JoinStrategy","ExternalMessageConverterMessage","convertConfig","joinStrategy","role","toolCallId","toolName","result","artifact","isError","messages","ExternalMessageConverterMetadata","toolStatuses","Record","error","cancelledMessageIds","ReadonlySet","messageTiming","ExternalMessageConverterCallback","message","T","metadata","ExternalMessageConverterCallbackResult","input","outputs","ExternalMessageConverterChunk","inputs","Mutable","P","stringifyForError","value","text","Error","String","JSON","stringify","length","slice","toCallbackOutputs","output","Array","isArray","o","valid","content","filter","warnedDroppedToolResults","has","add","console","warn","WeakSet","convertExternalMessageCallback","callback","mergeInnerMessages","existing","incoming","joinExternalMessages","assistantMessage","Omit","Exclude","toolCallIdx","findIndex","c","type","toolCall","const","map","id","createdAt","status","attachments","unstable_state","undefined","unstable_annotations","unstable_data","steps","custom","timing","submittedFeedback","isOptimistic","part","existingIdx","parentId","push","unsupportedRole","chunkExternalMessages","callbackResults","results","isAssistant","pendingNone","flush","callbackResult","at","shallowArrayEqual","a","b","i","ExternalMessageConversionCache","generatedFallbackMessages","convertExternalMessageChunk","idx","chunkCount","isRunning","cache","isLast","joined","isCancelled","some","hasInterruptedToolCalls","hasPendingToolCalls","autoStatus","fallbackId","cachedMessage","reason","updated","newMessage","createErrorAssistantMessage","msg","Date","completeExternalMessageConversion","lastMessage","convertExternalMessages","WeakKey","chunks"],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ToolExecutionStatus } from \"../../runtimes/tool-invocations/ToolInvocationTracker\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport { isJSONValueEqual } from \"../../utils/json/is-json-equal\";\nimport {\n getAutoStatus,\n isAutoStatus,\n isInterruptedToolCall,\n isPendingToolCall,\n} from \"./auto-status\";\nimport {\n bindExternalStoreMessage,\n FALLBACK_ID_PREFIX,\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"./thread-message-like\";\n\nexport type JoinStrategy = \"concat-content\" | \"none\";\n\nexport type ExternalMessageConverterMessage =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: JoinStrategy;\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\nexport type ExternalMessageConverterMetadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly cancelledMessageIds?: ReadonlySet<string>;\n readonly messageTiming?: Record<string, MessageTiming>;\n};\n\nexport type ExternalMessageConverterCallback<T> = (\n message: T,\n metadata: ExternalMessageConverterMetadata,\n) => ExternalMessageConverterMessage | ExternalMessageConverterMessage[];\n\nexport type ExternalMessageConverterCallbackResult<T> = {\n input: T;\n outputs: ExternalMessageConverterMessage[];\n};\n\nexport type ExternalMessageConverterChunk<T> = {\n inputs: T[];\n outputs: ExternalMessageConverterMessage[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst stringifyForError = (value: unknown) => {\n let text;\n try {\n text = value instanceof Error ? String(value) : JSON.stringify(value);\n } catch {\n /* circular */\n }\n text ??= String(value);\n return text.length > 200 ? `${text.slice(0, 200)}…` : text;\n};\n\nconst toCallbackOutputs = (\n output: ExternalMessageConverterMessage | ExternalMessageConverterMessage[],\n input: unknown,\n): ExternalMessageConverterMessage[] => {\n const outputs = Array.isArray(output) ? output : [output];\n for (const o of outputs) {\n const valid =\n typeof o === \"object\" &&\n o !== null &&\n (o.role === \"tool\" ||\n ((o.role === \"assistant\" || o.role === \"user\" || o.role === \"system\") &&\n (typeof o.content === \"string\" || Array.isArray(o.content))));\n if (!valid)\n throw new Error(\n `External message converter: the converter callback returned an invalid message (${stringifyForError(o)}) for input ${stringifyForError(input)}. Return an empty array to skip a message.`,\n );\n }\n // Providers can emit tool results without a usable id (react-langchain maps\n // a missing tool_call_id to \"\"); converters must not throw on those, so the\n // result is dropped like any other orphaned tool output.\n return outputs.filter((o) => {\n if (o.role !== \"tool\") return true;\n if (typeof o.toolCallId === \"string\" && o.toolCallId.length > 0)\n return true;\n if (!warnedDroppedToolResults.has(o)) {\n warnedDroppedToolResults.add(o);\n console.warn(\n `External message converter: dropping a tool result without a toolCallId (${stringifyForError(o)}) for input ${stringifyForError(input)}.`,\n );\n }\n return false;\n });\n};\n\nconst warnedDroppedToolResults = new WeakSet<object>();\n\nexport const convertExternalMessageCallback = <T>(\n input: T,\n callback: ExternalMessageConverterCallback<T>,\n metadata: ExternalMessageConverterMetadata,\n): ExternalMessageConverterCallbackResult<T> => ({\n input,\n outputs: toCallbackOutputs(callback(input, metadata), input),\n});\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nexport const joinExternalMessages = (\n messages: readonly ExternalMessageConverterMessage[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName != null) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state !== undefined) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n\n if (output.metadata.isOptimistic) {\n assistantMessage.metadata.isOptimistic = true;\n }\n // TODO keep this in sync with ThreadMessageLike[\"metadata\"] / fromThreadMessageLike\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\") {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"tool-call\" && c.toolCallId === part.toolCallId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"reasoning\" &&\n \"parentId\" in c &&\n c.parentId === part.parentId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n assistantMessage.content.push(part);\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nexport const chunkExternalMessages = <T>(\n callbackResults: ExternalMessageConverterCallbackResult<T>[],\n joinStrategy?: JoinStrategy,\n) => {\n const results: ExternalMessageConverterChunk<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: ExternalMessageConverterMessage[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const shallowArrayEqual = (\n a: readonly unknown[],\n b: readonly unknown[],\n) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\ntype ExternalMessageConversionCache = {\n message: ThreadMessage | undefined;\n generatedFallbackMessages: WeakSet<object>;\n};\n\nexport const convertExternalMessageChunk = <T>(\n message: ExternalMessageConverterChunk<T>,\n idx: number,\n chunkCount: number,\n isRunning: boolean,\n error: ReadonlyJSONValue | undefined,\n cache?: ExternalMessageConversionCache,\n cancelledMessageIds?: ReadonlySet<string>,\n) => {\n const isLast = idx === chunkCount - 1;\n const joined = joinExternalMessages(message.outputs);\n const isCancelled =\n cancelledMessageIds !== undefined &&\n message.outputs.some(\n (output) =>\n output.role !== \"tool\" &&\n output.id != null &&\n cancelledMessageIds.has(output.id),\n );\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? error : undefined,\n isCancelled,\n );\n const fallbackId = `${FALLBACK_ID_PREFIX}${idx}`;\n\n const cachedMessage = cache?.message;\n if (\n cachedMessage &&\n (cachedMessage.role !== \"assistant\" ||\n !isAutoStatus(cachedMessage.status) ||\n cachedMessage.status === autoStatus ||\n (cachedMessage.status.type === \"incomplete\" &&\n cachedMessage.status.reason === \"error\" &&\n cachedMessage.status.error !== undefined &&\n autoStatus.type === \"incomplete\" &&\n autoStatus.reason === \"error\" &&\n autoStatus.error !== undefined &&\n (cachedMessage.status.error === autoStatus.error ||\n isJSONValueEqual(cachedMessage.status.error, autoStatus.error))))\n ) {\n const inputs = getExternalStoreMessages<T>(cachedMessage);\n if (shallowArrayEqual(inputs, message.inputs)) {\n // A positional fallback id goes stale when messages are prepended\n // or reordered; serving it unchanged makes two messages collide on\n // one id and the dedup downstream drops one of them.\n if (\n cache.generatedFallbackMessages.has(cachedMessage) &&\n cachedMessage.id !== fallbackId\n ) {\n const updated = { ...cachedMessage, id: fallbackId };\n cache.generatedFallbackMessages.add(updated);\n bindExternalStoreMessage(updated, message.inputs);\n return updated;\n }\n return cachedMessage;\n }\n }\n\n const newMessage = fromThreadMessageLike(joined, fallbackId, autoStatus);\n if (cache && joined.id == null) {\n cache.generatedFallbackMessages.add(newMessage);\n }\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const completeExternalMessageConversion = (\n messages: ThreadMessage[],\n error: ReadonlyJSONValue | undefined,\n) => {\n if (error) {\n const lastMessage = messages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n messages.push(createErrorAssistantMessage(error));\n }\n }\n return messages;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: ExternalMessageConverterCallback<T>,\n isRunning: boolean,\n metadata: ExternalMessageConverterMetadata,\n) => {\n const callbackResults = messages.map((message) =>\n convertExternalMessageCallback(message, callback, metadata),\n );\n const chunks = chunkExternalMessages(callbackResults);\n const result = chunks.map((message, idx) =>\n convertExternalMessageChunk(\n message,\n idx,\n chunks.length,\n isRunning,\n metadata.error,\n undefined,\n metadata.cancelledMessageIds,\n ),\n );\n return completeExternalMessageConversion(result, metadata.error);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"external-message-conversion.js","names":["ReadonlyJSONValue","ToolExecutionStatus","ThreadAssistantMessage","ThreadMessage","ToolCallMessagePart","MessageTiming","generateErrorMessageId","isJSONValueEqual","getAutoStatus","isAutoStatus","isInterruptedToolCall","isPendingToolCall","bindExternalStoreMessage","FALLBACK_ID_PREFIX","getExternalStoreMessages","symbolInnerMessage","fromThreadMessageLike","ThreadMessageLike","JoinStrategy","ExternalMessageConverterMessage","convertConfig","joinStrategy","role","toolCallId","toolName","result","artifact","isError","messages","ExternalMessageConverterMetadata","toolStatuses","Record","error","cancelledMessageIds","ReadonlySet","messageTiming","ExternalMessageConverterCallback","message","T","metadata","ExternalMessageConverterCallbackResult","input","outputs","ExternalMessageConverterChunk","inputs","Mutable","P","stringifyForError","value","text","Error","String","JSON","stringify","length","slice","toCallbackOutputs","output","Array","isArray","o","valid","content","filter","warnedDroppedToolResults","has","add","console","warn","WeakSet","convertExternalMessageCallback","callback","mergeInnerMessages","existing","incoming","joinExternalMessages","assistantMessage","Omit","Exclude","toolCallIdx","findIndex","c","type","toolCall","const","map","id","createdAt","status","attachments","unstable_state","undefined","unstable_annotations","unstable_data","steps","custom","timing","submittedFeedback","isOptimistic","part","existingIdx","parentId","push","unsupportedRole","chunkExternalMessages","callbackResults","results","isAssistant","pendingNone","flush","callbackResult","at","shallowArrayEqual","a","b","i","ExternalMessageConversionCache","generatedFallbackMessages","convertExternalMessageChunk","idx","chunkCount","isRunning","cache","isLast","joined","isCancelled","some","hasInterruptedToolCalls","hasPendingToolCalls","autoStatus","fallbackId","cachedMessage","reason","updated","newMessage","createErrorAssistantMessage","msg","Date","completeExternalMessageConversion","lastMessage","convertExternalMessages","WeakKey","chunks"],"sources":["../../../src/runtime/utils/external-message-conversion.ts"],"sourcesContent":["import type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport type { ToolExecutionStatus } from \"../../runtimes/tool-invocations/ToolInvocationTracker\";\nimport type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"../../types/message\";\nimport type { MessageTiming } from \"../../types/message\";\nimport { generateErrorMessageId } from \"../../utils/id\";\nimport { isJSONValueEqual } from \"../../utils/json/is-json-equal\";\nimport {\n getAutoStatus,\n isAutoStatus,\n isInterruptedToolCall,\n isPendingToolCall,\n} from \"./auto-status\";\nimport {\n bindExternalStoreMessage,\n FALLBACK_ID_PREFIX,\n getExternalStoreMessages,\n symbolInnerMessage,\n} from \"./external-store-message\";\nimport {\n fromThreadMessageLike,\n type ThreadMessageLike,\n} from \"./thread-message-like\";\n\nexport type JoinStrategy = \"concat-content\" | \"none\";\n\nexport type ExternalMessageConverterMessage =\n | (ThreadMessageLike & {\n readonly convertConfig?: {\n readonly joinStrategy?: JoinStrategy;\n };\n })\n | {\n role: \"tool\";\n toolCallId: string;\n toolName?: string | undefined;\n result: any;\n artifact?: any;\n isError?: boolean;\n messages?: readonly ThreadMessage[];\n };\n\nexport type ExternalMessageConverterMetadata = {\n readonly toolStatuses?: Record<string, ToolExecutionStatus>;\n readonly error?: ReadonlyJSONValue;\n readonly cancelledMessageIds?: ReadonlySet<string>;\n readonly messageTiming?: Record<string, MessageTiming>;\n};\n\nexport type ExternalMessageConverterCallback<T> = (\n message: T,\n metadata: ExternalMessageConverterMetadata,\n) => ExternalMessageConverterMessage | ExternalMessageConverterMessage[];\n\nexport type ExternalMessageConverterCallbackResult<T> = {\n input: T;\n outputs: ExternalMessageConverterMessage[];\n};\n\nexport type ExternalMessageConverterChunk<T> = {\n inputs: T[];\n outputs: ExternalMessageConverterMessage[];\n};\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nconst stringifyForError = (value: unknown) => {\n let text;\n try {\n text = value instanceof Error ? String(value) : JSON.stringify(value);\n } catch {\n /* circular */\n }\n text ??= String(value);\n return text.length > 200 ? `${text.slice(0, 200)}…` : text;\n};\n\nconst toCallbackOutputs = (\n output: ExternalMessageConverterMessage | ExternalMessageConverterMessage[],\n input: unknown,\n): ExternalMessageConverterMessage[] => {\n const outputs = Array.isArray(output) ? output : [output];\n for (const o of outputs) {\n const valid =\n typeof o === \"object\" &&\n o !== null &&\n (o.role === \"tool\" ||\n ((o.role === \"assistant\" || o.role === \"user\" || o.role === \"system\") &&\n (typeof o.content === \"string\" || Array.isArray(o.content))));\n if (!valid)\n throw new Error(\n `External message converter: the converter callback returned an invalid message (${stringifyForError(o)}) for input ${stringifyForError(input)}. Return an empty array to skip a message.`,\n );\n }\n // Providers can emit tool results without a usable id (react-langchain maps\n // a missing tool_call_id to \"\"); converters must not throw on those, so the\n // result is dropped like any other orphaned tool output.\n return outputs.filter((o) => {\n if (o.role !== \"tool\") return true;\n if (typeof o.toolCallId === \"string\" && o.toolCallId.length > 0)\n return true;\n if (!warnedDroppedToolResults.has(o)) {\n warnedDroppedToolResults.add(o);\n console.warn(\n `External message converter: dropping a tool result without a toolCallId (${stringifyForError(o)}) for input ${stringifyForError(input)}.`,\n );\n }\n return false;\n });\n};\n\nconst warnedDroppedToolResults = new WeakSet<object>();\n\nexport const convertExternalMessageCallback = <T>(\n input: T,\n callback: ExternalMessageConverterCallback<T>,\n metadata: ExternalMessageConverterMetadata,\n): ExternalMessageConverterCallbackResult<T> => ({\n input,\n outputs: toCallbackOutputs(callback(input, metadata), input),\n});\n\nconst mergeInnerMessages = (existing: object, incoming: object) => ({\n [symbolInnerMessage]: [\n ...((existing as any)[symbolInnerMessage] ?? []),\n ...((incoming as any)[symbolInnerMessage] ?? []),\n ],\n});\n\nexport const joinExternalMessages = (\n messages: readonly ExternalMessageConverterMessage[],\n): ThreadMessageLike => {\n const assistantMessage: Mutable<Omit<ThreadMessageLike, \"metadata\">> & {\n content: Exclude<ThreadMessageLike[\"content\"][0], string>[];\n metadata?: Mutable<ThreadMessageLike[\"metadata\"]>;\n } = {\n role: \"assistant\",\n content: [],\n };\n for (const output of messages) {\n if (output.role === \"tool\") {\n const toolCallIdx = assistantMessage.content.findIndex(\n (c) => c.type === \"tool-call\" && c.toolCallId === output.toolCallId,\n );\n // Ignore orphaned tool results so one bad tool message does not\n // prevent rendering the rest of the conversation.\n if (toolCallIdx !== -1) {\n const toolCall = assistantMessage.content[\n toolCallIdx\n ]! as ToolCallMessagePart;\n if (output.toolName != null) {\n if (toolCall.toolName !== output.toolName)\n throw new Error(\n `Tool call name ${output.toolCallId} ${output.toolName} does not match existing tool call ${toolCall.toolName}`,\n );\n }\n assistantMessage.content[toolCallIdx] = {\n ...toolCall,\n ...{\n [symbolInnerMessage]: [\n ...((toolCall as any)[symbolInnerMessage] ?? []),\n output,\n ],\n },\n result: output.result,\n artifact: output.artifact,\n isError: output.isError,\n messages: output.messages,\n };\n }\n } else {\n const role = output.role;\n const content = (\n typeof output.content === \"string\"\n ? [{ type: \"text\" as const, text: output.content }]\n : output.content\n ).map((c) => ({\n ...c,\n ...{ [symbolInnerMessage]: [output] },\n }));\n switch (role) {\n case \"system\":\n case \"user\":\n return {\n ...output,\n content,\n };\n case \"assistant\":\n if (assistantMessage.content.length === 0) {\n assistantMessage.id = output.id;\n assistantMessage.createdAt ??= output.createdAt;\n assistantMessage.status ??= output.status;\n\n if (output.attachments) {\n assistantMessage.attachments = [\n ...(assistantMessage.attachments ?? []),\n ...output.attachments,\n ];\n }\n }\n\n if (output.metadata) {\n assistantMessage.metadata ??= {};\n if (output.metadata.unstable_state !== undefined) {\n assistantMessage.metadata.unstable_state =\n output.metadata.unstable_state;\n }\n if (output.metadata.unstable_annotations) {\n assistantMessage.metadata.unstable_annotations = [\n ...(assistantMessage.metadata.unstable_annotations ?? []),\n ...output.metadata.unstable_annotations,\n ];\n }\n if (output.metadata.unstable_data) {\n assistantMessage.metadata.unstable_data = [\n ...(assistantMessage.metadata.unstable_data ?? []),\n ...output.metadata.unstable_data,\n ];\n }\n if (output.metadata.steps) {\n assistantMessage.metadata.steps = [\n ...(assistantMessage.metadata.steps ?? []),\n ...output.metadata.steps,\n ];\n }\n if (output.metadata.custom) {\n assistantMessage.metadata.custom = {\n ...(assistantMessage.metadata.custom ?? {}),\n ...output.metadata.custom,\n };\n }\n\n if (output.metadata.timing) {\n assistantMessage.metadata.timing = output.metadata.timing;\n }\n\n if (output.metadata.submittedFeedback) {\n assistantMessage.metadata.submittedFeedback =\n output.metadata.submittedFeedback;\n }\n\n if (output.metadata.isOptimistic) {\n assistantMessage.metadata.isOptimistic = true;\n }\n // TODO keep this in sync with ThreadMessageLike[\"metadata\"] / fromThreadMessageLike\n }\n\n // Add content parts, merging reasoning parts with same parentId\n for (const part of content) {\n if (part.type === \"tool-call\" && part.toolCallId) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"tool-call\" && c.toolCallId === part.toolCallId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n ...part,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n\n if (\n part.type === \"reasoning\" &&\n \"parentId\" in part &&\n part.parentId\n ) {\n const existingIdx = assistantMessage.content.findIndex(\n (c) =>\n c.type === \"reasoning\" &&\n \"parentId\" in c &&\n c.parentId === part.parentId,\n );\n if (existingIdx !== -1) {\n const existing = assistantMessage.content[\n existingIdx\n ] as typeof part;\n assistantMessage.content[existingIdx] = {\n ...existing,\n text: `${existing.text}\\n\\n${part.text}`,\n ...mergeInnerMessages(existing, part),\n };\n continue;\n }\n }\n assistantMessage.content.push(part);\n }\n break;\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n }\n }\n return assistantMessage;\n};\n\nexport const chunkExternalMessages = <T>(\n callbackResults: ExternalMessageConverterCallbackResult<T>[],\n joinStrategy?: JoinStrategy,\n) => {\n const results: ExternalMessageConverterChunk<T>[] = [];\n let isAssistant = false;\n let pendingNone = false; // true if the previous assistant message had joinStrategy \"none\"\n let inputs: T[] = [];\n let outputs: ExternalMessageConverterMessage[] = [];\n\n const flush = () => {\n if (outputs.length) {\n results.push({\n inputs,\n outputs,\n });\n }\n inputs = [];\n outputs = [];\n isAssistant = false;\n pendingNone = false;\n };\n\n for (const callbackResult of callbackResults) {\n for (const output of callbackResult.outputs) {\n if (\n (pendingNone && output.role !== \"tool\") ||\n !isAssistant ||\n output.role === \"user\" ||\n output.role === \"system\"\n ) {\n flush();\n }\n isAssistant = output.role === \"assistant\" || output.role === \"tool\";\n\n if (inputs.at(-1) !== callbackResult.input) {\n inputs.push(callbackResult.input);\n }\n outputs.push(output);\n\n if (\n output.role === \"assistant\" &&\n (output.convertConfig?.joinStrategy === \"none\" ||\n joinStrategy === \"none\")\n ) {\n pendingNone = true;\n }\n }\n }\n flush();\n return results;\n};\n\nexport const shallowArrayEqual = (\n a: readonly unknown[],\n b: readonly unknown[],\n) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n};\n\ntype ExternalMessageConversionCache = {\n message: ThreadMessage | undefined;\n generatedFallbackMessages: WeakSet<object>;\n};\n\nexport const convertExternalMessageChunk = <T>(\n message: ExternalMessageConverterChunk<T>,\n idx: number,\n chunkCount: number,\n isRunning: boolean,\n error: ReadonlyJSONValue | undefined,\n cache?: ExternalMessageConversionCache,\n cancelledMessageIds?: ReadonlySet<string>,\n) => {\n const isLast = idx === chunkCount - 1;\n const joined = joinExternalMessages(message.outputs);\n const isCancelled =\n cancelledMessageIds !== undefined &&\n message.outputs.some(\n (output) =>\n output.role !== \"tool\" &&\n output.id != null &&\n cancelledMessageIds.has(output.id),\n );\n const hasInterruptedToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isInterruptedToolCall);\n const hasPendingToolCalls =\n typeof joined.content === \"object\" &&\n joined.content.some(isPendingToolCall);\n const autoStatus = getAutoStatus(\n isLast,\n isRunning,\n hasInterruptedToolCalls,\n hasPendingToolCalls,\n isLast ? error : undefined,\n isCancelled,\n );\n const fallbackId = `${FALLBACK_ID_PREFIX}${idx}`;\n\n const cachedMessage = cache?.message;\n if (\n cachedMessage &&\n (cachedMessage.role !== \"assistant\" ||\n !isAutoStatus(cachedMessage.status) ||\n cachedMessage.status === autoStatus ||\n (cachedMessage.status.type === \"incomplete\" &&\n cachedMessage.status.reason === \"error\" &&\n cachedMessage.status.error !== undefined &&\n autoStatus.type === \"incomplete\" &&\n autoStatus.reason === \"error\" &&\n autoStatus.error !== undefined &&\n (cachedMessage.status.error === autoStatus.error ||\n isJSONValueEqual(cachedMessage.status.error, autoStatus.error))))\n ) {\n const inputs = getExternalStoreMessages<T>(cachedMessage);\n if (shallowArrayEqual(inputs, message.inputs)) {\n // A positional fallback id goes stale when messages are prepended\n // or reordered; serving it unchanged makes two messages collide on\n // one id and the dedup downstream drops one of them.\n if (\n cache.generatedFallbackMessages.has(cachedMessage) &&\n cachedMessage.id !== fallbackId\n ) {\n const updated = { ...cachedMessage, id: fallbackId };\n cache.generatedFallbackMessages.add(updated);\n bindExternalStoreMessage(updated, message.inputs);\n return updated;\n }\n return cachedMessage;\n }\n }\n\n const newMessage = fromThreadMessageLike(joined, fallbackId, autoStatus);\n if (cache && joined.id == null) {\n cache.generatedFallbackMessages.add(newMessage);\n }\n bindExternalStoreMessage(newMessage, message.inputs);\n return newMessage;\n};\n\nfunction createErrorAssistantMessage(\n error: ReadonlyJSONValue,\n): ThreadAssistantMessage {\n const msg: ThreadAssistantMessage = {\n id: generateErrorMessageId(),\n role: \"assistant\",\n content: [],\n status: { type: \"incomplete\", reason: \"error\", error },\n createdAt: new Date(),\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n custom: {},\n steps: [],\n },\n };\n bindExternalStoreMessage(msg, []);\n return msg;\n}\n\nexport const completeExternalMessageConversion = (\n messages: ThreadMessage[],\n error: ReadonlyJSONValue | undefined,\n) => {\n if (error) {\n const lastMessage = messages.at(-1);\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n messages.push(createErrorAssistantMessage(error));\n }\n }\n return messages;\n};\n\nexport const convertExternalMessages = <T extends WeakKey>(\n messages: T[],\n callback: ExternalMessageConverterCallback<T>,\n isRunning: boolean,\n metadata: ExternalMessageConverterMetadata,\n) => {\n const callbackResults = messages.map((message) =>\n convertExternalMessageCallback(message, callback, metadata),\n );\n const chunks = chunkExternalMessages(callbackResults);\n const result = chunks.map((message, idx) =>\n convertExternalMessageChunk(\n message,\n idx,\n chunks.length,\n isRunning,\n metadata.error,\n undefined,\n metadata.cancelledMessageIds,\n ),\n );\n return completeExternalMessageConversion(result, metadata.error);\n};\n"],"mappings":"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"}
@@ -28,6 +28,7 @@ declare class MessageRepository {
28
28
  private head;
29
29
  private root;
30
30
  private updateLevels;
31
+ private selectPathTo;
31
32
  private performOp;
32
33
  private _messages;
33
34
  get headId(): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"message-repository.d.ts","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"mappings":";;;KAOY;EACV,SAAS;EACT;EACA,YAAY;;KAGF;EACV;EACA,UAAU;IACR,SAAS;IACT;IACA,YAAY;;;cAIH;EAEC,YAAA,mBAAS,wBAClB;EAkBM,sBAAA;IACL,SAAS;IACT;OACC;IACS;QACX;;cAgEQ;UACH;UACA;UACA;UAKA;UAgBA;UA2DA;MAQJ;MAIA;EAUJ,YAAY,2BAAe;EAuB3B,mBAAmB,yBAAyB,SAAS;EAiCrD,WAAW;;;;;EAcX,cAAc,mBAAmB;EAsCjC,YAAY;;;;;;;;;UAmBJ;EA+BR,eAAe;EAkBf,UAAU;EAiDV;EAUA,UAAU;EAwBV,SAAS,QAAQ,YAAY"}
1
+ {"version":3,"file":"message-repository.d.ts","names":[],"sources":["../../../src/runtime/utils/message-repository.ts"],"mappings":";;;KAOY;EACV,SAAS;EACT;EACA,YAAY;;KAGF;EACV;EACA,UAAU;IACR,SAAS;IACT;IACA,YAAY;;;cAIH;EAEC,YAAA,mBAAS,wBAClB;EAkBM,sBAAA;IACL,SAAS;IACT;OACC;IACS;QACX;;cAgEQ;UACH;UACA;UACA;UAKA;UAgBA;UAUA;UAgEA;MAQJ;MAIA;EAUJ,YAAY,2BAAe;EAuB3B,mBAAmB,yBAAyB,SAAS;EAiCrD,WAAW;;;;;EAcX,cAAc,mBAAmB;EAsCjC,YAAY;;;;;;;;;UAmBJ;EA+BR,eAAe;EAiBf,UAAU;EAuCV;EAUA,UAAU;EAgCV,SAAS,QAAQ,YAAY"}
@@ -66,6 +66,9 @@ var MessageRepository = class {
66
66
  }
67
67
  }
68
68
  }
69
+ selectPathTo(message) {
70
+ for (let current = message; current; current = current.prev) (current.prev ?? this.root).next = current;
71
+ }
69
72
  performOp(newParent, child, operation) {
70
73
  const parentOrRoot = child.prev ?? this.root;
71
74
  const newParentOrRoot = newParent ?? this.root;
@@ -84,8 +87,12 @@ var MessageRepository = class {
84
87
  }
85
88
  if (operation !== "cut") {
86
89
  newParentOrRoot.children = [...newParentOrRoot.children, child.current.id];
87
- if (findHead(child) === this.head || newParentOrRoot.next === null) newParentOrRoot.next = child;
88
90
  child.prev = newParent;
91
+ if (findHead(child) === this.head) this.selectPathTo(child);
92
+ else if (newParentOrRoot.next === null) {
93
+ newParentOrRoot.next = child;
94
+ if (this.head === newParentOrRoot) this.head = findHead(child);
95
+ }
89
96
  const newLevel = newParent ? newParent.level + 1 : 0;
90
97
  this.updateLevels(child, newLevel);
91
98
  }
@@ -186,8 +193,7 @@ var MessageRepository = class {
186
193
  const message = this.messages.get(messageId);
187
194
  if (!message) throw new Error("MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.");
188
195
  const previousHead = this.head;
189
- const prevOrRoot = message.prev ?? this.root;
190
- prevOrRoot.next = message;
196
+ this.selectPathTo(message);
191
197
  this.head = findHead(message);
192
198
  this.evictOffBranchOptimisticMessages(previousHead, this.head);
193
199
  this._messages.dirty();
@@ -214,8 +220,7 @@ var MessageRepository = class {
214
220
  message.next = null;
215
221
  }
216
222
  this.head = message;
217
- for (let current = message; current; current = current.prev) if (current.prev) current.prev.next = current;
218
- else this.root.next = current;
223
+ this.selectPathTo(message);
219
224
  this.evictOffBranchOptimisticMessages(previousHead, this.head);
220
225
  this._messages.dirty();
221
226
  }
@@ -230,7 +235,11 @@ var MessageRepository = class {
230
235
  }
231
236
  export() {
232
237
  const exportItems = [];
233
- for (const [, message] of this.messages) {
238
+ const pending = [...this.root.children].reverse();
239
+ while (pending.length > 0) {
240
+ const message = this.messages.get(pending.pop());
241
+ if (!message) continue;
242
+ for (let i = message.children.length - 1; i >= 0; i--) pending.push(message.children[i]);
234
243
  if (message.current.metadata?.isOptimistic) continue;
235
244
  let prev = message.prev;
236
245
  while (prev && prev.current.metadata?.isOptimistic) prev = prev.prev;
@@ -1 +1 @@
1
- {"version":3,"file":"message-repository.js","names":["ThreadMessage","RunConfig","generateId","ThreadMessageLike","getContentAutoStatus","fromThreadMessageLike","ExportedMessageRepositoryItem","message","parentId","runConfig","ExportedMessageRepository","headId","messages","Array","fromArray","conv","map","m","content","idx","id","fromBranchableArray","items","options","undefined","Error","RepositoryParent","children","next","RepositoryMessage","prev","current","level","findHead","CachedValue","_value","T","func","constructor","value","dirty","MessageRepository","Map","head","root","updateLevels","newLevel","pending","length","pop","childId","childMessage","get","push","performOp","newParent","child","operation","parentOrRoot","newParentOrRoot","filter","fallbackId","at","fallback","_messages","canonicalHeadId","metadata","isOptimistic","getMessages","headMessage","addOrUpdateMessage","existingItem","newItem","set","getMessage","messageId","index","deleteMessage","replacementId","replacement","delete","getBranches","evictOffBranchOptimisticMessages","previousHead","currentHead","onHeadBranch","Set","add","stale","has","switchToBranch","prevOrRoot","resetHead","clear","descendantId","export","exportItems","import"],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getContentAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getContentAutoStatus(m.content, false, false),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(\n message,\n message.id,\n getContentAutoStatus(message.content, false, false),\n ),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n let current = message;\n while (current.next) current = current.next;\n return \"current\" in current ? current : null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n private func: () => T;\n\n constructor(func: () => T) {\n this.func = func;\n }\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n const pending = [{ message, level: newLevel }];\n\n while (pending.length > 0) {\n const current = pending.pop()!;\n current.message.level = current.level;\n\n for (const childId of current.message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n pending.push({ message: childMessage, level: current.level + 1 });\n }\n }\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.\n if (operation === \"relink\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n }\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n if (findHead(child) === this.head || newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n }\n\n child.prev = newParent;\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n get canonicalHeadId() {\n // Optimistic messages are ephemeral, so persisted callers need the nearest\n // non-optimistic ancestor rather than the raw head.\n let head = this.head;\n while (head?.current.metadata?.isOptimistic) {\n head = head.prev;\n }\n return head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved\n * away from. Since eviction runs on every head move, the only optimistic\n * messages in the repository live on the branch the head previously pointed\n * at — so we walk just that branch rather than the whole repository. Keeps a\n * client→server id swap from leaving a phantom sibling, and drops off-branch\n * placeholders.\n */\n private evictOffBranchOptimisticMessages(\n previousHead: RepositoryMessage | null,\n currentHead: RepositoryMessage | null,\n ) {\n if (!previousHead) return;\n\n const onHeadBranch = new Set<string>();\n for (let current = currentHead; current; current = current.prev) {\n onHeadBranch.add(current.current.id);\n }\n\n const stale: string[] = [];\n for (\n let current: RepositoryMessage | null = previousHead;\n current;\n current = current.prev\n ) {\n // Stop at the first node shared with the current head branch: every\n // ancestor above it is shared too, so nothing further can be off-branch.\n if (onHeadBranch.has(current.current.id)) break;\n if (current.current.metadata?.isOptimistic) {\n stale.push(current.current.id);\n }\n }\n\n for (const id of stale) {\n // A prior deletion may have already removed this node.\n if (this.messages.has(id)) this.deleteMessage(id);\n }\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n const prevOrRoot = message.prev ?? this.root;\n prevOrRoot.next = message;\n\n this.head = findHead(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n\n if (message.children.length > 0) {\n const pending = [...message.children];\n while (pending.length > 0) {\n const childId = pending.pop()!;\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n for (const descendantId of childMessage.children) {\n pending.push(descendantId);\n }\n this.messages.delete(childId);\n }\n }\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n if (current.prev) {\n current.prev.next = current;\n } else {\n this.root.next = current;\n }\n }\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // Optimistic messages are ephemeral and never persisted. A persisted child\n // of an optimistic node is re-parented onto its nearest persisted ancestor\n // so the exported tree never references a skipped id.\n for (const [, message] of this.messages) {\n if (message.current.metadata?.isOptimistic) continue;\n let prev = message.prev;\n while (prev && prev.current.metadata?.isOptimistic) {\n prev = prev.prev;\n }\n exportItems.push({\n message: message.current,\n parentId: prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.canonicalHeadId,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"message-repository.js","names":["ThreadMessage","RunConfig","generateId","ThreadMessageLike","getContentAutoStatus","fromThreadMessageLike","ExportedMessageRepositoryItem","message","parentId","runConfig","ExportedMessageRepository","headId","messages","Array","fromArray","conv","map","m","content","idx","id","fromBranchableArray","items","options","undefined","Error","RepositoryParent","children","next","RepositoryMessage","prev","current","level","findHead","CachedValue","_value","T","func","constructor","value","dirty","MessageRepository","Map","head","root","updateLevels","newLevel","pending","length","pop","childId","childMessage","get","push","selectPathTo","performOp","newParent","child","operation","parentOrRoot","newParentOrRoot","filter","fallbackId","at","fallback","_messages","canonicalHeadId","metadata","isOptimistic","getMessages","headMessage","addOrUpdateMessage","existingItem","newItem","set","getMessage","messageId","index","deleteMessage","replacementId","replacement","delete","getBranches","evictOffBranchOptimisticMessages","previousHead","currentHead","onHeadBranch","Set","add","stale","has","switchToBranch","resetHead","clear","descendantId","export","exportItems","reverse","i","import"],"sources":["../../../src/runtime/utils/message-repository.ts"],"sourcesContent":["import type { ThreadMessage } from \"../../types/message\";\nimport type { RunConfig } from \"../../types/message\";\nimport { generateId } from \"../../utils/id\";\nimport type { ThreadMessageLike } from \"./thread-message-like\";\nimport { getContentAutoStatus } from \"./auto-status\";\nimport { fromThreadMessageLike } from \"./thread-message-like\";\n\nexport type ExportedMessageRepositoryItem = {\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n};\n\nexport type ExportedMessageRepository = {\n headId?: string | null;\n messages: Array<{\n message: ThreadMessage;\n parentId: string | null;\n runConfig?: RunConfig;\n }>;\n};\n\nexport const ExportedMessageRepository = {\n fromArray: (\n messages: readonly ThreadMessageLike[],\n ): ExportedMessageRepository => {\n const conv = messages.map((m) =>\n fromThreadMessageLike(\n m,\n generateId(),\n getContentAutoStatus(m.content, false, false),\n ),\n );\n\n return {\n messages: conv.map((m, idx) => ({\n parentId: idx > 0 ? conv[idx - 1]!.id : null,\n message: m,\n })),\n };\n },\n\n fromBranchableArray: (\n items: readonly {\n message: ThreadMessageLike;\n parentId: string | null;\n }[],\n options?: { headId?: string | null },\n ): ExportedMessageRepository => {\n return {\n ...(options?.headId !== undefined\n ? { headId: options.headId }\n : undefined),\n messages: items.map(({ message, parentId }) => {\n if (!message.id) {\n throw new Error(\n \"ExportedMessageRepository.fromBranchableArray: Each message must have an 'id' field set.\",\n );\n }\n return {\n parentId,\n message: fromThreadMessageLike(\n message,\n message.id,\n getContentAutoStatus(message.content, false, false),\n ),\n };\n }),\n };\n },\n};\n\ntype RepositoryParent = {\n children: string[];\n next: RepositoryMessage | null;\n};\n\ntype RepositoryMessage = RepositoryParent & {\n prev: RepositoryMessage | null;\n current: ThreadMessage;\n level: number;\n};\n\nconst findHead = (\n message: RepositoryMessage | RepositoryParent,\n): RepositoryMessage | null => {\n let current = message;\n while (current.next) current = current.next;\n return \"current\" in current ? current : null;\n};\n\nclass CachedValue<T> {\n private _value: T | null = null;\n\n private func: () => T;\n\n constructor(func: () => T) {\n this.func = func;\n }\n\n get value() {\n if (this._value === null) {\n this._value = this.func();\n }\n return this._value;\n }\n\n dirty() {\n this._value = null;\n }\n}\n\nexport class MessageRepository {\n private messages = new Map<string, RepositoryMessage>();\n private head: RepositoryMessage | null = null;\n private root: RepositoryParent = {\n children: [],\n next: null,\n };\n\n private updateLevels(message: RepositoryMessage, newLevel: number) {\n const pending = [{ message, level: newLevel }];\n\n while (pending.length > 0) {\n const current = pending.pop()!;\n current.message.level = current.level;\n\n for (const childId of current.message.children) {\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n pending.push({ message: childMessage, level: current.level + 1 });\n }\n }\n }\n }\n\n private selectPathTo(message: RepositoryMessage) {\n for (\n let current: RepositoryMessage | null = message;\n current;\n current = current.prev\n ) {\n (current.prev ?? this.root).next = current;\n }\n }\n\n private performOp(\n newParent: RepositoryMessage | null,\n child: RepositoryMessage,\n operation: \"cut\" | \"link\" | \"relink\",\n ) {\n const parentOrRoot = child.prev ?? this.root;\n const newParentOrRoot = newParent ?? this.root;\n\n if (operation === \"relink\" && parentOrRoot === newParentOrRoot) return;\n\n // `link` receives a fresh ID from `addOrUpdateMessage`; only `relink` can introduce a cycle.\n if (operation === \"relink\") {\n for (\n let current: RepositoryMessage | null = newParent;\n current;\n current = current.prev\n ) {\n if (current.current.id === child.current.id) {\n throw new Error(\n \"MessageRepository(performOp/relink): A message with the same id already exists in the parent tree. This error occurs if the same message id is found multiple times. This is likely an internal bug in assistant-ui.\",\n );\n }\n }\n }\n\n if (operation !== \"link\") {\n parentOrRoot.children = parentOrRoot.children.filter(\n (m) => m !== child.current.id,\n );\n\n if (parentOrRoot.next === child) {\n const fallbackId = parentOrRoot.children.at(-1);\n const fallback = fallbackId ? this.messages.get(fallbackId) : null;\n if (fallback === undefined) {\n throw new Error(\n \"MessageRepository(performOp/cut): Fallback sibling message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n parentOrRoot.next = fallback;\n }\n }\n\n if (operation !== \"cut\") {\n newParentOrRoot.children = [\n ...newParentOrRoot.children,\n child.current.id,\n ];\n\n child.prev = newParent;\n\n if (findHead(child) === this.head) {\n this.selectPathTo(child);\n } else if (newParentOrRoot.next === null) {\n newParentOrRoot.next = child;\n if (this.head === newParentOrRoot) {\n this.head = findHead(child);\n }\n }\n\n const newLevel = newParent ? newParent.level + 1 : 0;\n this.updateLevels(child, newLevel);\n }\n }\n\n private _messages = new CachedValue<readonly ThreadMessage[]>(() => {\n const messages = new Array<ThreadMessage>((this.head?.level ?? -1) + 1);\n for (let current = this.head; current; current = current.prev) {\n messages[current.level] = current.current;\n }\n return messages;\n });\n\n get headId() {\n return this.head?.current.id ?? null;\n }\n\n get canonicalHeadId() {\n // Optimistic messages are ephemeral, so persisted callers need the nearest\n // non-optimistic ancestor rather than the raw head.\n let head = this.head;\n while (head?.current.metadata?.isOptimistic) {\n head = head.prev;\n }\n return head?.current.id ?? null;\n }\n\n getMessages(headId?: string) {\n if (headId === undefined || headId === this.head?.current.id) {\n return this._messages.value;\n }\n\n const headMessage = this.messages.get(headId);\n if (!headMessage) {\n throw new Error(\n \"MessageRepository(getMessages): Head message not found. This is likely an internal bug in assistant-ui.\",\n );\n }\n\n const messages = new Array<ThreadMessage>(headMessage.level + 1);\n for (\n let current: RepositoryMessage | null = headMessage;\n current;\n current = current.prev\n ) {\n messages[current.level] = current.current;\n }\n return messages;\n }\n\n addOrUpdateMessage(parentId: string | null, message: ThreadMessage) {\n const existingItem = this.messages.get(message.id);\n const prev = parentId ? this.messages.get(parentId) : null;\n if (prev === undefined)\n throw new Error(\n \"MessageRepository(addOrUpdateMessage): Parent message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n if (existingItem) {\n existingItem.current = message;\n this.performOp(prev, existingItem, \"relink\");\n this._messages.dirty();\n return;\n }\n\n const newItem: RepositoryMessage = {\n prev,\n current: message,\n next: null,\n children: [],\n level: prev ? prev.level + 1 : 0,\n };\n\n this.messages.set(message.id, newItem);\n this.performOp(prev, newItem, \"link\");\n\n if (this.head === prev) {\n this.head = newItem;\n }\n\n this._messages.dirty();\n }\n\n getMessage(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(updateMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n return {\n parentId: message.prev?.current.id ?? null,\n message: message.current,\n index: message.level,\n };\n }\n\n deleteMessage(messageId: string, replacementId?: string | null | undefined) {\n const message = this.messages.get(messageId);\n\n if (!message)\n throw new Error(\n \"MessageRepository(deleteMessage): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const replacement =\n replacementId === undefined\n ? message.prev\n : replacementId === null\n ? null\n : this.messages.get(replacementId);\n if (replacement === undefined)\n throw new Error(\n \"MessageRepository(deleteMessage): Replacement not found. This is likely an internal bug in assistant-ui.\",\n );\n\n for (const child of message.children) {\n const childMessage = this.messages.get(child);\n if (!childMessage)\n throw new Error(\n \"MessageRepository(deleteMessage): Child message not found. This is likely an internal bug in assistant-ui.\",\n );\n this.performOp(replacement, childMessage, \"relink\");\n }\n\n this.performOp(null, message, \"cut\");\n this.messages.delete(messageId);\n\n if (this.head === message) {\n this.head = findHead(replacement ?? this.root);\n }\n\n this._messages.dirty();\n }\n\n getBranches(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(getBranches): Message not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const { children } = message.prev ?? this.root;\n return children;\n }\n\n /**\n * Evicts optimistic messages (`metadata.isOptimistic`) the head just moved\n * away from. Since eviction runs on every head move, the only optimistic\n * messages in the repository live on the branch the head previously pointed\n * at — so we walk just that branch rather than the whole repository. Keeps a\n * client→server id swap from leaving a phantom sibling, and drops off-branch\n * placeholders.\n */\n private evictOffBranchOptimisticMessages(\n previousHead: RepositoryMessage | null,\n currentHead: RepositoryMessage | null,\n ) {\n if (!previousHead) return;\n\n const onHeadBranch = new Set<string>();\n for (let current = currentHead; current; current = current.prev) {\n onHeadBranch.add(current.current.id);\n }\n\n const stale: string[] = [];\n for (\n let current: RepositoryMessage | null = previousHead;\n current;\n current = current.prev\n ) {\n // Stop at the first node shared with the current head branch: every\n // ancestor above it is shared too, so nothing further can be off-branch.\n if (onHeadBranch.has(current.current.id)) break;\n if (current.current.metadata?.isOptimistic) {\n stale.push(current.current.id);\n }\n }\n\n for (const id of stale) {\n // A prior deletion may have already removed this node.\n if (this.messages.has(id)) this.deleteMessage(id);\n }\n }\n\n switchToBranch(messageId: string) {\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(switchToBranch): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n this.selectPathTo(message);\n\n this.head = findHead(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n resetHead(messageId: string | null) {\n if (messageId === null) {\n this.clear();\n return;\n }\n\n const message = this.messages.get(messageId);\n if (!message)\n throw new Error(\n \"MessageRepository(resetHead): Branch not found. This is likely an internal bug in assistant-ui.\",\n );\n\n const previousHead = this.head;\n\n if (message.children.length > 0) {\n const pending = [...message.children];\n while (pending.length > 0) {\n const childId = pending.pop()!;\n const childMessage = this.messages.get(childId);\n if (childMessage) {\n for (const descendantId of childMessage.children) {\n pending.push(descendantId);\n }\n this.messages.delete(childId);\n }\n }\n\n message.children = [];\n message.next = null;\n }\n\n this.head = message;\n this.selectPathTo(message);\n\n this.evictOffBranchOptimisticMessages(previousHead, this.head);\n\n this._messages.dirty();\n }\n\n clear(): void {\n this.messages.clear();\n this.head = null;\n this.root = {\n children: [],\n next: null,\n };\n this._messages.dirty();\n }\n\n export(): ExportedMessageRepository {\n const exportItems: ExportedMessageRepository[\"messages\"] = [];\n\n // Optimistic messages are ephemeral and never persisted. A persisted child\n // of an optimistic node is re-parented onto its nearest persisted ancestor\n // so the exported tree never references a skipped id.\n // Import and external-state conversion require parents before children, so\n // the tree is walked in pre-order rather than iterated in insertion order.\n const pending = [...this.root.children].reverse();\n while (pending.length > 0) {\n const message = this.messages.get(pending.pop()!);\n if (!message) continue;\n for (let i = message.children.length - 1; i >= 0; i--) {\n pending.push(message.children[i]!);\n }\n if (message.current.metadata?.isOptimistic) continue;\n let prev = message.prev;\n while (prev && prev.current.metadata?.isOptimistic) {\n prev = prev.prev;\n }\n exportItems.push({\n message: message.current,\n parentId: prev?.current.id ?? null,\n });\n }\n\n return {\n headId: this.canonicalHeadId,\n messages: exportItems,\n };\n }\n\n import({ headId, messages }: ExportedMessageRepository) {\n for (const { message, parentId } of messages) {\n this.addOrUpdateMessage(parentId, message);\n }\n\n this.resetHead(headId ?? messages.at(-1)?.message.id ?? null);\n }\n}\n"],"mappings":"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"}
@@ -61,7 +61,7 @@ const fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
61
61
  const { parentId, messages, ...basePart } = part;
62
62
  const commonProps = {
63
63
  ...basePart,
64
- toolCallId: part.toolCallId ?? `tool-${generateId()}`,
64
+ toolCallId: part.toolCallId || `tool-${generateId()}`,
65
65
  ...parentId !== void 0 && { parentId },
66
66
  ...messages !== void 0 && { messages }
67
67
  };
@@ -1 +1 @@
1
- {"version":3,"file":"thread-message-like.js","names":["parsePartialJsonObject","generateId","parseDataUrl","ReasoningMessagePart","SourceMessagePart","ThreadStep","MessageStatus","ImageMessagePart","ThreadMessage","ThreadAssistantMessagePart","ThreadAssistantMessage","ThreadUserMessagePart","ThreadUserMessage","ThreadSystemMessage","FileMessagePart","DataMessagePart","GenerativeUIMessagePart","Unstable_AudioMessagePart","CompleteAttachment","MessageTiming","PartProviderMetadata","TextMessagePart","ToolCallTiming","ToolCallMessagePart","ToolCallMessagePartMcpMetadata","ReadonlyJSONObject","ReadonlyJSONValue","DataPrefixedPart","type","data","ThreadMessageLike","role","content","toolCallId","toolName","args","argsText","artifact","result","isError","parentId","messages","interrupt","payload","timing","mcp","providerMetadata","approval","NonNullable","id","createdAt","Date","status","attachments","Omit","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","isOptimistic","custom","Record","convertDataPrefixedPart","startsWith","undefined","name","substring","fromThreadMessageLike","like","fallbackId","fallbackStatus","common","const","text","sanitizeImageContent","image","rest","mimeType","test","console","warn","length","Error","map","part","trim","unstable_summary","basePart","commonProps","JSON","stringify","converted","filter","c","att","unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport { parseDataUrl } from \"../../utils/data-url\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type {\n MessageTiming,\n PartProviderMetadata,\n TextMessagePart,\n ToolCallTiming,\n ToolCallMessagePart,\n ToolCallMessagePartMcpMetadata,\n} from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly timing?: ToolCallTiming;\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n readonly providerMetadata?: PartProviderMetadata;\n readonly approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly isOptimistic?: boolean | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\n/**\n * @deprecated This API is experimental and may change without notice.\n */\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n if (typeof image !== \"string\") return null;\n if (parseDataUrl(image)?.mimeType.startsWith(\"image/\")) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/i.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n if (!part.text?.trim()) return null;\n return part;\n\n case \"reasoning\":\n if (!part.text?.trim() && !part.unstable_summary?.trim())\n return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId ?? `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"thread-message-like.js","names":["parsePartialJsonObject","generateId","parseDataUrl","ReasoningMessagePart","SourceMessagePart","ThreadStep","MessageStatus","ImageMessagePart","ThreadMessage","ThreadAssistantMessagePart","ThreadAssistantMessage","ThreadUserMessagePart","ThreadUserMessage","ThreadSystemMessage","FileMessagePart","DataMessagePart","GenerativeUIMessagePart","Unstable_AudioMessagePart","CompleteAttachment","MessageTiming","PartProviderMetadata","TextMessagePart","ToolCallTiming","ToolCallMessagePart","ToolCallMessagePartMcpMetadata","ReadonlyJSONObject","ReadonlyJSONValue","DataPrefixedPart","type","data","ThreadMessageLike","role","content","toolCallId","toolName","args","argsText","artifact","result","isError","parentId","messages","interrupt","payload","timing","mcp","providerMetadata","approval","NonNullable","id","createdAt","Date","status","attachments","Omit","metadata","unstable_state","unstable_annotations","unstable_data","steps","submittedFeedback","isOptimistic","custom","Record","convertDataPrefixedPart","startsWith","undefined","name","substring","fromThreadMessageLike","like","fallbackId","fallbackStatus","common","const","text","sanitizeImageContent","image","rest","mimeType","test","console","warn","length","Error","map","part","trim","unstable_summary","basePart","commonProps","JSON","stringify","converted","filter","c","att","unsupportedRole"],"sources":["../../../src/runtime/utils/thread-message-like.ts"],"sourcesContent":["import { parsePartialJsonObject } from \"assistant-stream/utils\";\nimport { generateId } from \"../../utils/id\";\nimport { parseDataUrl } from \"../../utils/data-url\";\nimport type {\n ReasoningMessagePart,\n SourceMessagePart,\n ThreadStep,\n MessageStatus,\n ImageMessagePart,\n ThreadMessage,\n ThreadAssistantMessagePart,\n ThreadAssistantMessage,\n ThreadUserMessagePart,\n ThreadUserMessage,\n ThreadSystemMessage,\n FileMessagePart,\n DataMessagePart,\n GenerativeUIMessagePart,\n Unstable_AudioMessagePart,\n} from \"../../types/message\";\nimport type { CompleteAttachment } from \"../../types/attachment\";\nimport type {\n MessageTiming,\n PartProviderMetadata,\n TextMessagePart,\n ToolCallTiming,\n ToolCallMessagePart,\n ToolCallMessagePartMcpMetadata,\n} from \"../../types/message\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"assistant-stream/utils\";\n\ntype DataPrefixedPart = {\n readonly type: `data-${string}`;\n readonly data: any;\n};\n\nexport type ThreadMessageLike = {\n readonly role: \"assistant\" | \"user\" | \"system\";\n readonly content:\n | string\n | readonly (\n | TextMessagePart\n | ReasoningMessagePart\n | SourceMessagePart\n | ImageMessagePart\n | FileMessagePart\n | DataMessagePart\n | GenerativeUIMessagePart\n | Unstable_AudioMessagePart\n | DataPrefixedPart\n | {\n readonly type: \"tool-call\";\n readonly toolCallId?: string;\n readonly toolName: string;\n readonly args?: ReadonlyJSONObject;\n readonly argsText?: string;\n readonly artifact?: any;\n readonly result?: any | undefined;\n readonly isError?: boolean | undefined;\n readonly parentId?: string | undefined;\n readonly messages?: readonly ThreadMessage[] | undefined;\n readonly interrupt?: { type: \"human\"; payload: unknown };\n readonly timing?: ToolCallTiming;\n readonly mcp?: ToolCallMessagePartMcpMetadata;\n readonly providerMetadata?: PartProviderMetadata;\n readonly approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n }\n )[];\n readonly id?: string | undefined;\n readonly createdAt?: Date | undefined;\n readonly status?: MessageStatus | undefined;\n readonly attachments?:\n | readonly (Omit<CompleteAttachment, \"content\"> & {\n readonly content: readonly (ThreadUserMessagePart | DataPrefixedPart)[];\n })[]\n | undefined;\n readonly metadata?:\n | {\n readonly unstable_state?: ReadonlyJSONValue;\n readonly unstable_annotations?:\n | readonly ReadonlyJSONValue[]\n | undefined;\n readonly unstable_data?: readonly ReadonlyJSONValue[] | undefined;\n readonly steps?: readonly ThreadStep[] | undefined;\n readonly timing?: MessageTiming | undefined;\n readonly submittedFeedback?: { readonly type: \"positive\" | \"negative\" };\n readonly isOptimistic?: boolean | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n }\n | undefined;\n};\n\nconst convertDataPrefixedPart = (\n type: string,\n data: unknown,\n): DataMessagePart | undefined => {\n if (!type.startsWith(\"data-\")) return undefined;\n return { type: \"data\", name: type.substring(5), data };\n};\n\n/**\n * @deprecated This API is experimental and may change without notice.\n */\nexport const fromThreadMessageLike = (\n like: ThreadMessageLike,\n fallbackId: string,\n fallbackStatus: MessageStatus,\n): ThreadMessage => {\n const { role, id, createdAt, attachments, status, metadata } = like;\n const common = {\n id: id ?? fallbackId,\n createdAt: createdAt ?? new Date(),\n };\n\n const content =\n typeof like.content === \"string\"\n ? [{ type: \"text\" as const, text: like.content }]\n : like.content;\n\n const sanitizeImageContent = ({\n image,\n ...rest\n }: ImageMessagePart): ImageMessagePart | null => {\n if (typeof image !== \"string\") return null;\n if (parseDataUrl(image)?.mimeType.startsWith(\"image/\")) {\n return { ...rest, image };\n }\n if (/^(https:\\/\\/|blob:)/i.test(image)) {\n return { ...rest, image };\n }\n console.warn(`Invalid image data format detected`);\n return null;\n };\n\n if (role !== \"user\" && attachments?.length)\n throw new Error(\"attachments are only supported for user messages\");\n\n if (role !== \"assistant\" && status)\n throw new Error(\"status is only supported for assistant messages\");\n\n if (role !== \"assistant\" && metadata?.steps)\n throw new Error(\"metadata.steps is only supported for assistant messages\");\n\n switch (role) {\n case \"assistant\":\n return {\n ...common,\n role,\n content: content\n .map((part): ThreadAssistantMessagePart | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n if (!part.text?.trim()) return null;\n return part;\n\n case \"reasoning\":\n if (!part.text?.trim() && !part.unstable_summary?.trim())\n return null;\n return part;\n\n case \"file\":\n case \"source\":\n return part;\n\n case \"image\":\n return sanitizeImageContent(part);\n\n case \"data\":\n return part;\n\n case \"generative-ui\":\n return part;\n\n case \"tool-call\": {\n const { parentId, messages, ...basePart } = part;\n const commonProps = {\n ...basePart,\n toolCallId: part.toolCallId || `tool-${generateId()}`,\n ...(parentId !== undefined && { parentId }),\n ...(messages !== undefined && { messages }),\n };\n\n if (part.args) {\n return {\n ...commonProps,\n args: part.args,\n argsText: part.argsText ?? JSON.stringify(part.args),\n };\n }\n return {\n ...commonProps,\n args: parsePartialJsonObject(part.argsText ?? \"\") ?? {},\n argsText: part.argsText ?? \"\",\n };\n }\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(\n `Unsupported assistant message part type: ${type}`,\n );\n }\n }\n })\n .filter((c) => !!c),\n status: status ?? fallbackStatus,\n metadata: {\n unstable_state: metadata?.unstable_state ?? null,\n unstable_annotations: metadata?.unstable_annotations ?? [],\n unstable_data: metadata?.unstable_data ?? [],\n custom: metadata?.custom ?? {},\n steps: metadata?.steps ?? [],\n ...(metadata?.timing && { timing: metadata.timing }),\n ...(metadata?.submittedFeedback && {\n submittedFeedback: metadata.submittedFeedback,\n }),\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadAssistantMessage;\n\n case \"user\":\n return {\n ...common,\n role,\n content: content.map((part): ThreadUserMessagePart => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"image\":\n case \"audio\":\n case \"file\":\n case \"data\":\n return part;\n\n default: {\n const converted = convertDataPrefixedPart(\n type,\n (part as DataPrefixedPart).data,\n );\n if (converted) return converted;\n throw new Error(`Unsupported user message part type: ${type}`);\n }\n }\n }),\n attachments: (attachments ?? []).map((att) => ({\n ...att,\n content: att.content.map((part): ThreadUserMessagePart => {\n const converted = convertDataPrefixedPart(\n part.type,\n (part as DataPrefixedPart).data,\n );\n return converted ?? (part as ThreadUserMessagePart);\n }),\n })),\n metadata: {\n custom: metadata?.custom ?? {},\n ...(metadata?.isOptimistic && { isOptimistic: true }),\n },\n } satisfies ThreadUserMessage;\n\n case \"system\":\n if (content.length !== 1 || content[0]!.type !== \"text\")\n throw new Error(\n \"System messages must have exactly one text message part.\",\n );\n\n return {\n ...common,\n role,\n content: content as [TextMessagePart],\n metadata: {\n custom: metadata?.custom ?? {},\n },\n } satisfies ThreadSystemMessage;\n\n default: {\n const unsupportedRole: never = role;\n throw new Error(`Unknown message role: ${unsupportedRole}`);\n }\n }\n};\n"],"mappings":";;;;AA+FA,MAAMgE,2BACJpC,MACAC,SACgC;CAChC,IAAI,CAACD,KAAKqC,WAAW,OAAO,GAAG,OAAOC,KAAAA;CACtC,OAAO;EAAEtC,MAAM;EAAQuC,MAAMvC,KAAKwC,UAAU,CAAC;EAAGvC;CAAK;AACvD;;;;AAKA,MAAawC,yBACXC,MACAC,YACAC,mBACkB;CAClB,MAAM,EAAEzC,MAAMkB,IAAIC,WAAWG,aAAaD,QAAQG,aAAae;CAC/D,MAAMG,SAAS;EACbxB,IAAIA,MAAMsB;EACVrB,WAAWA,6BAAa,IAAIC,KAAK;CACnC;CAEA,MAAMnB,UACJ,OAAOsC,KAAKtC,YAAY,WACpB,CAAC;EAAEJ,MAAM;EAAiB+C,MAAML,KAAKtC;CAAQ,CAAC,IAC9CsC,KAAKtC;CAEX,MAAM4C,wBAAwB,EAC5BC,OACA,GAAGC,WAC4C;EAC/C,IAAI,OAAOD,UAAU,UAAU,OAAO;EACtC,IAAI3E,aAAa2E,KAAK,CAAC,EAAEE,SAASd,WAAW,QAAQ,GACnD,OAAO;GAAE,GAAGa;GAAMD;EAAM;EAE1B,IAAI,uBAAuBG,KAAKH,KAAK,GACnC,OAAO;GAAE,GAAGC;GAAMD;EAAM;EAE1BI,QAAQC,KAAK,oCAAoC;EACjD,OAAO;CACT;CAEA,IAAInD,SAAS,UAAUsB,aAAa8B,QAClC,MAAM,IAAIC,MAAM,kDAAkD;CAEpE,IAAIrD,SAAS,eAAeqB,QAC1B,MAAM,IAAIgC,MAAM,iDAAiD;CAEnE,IAAIrD,SAAS,eAAewB,UAAUI,OACpC,MAAM,IAAIyB,MAAM,yDAAyD;CAE3E,QAAQrD,MAAR;EACE,KAAK,aACH,OAAO;GACL,GAAG0C;GACH1C;GACAC,SAASA,QACNqD,KAAKC,SAA4C;IAChD,MAAM1D,OAAO0D,KAAK1D;IAClB,QAAQA,MAAR;KACE,KAAK;MACH,IAAI,CAAC0D,KAAKX,MAAMY,KAAK,GAAG,OAAO;MAC/B,OAAOD;KAET,KAAK;MACH,IAAI,CAACA,KAAKX,MAAMY,KAAK,KAAK,CAACD,KAAKE,kBAAkBD,KAAK,GACrD,OAAO;MACT,OAAOD;KAET,KAAK;KACL,KAAK,UACH,OAAOA;KAET,KAAK,SACH,OAAOV,qBAAqBU,IAAI;KAElC,KAAK,QACH,OAAOA;KAET,KAAK,iBACH,OAAOA;KAET,KAAK,aAAa;MAChB,MAAM,EAAE9C,UAAUC,UAAU,GAAGgD,aAAaH;MAC5C,MAAMI,cAAc;OAClB,GAAGD;OACHxD,YAAYqD,KAAKrD,cAAc,QAAQhC,WAAW;OAClD,GAAIuC,aAAa0B,KAAAA,KAAa,EAAE1B,SAAS;OACzC,GAAIC,aAAayB,KAAAA,KAAa,EAAEzB,SAAS;MAC3C;MAEA,IAAI6C,KAAKnD,MACP,OAAO;OACL,GAAGuD;OACHvD,MAAMmD,KAAKnD;OACXC,UAAUkD,KAAKlD,YAAYuD,KAAKC,UAAUN,KAAKnD,IAAI;MACrD;MAEF,OAAO;OACL,GAAGuD;OACHvD,MAAMnC,uBAAuBsF,KAAKlD,YAAY,EAAE,KAAK,CAAC;OACtDA,UAAUkD,KAAKlD,YAAY;MAC7B;KACF;KAEA,SAAS;MACP,MAAMyD,YAAY7B,wBAChBpC,MACC0D,KAA0BzD,IAC7B;MACA,IAAIgE,WAAW,OAAOA;MACtB,MAAM,IAAIT,MACR,4CAA4CxD,MAC9C;KACF;IACF;GACF,CAAC,CAAC,CACDkE,QAAQC,MAAM,CAAC,CAACA,CAAC;GACpB3C,QAAQA,UAAUoB;GAClBjB,UAAU;IACRC,gBAAgBD,UAAUC,kBAAkB;IAC5CC,sBAAsBF,UAAUE,wBAAwB,CAAA;IACxDC,eAAeH,UAAUG,iBAAiB,CAAA;IAC1CI,QAAQP,UAAUO,UAAU,CAAC;IAC7BH,OAAOJ,UAAUI,SAAS,CAAA;IAC1B,GAAIJ,UAAUX,UAAU,EAAEA,QAAQW,SAASX,OAAO;IAClD,GAAIW,UAAUK,qBAAqB,EACjCA,mBAAmBL,SAASK,kBAC9B;IACA,GAAIL,UAAUM,gBAAgB,EAAEA,cAAc,KAAK;GACrD;EACF;EAEF,KAAK,QACH,OAAO;GACL,GAAGY;GACH1C;GACAC,SAASA,QAAQqD,KAAKC,SAAgC;IACpD,MAAM1D,OAAO0D,KAAK1D;IAClB,QAAQA,MAAR;KACE,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK;KACL,KAAK,QACH,OAAO0D;KAET,SAAS;MACP,MAAMO,YAAY7B,wBAChBpC,MACC0D,KAA0BzD,IAC7B;MACA,IAAIgE,WAAW,OAAOA;MACtB,MAAM,IAAIT,MAAM,uCAAuCxD,MAAM;KAC/D;IACF;GACF,CAAC;GACDyB,cAAcA,eAAe,CAAA,EAAA,CAAIgC,KAAKW,SAAS;IAC7C,GAAGA;IACHhE,SAASgE,IAAIhE,QAAQqD,KAAKC,SAAgC;KAKxD,OAJkBtB,wBAChBsB,KAAK1D,MACJ0D,KAA0BzD,IAEtBgE,KAAcP;IACvB,CAAC;GACH,EAAE;GACF/B,UAAU;IACRO,QAAQP,UAAUO,UAAU,CAAC;IAC7B,GAAIP,UAAUM,gBAAgB,EAAEA,cAAc,KAAK;GACrD;EACF;EAEF,KAAK;GACH,IAAI7B,QAAQmD,WAAW,KAAKnD,QAAQ,EAAE,CAAEJ,SAAS,QAC/C,MAAM,IAAIwD,MACR,0DACF;GAEF,OAAO;IACL,GAAGX;IACH1C;IACSC;IACTuB,UAAU,EACRO,QAAQP,UAAUO,UAAU,CAAC,EAC/B;GACF;EAEF,SAEE,MAAM,IAAIsB,MAAM,yBAAyBa,MAAiB;CAE9D;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-list-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"mappings":";;;;;KASY,mCAAmC;cAgBlC,2CACH,4BACG;UAEH;UACA;UACA;UACA;UAEA;MAEG;MAIA;MAIA;MAIA;MAIA,eAAW,SAAA,eAAA;EAIf,yBAAqB;UAIpB;MAEG;UAIH;EAGN,YAAA,SAAS,4CACT,eAAe;EAOV,4BAAwB;EAIxB;EAIA,YAAY,mBAAgB;EAI5B,sBACL,SAAS,gCACT;EAsFW,oBAAoB;EASpB,eACX,kBACA;IAAa;MACZ;EAUU,qBAAqB;EAUrB,OAAO,kBAAkB,mBAAmB;EAQ5C,aACX,kBACA,QAAQ,sCACP;EAUU,UAAU;EAIV,QAAQ,mBAAmB;EAQ3B,UAAU,mBAAmB;EAQ7B,OAAO,mBAAmB;EAQhC,WACL,mBACC;IAAU;IAAkB;;EAIxB"}
1
+ {"version":3,"file":"external-store-thread-list-runtime-core.d.ts","names":[],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"mappings":";;;;;KAUY,mCAAmC;cAkBlC,2CACH,4BACG;UAEH;UACA;UACA;UACA;UAEA;MAEG;MAIA;MAIA;MAIA;MAIA,eAAW,SAAA,eAAA;EAIf,yBAAqB;UAIpB;MAEG;UAIH;EAGN,YAAA,SAAS,4CACT,eAAe;EAOV,4BAAwB;EAIxB;EAIA,YAAY,mBAAgB;EAM5B,sBACL,SAAS,gCACT;EAsFW,oBAAoB;EASpB,eACX,kBACA;IAAa;MACZ;EAUU,qBAAqB;EAUrB,OAAO,kBAAkB,mBAAmB;EAQ5C,aACX,kBACA,QAAQ,sCACP;EAUU,UAAU;EAIV,QAAQ,mBAAmB;EAQ3B,UAAU,mBAAmB;EAQ7B,OAAO,mBAAmB;EAQhC,WACL,mBACC;IAAU;IAAkB;;EAIxB"}
@@ -1,3 +1,4 @@
1
+ import { nullProtoRecord } from "../../utils/record.js";
1
2
  import { BaseSubscribable } from "../../subscribable/subscribable.js";
2
3
  import { invalidateThreadRuntime } from "../../runtime/utils/thread-runtime-lifecycle.js";
3
4
  //#region src/runtimes/external-store/external-store-thread-list-runtime-core.ts
@@ -11,7 +12,7 @@ const DEFAULT_THREAD = Object.freeze({
11
12
  status: "regular"
12
13
  });
13
14
  const RESOLVED_PROMISE = Promise.resolve();
14
- const DEFAULT_THREAD_DATA = Object.freeze({ [DEFAULT_THREAD_ID]: DEFAULT_THREAD });
15
+ const DEFAULT_THREAD_DATA = Object.freeze(nullProtoRecord({ [DEFAULT_THREAD_ID]: DEFAULT_THREAD }));
15
16
  var ExternalStoreThreadListRuntimeCore = class extends BaseSubscribable {
16
17
  _mainThreadId = DEFAULT_THREAD_ID;
17
18
  _threads = DEFAULT_THREADS;
@@ -51,7 +52,7 @@ var ExternalStoreThreadListRuntimeCore = class extends BaseSubscribable {
51
52
  throw new Error("Method not implemented.");
52
53
  }
53
54
  getItemById(threadId) {
54
- return this._threadData[threadId];
55
+ return Object.hasOwn(this._threadData, threadId) ? this._threadData[threadId] : void 0;
55
56
  }
56
57
  __internal_setAdapter(adapter, initialLoad = false) {
57
58
  const previousAdapter = this.adapter;
@@ -62,22 +63,18 @@ var ExternalStoreThreadListRuntimeCore = class extends BaseSubscribable {
62
63
  const previousThreadId = previousAdapter.threadId ?? DEFAULT_THREAD_ID;
63
64
  const previousThreads = previousAdapter.threads ?? EMPTY_ARRAY;
64
65
  const previousArchivedThreads = previousAdapter.archivedThreads ?? EMPTY_ARRAY;
65
- if (!initialLoad && previousThreadId === newThreadId && previousThreads === newThreads && previousArchivedThreads === newArchivedThreads) return;
66
- if (previousThreads !== newThreads || previousArchivedThreads !== newArchivedThreads || previousThreadId !== newThreadId) this._threadData = {
67
- ...DEFAULT_THREAD_DATA,
68
- ...Object.fromEntries(adapter.threads?.map((t) => [t.id, {
69
- ...t,
70
- remoteId: t.remoteId,
71
- externalId: t.externalId,
72
- status: "regular"
73
- }]) ?? []),
74
- ...Object.fromEntries(adapter.archivedThreads?.map((t) => [t.id, {
75
- ...t,
76
- remoteId: t.remoteId,
77
- externalId: t.externalId,
78
- status: "archived"
79
- }]) ?? [])
80
- };
66
+ if (!initialLoad && (previousAdapter.isLoading ?? false) === (adapter.isLoading ?? false) && previousThreadId === newThreadId && previousThreads === newThreads && previousArchivedThreads === newArchivedThreads) return;
67
+ if (previousThreads !== newThreads || previousArchivedThreads !== newArchivedThreads || previousThreadId !== newThreadId) this._threadData = nullProtoRecord(DEFAULT_THREAD_DATA, Object.fromEntries(adapter.threads?.map((t) => [t.id, {
68
+ ...t,
69
+ remoteId: t.remoteId,
70
+ externalId: t.externalId,
71
+ status: "regular"
72
+ }]) ?? []), Object.fromEntries(adapter.archivedThreads?.map((t) => [t.id, {
73
+ ...t,
74
+ remoteId: t.remoteId,
75
+ externalId: t.externalId,
76
+ status: "archived"
77
+ }]) ?? []));
81
78
  if (previousThreads !== newThreads) this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;
82
79
  if (previousArchivedThreads !== newArchivedThreads) this._archivedThreads = this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;
83
80
  if (initialLoad || previousThreadId !== newThreadId) {
@@ -85,15 +82,12 @@ var ExternalStoreThreadListRuntimeCore = class extends BaseSubscribable {
85
82
  this._mainThreadId = newThreadId;
86
83
  this._mainThread = this.threadFactory();
87
84
  }
88
- if (!this._threadData[this._mainThreadId]) this._threadData = {
89
- ...this._threadData,
90
- [this._mainThreadId]: {
91
- id: this._mainThreadId,
92
- remoteId: void 0,
93
- externalId: void 0,
94
- status: "regular"
95
- }
96
- };
85
+ if (!Object.hasOwn(this._threadData, this._mainThreadId)) this._threadData = nullProtoRecord(this._threadData, { [this._mainThreadId]: {
86
+ id: this._mainThreadId,
87
+ remoteId: void 0,
88
+ externalId: void 0,
89
+ status: "regular"
90
+ } });
97
91
  this._notifySubscribers();
98
92
  }
99
93
  async reloadMainThread() {
@@ -1 +1 @@
1
- {"version":3,"file":"external-store-thread-list-runtime-core.js","names":["ExternalStoreThreadRuntimeCore","ThreadListItemCoreState","ThreadListRuntimeCore","ExternalStoreThreadListAdapter","invalidateThreadRuntime","BaseSubscribable","ExternalStoreThreadFactory","EMPTY_ARRAY","Object","freeze","DEFAULT_THREAD_ID","DEFAULT_THREADS","DEFAULT_THREAD","id","remoteId","undefined","externalId","status","RESOLVED_PROMISE","Promise","resolve","DEFAULT_THREAD_DATA","ExternalStoreThreadListRuntimeCore","_mainThreadId","_threads","_archivedThreads","_threadData","Readonly","Record","adapter","isLoading","newThreadId","threadIds","archivedThreadIds","threadItems","getLoadThreadsPromise","_mainThread","mainThreadId","threadFactory","constructor","__internal_setAdapter","getMainThreadRuntimeCore","getThreadRuntimeCore","Error","getItemById","threadId","initialLoad","previousAdapter","newThreads","threads","newArchivedThreads","archivedThreads","previousThreadId","previousThreads","previousArchivedThreads","fromEntries","map","t","_notifySubscribers","reloadMainThread","unstable_refetchThread","switchToThread","_options","unarchive","onSwitchToThread","switchToNewThread","onSwitchToNewThread","rename","newTitle","onRename","updateCustom","custom","onUpdateCustom","detach","archive","onArchive","onUnarchive","delete","onDelete","initialize","generateTitle"],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"sourcesContent":["import type { ExternalStoreThreadRuntimeCore } from \"./external-store-thread-runtime-core\";\nimport type {\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"../../runtime/interfaces/thread-list-runtime-core\";\nimport type { ExternalStoreThreadListAdapter } from \"./external-store-adapter\";\nimport { invalidateThreadRuntime } from \"../../runtime/utils/thread-runtime-lifecycle\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\n\nexport type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;\n\nconst EMPTY_ARRAY = Object.freeze([]);\nconst DEFAULT_THREAD_ID = \"DEFAULT_THREAD_ID\";\nconst DEFAULT_THREADS = Object.freeze([DEFAULT_THREAD_ID]);\nconst DEFAULT_THREAD = Object.freeze({\n id: DEFAULT_THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n});\nconst RESOLVED_PROMISE = Promise.resolve();\nconst DEFAULT_THREAD_DATA = Object.freeze({\n [DEFAULT_THREAD_ID]: DEFAULT_THREAD,\n});\n\nexport class ExternalStoreThreadListRuntimeCore\n extends BaseSubscribable\n implements ThreadListRuntimeCore\n{\n private _mainThreadId: string = DEFAULT_THREAD_ID;\n private _threads: readonly string[] = DEFAULT_THREADS;\n private _archivedThreads: readonly string[] = EMPTY_ARRAY;\n private _threadData: Readonly<Record<string, ThreadListItemCoreState>> =\n DEFAULT_THREAD_DATA;\n private adapter: ExternalStoreThreadListAdapter = {};\n\n public get isLoading() {\n return this.adapter.isLoading ?? false;\n }\n\n public get newThreadId() {\n return undefined;\n }\n\n public get threadIds() {\n return this._threads;\n }\n\n public get archivedThreadIds() {\n return this._archivedThreads;\n }\n\n public get threadItems() {\n return this._threadData;\n }\n\n public getLoadThreadsPromise() {\n return RESOLVED_PROMISE;\n }\n\n private _mainThread!: ExternalStoreThreadRuntimeCore;\n\n public get mainThreadId() {\n return this._mainThreadId;\n }\n\n private threadFactory: ExternalStoreThreadFactory;\n\n constructor(\n adapter: ExternalStoreThreadListAdapter = {},\n threadFactory: ExternalStoreThreadFactory,\n ) {\n super();\n this.threadFactory = threadFactory;\n this.__internal_setAdapter(adapter, true);\n }\n\n public getMainThreadRuntimeCore() {\n return this._mainThread;\n }\n\n public getThreadRuntimeCore(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n public getItemById(threadId: string) {\n return this._threadData[threadId];\n }\n\n public __internal_setAdapter(\n adapter: ExternalStoreThreadListAdapter,\n initialLoad = false,\n ) {\n const previousAdapter = this.adapter;\n this.adapter = adapter;\n\n const newThreadId = adapter.threadId ?? DEFAULT_THREAD_ID;\n const newThreads = adapter.threads ?? EMPTY_ARRAY;\n const newArchivedThreads = adapter.archivedThreads ?? EMPTY_ARRAY;\n\n const previousThreadId = previousAdapter.threadId ?? DEFAULT_THREAD_ID;\n const previousThreads = previousAdapter.threads ?? EMPTY_ARRAY;\n const previousArchivedThreads =\n previousAdapter.archivedThreads ?? EMPTY_ARRAY;\n\n if (\n !initialLoad &&\n previousThreadId === newThreadId &&\n previousThreads === newThreads &&\n previousArchivedThreads === newArchivedThreads\n ) {\n return;\n }\n\n if (\n previousThreads !== newThreads ||\n previousArchivedThreads !== newArchivedThreads ||\n previousThreadId !== newThreadId\n ) {\n this._threadData = {\n ...DEFAULT_THREAD_DATA,\n ...Object.fromEntries(\n adapter.threads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"regular\",\n },\n ]) ?? [],\n ),\n ...Object.fromEntries(\n adapter.archivedThreads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"archived\",\n },\n ]) ?? [],\n ),\n };\n }\n\n if (previousThreads !== newThreads) {\n this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n if (previousArchivedThreads !== newArchivedThreads) {\n this._archivedThreads =\n this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n // `initialLoad ||`: `_mainThread!` must be assigned on construction.\n if (initialLoad || previousThreadId !== newThreadId) {\n if (!initialLoad) invalidateThreadRuntime(this._mainThread);\n this._mainThreadId = newThreadId;\n this._mainThread = this.threadFactory();\n }\n\n if (!this._threadData[this._mainThreadId]) {\n this._threadData = {\n ...this._threadData,\n [this._mainThreadId]: {\n id: this._mainThreadId,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n },\n };\n }\n\n this._notifySubscribers();\n }\n\n public async reloadMainThread(): Promise<void> {\n // There is no runtime hook to remount here, so the capability is the only\n // path and an adapter without it has nothing to refetch with.\n if (!this._mainThread.unstable_refetchThread) return;\n // No unsent-thread guard: every entry here is regular or archived, so the\n // \"new\" status the remote thread list has to exclude cannot occur.\n await this._mainThread.unstable_refetchThread();\n }\n\n public async switchToThread(\n threadId: string,\n _options?: { unarchive?: boolean },\n ): Promise<void> {\n if (this._mainThreadId === threadId) return;\n const onSwitchToThread = this.adapter.onSwitchToThread;\n if (!onSwitchToThread)\n throw new Error(\n \"External store adapter does not support switching to thread\",\n );\n await onSwitchToThread(threadId);\n }\n\n public async switchToNewThread(): Promise<void> {\n const onSwitchToNewThread = this.adapter.onSwitchToNewThread;\n if (!onSwitchToNewThread)\n throw new Error(\n \"External store adapter does not support switching to new thread\",\n );\n\n await onSwitchToNewThread();\n }\n\n public async rename(threadId: string, newTitle: string): Promise<void> {\n const onRename = this.adapter.onRename;\n if (!onRename)\n throw new Error(\"External store adapter does not support renaming\");\n\n await onRename(threadId, newTitle);\n }\n\n public async updateCustom(\n threadId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n const onUpdateCustom = this.adapter.onUpdateCustom;\n if (!onUpdateCustom)\n throw new Error(\n \"External store adapter does not support updating custom metadata\",\n );\n\n await onUpdateCustom(threadId, custom);\n }\n\n public async detach(): Promise<void> {\n // no-op\n }\n\n public async archive(threadId: string): Promise<void> {\n const onArchive = this.adapter.onArchive;\n if (!onArchive)\n throw new Error(\"External store adapter does not support archiving\");\n\n await onArchive(threadId);\n }\n\n public async unarchive(threadId: string): Promise<void> {\n const onUnarchive = this.adapter.onUnarchive;\n if (!onUnarchive)\n throw new Error(\"External store adapter does not support unarchiving\");\n\n await onUnarchive(threadId);\n }\n\n public async delete(threadId: string): Promise<void> {\n const onDelete = this.adapter.onDelete;\n if (!onDelete)\n throw new Error(\"External store adapter does not support deleting\");\n\n await onDelete(threadId);\n }\n\n public initialize(\n threadId: string,\n ): Promise<{ remoteId: string; externalId: string | undefined }> {\n return Promise.resolve({ remoteId: threadId, externalId: undefined });\n }\n\n public generateTitle(): never {\n throw new Error(\"Method not implemented.\");\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"external-store-thread-list-runtime-core.js","names":["ExternalStoreThreadRuntimeCore","ThreadListItemCoreState","ThreadListRuntimeCore","ExternalStoreThreadListAdapter","invalidateThreadRuntime","BaseSubscribable","nullProtoRecord","ExternalStoreThreadFactory","EMPTY_ARRAY","Object","freeze","DEFAULT_THREAD_ID","DEFAULT_THREADS","DEFAULT_THREAD","id","remoteId","undefined","externalId","status","RESOLVED_PROMISE","Promise","resolve","DEFAULT_THREAD_DATA","ExternalStoreThreadListRuntimeCore","_mainThreadId","_threads","_archivedThreads","_threadData","Readonly","Record","adapter","isLoading","newThreadId","threadIds","archivedThreadIds","threadItems","getLoadThreadsPromise","_mainThread","mainThreadId","threadFactory","constructor","__internal_setAdapter","getMainThreadRuntimeCore","getThreadRuntimeCore","Error","getItemById","threadId","hasOwn","initialLoad","previousAdapter","newThreads","threads","newArchivedThreads","archivedThreads","previousThreadId","previousThreads","previousArchivedThreads","fromEntries","map","t","_notifySubscribers","reloadMainThread","unstable_refetchThread","switchToThread","_options","unarchive","onSwitchToThread","switchToNewThread","onSwitchToNewThread","rename","newTitle","onRename","updateCustom","custom","onUpdateCustom","detach","archive","onArchive","onUnarchive","delete","onDelete","initialize","generateTitle"],"sources":["../../../src/runtimes/external-store/external-store-thread-list-runtime-core.ts"],"sourcesContent":["import type { ExternalStoreThreadRuntimeCore } from \"./external-store-thread-runtime-core\";\nimport type {\n ThreadListItemCoreState,\n ThreadListRuntimeCore,\n} from \"../../runtime/interfaces/thread-list-runtime-core\";\nimport type { ExternalStoreThreadListAdapter } from \"./external-store-adapter\";\nimport { invalidateThreadRuntime } from \"../../runtime/utils/thread-runtime-lifecycle\";\nimport { BaseSubscribable } from \"../../subscribable/subscribable\";\nimport { nullProtoRecord } from \"../../utils/record\";\n\nexport type ExternalStoreThreadFactory = () => ExternalStoreThreadRuntimeCore;\n\nconst EMPTY_ARRAY = Object.freeze([]);\nconst DEFAULT_THREAD_ID = \"DEFAULT_THREAD_ID\";\nconst DEFAULT_THREADS = Object.freeze([DEFAULT_THREAD_ID]);\nconst DEFAULT_THREAD = Object.freeze({\n id: DEFAULT_THREAD_ID,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n});\nconst RESOLVED_PROMISE = Promise.resolve();\nconst DEFAULT_THREAD_DATA = Object.freeze(\n nullProtoRecord<ThreadListItemCoreState>({\n [DEFAULT_THREAD_ID]: DEFAULT_THREAD,\n }),\n);\n\nexport class ExternalStoreThreadListRuntimeCore\n extends BaseSubscribable\n implements ThreadListRuntimeCore\n{\n private _mainThreadId: string = DEFAULT_THREAD_ID;\n private _threads: readonly string[] = DEFAULT_THREADS;\n private _archivedThreads: readonly string[] = EMPTY_ARRAY;\n private _threadData: Readonly<Record<string, ThreadListItemCoreState>> =\n DEFAULT_THREAD_DATA;\n private adapter: ExternalStoreThreadListAdapter = {};\n\n public get isLoading() {\n return this.adapter.isLoading ?? false;\n }\n\n public get newThreadId() {\n return undefined;\n }\n\n public get threadIds() {\n return this._threads;\n }\n\n public get archivedThreadIds() {\n return this._archivedThreads;\n }\n\n public get threadItems() {\n return this._threadData;\n }\n\n public getLoadThreadsPromise() {\n return RESOLVED_PROMISE;\n }\n\n private _mainThread!: ExternalStoreThreadRuntimeCore;\n\n public get mainThreadId() {\n return this._mainThreadId;\n }\n\n private threadFactory: ExternalStoreThreadFactory;\n\n constructor(\n adapter: ExternalStoreThreadListAdapter = {},\n threadFactory: ExternalStoreThreadFactory,\n ) {\n super();\n this.threadFactory = threadFactory;\n this.__internal_setAdapter(adapter, true);\n }\n\n public getMainThreadRuntimeCore() {\n return this._mainThread;\n }\n\n public getThreadRuntimeCore(): never {\n throw new Error(\"Method not implemented.\");\n }\n\n public getItemById(threadId: string) {\n return Object.hasOwn(this._threadData, threadId)\n ? this._threadData[threadId]\n : undefined;\n }\n\n public __internal_setAdapter(\n adapter: ExternalStoreThreadListAdapter,\n initialLoad = false,\n ) {\n const previousAdapter = this.adapter;\n this.adapter = adapter;\n\n const newThreadId = adapter.threadId ?? DEFAULT_THREAD_ID;\n const newThreads = adapter.threads ?? EMPTY_ARRAY;\n const newArchivedThreads = adapter.archivedThreads ?? EMPTY_ARRAY;\n\n const previousThreadId = previousAdapter.threadId ?? DEFAULT_THREAD_ID;\n const previousThreads = previousAdapter.threads ?? EMPTY_ARRAY;\n const previousArchivedThreads =\n previousAdapter.archivedThreads ?? EMPTY_ARRAY;\n\n if (\n !initialLoad &&\n (previousAdapter.isLoading ?? false) === (adapter.isLoading ?? false) &&\n previousThreadId === newThreadId &&\n previousThreads === newThreads &&\n previousArchivedThreads === newArchivedThreads\n ) {\n return;\n }\n\n if (\n previousThreads !== newThreads ||\n previousArchivedThreads !== newArchivedThreads ||\n previousThreadId !== newThreadId\n ) {\n this._threadData = nullProtoRecord(\n DEFAULT_THREAD_DATA,\n Object.fromEntries(\n adapter.threads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"regular\",\n },\n ]) ?? [],\n ),\n Object.fromEntries(\n adapter.archivedThreads?.map((t) => [\n t.id,\n {\n ...t,\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: \"archived\",\n },\n ]) ?? [],\n ),\n );\n }\n\n if (previousThreads !== newThreads) {\n this._threads = this.adapter.threads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n if (previousArchivedThreads !== newArchivedThreads) {\n this._archivedThreads =\n this.adapter.archivedThreads?.map((t) => t.id) ?? EMPTY_ARRAY;\n }\n\n // `initialLoad ||`: `_mainThread!` must be assigned on construction.\n if (initialLoad || previousThreadId !== newThreadId) {\n if (!initialLoad) invalidateThreadRuntime(this._mainThread);\n this._mainThreadId = newThreadId;\n this._mainThread = this.threadFactory();\n }\n\n if (!Object.hasOwn(this._threadData, this._mainThreadId)) {\n this._threadData = nullProtoRecord(this._threadData, {\n [this._mainThreadId]: {\n id: this._mainThreadId,\n remoteId: undefined,\n externalId: undefined,\n status: \"regular\",\n },\n });\n }\n\n this._notifySubscribers();\n }\n\n public async reloadMainThread(): Promise<void> {\n // There is no runtime hook to remount here, so the capability is the only\n // path and an adapter without it has nothing to refetch with.\n if (!this._mainThread.unstable_refetchThread) return;\n // No unsent-thread guard: every entry here is regular or archived, so the\n // \"new\" status the remote thread list has to exclude cannot occur.\n await this._mainThread.unstable_refetchThread();\n }\n\n public async switchToThread(\n threadId: string,\n _options?: { unarchive?: boolean },\n ): Promise<void> {\n if (this._mainThreadId === threadId) return;\n const onSwitchToThread = this.adapter.onSwitchToThread;\n if (!onSwitchToThread)\n throw new Error(\n \"External store adapter does not support switching to thread\",\n );\n await onSwitchToThread(threadId);\n }\n\n public async switchToNewThread(): Promise<void> {\n const onSwitchToNewThread = this.adapter.onSwitchToNewThread;\n if (!onSwitchToNewThread)\n throw new Error(\n \"External store adapter does not support switching to new thread\",\n );\n\n await onSwitchToNewThread();\n }\n\n public async rename(threadId: string, newTitle: string): Promise<void> {\n const onRename = this.adapter.onRename;\n if (!onRename)\n throw new Error(\"External store adapter does not support renaming\");\n\n await onRename(threadId, newTitle);\n }\n\n public async updateCustom(\n threadId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n const onUpdateCustom = this.adapter.onUpdateCustom;\n if (!onUpdateCustom)\n throw new Error(\n \"External store adapter does not support updating custom metadata\",\n );\n\n await onUpdateCustom(threadId, custom);\n }\n\n public async detach(): Promise<void> {\n // no-op\n }\n\n public async archive(threadId: string): Promise<void> {\n const onArchive = this.adapter.onArchive;\n if (!onArchive)\n throw new Error(\"External store adapter does not support archiving\");\n\n await onArchive(threadId);\n }\n\n public async unarchive(threadId: string): Promise<void> {\n const onUnarchive = this.adapter.onUnarchive;\n if (!onUnarchive)\n throw new Error(\"External store adapter does not support unarchiving\");\n\n await onUnarchive(threadId);\n }\n\n public async delete(threadId: string): Promise<void> {\n const onDelete = this.adapter.onDelete;\n if (!onDelete)\n throw new Error(\"External store adapter does not support deleting\");\n\n await onDelete(threadId);\n }\n\n public initialize(\n threadId: string,\n ): Promise<{ remoteId: string; externalId: string | undefined }> {\n return Promise.resolve({ remoteId: threadId, externalId: undefined });\n }\n\n public generateTitle(): never {\n throw new Error(\"Method not implemented.\");\n }\n}\n"],"mappings":"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"}
@@ -12,5 +12,5 @@ import { ConverterCallback, ThreadMessageConverter } from "./external-store/thre
12
12
  import { ReadonlyThreadRuntimeCore } from "./readonly/ReadonlyThreadRuntimeCore.js";
13
13
  import { OptimisticState } from "./remote-thread-list/optimistic-state.js";
14
14
  import { EMPTY_THREAD_CORE } from "./remote-thread-list/empty-thread-core.js";
15
- import { RemoteThreadData, RemoteThreadState, THREAD_MAPPING_ID, createThreadMappingId, getThreadData, updateStatusReducer } from "./remote-thread-list/remote-thread-state.js";
16
- export { type ConverterCallback, EMPTY_THREAD_CORE, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type THREAD_MAPPING_ID, ThreadMessageConverter, ToolInvocationTracker, createThreadMappingId, getThreadData, hasUpcomingMessage, shouldContinue, updateStatusReducer };
15
+ import { RemoteThreadData, RemoteThreadState, THREAD_MAPPING_ID, createThreadMappingId, getThreadData, promoteNewThreadReducer, updateStatusReducer } from "./remote-thread-list/remote-thread-state.js";
16
+ export { type ConverterCallback, EMPTY_THREAD_CORE, ExternalStoreRuntimeCore, type ExternalStoreThreadFactory, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LocalRuntimeCore, type LocalRuntimeOptionsBase, type LocalThreadFactory, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, OptimisticState, ReadonlyThreadRuntimeCore, type RemoteThreadData, type RemoteThreadInitializeResponse, type RemoteThreadListOptions, type RemoteThreadState, type THREAD_MAPPING_ID, ThreadMessageConverter, ToolInvocationTracker, createThreadMappingId, getThreadData, hasUpcomingMessage, promoteNewThreadReducer, shouldContinue, updateStatusReducer };
@@ -10,5 +10,5 @@ import { ExternalStoreRuntimeCore } from "./external-store/external-store-runtim
10
10
  import { ReadonlyThreadRuntimeCore } from "./readonly/ReadonlyThreadRuntimeCore.js";
11
11
  import { OptimisticState } from "./remote-thread-list/optimistic-state.js";
12
12
  import { EMPTY_THREAD_CORE } from "./remote-thread-list/empty-thread-core.js";
13
- import { createThreadMappingId, getThreadData, updateStatusReducer } from "./remote-thread-list/remote-thread-state.js";
14
- export { EMPTY_THREAD_CORE, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, OptimisticState, ReadonlyThreadRuntimeCore, ThreadMessageConverter, ToolInvocationTracker, createThreadMappingId, getThreadData, hasUpcomingMessage, shouldContinue, updateStatusReducer };
13
+ import { createThreadMappingId, getThreadData, promoteNewThreadReducer, updateStatusReducer } from "./remote-thread-list/remote-thread-state.js";
14
+ export { EMPTY_THREAD_CORE, ExternalStoreRuntimeCore, ExternalStoreThreadListRuntimeCore, ExternalStoreThreadRuntimeCore, LocalRuntimeCore, LocalThreadListRuntimeCore, LocalThreadRuntimeCore, OptimisticState, ReadonlyThreadRuntimeCore, ThreadMessageConverter, ToolInvocationTracker, createThreadMappingId, getThreadData, hasUpcomingMessage, promoteNewThreadReducer, shouldContinue, updateStatusReducer };