@assistant-ui/core 0.3.17 → 0.3.19

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 (470) 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/adapters/speech.d.ts.map +1 -1
  5. package/dist/adapters/speech.js +13 -3
  6. package/dist/adapters/speech.js.map +1 -1
  7. package/dist/adapters/thread-history.d.ts +4 -0
  8. package/dist/adapters/thread-history.d.ts.map +1 -1
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal.d.ts +4 -3
  12. package/dist/internal.js +3 -2
  13. package/dist/model-context/frame/host.d.ts.map +1 -1
  14. package/dist/model-context/frame/host.js +35 -14
  15. package/dist/model-context/frame/host.js.map +1 -1
  16. package/dist/model-context/frame/provider.d.ts +2 -0
  17. package/dist/model-context/frame/provider.d.ts.map +1 -1
  18. package/dist/model-context/frame/provider.js +30 -7
  19. package/dist/model-context/frame/provider.js.map +1 -1
  20. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  21. package/dist/model-context/interactable-composer-metadata.js +27 -18
  22. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  23. package/dist/model-context/registry.d.ts.map +1 -1
  24. package/dist/model-context/registry.js +3 -5
  25. package/dist/model-context/registry.js.map +1 -1
  26. package/dist/model-context/types.d.ts.map +1 -1
  27. package/dist/model-context/types.js +5 -4
  28. package/dist/model-context/types.js.map +1 -1
  29. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  30. package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
  31. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  32. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  33. package/dist/react/client/DataRenderers.js +20 -15
  34. package/dist/react/client/DataRenderers.js.map +1 -1
  35. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  36. package/dist/react/client/InMemoryThreadList.js +62 -56
  37. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  38. package/dist/react/client/Interactables.d.ts.map +1 -1
  39. package/dist/react/client/Interactables.js +35 -32
  40. package/dist/react/client/Interactables.js.map +1 -1
  41. package/dist/react/client/RemoteThreadList.d.ts +1 -0
  42. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  43. package/dist/react/client/RemoteThreadList.js +154 -143
  44. package/dist/react/client/RemoteThreadList.js.map +1 -1
  45. package/dist/react/client/Tools.d.ts.map +1 -1
  46. package/dist/react/client/Tools.js +18 -16
  47. package/dist/react/client/Tools.js.map +1 -1
  48. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  49. package/dist/react/client/interactable-model-context.js +3 -2
  50. package/dist/react/client/interactable-model-context.js.map +1 -1
  51. package/dist/react/index.d.ts +2 -2
  52. package/dist/react/index.js +2 -2
  53. package/dist/react/interactables-legacy/Interactables.js +242 -121
  54. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  55. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
  56. package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
  57. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
  58. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
  59. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
  60. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
  61. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  62. package/dist/react/model-context/makeAssistantTool.js +1 -1
  63. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  64. package/dist/react/model-context/useAssistantTool.d.ts +2 -2
  65. package/dist/react/model-context/useAssistantTool.js +1 -1
  66. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  67. package/dist/react/model-context/useInteractable.d.ts.map +1 -1
  68. package/dist/react/model-context/useInteractable.js +4 -1
  69. package/dist/react/model-context/useInteractable.js.map +1 -1
  70. package/dist/react/model-context/useInteractableVersions.js +1 -1
  71. package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
  72. package/dist/react/model-context/useToolArgsStatus.js +2 -1
  73. package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
  74. package/dist/react/primitives/message/MessageGroupedParts.d.ts +11 -2
  75. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  76. package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
  77. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  78. package/dist/react/primitives/part/PartMessages.d.ts +1 -0
  79. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  80. package/dist/react/primitives/part/PartMessages.js +1 -0
  81. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  82. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  83. package/dist/react/primitives/thread/ThreadMessages.js +6 -5
  84. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  85. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  86. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +16 -8
  87. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  88. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +5 -1
  89. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  90. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +105 -104
  91. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  92. package/dist/react/runtimes/RemoteThreadResource.d.ts +1 -0
  93. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  94. package/dist/react/runtimes/RemoteThreadResource.js +13 -11
  95. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  96. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +5 -24
  97. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  98. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +354 -226
  99. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  100. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
  101. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  102. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
  103. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  104. package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
  105. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  106. package/dist/react/runtimes/cloud/auiV0.js +62 -15
  107. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  108. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
  109. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
  110. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +6 -1
  111. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
  112. package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
  113. package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
  114. package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
  115. package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
  116. package/dist/react/runtimes/external-message-converter.d.ts +12 -2
  117. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  118. package/dist/react/runtimes/external-message-converter.js +26 -61
  119. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  120. package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
  121. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  122. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  123. package/dist/react/runtimes/useRemoteThreadListRuntime.js +64 -24
  124. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  125. package/dist/react/utils/groupParts.d.ts +6 -1
  126. package/dist/react/utils/groupParts.d.ts.map +1 -1
  127. package/dist/react/utils/groupParts.js +6 -0
  128. package/dist/react/utils/groupParts.js.map +1 -1
  129. package/dist/react/utils/useJSONEqual.d.ts +3 -1
  130. package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
  131. package/dist/react/utils/useJSONEqual.js +6 -1
  132. package/dist/react/utils/useJSONEqual.js.map +1 -1
  133. package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
  134. package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
  135. package/dist/react/utils/useJSONSchemaDependency.js +20 -0
  136. package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
  137. package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
  138. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  139. package/dist/runtime/api/thread-list-item-runtime.js +2 -2
  140. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  141. package/dist/runtime/api/thread-list-runtime.d.ts +3 -0
  142. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  143. package/dist/runtime/api/thread-list-runtime.js +18 -14
  144. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  145. package/dist/runtime/api/thread-runtime.d.ts +4 -0
  146. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  147. package/dist/runtime/api/thread-runtime.js +3 -6
  148. package/dist/runtime/api/thread-runtime.js.map +1 -1
  149. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
  150. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  151. package/dist/runtime/base/base-composer-runtime-core.js +62 -22
  152. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  153. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
  154. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  155. package/dist/runtime/base/base-thread-runtime-core.js +161 -69
  156. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  157. package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
  158. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  159. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +4 -1
  160. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  161. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  162. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  163. package/dist/runtime/queue/message-queue.d.ts +5 -0
  164. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  165. package/dist/runtime/queue/message-queue.js +61 -6
  166. package/dist/runtime/queue/message-queue.js.map +1 -1
  167. package/dist/runtime/utils/auto-status.d.ts +6 -2
  168. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  169. package/dist/runtime/utils/auto-status.js +12 -4
  170. package/dist/runtime/utils/auto-status.js.map +1 -1
  171. package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
  172. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  173. package/dist/runtime/utils/external-message-conversion.js +49 -13
  174. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  175. package/dist/runtime/utils/message-repository.d.ts +1 -0
  176. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  177. package/dist/runtime/utils/message-repository.js +18 -9
  178. package/dist/runtime/utils/message-repository.js.map +1 -1
  179. package/dist/runtime/utils/thread-message-like.d.ts +2 -1
  180. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  181. package/dist/runtime/utils/thread-message-like.js +5 -3
  182. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  183. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  184. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
  185. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  186. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  187. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
  188. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  189. package/dist/runtimes/internal.d.ts +3 -3
  190. package/dist/runtimes/internal.js +2 -2
  191. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  192. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  193. package/dist/runtimes/local/local-thread-runtime-core.js +4 -1
  194. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  195. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
  196. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  197. package/dist/runtimes/remote-thread-list/remote-thread-state.js +130 -42
  198. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  199. package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
  200. package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
  201. package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
  202. package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
  203. package/dist/runtimes/remote-thread-list/title.d.ts +3 -1
  204. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -1
  205. package/dist/runtimes/remote-thread-list/title.js +9 -1
  206. package/dist/runtimes/remote-thread-list/title.js.map +1 -1
  207. package/dist/runtimes/remote-thread-list/types.d.ts +10 -0
  208. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  209. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  210. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
  211. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  212. package/dist/store/clients/external-thread.d.ts.map +1 -1
  213. package/dist/store/clients/external-thread.js +260 -203
  214. package/dist/store/clients/external-thread.js.map +1 -1
  215. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  216. package/dist/store/clients/model-context-client.js +2 -1
  217. package/dist/store/clients/model-context-client.js.map +1 -1
  218. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  219. package/dist/store/clients/single-thread-list.js +1 -0
  220. package/dist/store/clients/single-thread-list.js.map +1 -1
  221. package/dist/store/clients/suggestions.d.ts.map +1 -1
  222. package/dist/store/clients/suggestions.js +5 -4
  223. package/dist/store/clients/suggestions.js.map +1 -1
  224. package/dist/store/clients/thread-tasks.d.ts +13 -0
  225. package/dist/store/clients/thread-tasks.d.ts.map +1 -0
  226. package/dist/store/clients/thread-tasks.js +69 -0
  227. package/dist/store/clients/thread-tasks.js.map +1 -0
  228. package/dist/store/index.d.ts +3 -2
  229. package/dist/store/index.js +3 -3
  230. package/dist/store/primitive-predicates.d.ts.map +1 -1
  231. package/dist/store/primitive-predicates.js +4 -4
  232. package/dist/store/primitive-predicates.js.map +1 -1
  233. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
  234. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  235. package/dist/store/runtime-clients/composer-runtime-client.js +97 -61
  236. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  237. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
  238. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  239. package/dist/store/runtime-clients/message-runtime-client.js +221 -144
  240. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  241. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  242. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -1
  243. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  244. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  245. package/dist/store/runtime-clients/thread-list-runtime-client.js +54 -52
  246. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  247. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  248. package/dist/store/runtime-clients/thread-runtime-client.js +246 -126
  249. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  250. package/dist/store/scope-registration.d.ts +2 -0
  251. package/dist/store/scope-registration.d.ts.map +1 -1
  252. package/dist/store/scopes/composer.d.ts +10 -2
  253. package/dist/store/scopes/composer.d.ts.map +1 -1
  254. package/dist/store/scopes/message.d.ts +30 -1
  255. package/dist/store/scopes/message.d.ts.map +1 -1
  256. package/dist/store/scopes/task.d.ts +36 -0
  257. package/dist/store/scopes/task.d.ts.map +1 -0
  258. package/dist/store/scopes/task.js +0 -0
  259. package/dist/store/scopes/thread-list-item.d.ts +2 -2
  260. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  261. package/dist/store/scopes/thread.d.ts +28 -0
  262. package/dist/store/scopes/thread.d.ts.map +1 -1
  263. package/dist/store/scopes/threads.d.ts +1 -0
  264. package/dist/store/scopes/threads.d.ts.map +1 -1
  265. package/dist/subscribable/subscribable.d.ts +2 -1
  266. package/dist/subscribable/subscribable.d.ts.map +1 -1
  267. package/dist/subscribable/subscribable.js +23 -15
  268. package/dist/subscribable/subscribable.js.map +1 -1
  269. package/dist/types/attachment.d.ts +2 -1
  270. package/dist/types/attachment.d.ts.map +1 -1
  271. package/dist/types/attachment.js +2 -1
  272. package/dist/types/attachment.js.map +1 -1
  273. package/dist/types/index.d.ts +2 -2
  274. package/dist/types/message.d.ts +8 -1
  275. package/dist/types/message.d.ts.map +1 -1
  276. package/dist/types/message.js.map +1 -1
  277. package/dist/utils/abortable-iterable.d.ts +19 -0
  278. package/dist/utils/abortable-iterable.d.ts.map +1 -0
  279. package/dist/utils/abortable-iterable.js +88 -0
  280. package/dist/utils/abortable-iterable.js.map +1 -0
  281. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  282. package/dist/utils/composite-context-provider.js +20 -2
  283. package/dist/utils/composite-context-provider.js.map +1 -1
  284. package/dist/utils/getGroupStatus.d.ts +18 -2
  285. package/dist/utils/getGroupStatus.d.ts.map +1 -1
  286. package/dist/utils/getGroupStatus.js +32 -7
  287. package/dist/utils/getGroupStatus.js.map +1 -1
  288. package/dist/utils/record.d.ts +11 -0
  289. package/dist/utils/record.d.ts.map +1 -0
  290. package/dist/utils/record.js +12 -0
  291. package/dist/utils/record.js.map +1 -0
  292. package/dist/utils/wire-media.d.ts.map +1 -1
  293. package/dist/utils/wire-media.js +2 -2
  294. package/dist/utils/wire-media.js.map +1 -1
  295. package/package.json +11 -11
  296. package/src/adapters/attachment.test.ts +50 -1
  297. package/src/adapters/attachment.ts +7 -4
  298. package/src/adapters/speech.test.ts +236 -0
  299. package/src/adapters/speech.ts +17 -10
  300. package/src/adapters/thread-history.ts +3 -0
  301. package/src/index.ts +2 -0
  302. package/src/internal.ts +4 -0
  303. package/src/model-context/frame/host.test.ts +137 -1
  304. package/src/model-context/frame/host.ts +49 -16
  305. package/src/model-context/frame/provider.test.ts +71 -0
  306. package/src/model-context/frame/provider.ts +37 -7
  307. package/src/model-context/interactable-composer-metadata.test.ts +58 -0
  308. package/src/model-context/interactable-composer-metadata.ts +19 -13
  309. package/src/model-context/registry.test.ts +12 -0
  310. package/src/model-context/registry.ts +3 -2
  311. package/src/model-context/types.test.ts +25 -0
  312. package/src/model-context/types.ts +9 -4
  313. package/src/react/RuntimeAdapter.test.ts +34 -0
  314. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
  315. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
  316. package/src/react/client/DataRenderers.test.tsx +45 -0
  317. package/src/react/client/DataRenderers.ts +13 -9
  318. package/src/react/client/InMemoryThreadList.ts +1 -0
  319. package/src/react/client/Interactables.test.ts +72 -1
  320. package/src/react/client/Interactables.ts +22 -14
  321. package/src/react/client/RemoteThreadList.background.test.ts +148 -6
  322. package/src/react/client/RemoteThreadList.concurrent.test.tsx +42 -1
  323. package/src/react/client/RemoteThreadList.test.ts +386 -4
  324. package/src/react/client/RemoteThreadList.ts +181 -112
  325. package/src/react/client/Tools.ts +22 -11
  326. package/src/react/client/interactable-model-context.test.ts +44 -0
  327. package/src/react/client/interactable-model-context.ts +3 -2
  328. package/src/react/index.ts +5 -1
  329. package/src/react/interactables-legacy/Interactables.ts +16 -16
  330. package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
  331. package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
  332. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
  333. package/src/react/model-context/makeAssistantTool.ts +2 -2
  334. package/src/react/model-context/useAssistantTool.ts +2 -2
  335. package/src/react/model-context/useInteractable.test.tsx +177 -0
  336. package/src/react/model-context/useInteractable.ts +3 -0
  337. package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
  338. package/src/react/model-context/useToolArgsStatus.ts +2 -1
  339. package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
  340. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
  341. package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
  342. package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
  343. package/src/react/primitives/part/PartMessages.test.tsx +104 -1
  344. package/src/react/primitives/part/PartMessages.tsx +1 -0
  345. package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
  346. package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
  347. package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
  348. package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
  349. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +33 -0
  350. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
  351. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +28 -5
  352. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
  353. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +105 -0
  354. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +143 -112
  355. package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
  356. package/src/react/runtimes/RemoteThreadResource.ts +19 -12
  357. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
  358. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +703 -6
  359. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +492 -402
  360. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
  361. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
  362. package/src/react/runtimes/cloud/auiV0.ts +160 -25
  363. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +36 -0
  364. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +8 -1
  365. package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
  366. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
  367. package/src/react/runtimes/external-message-converter.test.ts +136 -1
  368. package/src/react/runtimes/external-message-converter.ts +39 -93
  369. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
  370. package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
  371. package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
  372. package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
  373. package/src/react/runtimes/useRemoteThreadListRuntime.ts +34 -1
  374. package/src/react/utils/groupParts.ts +12 -1
  375. package/src/react/utils/useJSONEqual.ts +9 -0
  376. package/src/react/utils/useJSONSchemaDependency.ts +22 -0
  377. package/src/runtime/api/message-runtime.test.ts +75 -0
  378. package/src/runtime/api/thread-list-item-runtime.ts +10 -3
  379. package/src/runtime/api/thread-list-runtime.ts +21 -11
  380. package/src/runtime/api/thread-runtime.test.ts +136 -0
  381. package/src/runtime/api/thread-runtime.ts +10 -5
  382. package/src/runtime/base/base-composer-runtime-core.ts +105 -24
  383. package/src/runtime/base/base-thread-runtime-core.test.ts +1063 -2
  384. package/src/runtime/base/base-thread-runtime-core.ts +228 -87
  385. package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
  386. package/src/runtime/interfaces/thread-list-runtime-core.ts +5 -1
  387. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  388. package/src/runtime/queue/message-queue.ts +68 -6
  389. package/src/runtime/utils/auto-status.test.ts +112 -1
  390. package/src/runtime/utils/auto-status.ts +31 -5
  391. package/src/runtime/utils/external-message-conversion.test.ts +202 -0
  392. package/src/runtime/utils/external-message-conversion.ts +123 -32
  393. package/src/runtime/utils/message-repository.test.ts +49 -0
  394. package/src/runtime/utils/message-repository.ts +32 -20
  395. package/src/runtime/utils/thread-message-like.test.ts +52 -0
  396. package/src/runtime/utils/thread-message-like.ts +5 -1
  397. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
  398. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -1
  399. package/src/runtimes/internal.ts +1 -0
  400. package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
  401. package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
  402. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +128 -2
  403. package/src/runtimes/remote-thread-list/remote-thread-state.ts +182 -42
  404. package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
  405. package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
  406. package/src/runtimes/remote-thread-list/title.test.ts +62 -0
  407. package/src/runtimes/remote-thread-list/title.ts +13 -0
  408. package/src/runtimes/remote-thread-list/types.ts +10 -0
  409. package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
  410. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
  411. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
  412. package/src/store/clients/external-thread.ts +67 -4
  413. package/src/store/clients/model-context-client.ts +5 -1
  414. package/src/store/clients/single-thread-list.ts +1 -0
  415. package/src/store/clients/suggestions.test.ts +40 -0
  416. package/src/store/clients/suggestions.ts +13 -10
  417. package/src/store/clients/thread-tasks.test.ts +274 -0
  418. package/src/store/clients/thread-tasks.ts +138 -0
  419. package/src/store/index.ts +8 -0
  420. package/src/store/primitive-predicates.test.ts +48 -5
  421. package/src/store/primitive-predicates.ts +7 -2
  422. package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
  423. package/src/store/runtime-clients/message-runtime-client.ts +54 -6
  424. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
  425. package/src/store/runtime-clients/thread-list-runtime-client.ts +1 -0
  426. package/src/store/runtime-clients/thread-runtime-client.ts +89 -11
  427. package/src/store/scope-registration.ts +2 -0
  428. package/src/store/scopes/composer.ts +16 -4
  429. package/src/store/scopes/message.ts +14 -0
  430. package/src/store/scopes/task.ts +34 -0
  431. package/src/store/scopes/thread-list-item.ts +5 -2
  432. package/src/store/scopes/thread.ts +20 -0
  433. package/src/store/scopes/threads.ts +1 -0
  434. package/src/store/thread-tasks.test.tsx +209 -0
  435. package/src/subscribable/subscribable.test.ts +156 -1
  436. package/src/subscribable/subscribable.ts +25 -15
  437. package/src/tests/MessageRepository.test.ts +117 -5
  438. package/src/tests/OptimisticState-list-race.test.ts +1 -0
  439. package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
  440. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +47 -0
  441. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
  442. package/src/tests/attachment-adapters.test.ts +14 -0
  443. package/src/tests/auiV0Encode.test.ts +300 -0
  444. package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
  445. package/src/tests/base-composer-runtime-core.test.ts +353 -2
  446. package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
  447. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +178 -18
  448. package/src/tests/external-thread-attachments.test.tsx +208 -0
  449. package/src/tests/external-thread-parity.test.tsx +57 -0
  450. package/src/tests/groupParts.test.ts +71 -0
  451. package/src/tests/message-queue.test.ts +253 -0
  452. package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
  453. package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
  454. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  455. package/src/tests/thread-switch-events.test.tsx +78 -0
  456. package/src/tests/tools-scope-migration.test.tsx +28 -0
  457. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
  458. package/src/types/attachment.ts +4 -0
  459. package/src/types/index.ts +1 -0
  460. package/src/types/message.ts +8 -0
  461. package/src/utils/abortable-iterable.test.ts +328 -0
  462. package/src/utils/abortable-iterable.ts +104 -0
  463. package/src/utils/composite-context-provider.test.ts +25 -0
  464. package/src/utils/composite-context-provider.ts +23 -2
  465. package/src/utils/getGroupStatus.test.ts +70 -4
  466. package/src/utils/getGroupStatus.ts +35 -12
  467. package/src/utils/record.test.ts +48 -0
  468. package/src/utils/record.ts +11 -0
  469. package/src/utils/wire-media.test.ts +10 -0
  470. package/src/utils/wire-media.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"remote-thread-state.js","names":["RemoteThreadInitializeResponse","RemoteThreadMetadata","generateId","RemoteThreadData","id","remoteId","externalId","status","title","custom","localOrigin","initializeTask","Promise","lastMessageAt","Date","Record","THREAD_MAPPING_ID","__brand","createThreadMappingId","LOCAL_THREAD_ID_PREFIX","normalizeCursor","c","undefined","ClassifyAccumulator","threadIds","archivedThreadIds","threadIdMap","threadData","classifyThreads","threads","acc","listed","Set","thread","_exhaustiveCheck","Error","existingMappingId","existing","mappingId","existingTask","has","add","push","filter","t","const","resolve","RemoteThreadState","isLoading","isLoadingMore","cursor","newThreadId","Readonly","createEmptyRemoteThreadState","seedNewThread","state","preserveMidLoadTransitions","priorOrder","Pick","statusAtRequest","ReadonlyMap","regular","archived","rescuedRegular","rescuedArchived","contains","ids","ReadonlySet","data","Object","values","before","get","length","position","byId","indexOf","byRemoteId","Number","MAX_SAFE_INTEGER","sort","a","b","map","d","statusSnapshot","Map","getThreadData","threadIdOrRemoteId","idx","updateStatusReducer","newStatus","lastStatus","newState","fromEntries","entries","key","value"],"sources":["../../../src/runtimes/remote-thread-list/remote-thread-state.ts"],"sourcesContent":["import type {\n RemoteThreadInitializeResponse,\n RemoteThreadMetadata,\n} from \"./types\";\nimport { generateId } from \"../../utils/id\";\n\nexport type RemoteThreadData =\n | {\n readonly id: string;\n readonly remoteId: undefined;\n readonly externalId: undefined;\n readonly status: \"new\";\n readonly title: undefined;\n readonly custom: undefined;\n readonly localOrigin?: true;\n }\n | {\n readonly id: string;\n readonly initializeTask: Promise<RemoteThreadInitializeResponse>;\n readonly remoteId: undefined;\n readonly externalId: undefined;\n readonly status: \"regular\" | \"archived\";\n readonly title?: string | undefined;\n readonly custom: undefined;\n readonly localOrigin?: true;\n }\n | {\n readonly id: string;\n readonly initializeTask: Promise<RemoteThreadInitializeResponse>;\n readonly remoteId: string;\n readonly externalId: string | undefined;\n readonly status: \"regular\" | \"archived\";\n readonly title?: string | undefined;\n readonly lastMessageAt?: Date | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n readonly localOrigin?: true;\n };\n\nexport type THREAD_MAPPING_ID = string & { __brand: \"THREAD_MAPPING_ID\" };\n\nexport function createThreadMappingId(id: string): THREAD_MAPPING_ID {\n return id as THREAD_MAPPING_ID;\n}\n\nexport const LOCAL_THREAD_ID_PREFIX = \"__LOCALID_\";\n\nexport const normalizeCursor = (c: string | undefined): string | undefined =>\n c || undefined;\n\nexport type ClassifyAccumulator = {\n threadIds: string[];\n archivedThreadIds: string[];\n threadIdMap: Record<string, THREAD_MAPPING_ID>;\n threadData: Record<THREAD_MAPPING_ID, RemoteThreadData>;\n};\n\n// A slot's `id` is fixed when it is minted: the hook instance manager keys live\n// thread runtimes by it, so renaming a slot would detach the runtime the user is\n// chatting in. A listed thread whose `remoteId` already maps to a slot therefore\n// refreshes that slot instead of minting a second one, and a slot minted by a\n// list() that raced ahead of the remote id collapses when `initialize()` settles.\n// `threadIds`/`archivedThreadIds` carry slot ids, never remote ids.\nexport const classifyThreads = (\n threads: readonly RemoteThreadMetadata[],\n acc: ClassifyAccumulator,\n): ClassifyAccumulator => {\n const listed = new Set([...acc.threadIds, ...acc.archivedThreadIds]);\n\n for (const thread of threads) {\n switch (thread.status) {\n case \"regular\":\n case \"archived\":\n break;\n default: {\n const _exhaustiveCheck: never = thread.status;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n const existingMappingId = acc.threadIdMap[thread.remoteId];\n const existing =\n existingMappingId !== undefined\n ? acc.threadData[existingMappingId]\n : undefined;\n const id = existing?.id ?? thread.remoteId;\n const mappingId = existingMappingId ?? createThreadMappingId(id);\n const existingTask =\n existing !== undefined && existing.status !== \"new\"\n ? existing.initializeTask\n : undefined;\n\n if (!listed.has(id)) {\n listed.add(id);\n if (thread.status === \"regular\") {\n acc.threadIds.push(id);\n } else {\n acc.archivedThreadIds.push(id);\n }\n } else if (existing !== undefined && existing.status !== thread.status) {\n if (thread.status === \"regular\") {\n acc.archivedThreadIds = acc.archivedThreadIds.filter((t) => t !== id);\n acc.threadIds.push(id);\n } else {\n acc.threadIds = acc.threadIds.filter((t) => t !== id);\n acc.archivedThreadIds.push(id);\n }\n }\n\n acc.threadIdMap[id] = mappingId;\n acc.threadIdMap[thread.remoteId] = mappingId;\n acc.threadData[mappingId] = {\n ...(existing?.localOrigin === true ? { localOrigin: true as const } : {}),\n id,\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n lastMessageAt: thread.lastMessageAt,\n custom: thread.custom,\n initializeTask:\n existingTask ??\n Promise.resolve({\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n }),\n };\n }\n return acc;\n};\n\nexport type RemoteThreadState = {\n readonly isLoading: boolean;\n readonly isLoadingMore: boolean;\n readonly cursor: string | undefined;\n readonly newThreadId: string | undefined;\n readonly threadIds: readonly string[];\n readonly archivedThreadIds: readonly string[];\n readonly threadIdMap: Readonly<Record<string, THREAD_MAPPING_ID>>;\n readonly threadData: Readonly<Record<THREAD_MAPPING_ID, RemoteThreadData>>;\n};\n\nexport const createEmptyRemoteThreadState = (): RemoteThreadState => ({\n isLoading: true,\n isLoadingMore: false,\n cursor: undefined,\n newThreadId: undefined,\n threadIds: [],\n archivedThreadIds: [],\n threadIdMap: {},\n threadData: {},\n});\n\nexport const seedNewThread = (\n state: RemoteThreadState,\n): { id: string; state: RemoteThreadState } => {\n let id: string;\n do {\n id = `${LOCAL_THREAD_ID_PREFIX}${generateId()}`;\n } while (state.threadIdMap[id]);\n const mappingId = createThreadMappingId(id);\n return {\n id,\n state: {\n ...state,\n newThreadId: id,\n threadIdMap: {\n ...state.threadIdMap,\n [id]: mappingId,\n },\n threadData: {\n ...state.threadData,\n [mappingId]: {\n status: \"new\",\n id,\n remoteId: undefined,\n externalId: undefined,\n title: undefined,\n custom: undefined,\n localOrigin: true,\n } satisfies RemoteThreadData,\n },\n },\n };\n};\n\n// A list() response predating a mid-flight local transition (a thread\n// initialized while the request was running) omits that thread, and the\n// completed-optimistic replay cannot re-add it because the merged threadData\n// already carries the final status. Threads whose status moved from new (or\n// nonexistent) at request time to regular/archived are re-inserted at the\n// top, in the order the pre-response lists carried them: updateStatusReducer\n// prepends as transitions happen, so the pre-response lists hold newest\n// first, which threadData insertion order need not match. Threads the server already knew stay governed by the response, so\n// a server-side deletion is not resurrected — and a thread unknown to the\n// snapshot is only rescued when it carries the localOrigin marker stamped at\n// draft creation, so a deep-linked thread the fetch path deliberately\n// appended at the tail is not hoisted, whatever its remote id looks like.\nexport const preserveMidLoadTransitions = (\n state: RemoteThreadState,\n priorOrder: Pick<RemoteThreadState, \"threadIds\" | \"archivedThreadIds\">,\n statusAtRequest: ReadonlyMap<string, RemoteThreadData[\"status\"]>,\n): RemoteThreadState => {\n const regular = new Set(state.threadIds);\n const archived = new Set(state.archivedThreadIds);\n const rescuedRegular: RemoteThreadData[] = [];\n const rescuedArchived: RemoteThreadData[] = [];\n\n const contains = (ids: ReadonlySet<string>, data: RemoteThreadData) =>\n ids.has(data.id) || (data.remoteId !== undefined && ids.has(data.remoteId));\n\n for (const data of Object.values(state.threadData)) {\n const before = statusAtRequest.get(data.id);\n if (before !== undefined && before !== \"new\") continue;\n if (before === undefined && data.localOrigin !== true) continue;\n\n if (data.status === \"regular\" && !contains(regular, data)) {\n rescuedRegular.push(data);\n regular.add(data.id);\n } else if (data.status === \"archived\" && !contains(archived, data)) {\n rescuedArchived.push(data);\n archived.add(data.id);\n }\n }\n\n if (rescuedRegular.length === 0 && rescuedArchived.length === 0) return state;\n\n const position = (ids: readonly string[], data: RemoteThreadData) => {\n const byId = ids.indexOf(data.id);\n if (byId !== -1) return byId;\n const byRemoteId =\n data.remoteId !== undefined ? ids.indexOf(data.remoteId) : -1;\n return byRemoteId !== -1 ? byRemoteId : Number.MAX_SAFE_INTEGER;\n };\n rescuedRegular.sort(\n (a, b) =>\n position(priorOrder.threadIds, a) - position(priorOrder.threadIds, b),\n );\n rescuedArchived.sort(\n (a, b) =>\n position(priorOrder.archivedThreadIds, a) -\n position(priorOrder.archivedThreadIds, b),\n );\n\n return {\n ...state,\n threadIds: [...rescuedRegular.map((d) => d.id), ...state.threadIds],\n archivedThreadIds: [\n ...rescuedArchived.map((d) => d.id),\n ...state.archivedThreadIds,\n ],\n };\n};\n\nexport const statusSnapshot = (\n state: RemoteThreadState,\n): ReadonlyMap<string, RemoteThreadData[\"status\"]> =>\n new Map(Object.values(state.threadData).map((d) => [d.id, d.status]));\n\nexport const getThreadData = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n) => {\n const idx = state.threadIdMap[threadIdOrRemoteId];\n if (idx === undefined) return undefined;\n return state.threadData[idx];\n};\n\nexport const updateStatusReducer = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n newStatus: \"regular\" | \"archived\" | \"deleted\",\n) => {\n const data = getThreadData(state, threadIdOrRemoteId);\n if (!data) return state;\n\n const { id, status: lastStatus } = data;\n if (lastStatus === newStatus) return state;\n\n const newState = { ...state };\n\n // lastStatus\n switch (lastStatus) {\n case \"new\":\n newState.newThreadId = undefined;\n break;\n case \"regular\":\n newState.threadIds = newState.threadIds.filter((t) => t !== id);\n break;\n case \"archived\":\n newState.archivedThreadIds = newState.archivedThreadIds.filter(\n (t) => t !== id,\n );\n break;\n\n default: {\n const _exhaustiveCheck: never = lastStatus;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n // newStatus\n switch (newStatus) {\n case \"regular\":\n newState.threadIds = [id, ...newState.threadIds];\n break;\n\n case \"archived\":\n newState.archivedThreadIds = [id, ...newState.archivedThreadIds];\n break;\n\n case \"deleted\": {\n const mappingId = state.threadIdMap[threadIdOrRemoteId]!;\n newState.threadData = Object.fromEntries(\n Object.entries(newState.threadData).filter(\n ([key]) => key !== mappingId,\n ),\n );\n newState.threadIdMap = Object.fromEntries(\n Object.entries(newState.threadIdMap).filter(\n ([, value]) => value !== mappingId,\n ),\n );\n break;\n }\n\n default: {\n const _exhaustiveCheck: never = newStatus;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n if (newStatus !== \"deleted\") {\n newState.threadData = {\n ...newState.threadData,\n [id]: {\n ...data,\n status: newStatus,\n },\n };\n }\n\n return newState;\n};\n"],"mappings":";;AAwCA,SAAgBkB,sBAAsBd,IAA+B;CACnE,OAAOA;AACT;AAEA,MAAae,yBAAyB;AAEtC,MAAaC,mBAAmBC,MAC9BA,KAAKC,KAAAA;AAeP,MAAaM,mBACXC,SACAC,QACwB;CACxB,MAAMC,yBAAS,IAAIC,IAAI,CAAC,GAAGF,IAAIN,WAAW,GAAGM,IAAIL,iBAAiB,CAAC;CAEnE,KAAK,MAAMQ,UAAUJ,SAAS;EAC5B,QAAQI,OAAO1B,QAAf;GACE,KAAK;GACL,KAAK,YACH;GACF,SAAS;IACP,MAAM2B,mBAA0BD,OAAO1B;IACvC,MAAM,IAAI4B,MAAM,sBAAsBD,kBAAkB;GAC1D;EACF;EAEA,MAAME,oBAAoBN,IAAIJ,YAAYO,OAAO5B;EACjD,MAAMgC,WACJD,sBAAsBd,KAAAA,IAClBQ,IAAIH,WAAWS,qBACfd,KAAAA;EACN,MAAMlB,KAAKiC,UAAUjC,MAAM6B,OAAO5B;EAClC,MAAMiC,YAAYF,qBAAqBlB,sBAAsBd,EAAE;EAC/D,MAAMmC,eACJF,aAAaf,KAAAA,KAAae,SAAS9B,WAAW,QAC1C8B,SAAS1B,iBACTW,KAAAA;EAEN,IAAI,CAACS,OAAOS,IAAIpC,EAAE,GAAG;GACnB2B,OAAOU,IAAIrC,EAAE;GACb,IAAI6B,OAAO1B,WAAW,WACpBuB,IAAIN,UAAUkB,KAAKtC,EAAE;QAErB0B,IAAIL,kBAAkBiB,KAAKtC,EAAE;EAEjC,OAAO,IAAIiC,aAAaf,KAAAA,KAAae,SAAS9B,WAAW0B,OAAO1B,QAAQ;GACtE,IAAI0B,OAAO1B,WAAW,WAAW;IAC/BuB,IAAIL,oBAAoBK,IAAIL,kBAAkBkB,QAAQC,MAAMA,MAAMxC,EAAE;IACpE0B,IAAIN,UAAUkB,KAAKtC,EAAE;GACvB,OAAO;IACL0B,IAAIN,YAAYM,IAAIN,UAAUmB,QAAQC,MAAMA,MAAMxC,EAAE;IACpD0B,IAAIL,kBAAkBiB,KAAKtC,EAAE;GAC/B;EACF;EAEA0B,IAAIJ,YAAYtB,MAAMkC;EACtBR,IAAIJ,YAAYO,OAAO5B,YAAYiC;EACnCR,IAAIH,WAAWW,aAAa;GAC1B,GAAID,UAAU3B,gBAAgB,OAAO,EAAEA,aAAa,KAAc,IAAI,CAAC;GACvEN;GACAC,UAAU4B,OAAO5B;GACjBC,YAAY2B,OAAO3B;GACnBC,QAAQ0B,OAAO1B;GACfC,OAAOyB,OAAOzB;GACdK,eAAeoB,OAAOpB;GACtBJ,QAAQwB,OAAOxB;GACfE,gBACE4B,gBACA3B,QAAQkC,QAAQ;IACdzC,UAAU4B,OAAO5B;IACjBC,YAAY2B,OAAO3B;GACrB,CAAC;EACL;CACF;CACA,OAAOwB;AACT;AAaA,MAAauB,sCAAyD;CACpEL,WAAW;CACXC,eAAe;CACfC,QAAQ5B,KAAAA;CACR6B,aAAa7B,KAAAA;CACbE,WAAW,CAAA;CACXC,mBAAmB,CAAA;CACnBC,aAAa,CAAC;CACdC,YAAY,CAAC;AACf;AAEA,MAAa2B,iBACXC,UAC6C;CAC7C,IAAInD;CACJ;EACEA,KAAK,GAAGe,yBAAyBjB,WAAW;QACrCqD,MAAM7B,YAAYtB;CAC3B,MAAMkC,YAAYpB,sBAAsBd,EAAE;CAC1C,OAAO;EACLA;EACAmD,OAAO;GACL,GAAGA;GACHJ,aAAa/C;GACbsB,aAAa;IACX,GAAG6B,MAAM7B;KACRtB,KAAKkC;GACR;GACAX,YAAY;IACV,GAAG4B,MAAM5B;KACRW,YAAY;KACX/B,QAAQ;KACRH;KACAC,UAAUiB,KAAAA;KACVhB,YAAYgB,KAAAA;KACZd,OAAOc,KAAAA;KACPb,QAAQa,KAAAA;KACRZ,aAAa;IACf;GACF;EACF;CACF;AACF;AAcA,MAAa8C,8BACXD,OACAE,YACAE,oBACsB;CACtB,MAAME,UAAU,IAAI7B,IAAIuB,MAAM/B,SAAS;CACvC,MAAMsC,WAAW,IAAI9B,IAAIuB,MAAM9B,iBAAiB;CAChD,MAAMsC,iBAAqC,CAAA;CAC3C,MAAMC,kBAAsC,CAAA;CAE5C,MAAMC,YAAYC,KAA0BE,SAC1CF,IAAI1B,IAAI4B,KAAKhE,EAAE,KAAMgE,KAAK/D,aAAaiB,KAAAA,KAAa4C,IAAI1B,IAAI4B,KAAK/D,QAAQ;CAE3E,KAAK,MAAM+D,QAAQC,OAAOC,OAAOf,MAAM5B,UAAU,GAAG;EAClD,MAAM4C,SAASZ,gBAAgBa,IAAIJ,KAAKhE,EAAE;EAC1C,IAAImE,WAAWjD,KAAAA,KAAaiD,WAAW,OAAO;EAC9C,IAAIA,WAAWjD,KAAAA,KAAa8C,KAAK1D,gBAAgB,MAAM;EAEvD,IAAI0D,KAAK7D,WAAW,aAAa,CAAC0D,SAASJ,SAASO,IAAI,GAAG;GACzDL,eAAerB,KAAK0B,IAAI;GACxBP,QAAQpB,IAAI2B,KAAKhE,EAAE;EACrB,OAAO,IAAIgE,KAAK7D,WAAW,cAAc,CAAC0D,SAASH,UAAUM,IAAI,GAAG;GAClEJ,gBAAgBtB,KAAK0B,IAAI;GACzBN,SAASrB,IAAI2B,KAAKhE,EAAE;EACtB;CACF;CAEA,IAAI2D,eAAeU,WAAW,KAAKT,gBAAgBS,WAAW,GAAG,OAAOlB;CAExE,MAAMmB,YAAYR,KAAwBE,SAA2B;EACnE,MAAMO,OAAOT,IAAIU,QAAQR,KAAKhE,EAAE;EAChC,IAAIuE,SAAS,IAAI,OAAOA;EACxB,MAAME,aACJT,KAAK/D,aAAaiB,KAAAA,IAAY4C,IAAIU,QAAQR,KAAK/D,QAAQ,IAAI;EAC7D,OAAOwE,eAAe,KAAKA,aAAaC,OAAOC;CACjD;CACAhB,eAAeiB,MACZC,GAAGC,MACFR,SAASjB,WAAWjC,WAAWyD,CAAC,IAAIP,SAASjB,WAAWjC,WAAW0D,CAAC,CACxE;CACAlB,gBAAgBgB,MACbC,GAAGC,MACFR,SAASjB,WAAWhC,mBAAmBwD,CAAC,IACxCP,SAASjB,WAAWhC,mBAAmByD,CAAC,CAC5C;CAEA,OAAO;EACL,GAAG3B;EACH/B,WAAW,CAAC,GAAGuC,eAAeoB,KAAKC,MAAMA,EAAEhF,EAAE,GAAG,GAAGmD,MAAM/B,SAAS;EAClEC,mBAAmB,CACjB,GAAGuC,gBAAgBmB,KAAKC,MAAMA,EAAEhF,EAAE,GAClC,GAAGmD,MAAM9B,iBAAiB;CAE9B;AACF;AAEA,MAAa4D,kBACX9B,UAEA,IAAI+B,IAAIjB,OAAOC,OAAOf,MAAM5B,UAAU,CAAC,CAACwD,KAAKC,MAAM,CAACA,EAAEhF,IAAIgF,EAAE7E,MAAM,CAAC,CAAC;AAEtE,MAAagF,iBACXhC,OACAiC,uBACG;CACH,MAAMC,MAAMlC,MAAM7B,YAAY8D;CAC9B,IAAIC,QAAQnE,KAAAA,GAAW,OAAOA,KAAAA;CAC9B,OAAOiC,MAAM5B,WAAW8D;AAC1B;AAEA,MAAaC,uBACXnC,OACAiC,oBACAG,cACG;CACH,MAAMvB,OAAOmB,cAAchC,OAAOiC,kBAAkB;CACpD,IAAI,CAACpB,MAAM,OAAOb;CAElB,MAAM,EAAEnD,IAAIG,QAAQqF,eAAexB;CACnC,IAAIwB,eAAeD,WAAW,OAAOpC;CAErC,MAAMsC,WAAW,EAAE,GAAGtC,MAAM;CAG5B,QAAQqC,YAAR;EACE,KAAK;GACHC,SAAS1C,cAAc7B,KAAAA;GACvB;EACF,KAAK;GACHuE,SAASrE,YAAYqE,SAASrE,UAAUmB,QAAQC,MAAMA,MAAMxC,EAAE;GAC9D;EACF,KAAK;GACHyF,SAASpE,oBAAoBoE,SAASpE,kBAAkBkB,QACrDC,MAAMA,MAAMxC,EACf;GACA;EAEF,SAEE,MAAM,IAAI+B,MAAM,sBAAsBD,YAAkB;CAE5D;CAGA,QAAQyD,WAAR;EACE,KAAK;GACHE,SAASrE,YAAY,CAACpB,IAAI,GAAGyF,SAASrE,SAAS;GAC/C;EAEF,KAAK;GACHqE,SAASpE,oBAAoB,CAACrB,IAAI,GAAGyF,SAASpE,iBAAiB;GAC/D;EAEF,KAAK,WAAW;GACd,MAAMa,YAAYiB,MAAM7B,YAAY8D;GACpCK,SAASlE,aAAa0C,OAAOyB,YAC3BzB,OAAO0B,QAAQF,SAASlE,UAAU,CAAC,CAACgB,QACjC,CAACqD,SAASA,QAAQ1D,SACrB,CACF;GACAuD,SAASnE,cAAc2C,OAAOyB,YAC5BzB,OAAO0B,QAAQF,SAASnE,WAAW,CAAC,CAACiB,QAClC,GAAGsD,WAAWA,UAAU3D,SAC3B,CACF;GACA;EACF;EAEA,SAEE,MAAM,IAAIH,MAAM,sBAAsBD,WAAkB;CAE5D;CAEA,IAAIyD,cAAc,WAChBE,SAASlE,aAAa;EACpB,GAAGkE,SAASlE;GACXvB,KAAK;GACJ,GAAGgE;GACH7D,QAAQoF;EACV;CACF;CAGF,OAAOE;AACT"}
1
+ {"version":3,"file":"remote-thread-state.js","names":["RemoteThreadInitializeResponse","RemoteThreadMetadata","generateId","nullProtoRecord","RemoteThreadData","id","remoteId","externalId","status","title","custom","localOrigin","initializeTask","Promise","lastMessageAt","Date","Record","THREAD_MAPPING_ID","__brand","createThreadMappingId","LOCAL_THREAD_ID_PREFIX","normalizeCursor","c","undefined","ClassifyAccumulator","threadIds","archivedThreadIds","threadIdMap","threadData","classifyThreads","threads","acc","listed","Set","thread","_exhaustiveCheck","Error","existingMappingId","existing","mappingId","existingTask","has","add","push","filter","t","const","resolve","RemoteThreadState","isLoading","loadError","isLoadingMore","cursor","newThreadId","Readonly","createEmptyRemoteThreadState","seedNewThread","state","preserveMidLoadTransitions","priorOrder","Pick","statusAtRequest","ReadonlyMap","regular","archived","rescuedRegular","rescuedArchived","contains","ids","ReadonlySet","data","Object","values","before","get","length","position","byId","indexOf","byRemoteId","Number","MAX_SAFE_INTEGER","sort","a","b","map","d","statusSnapshot","Map","getThreadData","threadIdOrRemoteId","idx","hasOwn","reconcileInitializedThread","threadId","retainedThreadId","removedMappingId","survivorMappingId","listedMappingId","listedData","listedSlot","retainedMappingId","resolvedExternalId","initializedData","target","entries","rewire","transitionReducer","newStatus","lastStatus","nextData","newState","key","value","updateStatusReducer","promoteNewThreadReducer"],"sources":["../../../src/runtimes/remote-thread-list/remote-thread-state.ts"],"sourcesContent":["import type {\n RemoteThreadInitializeResponse,\n RemoteThreadMetadata,\n} from \"./types\";\nimport { generateId } from \"../../utils/id\";\nimport { nullProtoRecord } from \"../../utils/record\";\n\nexport type RemoteThreadData =\n | {\n readonly id: string;\n readonly remoteId: undefined;\n readonly externalId: undefined;\n readonly status: \"new\";\n readonly title: undefined;\n readonly custom: undefined;\n readonly localOrigin?: true;\n }\n | {\n readonly id: string;\n readonly initializeTask: Promise<RemoteThreadInitializeResponse>;\n readonly remoteId: undefined;\n readonly externalId: undefined;\n readonly status: \"regular\" | \"archived\";\n readonly title?: string | undefined;\n readonly custom: undefined;\n readonly localOrigin?: true;\n }\n | {\n readonly id: string;\n readonly initializeTask: Promise<RemoteThreadInitializeResponse>;\n readonly remoteId: string;\n readonly externalId: string | undefined;\n readonly status: \"regular\" | \"archived\";\n readonly title?: string | undefined;\n readonly lastMessageAt?: Date | undefined;\n readonly custom?: Record<string, unknown> | undefined;\n readonly localOrigin?: true;\n };\n\nexport type THREAD_MAPPING_ID = string & { __brand: \"THREAD_MAPPING_ID\" };\n\nexport function createThreadMappingId(id: string): THREAD_MAPPING_ID {\n return id as THREAD_MAPPING_ID;\n}\n\nexport const LOCAL_THREAD_ID_PREFIX = \"__LOCALID_\";\n\nexport const normalizeCursor = (c: string | undefined): string | undefined =>\n c || undefined;\n\nexport type ClassifyAccumulator = {\n threadIds: string[];\n archivedThreadIds: string[];\n threadIdMap: Record<string, THREAD_MAPPING_ID>;\n threadData: Record<THREAD_MAPPING_ID, RemoteThreadData>;\n};\n\n// A slot's `id` is fixed when it is minted: the hook instance manager keys live\n// thread runtimes by it, so renaming a slot would detach the runtime the user is\n// chatting in. A listed thread whose `remoteId` already maps to a slot therefore\n// refreshes that slot instead of minting a second one, and a slot minted by a\n// list() that raced ahead of the remote id collapses when `initialize()` settles.\n// `threadIds`/`archivedThreadIds` carry slot ids, never remote ids.\nexport const classifyThreads = (\n threads: readonly RemoteThreadMetadata[],\n acc: ClassifyAccumulator,\n): ClassifyAccumulator => {\n let threadIds = [...acc.threadIds];\n let archivedThreadIds = [...acc.archivedThreadIds];\n const threadIdMap = nullProtoRecord(acc.threadIdMap);\n const threadData = nullProtoRecord(acc.threadData);\n const listed = new Set([...threadIds, ...archivedThreadIds]);\n\n for (const thread of threads) {\n switch (thread.status) {\n case \"regular\":\n case \"archived\":\n break;\n default: {\n const _exhaustiveCheck: never = thread.status;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n const existingMappingId = threadIdMap[thread.remoteId];\n const existing =\n existingMappingId !== undefined\n ? threadData[existingMappingId]\n : undefined;\n const id = existing?.id ?? thread.remoteId;\n const mappingId = existingMappingId ?? createThreadMappingId(id);\n const existingTask =\n existing !== undefined && existing.status !== \"new\"\n ? existing.initializeTask\n : undefined;\n\n if (!listed.has(id)) {\n listed.add(id);\n if (thread.status === \"regular\") {\n threadIds.push(id);\n } else {\n archivedThreadIds.push(id);\n }\n } else if (existing !== undefined && existing.status !== thread.status) {\n if (thread.status === \"regular\") {\n archivedThreadIds = archivedThreadIds.filter((t) => t !== id);\n threadIds.push(id);\n } else {\n threadIds = threadIds.filter((t) => t !== id);\n archivedThreadIds.push(id);\n }\n }\n\n threadIdMap[id] = mappingId;\n threadIdMap[thread.remoteId] = mappingId;\n threadData[mappingId] = {\n ...(existing?.localOrigin === true ? { localOrigin: true as const } : {}),\n id,\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n lastMessageAt: thread.lastMessageAt,\n custom: thread.custom,\n initializeTask:\n existingTask ??\n Promise.resolve({\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n }),\n };\n }\n return { threadIds, archivedThreadIds, threadIdMap, threadData };\n};\n\nexport type RemoteThreadState = {\n readonly isLoading: boolean;\n readonly loadError: unknown;\n readonly isLoadingMore: boolean;\n readonly cursor: string | undefined;\n readonly newThreadId: string | undefined;\n readonly threadIds: readonly string[];\n readonly archivedThreadIds: readonly string[];\n readonly threadIdMap: Readonly<Record<string, THREAD_MAPPING_ID>>;\n readonly threadData: Readonly<Record<THREAD_MAPPING_ID, RemoteThreadData>>;\n};\n\nexport const createEmptyRemoteThreadState = (): RemoteThreadState => ({\n isLoading: true,\n loadError: undefined,\n isLoadingMore: false,\n cursor: undefined,\n newThreadId: undefined,\n threadIds: [],\n archivedThreadIds: [],\n threadIdMap: nullProtoRecord(),\n threadData: nullProtoRecord(),\n});\n\nexport const seedNewThread = (\n state: RemoteThreadState,\n): { id: string; state: RemoteThreadState } => {\n let id: string;\n do {\n id = `${LOCAL_THREAD_ID_PREFIX}${generateId()}`;\n } while (state.threadIdMap[id]);\n const mappingId = createThreadMappingId(id);\n return {\n id,\n state: {\n ...state,\n newThreadId: id,\n threadIdMap: nullProtoRecord(state.threadIdMap, {\n [id]: mappingId,\n }),\n threadData: nullProtoRecord(state.threadData, {\n [mappingId]: {\n status: \"new\",\n id,\n remoteId: undefined,\n externalId: undefined,\n title: undefined,\n custom: undefined,\n localOrigin: true,\n } satisfies RemoteThreadData,\n }),\n },\n };\n};\n\n// A list() response predating a mid-flight local transition (a thread\n// initialized while the request was running) omits that thread, and the\n// completed-optimistic replay cannot re-add it because the merged threadData\n// already carries the final status. Threads whose status moved from new (or\n// nonexistent) at request time to regular/archived are re-inserted at the\n// top, in the order the pre-response lists carried them: updateStatusReducer\n// prepends as transitions happen, so the pre-response lists hold newest\n// first, which threadData insertion order need not match. Threads the server already knew stay governed by the response, so\n// a server-side deletion is not resurrected — and a thread unknown to the\n// snapshot is only rescued when it carries the localOrigin marker stamped at\n// draft creation, so a deep-linked thread the fetch path deliberately\n// appended at the tail is not hoisted, whatever its remote id looks like.\nexport const preserveMidLoadTransitions = (\n state: RemoteThreadState,\n priorOrder: Pick<RemoteThreadState, \"threadIds\" | \"archivedThreadIds\">,\n statusAtRequest: ReadonlyMap<string, RemoteThreadData[\"status\"]>,\n): RemoteThreadState => {\n const regular = new Set(state.threadIds);\n const archived = new Set(state.archivedThreadIds);\n const rescuedRegular: RemoteThreadData[] = [];\n const rescuedArchived: RemoteThreadData[] = [];\n\n const contains = (ids: ReadonlySet<string>, data: RemoteThreadData) =>\n ids.has(data.id) || (data.remoteId !== undefined && ids.has(data.remoteId));\n\n for (const data of Object.values(state.threadData)) {\n const before = statusAtRequest.get(data.id);\n if (before !== undefined && before !== \"new\") continue;\n if (before === undefined && data.localOrigin !== true) continue;\n\n if (data.status === \"regular\" && !contains(regular, data)) {\n rescuedRegular.push(data);\n regular.add(data.id);\n } else if (data.status === \"archived\" && !contains(archived, data)) {\n rescuedArchived.push(data);\n archived.add(data.id);\n }\n }\n\n if (rescuedRegular.length === 0 && rescuedArchived.length === 0) return state;\n\n const position = (ids: readonly string[], data: RemoteThreadData) => {\n const byId = ids.indexOf(data.id);\n if (byId !== -1) return byId;\n const byRemoteId =\n data.remoteId !== undefined ? ids.indexOf(data.remoteId) : -1;\n return byRemoteId !== -1 ? byRemoteId : Number.MAX_SAFE_INTEGER;\n };\n rescuedRegular.sort(\n (a, b) =>\n position(priorOrder.threadIds, a) - position(priorOrder.threadIds, b),\n );\n rescuedArchived.sort(\n (a, b) =>\n position(priorOrder.archivedThreadIds, a) -\n position(priorOrder.archivedThreadIds, b),\n );\n\n return {\n ...state,\n threadIds: [...rescuedRegular.map((d) => d.id), ...state.threadIds],\n archivedThreadIds: [\n ...rescuedArchived.map((d) => d.id),\n ...state.archivedThreadIds,\n ],\n };\n};\n\nexport const statusSnapshot = (\n state: RemoteThreadState,\n): ReadonlyMap<string, RemoteThreadData[\"status\"]> =>\n new Map(Object.values(state.threadData).map((d) => [d.id, d.status]));\n\nexport const getThreadData = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n) => {\n const idx = Object.hasOwn(state.threadIdMap, threadIdOrRemoteId)\n ? state.threadIdMap[threadIdOrRemoteId]\n : undefined;\n if (idx === undefined) return undefined;\n return Object.hasOwn(state.threadData, idx)\n ? state.threadData[idx]\n : undefined;\n};\n\nexport const reconcileInitializedThread = (\n state: RemoteThreadState,\n threadId: string,\n remoteId: string,\n externalId: string | undefined,\n retainedThreadId?: string,\n): {\n state: RemoteThreadState;\n removedMappingId: THREAD_MAPPING_ID | undefined;\n survivorMappingId: THREAD_MAPPING_ID;\n} => {\n const mappingId = createThreadMappingId(threadId);\n const data = Object.hasOwn(state.threadData, mappingId)\n ? state.threadData[mappingId]\n : undefined;\n if (!data) {\n return { state, removedMappingId: undefined, survivorMappingId: mappingId };\n }\n\n // A concurrent list cannot associate the remote ID with this initializing\n // slot and may mint a duplicate. Retain the slot whose mounted runtime owns\n // local state; initialized metadata remains authoritative over list metadata.\n const listedMappingId = Object.hasOwn(state.threadIdMap, remoteId)\n ? state.threadIdMap[remoteId]\n : undefined;\n const listedData =\n listedMappingId !== undefined &&\n listedMappingId !== mappingId &&\n Object.hasOwn(state.threadData, listedMappingId)\n ? state.threadData[listedMappingId]\n : undefined;\n const listedSlot =\n listedMappingId !== undefined && listedData !== undefined\n ? { mappingId: listedMappingId, data: listedData }\n : undefined;\n const retainedMappingId =\n retainedThreadId !== undefined &&\n Object.hasOwn(state.threadIdMap, retainedThreadId)\n ? state.threadIdMap[retainedThreadId]\n : undefined;\n const survivorMappingId =\n listedSlot !== undefined && retainedMappingId === listedSlot.mappingId\n ? listedSlot.mappingId\n : mappingId;\n const removedMappingId =\n listedSlot === undefined\n ? undefined\n : survivorMappingId === mappingId\n ? listedSlot.mappingId\n : mappingId;\n const resolvedExternalId = externalId ?? listedSlot?.data.externalId;\n const threadData = nullProtoRecord(state.threadData);\n if (removedMappingId !== undefined) delete threadData[removedMappingId];\n const initializedData = {\n ...data,\n id: survivorMappingId,\n initializeTask: Promise.resolve({\n remoteId,\n externalId: resolvedExternalId,\n }),\n remoteId,\n externalId: resolvedExternalId,\n } as RemoteThreadData;\n threadData[survivorMappingId] = {\n ...listedSlot?.data,\n ...initializedData,\n title: data.title ?? listedSlot?.data.title,\n lastMessageAt:\n (\"lastMessageAt\" in data ? data.lastMessageAt : undefined) ??\n (listedSlot && \"lastMessageAt\" in listedSlot.data\n ? listedSlot.data.lastMessageAt\n : undefined),\n custom: data.custom ?? listedSlot?.data.custom,\n } as RemoteThreadData;\n\n const threadIdMap = nullProtoRecord(state.threadIdMap);\n if (removedMappingId !== undefined) {\n for (const [id, target] of Object.entries(threadIdMap)) {\n if (target === removedMappingId) threadIdMap[id] = survivorMappingId;\n }\n }\n threadIdMap[threadId] = survivorMappingId;\n threadIdMap[remoteId] = survivorMappingId;\n\n const rewire = (ids: readonly string[]) =>\n listedSlot === undefined\n ? ids\n : ids\n .filter((id) => id !== listedSlot.data.id)\n .map((id) => (id === data.id ? survivorMappingId : id));\n\n return {\n state: {\n ...state,\n threadIds: rewire(state.threadIds),\n archivedThreadIds: rewire(state.archivedThreadIds),\n threadIdMap,\n threadData,\n },\n removedMappingId,\n survivorMappingId,\n };\n};\n\nconst transitionReducer = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n newStatus: \"regular\" | \"archived\" | \"deleted\",\n initializeTask: Promise<RemoteThreadInitializeResponse> | undefined,\n) => {\n const data = getThreadData(state, threadIdOrRemoteId);\n if (!data) return state;\n\n const { id, status: lastStatus } = data;\n if (lastStatus === newStatus) return state;\n\n let nextData: RemoteThreadData | undefined;\n if (newStatus !== \"deleted\") {\n if (data.status === \"new\") {\n // The new variant holds no initialization promise, so the destination\n // union member cannot be built unless the caller supplies one.\n if (initializeTask === undefined) return state;\n nextData = { ...data, initializeTask, status: newStatus };\n } else {\n nextData = { ...data, status: newStatus };\n }\n }\n\n const newState = { ...state };\n\n // lastStatus\n switch (lastStatus) {\n case \"new\":\n newState.newThreadId = undefined;\n break;\n case \"regular\":\n newState.threadIds = newState.threadIds.filter((t) => t !== id);\n break;\n case \"archived\":\n newState.archivedThreadIds = newState.archivedThreadIds.filter(\n (t) => t !== id,\n );\n break;\n\n default: {\n const _exhaustiveCheck: never = lastStatus;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n // newStatus\n switch (newStatus) {\n case \"regular\":\n newState.threadIds = [id, ...newState.threadIds];\n break;\n\n case \"archived\":\n newState.archivedThreadIds = [id, ...newState.archivedThreadIds];\n break;\n\n case \"deleted\": {\n const mappingId = state.threadIdMap[threadIdOrRemoteId]!;\n const threadData = nullProtoRecord(newState.threadData);\n delete threadData[mappingId];\n newState.threadData = threadData;\n const threadIdMap = nullProtoRecord(newState.threadIdMap);\n for (const [key, value] of Object.entries(threadIdMap)) {\n if (value === mappingId) delete threadIdMap[key];\n }\n newState.threadIdMap = threadIdMap;\n break;\n }\n\n default: {\n const _exhaustiveCheck: never = newStatus;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n if (nextData !== undefined) {\n newState.threadData = { ...newState.threadData, [id]: nextData };\n }\n\n return newState;\n};\n\n/**\n * Transitions a thread that already exists remotely. Promoting the local draft\n * off `new` needs the initialization promise its destination variant requires,\n * so that goes through `promoteNewThreadReducer`; asking for it here leaves the\n * state unchanged.\n */\nexport const updateStatusReducer = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n newStatus: \"regular\" | \"archived\" | \"deleted\",\n) => transitionReducer(state, threadIdOrRemoteId, newStatus, undefined);\n\n/**\n * Promotes the local draft to `regular`, carrying the initialization promise\n * onto the slot.\n */\nexport const promoteNewThreadReducer = (\n state: RemoteThreadState,\n threadIdOrRemoteId: string,\n initializeTask: Promise<RemoteThreadInitializeResponse>,\n) => transitionReducer(state, threadIdOrRemoteId, \"regular\", initializeTask);\n"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ //#region src/runtimes/remote-thread-list/title-generation.d.ts
2
+ type ThreadTitleClaim = {
3
+ readonly title: string;
4
+ readonly order: number;
5
+ readonly settled: Promise<boolean>;
6
+ readonly settle: (renamed: boolean) => void;
7
+ };
8
+ type ThreadTitleGeneration = {
9
+ readonly automatic: boolean;
10
+ readonly order: number;
11
+ claim: ThreadTitleClaim | null;
12
+ beforeGenerationClaims: readonly ThreadTitleClaim[];
13
+ superseded: boolean;
14
+ readonly persisted: Promise<string | undefined>;
15
+ readonly settlePersisted: (title: string | undefined) => void;
16
+ };
17
+ type ThreadTitleState = {
18
+ generations: Set<ThreadTitleGeneration>;
19
+ pendingClaim: ThreadTitleClaim | null;
20
+ inFlightClaims: Set<ThreadTitleClaim>;
21
+ manualTitle: string | undefined;
22
+ latestExplicit: ThreadTitleGeneration | null;
23
+ nextOrder: number;
24
+ };
25
+ type ThreadTitleGenerationRun = {
26
+ states: Map<string, ThreadTitleState>;
27
+ threadId: string;
28
+ automatic: boolean;
29
+ generate: (onTitle: (title: string | undefined) => Promise<void>) => Promise<void>;
30
+ rename: (title: string) => Promise<void>;
31
+ applyTitle: (title: string | undefined) => Promise<void>;
32
+ };
33
+ declare function startThreadTitleRename(states: Map<string, ThreadTitleState>, threadId: string, title: string): ThreadTitleClaim;
34
+ declare function finishThreadTitleRename(states: Map<string, ThreadTitleState>, threadId: string, claim: ThreadTitleClaim, renamed: boolean): void;
35
+ declare function clearThreadTitleState(states: Map<string, ThreadTitleState>, threadId: string): void;
36
+ /**
37
+ * Runs one title generation under the per-thread rename claims and generation
38
+ * ordering, so the title that wins locally is also the title left on the
39
+ * server.
40
+ *
41
+ * A generated run persists the title itself, and the adapter exposes no
42
+ * compare-and-set, so the run that loses reasserts the winner through `rename`
43
+ * only after `generate` has resolved. Reasserting mid-stream would race the
44
+ * run's own write and lose the winning title on the server.
45
+ */
46
+ declare function runThreadTitleGeneration({ states, threadId, automatic, generate, rename, applyTitle }: ThreadTitleGenerationRun): Promise<void>;
47
+ //#endregion
48
+ export { ThreadTitleClaim, ThreadTitleGenerationRun, ThreadTitleState, clearThreadTitleState, finishThreadTitleRename, runThreadTitleGeneration, startThreadTitleRename };
49
+ //# sourceMappingURL=title-generation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-generation.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/title-generation.ts"],"mappings":";KAAY;WACD;WACA;WACA,SAAS;WACT,SAAS;;KAGf;WACM;WACA;EACT,OAAO;EACP,iCAAiC;EACjC;WACS,WAAW;WACX,kBAAkB;;KAGjB;EACV,aAAa,IAAI;EACjB,cAAc;EACd,gBAAgB,IAAI;EACpB;EACA,gBAAgB;EAChB;;KAGU;EACV,QAAQ,YAAY;EACpB;EACA;EACA,WACE,UAAU,8BAA8B,kBACrC;EACL,SAAS,kBAAkB;EAC3B,aAAa,8BAA8B;;iBAuD7B,uBACd,QAAQ,YAAY,mBACpB,kBACA,gBACC;iBAoBa,wBACd,QAAQ,YAAY,mBACpB,kBACA,OAAO,kBACP;iBA2Bc,sBACd,QAAQ,YAAY,mBACpB;;;;;;;;;;;iBAsDoB,2BACpB,QACA,UACA,WACA,UACA,QACA,cACC,2BAA2B"}
@@ -0,0 +1,197 @@
1
+ //#region src/runtimes/remote-thread-list/title-generation.ts
2
+ function getThreadTitleState(states, threadId) {
3
+ let state = states.get(threadId);
4
+ if (state === void 0) {
5
+ state = {
6
+ generations: /* @__PURE__ */ new Set(),
7
+ pendingClaim: null,
8
+ inFlightClaims: /* @__PURE__ */ new Set(),
9
+ manualTitle: void 0,
10
+ latestExplicit: null,
11
+ nextOrder: 0
12
+ };
13
+ states.set(threadId, state);
14
+ }
15
+ return state;
16
+ }
17
+ function pruneThreadTitleState(states, threadId, state) {
18
+ if (state.generations.size === 0 && state.pendingClaim === null && state.inFlightClaims.size === 0 && state.manualTitle === void 0 && states.get(threadId) === state) states.delete(threadId);
19
+ }
20
+ function isCurrentGeneration(state, generation) {
21
+ return !generation.superseded && (state.latestExplicit?.order ?? 0) <= generation.order;
22
+ }
23
+ function isCurrentClaim(state, claim) {
24
+ return (state.latestExplicit?.order ?? 0) < claim.order;
25
+ }
26
+ function startThreadTitleRename(states, threadId, title) {
27
+ const state = getThreadTitleState(states, threadId);
28
+ let settle;
29
+ const settled = new Promise((resolve) => {
30
+ settle = resolve;
31
+ });
32
+ const claim = {
33
+ title,
34
+ order: ++state.nextOrder,
35
+ settled,
36
+ settle
37
+ };
38
+ state.pendingClaim = claim;
39
+ state.inFlightClaims.add(claim);
40
+ for (const generation of state.generations) if (generation.order < claim.order) generation.claim = claim;
41
+ return claim;
42
+ }
43
+ function finishThreadTitleRename(states, threadId, claim, renamed) {
44
+ claim.settle(renamed);
45
+ const state = states.get(threadId);
46
+ if (state === void 0) return;
47
+ state.inFlightClaims.delete(claim);
48
+ if (state.pendingClaim === claim) {
49
+ state.pendingClaim = null;
50
+ if (renamed) state.manualTitle = claim.title;
51
+ }
52
+ pruneThreadTitleState(states, threadId, state);
53
+ }
54
+ function takeManualTitle(states, threadId, state) {
55
+ const retained = state.manualTitle;
56
+ if (retained === void 0) return void 0;
57
+ state.manualTitle = void 0;
58
+ pruneThreadTitleState(states, threadId, state);
59
+ return retained;
60
+ }
61
+ function clearThreadTitleState(states, threadId) {
62
+ states.delete(threadId);
63
+ }
64
+ function startThreadTitleGeneration(states, threadId, automatic) {
65
+ const state = getThreadTitleState(states, threadId);
66
+ if (automatic && state.pendingClaim === null && takeManualTitle(states, threadId, state) !== void 0) return null;
67
+ let settlePersisted;
68
+ const persisted = new Promise((resolve) => {
69
+ settlePersisted = resolve;
70
+ });
71
+ const generation = {
72
+ automatic,
73
+ order: ++state.nextOrder,
74
+ claim: automatic ? state.pendingClaim : null,
75
+ beforeGenerationClaims: automatic ? [] : [...state.inFlightClaims],
76
+ superseded: false,
77
+ persisted,
78
+ settlePersisted
79
+ };
80
+ if (!automatic) {
81
+ state.pendingClaim = null;
82
+ state.manualTitle = void 0;
83
+ state.latestExplicit = generation;
84
+ for (const active of state.generations) if (active.automatic) active.superseded = true;
85
+ }
86
+ state.generations.add(generation);
87
+ return generation;
88
+ }
89
+ /**
90
+ * Runs one title generation under the per-thread rename claims and generation
91
+ * ordering, so the title that wins locally is also the title left on the
92
+ * server.
93
+ *
94
+ * A generated run persists the title itself, and the adapter exposes no
95
+ * compare-and-set, so the run that loses reasserts the winner through `rename`
96
+ * only after `generate` has resolved. Reasserting mid-stream would race the
97
+ * run's own write and lose the winning title on the server.
98
+ */
99
+ async function runThreadTitleGeneration({ states, threadId, automatic, generate, rename, applyTitle }) {
100
+ const state = getThreadTitleState(states, threadId);
101
+ const generation = startThreadTitleGeneration(states, threadId, automatic);
102
+ if (generation === null) return;
103
+ let persistedTitle;
104
+ let persistedOrder = generation.order;
105
+ const settleClaim = async (claim) => {
106
+ const renamed = await claim.settled;
107
+ if (generation.claim !== claim) return void 0;
108
+ if (!renamed) {
109
+ generation.claim = null;
110
+ if (state.pendingClaim === claim) state.pendingClaim = null;
111
+ }
112
+ return renamed;
113
+ };
114
+ const retainManualTitle = () => automatic && takeManualTitle(states, threadId, state) !== void 0;
115
+ const repairLostRace = async () => {
116
+ if (persistedTitle === void 0) return;
117
+ while (true) {
118
+ const claim = generation.claim;
119
+ if (claim !== null && claim.order > persistedOrder && isCurrentClaim(state, claim)) {
120
+ if (await settleClaim(claim) === true) {
121
+ persistedTitle = claim.title;
122
+ persistedOrder = claim.order;
123
+ await rename(claim.title);
124
+ }
125
+ continue;
126
+ }
127
+ const winner = state.latestExplicit;
128
+ if (winner === null || winner.order <= persistedOrder) return;
129
+ const title = await winner.persisted;
130
+ if (state.latestExplicit !== winner) continue;
131
+ persistedOrder = winner.order;
132
+ if (title === void 0 || title === persistedTitle) return;
133
+ persistedTitle = title;
134
+ await rename(title);
135
+ }
136
+ };
137
+ const runGeneration = async () => {
138
+ if (generation.beforeGenerationClaims.length > 0) await Promise.all(generation.beforeGenerationClaims.map((claim) => claim.settled));
139
+ if (generation.claim !== null) {
140
+ const renamed = await settleClaim(generation.claim);
141
+ if (renamed === true) {
142
+ generation.superseded = true;
143
+ return;
144
+ }
145
+ if (renamed === false && retainManualTitle()) return;
146
+ }
147
+ if (!isCurrentGeneration(state, generation)) return;
148
+ let sawTitle = false;
149
+ let lastTitle;
150
+ await generate(async (title) => {
151
+ sawTitle = true;
152
+ lastTitle = title;
153
+ if (title !== void 0) persistedTitle = title;
154
+ const claim = generation.claim;
155
+ if (claim !== null) {
156
+ if (await settleClaim(claim) !== false) return;
157
+ if (retainManualTitle()) {
158
+ generation.superseded = true;
159
+ return;
160
+ }
161
+ }
162
+ if (isCurrentGeneration(state, generation)) await applyTitle(lastTitle);
163
+ });
164
+ while (true) {
165
+ const claim = generation.claim;
166
+ if (claim === null) return;
167
+ const renamed = await settleClaim(claim);
168
+ if (renamed === void 0) continue;
169
+ if (renamed === false) {
170
+ if (retainManualTitle()) return;
171
+ if (sawTitle && isCurrentGeneration(state, generation)) await applyTitle(lastTitle);
172
+ return;
173
+ }
174
+ if (!isCurrentClaim(state, claim)) return;
175
+ await rename(claim.title);
176
+ persistedTitle = claim.title;
177
+ persistedOrder = claim.order;
178
+ if (generation.claim !== claim) continue;
179
+ if (!isCurrentGeneration(state, generation)) return;
180
+ await applyTitle(claim.title);
181
+ generation.superseded = true;
182
+ return;
183
+ }
184
+ };
185
+ try {
186
+ await runGeneration();
187
+ await repairLostRace();
188
+ } finally {
189
+ generation.settlePersisted(persistedTitle);
190
+ state.generations.delete(generation);
191
+ pruneThreadTitleState(states, threadId, state);
192
+ }
193
+ }
194
+ //#endregion
195
+ export { clearThreadTitleState, finishThreadTitleRename, runThreadTitleGeneration, startThreadTitleRename };
196
+
197
+ //# sourceMappingURL=title-generation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-generation.js","names":["ThreadTitleClaim","title","order","settled","Promise","settle","renamed","ThreadTitleGeneration","automatic","claim","beforeGenerationClaims","superseded","persisted","settlePersisted","ThreadTitleState","generations","Set","pendingClaim","inFlightClaims","manualTitle","latestExplicit","nextOrder","ThreadTitleGenerationRun","states","Map","threadId","generate","onTitle","rename","applyTitle","getThreadTitleState","state","get","undefined","set","pruneThreadTitleState","size","delete","isCurrentGeneration","generation","isCurrentClaim","startThreadTitleRename","resolve","add","finishThreadTitleRename","takeManualTitle","retained","clearThreadTitleState","startThreadTitleGeneration","active","runThreadTitleGeneration","persistedTitle","persistedOrder","settleClaim","retainManualTitle","repairLostRace","winner","runGeneration","length","all","map","sawTitle","lastTitle"],"sources":["../../../src/runtimes/remote-thread-list/title-generation.ts"],"sourcesContent":["export type ThreadTitleClaim = {\n readonly title: string;\n readonly order: number;\n readonly settled: Promise<boolean>;\n readonly settle: (renamed: boolean) => void;\n};\n\ntype ThreadTitleGeneration = {\n readonly automatic: boolean;\n readonly order: number;\n claim: ThreadTitleClaim | null;\n beforeGenerationClaims: readonly ThreadTitleClaim[];\n superseded: boolean;\n readonly persisted: Promise<string | undefined>;\n readonly settlePersisted: (title: string | undefined) => void;\n};\n\nexport type ThreadTitleState = {\n generations: Set<ThreadTitleGeneration>;\n pendingClaim: ThreadTitleClaim | null;\n inFlightClaims: Set<ThreadTitleClaim>;\n manualTitle: string | undefined;\n latestExplicit: ThreadTitleGeneration | null;\n nextOrder: number;\n};\n\nexport type ThreadTitleGenerationRun = {\n states: Map<string, ThreadTitleState>;\n threadId: string;\n automatic: boolean;\n generate: (\n onTitle: (title: string | undefined) => Promise<void>,\n ) => Promise<void>;\n rename: (title: string) => Promise<void>;\n applyTitle: (title: string | undefined) => Promise<void>;\n};\n\nfunction getThreadTitleState(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n): ThreadTitleState {\n let state = states.get(threadId);\n if (state === undefined) {\n state = {\n generations: new Set(),\n pendingClaim: null,\n inFlightClaims: new Set(),\n manualTitle: undefined,\n latestExplicit: null,\n nextOrder: 0,\n };\n states.set(threadId, state);\n }\n return state;\n}\n\nfunction pruneThreadTitleState(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n state: ThreadTitleState,\n): void {\n if (\n state.generations.size === 0 &&\n state.pendingClaim === null &&\n state.inFlightClaims.size === 0 &&\n state.manualTitle === undefined &&\n states.get(threadId) === state\n ) {\n states.delete(threadId);\n }\n}\n\nfunction isCurrentGeneration(\n state: ThreadTitleState,\n generation: ThreadTitleGeneration,\n): boolean {\n return (\n !generation.superseded &&\n (state.latestExplicit?.order ?? 0) <= generation.order\n );\n}\n\nfunction isCurrentClaim(\n state: ThreadTitleState,\n claim: ThreadTitleClaim,\n): boolean {\n return (state.latestExplicit?.order ?? 0) < claim.order;\n}\n\nexport function startThreadTitleRename(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n title: string,\n): ThreadTitleClaim {\n const state = getThreadTitleState(states, threadId);\n let settle!: (renamed: boolean) => void;\n const settled = new Promise<boolean>((resolve) => {\n settle = resolve;\n });\n const claim: ThreadTitleClaim = {\n title,\n order: ++state.nextOrder,\n settled,\n settle,\n };\n state.pendingClaim = claim;\n state.inFlightClaims.add(claim);\n for (const generation of state.generations) {\n if (generation.order < claim.order) generation.claim = claim;\n }\n return claim;\n}\n\nexport function finishThreadTitleRename(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n claim: ThreadTitleClaim,\n renamed: boolean,\n): void {\n claim.settle(renamed);\n const state = states.get(threadId);\n if (state === undefined) return;\n state.inFlightClaims.delete(claim);\n if (state.pendingClaim === claim) {\n state.pendingClaim = null;\n if (renamed) {\n state.manualTitle = claim.title;\n }\n }\n pruneThreadTitleState(states, threadId, state);\n}\n\nfunction takeManualTitle(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n state: ThreadTitleState,\n): string | undefined {\n const retained = state.manualTitle;\n if (retained === undefined) return undefined;\n state.manualTitle = undefined;\n pruneThreadTitleState(states, threadId, state);\n return retained;\n}\n\nexport function clearThreadTitleState(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n): void {\n states.delete(threadId);\n}\n\nfunction startThreadTitleGeneration(\n states: Map<string, ThreadTitleState>,\n threadId: string,\n automatic: boolean,\n): ThreadTitleGeneration | null {\n const state = getThreadTitleState(states, threadId);\n if (\n automatic &&\n state.pendingClaim === null &&\n takeManualTitle(states, threadId, state) !== undefined\n ) {\n return null;\n }\n\n let settlePersisted!: (title: string | undefined) => void;\n const persisted = new Promise<string | undefined>((resolve) => {\n settlePersisted = resolve;\n });\n const generation: ThreadTitleGeneration = {\n automatic,\n order: ++state.nextOrder,\n claim: automatic ? state.pendingClaim : null,\n beforeGenerationClaims: automatic ? [] : [...state.inFlightClaims],\n superseded: false,\n persisted,\n settlePersisted,\n };\n if (!automatic) {\n state.pendingClaim = null;\n state.manualTitle = undefined;\n state.latestExplicit = generation;\n for (const active of state.generations) {\n if (active.automatic) active.superseded = true;\n }\n }\n state.generations.add(generation);\n return generation;\n}\n\n/**\n * Runs one title generation under the per-thread rename claims and generation\n * ordering, so the title that wins locally is also the title left on the\n * server.\n *\n * A generated run persists the title itself, and the adapter exposes no\n * compare-and-set, so the run that loses reasserts the winner through `rename`\n * only after `generate` has resolved. Reasserting mid-stream would race the\n * run's own write and lose the winning title on the server.\n */\nexport async function runThreadTitleGeneration({\n states,\n threadId,\n automatic,\n generate,\n rename,\n applyTitle,\n}: ThreadTitleGenerationRun): Promise<void> {\n const state = getThreadTitleState(states, threadId);\n const generation = startThreadTitleGeneration(states, threadId, automatic);\n if (generation === null) return;\n\n let persistedTitle: string | undefined;\n let persistedOrder = generation.order;\n\n const settleClaim = async (claim: ThreadTitleClaim) => {\n const renamed = await claim.settled;\n if (generation.claim !== claim) return undefined;\n if (!renamed) {\n generation.claim = null;\n if (state.pendingClaim === claim) state.pendingClaim = null;\n }\n return renamed;\n };\n\n const retainManualTitle = () =>\n automatic && takeManualTitle(states, threadId, state) !== undefined;\n\n // `generate` resolves only once the run has persisted its title, so a run\n // that lost the ordering race while it streamed has already overwritten the\n // winner. It waits for the winning generation to persist its own title and\n // writes that title back.\n const repairLostRace = async () => {\n if (persistedTitle === undefined) return;\n while (true) {\n const claim = generation.claim;\n if (\n claim !== null &&\n claim.order > persistedOrder &&\n isCurrentClaim(state, claim)\n ) {\n const renamed = await settleClaim(claim);\n if (renamed === true) {\n persistedTitle = claim.title;\n persistedOrder = claim.order;\n await rename(claim.title);\n }\n continue;\n }\n const winner = state.latestExplicit;\n if (winner === null || winner.order <= persistedOrder) return;\n const title = await winner.persisted;\n if (state.latestExplicit !== winner) continue;\n persistedOrder = winner.order;\n if (title === undefined || title === persistedTitle) return;\n persistedTitle = title;\n await rename(title);\n }\n };\n\n const runGeneration = async () => {\n // An explicit generation waits for every earlier rename because any of\n // those server writes may settle last.\n if (generation.beforeGenerationClaims.length > 0) {\n await Promise.all(\n generation.beforeGenerationClaims.map((claim) => claim.settled),\n );\n }\n if (generation.claim !== null) {\n const renamed = await settleClaim(generation.claim);\n if (renamed === true) {\n generation.superseded = true;\n return;\n }\n if (renamed === false && retainManualTitle()) return;\n }\n if (!isCurrentGeneration(state, generation)) return;\n\n let sawTitle = false;\n let lastTitle: string | undefined;\n await generate(async (title) => {\n sawTitle = true;\n lastTitle = title;\n if (title !== undefined) persistedTitle = title;\n const claim = generation.claim;\n if (claim !== null) {\n const renamed = await settleClaim(claim);\n if (renamed !== false) return;\n if (retainManualTitle()) {\n generation.superseded = true;\n return;\n }\n }\n if (isCurrentGeneration(state, generation)) await applyTitle(lastTitle);\n });\n\n while (true) {\n const claim = generation.claim;\n if (claim === null) return;\n const renamed = await settleClaim(claim);\n if (renamed === undefined) continue;\n if (renamed === false) {\n if (retainManualTitle()) return;\n if (sawTitle && isCurrentGeneration(state, generation)) {\n await applyTitle(lastTitle);\n }\n return;\n }\n if (!isCurrentClaim(state, claim)) return;\n await rename(claim.title);\n persistedTitle = claim.title;\n persistedOrder = claim.order;\n if (generation.claim !== claim) continue;\n if (!isCurrentGeneration(state, generation)) return;\n await applyTitle(claim.title);\n generation.superseded = true;\n return;\n }\n };\n\n try {\n await runGeneration();\n await repairLostRace();\n } finally {\n generation.settlePersisted(persistedTitle);\n state.generations.delete(generation);\n pruneThreadTitleState(states, threadId, state);\n }\n}\n"],"mappings":"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"}
@@ -1,9 +1,11 @@
1
+ import { AssistantMessageStream } from "assistant-stream";
1
2
  //#region src/runtimes/remote-thread-list/title.d.ts
2
3
  declare const isTitleSourceMessage: (message: {
3
4
  status?: {
4
5
  type: string;
5
6
  } | undefined;
6
7
  }) => boolean;
8
+ declare const applyTitleStream: (stream: Parameters<typeof AssistantMessageStream.fromAssistantStream>[0], onTitle: (title: string | undefined) => Promise<void>) => Promise<void>;
7
9
  //#endregion
8
- export { isTitleSourceMessage };
10
+ export { applyTitleStream, isTitleSourceMessage };
9
11
  //# sourceMappingURL=title.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"title.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/title.ts"],"mappings":";cAAa,uBAAwB;EACnC;IAAW"}
1
+ {"version":3,"file":"title.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/title.ts"],"mappings":";;cAEa,uBAAwB;EACnC;IAAW;;;cAGA,mBACX,QAAQ,kBAAkB,uBAAuB,yBACjD,UAAU,8BAA8B,kBAAa"}
@@ -1,6 +1,14 @@
1
+ import { AssistantMessageStream } from "assistant-stream";
1
2
  //#region src/runtimes/remote-thread-list/title.ts
2
3
  const isTitleSourceMessage = (message) => message.status?.type !== "running";
4
+ const applyTitleStream = async (stream, onTitle) => {
5
+ const messageStream = AssistantMessageStream.fromAssistantStream(stream);
6
+ for await (const result of messageStream) {
7
+ const title = result.parts.filter((part) => part.type === "text")[0]?.text;
8
+ if (title?.trim()) await onTitle(title);
9
+ }
10
+ };
3
11
  //#endregion
4
- export { isTitleSourceMessage };
12
+ export { applyTitleStream, isTitleSourceMessage };
5
13
 
6
14
  //# sourceMappingURL=title.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"title.js","names":["isTitleSourceMessage","message","status","type"],"sources":["../../../src/runtimes/remote-thread-list/title.ts"],"sourcesContent":["export const isTitleSourceMessage = (message: {\n status?: { type: string } | undefined;\n}) => message.status?.type !== \"running\";\n"],"mappings":";AAAA,MAAaA,wBAAwBC,YAE/BA,QAAQC,QAAQC,SAAS"}
1
+ {"version":3,"file":"title.js","names":["AssistantMessageStream","isTitleSourceMessage","message","status","type","applyTitleStream","stream","Parameters","fromAssistantStream","onTitle","title","Promise","messageStream","result","parts","filter","part","text","trim"],"sources":["../../../src/runtimes/remote-thread-list/title.ts"],"sourcesContent":["import { AssistantMessageStream } from \"assistant-stream\";\n\nexport const isTitleSourceMessage = (message: {\n status?: { type: string } | undefined;\n}) => message.status?.type !== \"running\";\n\nexport const applyTitleStream = async (\n stream: Parameters<typeof AssistantMessageStream.fromAssistantStream>[0],\n onTitle: (title: string | undefined) => Promise<void>,\n) => {\n const messageStream = AssistantMessageStream.fromAssistantStream(stream);\n for await (const result of messageStream) {\n const title = result.parts.filter((part) => part.type === \"text\")[0]?.text;\n if (title?.trim()) await onTitle(title);\n }\n};\n"],"mappings":";;AAEA,MAAaC,wBAAwBC,YAE/BA,QAAQC,QAAQC,SAAS;AAE/B,MAAaC,mBAAmB,OAC9BC,QACAG,YACG;CACH,MAAMG,gBAAgBZ,uBAAuBQ,oBAAoBF,MAAM;CACvE,WAAW,MAAMO,UAAUD,eAAe;EACxC,MAAMF,QAAQG,OAAOC,MAAMC,QAAQC,SAASA,KAAKZ,SAAS,MAAM,CAAC,CAAC,EAAE,EAAEa;EACtE,IAAIP,OAAOQ,KAAK,GAAG,MAAMT,QAAQC,KAAK;CACxC;AACF"}
@@ -1,5 +1,6 @@
1
1
  import { ThreadMessage } from "../../types/message.js";
2
2
  import { AttachmentAdapter } from "../../adapters/attachment.js";
3
+ import { FeedbackAdapter } from "../../adapters/feedback.js";
3
4
  import { ModelContextProvider } from "../../model-context/types.js";
4
5
  import { ThreadHistoryAdapter } from "../../adapters/thread-history.js";
5
6
  import { AssistantRuntime } from "../../runtime/api/assistant-runtime.js";
@@ -32,6 +33,7 @@ type RuntimeAdapters = {
32
33
  modelContext?: ModelContextProvider | undefined;
33
34
  history?: ThreadHistoryAdapter | undefined;
34
35
  attachments?: AttachmentAdapter | undefined;
36
+ feedback?: FeedbackAdapter | undefined;
35
37
  };
36
38
  type RemoteThreadListAdapter = {
37
39
  list(params?: RemoteThreadListPageOptions): Promise<RemoteThreadListResponse>;
@@ -41,6 +43,14 @@ type RemoteThreadListAdapter = {
41
43
  unarchive(remoteId: string): Promise<void>;
42
44
  delete(remoteId: string): Promise<void>;
43
45
  initialize(threadId: string): Promise<RemoteThreadInitializeResponse>;
46
+ /**
47
+ * Generates a title for the thread and streams it back.
48
+ *
49
+ * When the generation persists the title itself, the returned stream must
50
+ * not complete before that write has landed. Concurrent generations are
51
+ * ordered by stream completion, and a run whose write outlives its stream
52
+ * can overwrite a newer title.
53
+ */
44
54
  generateTitle(remoteId: string, unstable_messages: readonly ThreadMessage[]): Promise<AssistantStream>;
45
55
  fetch(threadId: string): Promise<RemoteThreadMetadata>;
46
56
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/types.ts"],"mappings":";;;;;;;KAQK;EAAkC;;KAE3B,sCACN,OAAO,+CACH,OAAO;KAGL;EACV;EACA;;KAGU;WACD;WACA;WACA;WACA;WACA,gBAAgB;WAChB,SAAS;;KAGR;EACV,SAAS;EACT;;KAGU;EACV;;KAGU;EACV,eAAe;EACf,UAAU;EACV,cAAc;;KAGJ;EACV,KAAK,SAAS,8BAA8B,QAAQ;EAEpD,OAAO,kBAAkB,mBAAmB;EAC5C,cACE,kBACA,QAAQ,sCACP;EACH,QAAQ,mBAAmB;EAC3B,UAAU,mBAAmB;EAC7B,OAAO,mBAAmB;EAC1B,WAAW,mBAAmB,QAAQ;EACtC,cACE,kBACA,4BAA4B,kBAC3B,QAAQ;EACX,MAAM,mBAAmB,QAAQ;;;;;;;;;;;;;;;;EAiBjC,oBAAoB;;;;;;;;;;;;;;;;EAiBpB,8BAA8B;;KAGpB;EACV,mBAAmB;;;;EAKnB,SAAS;;;;;;;;EAST;;;;;;EAOA;;;;;;;;;;;;;EAcA,qBAAqB;;;;;;EAOrB"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/runtimes/remote-thread-list/types.ts"],"mappings":";;;;;;;;KASK;EAAkC;;KAE3B,sCACN,OAAO,+CACH,OAAO;KAGL;EACV;EACA;;KAGU;WACD;WACA;WACA;WACA;WACA,gBAAgB;WAChB,SAAS;;KAGR;EACV,SAAS;EACT;;KAGU;EACV;;KAGU;EACV,eAAe;EACf,UAAU;EACV,cAAc;EACd,WAAW;;KAGD;EACV,KAAK,SAAS,8BAA8B,QAAQ;EAEpD,OAAO,kBAAkB,mBAAmB;EAC5C,cACE,kBACA,QAAQ,sCACP;EACH,QAAQ,mBAAmB;EAC3B,UAAU,mBAAmB;EAC7B,OAAO,mBAAmB;EAC1B,WAAW,mBAAmB,QAAQ;;;;;;;;;EAStC,cACE,kBACA,4BAA4B,kBAC3B,QAAQ;EACX,MAAM,mBAAmB,QAAQ;;;;;;;;;;;;;;;;EAiBjC,oBAAoB;;;;;;;;;;;;;;;;EAiBpB,8BAA8B;;KAGpB;EACV,mBAAmB;;;;EAKnB,SAAS;;;;;;;;EAST;;;;;;EAOA;;;;;;;;;;;;;EAcA,qBAAqB;;;;;;EAOrB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ToolInvocationTracker.d.ts","names":[],"sources":["../../../src/runtimes/tool-invocations/ToolInvocationTracker.ts"],"mappings":";;;;;;;KAwBY;EACN;;EAEA;EACA;IAAW;IAAe;;;KAGpB;WACD;WACA;WACA;WACA,QAAQ;WACR;WACA,WAAW;WACX,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;cA+EtB;mBACM;mBACA;mBACA;mBAIA;mBACA;mBAQA;;;;;;;mBAOA;mBACA;UAET;UAEA;UACA;;UAGA;UACA;UAEA;;;;;;;;;;;UAYA;UACA;EAGN,YAAA,gBAAgB,eAAe,mBAC/B,WAAW,sBAAsB,WACjC,oBAAoB,UAAU;;;;;;UAcxB;;;;;EAsDD,SAAS,UAAU,sBAAsB;;;;;;EAmEzC;;;;;;;;;;EA8BA,MAAM;IAAY;MAA6B;;;;;;;EA2C/C,OAAO,oBAAoB;;;;;;;EAoB3B,eAAe,oBAAoB;UAMlC;UA6CA;UAaA;UAmCA;UAcA;UA0BA;UAkCA;UAWA;UAaA;UAOA;UAUA;;;;;;;UAeA;UAcA;;;;;;;;UA8BA;UAqBA;UA0GA;;kBAmFO;OACH,kBAAkB;OAElB;aACD,mBAAmB;;aAEnB;;;;;;aAMA;;OAGC;;;;;IAKV,WAAW,SAAS;;;;;;IAMpB,mBACE,UAAU,oBAAoB"}
1
+ {"version":3,"file":"ToolInvocationTracker.d.ts","names":[],"sources":["../../../src/runtimes/tool-invocations/ToolInvocationTracker.ts"],"mappings":";;;;;;;KAwBY;EACN;;EAEA;EACA;IAAW;IAAe;;;KAGpB;WACD;WACA;WACA;WACA,QAAQ;WACR;WACA,WAAW;WACX,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;cA+EtB;mBACM;mBACA;mBACA;mBAIA;mBACA;mBAQA;;;;;;;mBAOA;mBACA;UAET;UAEA;UACA;;UAGA;UACA;UAEA;;;;;;;;;;;UAYA;UACA;EAGN,YAAA,gBAAgB,eAAe,mBAC/B,WAAW,sBAAsB,WACjC,oBAAoB,UAAU;;;;;;UAcxB;;;;;EAsDD,SAAS,UAAU,sBAAsB;;;;;;EAmEzC;;;;;;;;;;EA8BA,MAAM;IAAY;MAA6B;;;;;;;EA2C/C,OAAO,oBAAoB;;;;;;;EAoB3B,eAAe,oBAAoB;UAMlC;UA6CA;UAaA;UAmCA;UAcA;UA0BA;UAkCA;UAWA;UAaA;UAOA;UAUA;;;;;;;UAeA;UAcA;;;;;;;;UA8BA;UAqBA;UA0GA;;kBAuFO;OACH,kBAAkB;OAElB;aACD,mBAAmB;;aAEnB;;;;;;aAMA;;OAGC;;;;;IAKV,WAAW,SAAS;;;;;;IAMpB,mBACE,UAAU,oBAAoB"}
@@ -487,7 +487,8 @@ var ToolInvocationTracker = class {
487
487
  let entry = existing;
488
488
  if (content.result !== void 0) this._discardedToolCallIds.delete(content.toolCallId);
489
489
  if (entry && !entry.controller) {
490
- if (!(content.argsText !== entry.argsText || content.result !== void 0 !== entry.hasResult)) continue;
490
+ if (entry.hasResult) continue;
491
+ if (!(content.argsText !== entry.argsText && !(isArgsTextComplete(entry.argsText) && isArgsTextComplete(content.argsText) && isEquivalentCompleteArgsText(entry.argsText, content.argsText))) && content.result === void 0) continue;
491
492
  this._entries.delete(content.toolCallId);
492
493
  entry = void 0;
493
494
  }