@assistant-ui/core 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/dist/adapters/attachment.d.ts.map +1 -1
  2. package/dist/adapters/attachment.js +5 -4
  3. package/dist/adapters/attachment.js.map +1 -1
  4. package/dist/index.d.ts +3 -3
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/internal.d.ts +4 -2
  8. package/dist/internal.js +4 -2
  9. package/dist/model-context/frame/host.d.ts.map +1 -1
  10. package/dist/model-context/frame/host.js +10 -4
  11. package/dist/model-context/frame/host.js.map +1 -1
  12. package/dist/model-context/frame/provider.d.ts +5 -0
  13. package/dist/model-context/frame/provider.d.ts.map +1 -1
  14. package/dist/model-context/frame/provider.js +101 -28
  15. package/dist/model-context/frame/provider.js.map +1 -1
  16. package/dist/model-context/interactable-composer-metadata.d.ts.map +1 -1
  17. package/dist/model-context/interactable-composer-metadata.js +16 -9
  18. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  19. package/dist/model-context/registry.d.ts.map +1 -1
  20. package/dist/model-context/registry.js +3 -5
  21. package/dist/model-context/registry.js.map +1 -1
  22. package/dist/model-context/tool-call-text.d.ts +26 -0
  23. package/dist/model-context/tool-call-text.d.ts.map +1 -0
  24. package/dist/model-context/tool-call-text.js +18 -0
  25. package/dist/model-context/tool-call-text.js.map +1 -0
  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/RuntimeAdapter.js +1 -1
  30. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  31. package/dist/react/adapters/LocalStorageThreadListAdapter.js +1 -1
  32. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  33. package/dist/react/client/AdaptedRemoteThread.js +1 -1
  34. package/dist/react/client/InMemoryThreadList.d.ts.map +1 -1
  35. package/dist/react/client/InMemoryThreadList.js +63 -57
  36. package/dist/react/client/InMemoryThreadList.js.map +1 -1
  37. package/dist/react/client/Interactables.d.ts.map +1 -1
  38. package/dist/react/client/Interactables.js +25 -28
  39. package/dist/react/client/Interactables.js.map +1 -1
  40. package/dist/react/client/RemoteThreadList.d.ts +16 -0
  41. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  42. package/dist/react/client/RemoteThreadList.js +354 -242
  43. package/dist/react/client/RemoteThreadList.js.map +1 -1
  44. package/dist/react/client/Tools.d.ts.map +1 -1
  45. package/dist/react/client/Tools.js +24 -18
  46. package/dist/react/client/Tools.js.map +1 -1
  47. package/dist/react/index.d.ts +2 -1
  48. package/dist/react/index.js +2 -1
  49. package/dist/react/interactables-legacy/Interactables.js +246 -125
  50. package/dist/react/interactables-legacy/Interactables.js.map +1 -1
  51. package/dist/react/interactables-shared/useInteractablePersistenceQueue.d.ts.map +1 -1
  52. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js +11 -9
  53. package/dist/react/interactables-shared/useInteractablePersistenceQueue.js.map +1 -1
  54. package/dist/react/model-context/makeAssistantTool.d.ts +2 -2
  55. package/dist/react/model-context/makeAssistantTool.js +1 -1
  56. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  57. package/dist/react/model-context/toolbox.d.ts +2 -14
  58. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  59. package/dist/react/model-context/toolbox.js +1 -13
  60. package/dist/react/model-context/toolbox.js.map +1 -1
  61. package/dist/react/model-context/useAssistantContext.js +37 -7
  62. package/dist/react/model-context/useAssistantContext.js.map +1 -1
  63. package/dist/react/model-context/useAssistantTool.d.ts +2 -2
  64. package/dist/react/model-context/useAssistantTool.js +1 -1
  65. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  66. package/dist/react/model-context/useAuiToolOverrides.js +31 -5
  67. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
  68. package/dist/react/model-context/useInlineRender.d.ts.map +1 -1
  69. package/dist/react/model-context/useInlineRender.js +10 -36
  70. package/dist/react/model-context/useInlineRender.js.map +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/primitive-hooks/useMessageError.d.ts.map +1 -1
  75. package/dist/react/primitive-hooks/useMessageError.js +2 -8
  76. package/dist/react/primitive-hooks/useMessageError.js.map +1 -1
  77. package/dist/react/primitive-hooks/useThreadListLoadMore.d.ts.map +1 -1
  78. package/dist/react/primitive-hooks/useThreadListLoadMore.js +2 -4
  79. package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
  80. package/dist/react/primitives/composer/ComposerAttachments.d.ts.map +1 -1
  81. package/dist/react/primitives/composer/ComposerAttachments.js +4 -3
  82. package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
  83. package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
  84. package/dist/react/primitives/composer/ComposerQueue.js +4 -3
  85. package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
  86. package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
  87. package/dist/react/primitives/message/MessageAttachments.js +7 -6
  88. package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
  89. package/dist/react/primitives/message/MessageGroupedParts.js +2 -2
  90. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  91. package/dist/react/primitives/message/MessageParts.js +3 -3
  92. package/dist/react/primitives/message/MessageParts.js.map +1 -1
  93. package/dist/react/primitives/threadList/ThreadListItems.d.ts.map +1 -1
  94. package/dist/react/primitives/threadList/ThreadListItems.js +5 -4
  95. package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
  96. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +6 -4
  97. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
  98. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +59 -29
  99. package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
  100. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +11 -6
  101. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  102. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +160 -143
  103. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  104. package/dist/react/runtimes/RemoteThreadResource.d.ts +2 -6
  105. package/dist/react/runtimes/RemoteThreadResource.d.ts.map +1 -1
  106. package/dist/react/runtimes/RemoteThreadResource.js +15 -13
  107. package/dist/react/runtimes/RemoteThreadResource.js.map +1 -1
  108. package/dist/react/runtimes/assistant-transport/useLatestRef.js +2 -2
  109. package/dist/react/runtimes/assistant-transport/useLatestRef.js.map +1 -1
  110. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +4 -1
  111. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  112. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +424 -52
  113. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  114. package/dist/react/runtimes/cloud/auiV0.d.ts +5 -1
  115. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  116. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  117. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +29 -0
  118. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -0
  119. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +160 -0
  120. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -0
  121. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts +1 -9
  122. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  123. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +16 -153
  124. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  125. package/dist/react/runtimes/external-message-converter.js +1 -1
  126. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  127. package/dist/react/runtimes/useExternalStoreRuntime.js +75 -46
  128. package/dist/react/runtimes/useExternalStoreRuntime.js.map +1 -1
  129. package/dist/react/runtimes/useRemoteThreadListRuntime.d.ts.map +1 -1
  130. package/dist/react/runtimes/useRemoteThreadListRuntime.js +77 -29
  131. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  132. package/dist/react/types/MessagePartComponentTypes.d.ts +7 -3
  133. package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
  134. package/dist/react/types/scopes/tools.d.ts +2 -0
  135. package/dist/react/types/scopes/tools.d.ts.map +1 -1
  136. package/dist/runtime/api/message-part-runtime.d.ts +2 -2
  137. package/dist/runtime/api/message-part-runtime.d.ts.map +1 -1
  138. package/dist/runtime/api/message-part-runtime.js +1 -1
  139. package/dist/runtime/api/message-part-runtime.js.map +1 -1
  140. package/dist/runtime/api/thread-list-item-runtime.d.ts +7 -3
  141. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  142. package/dist/runtime/api/thread-list-item-runtime.js +2 -2
  143. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  144. package/dist/runtime/api/thread-list-runtime.d.ts +12 -1
  145. package/dist/runtime/api/thread-list-runtime.d.ts.map +1 -1
  146. package/dist/runtime/api/thread-list-runtime.js +23 -14
  147. package/dist/runtime/api/thread-list-runtime.js.map +1 -1
  148. package/dist/runtime/api/thread-runtime.d.ts +5 -1
  149. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  150. package/dist/runtime/api/thread-runtime.js +1 -1
  151. package/dist/runtime/api/thread-runtime.js.map +1 -1
  152. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  153. package/dist/runtime/base/base-composer-runtime-core.js +16 -12
  154. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  155. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -2
  156. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  157. package/dist/runtime/base/base-thread-runtime-core.js +8 -7
  158. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  159. package/dist/runtime/interfaces/composer-runtime-core.d.ts +12 -5
  160. package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
  161. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +18 -3
  162. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  163. package/dist/runtime/interfaces/thread-runtime-core.d.ts +15 -1
  164. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  165. package/dist/runtime/utils/auto-status.d.ts +1 -1
  166. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  167. package/dist/runtime/utils/auto-status.js +6 -2
  168. package/dist/runtime/utils/auto-status.js.map +1 -1
  169. package/dist/runtime/utils/external-message-conversion.d.ts +3 -2
  170. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  171. package/dist/runtime/utils/external-message-conversion.js +5 -4
  172. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  173. package/dist/runtime/utils/message-repository.d.ts +1 -0
  174. package/dist/runtime/utils/message-repository.d.ts.map +1 -1
  175. package/dist/runtime/utils/message-repository.js +15 -6
  176. package/dist/runtime/utils/message-repository.js.map +1 -1
  177. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts +6 -3
  178. package/dist/runtime/utils/resolveToolApprovalResponse.d.ts.map +1 -1
  179. package/dist/runtime/utils/resolveToolApprovalResponse.js +12 -3
  180. package/dist/runtime/utils/resolveToolApprovalResponse.js.map +1 -1
  181. package/dist/runtime/utils/thread-message-like.d.ts +2 -10
  182. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  183. package/dist/runtime/utils/thread-message-like.js +1 -1
  184. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  185. package/dist/runtime/utils/tool-call-tree.d.ts +39 -0
  186. package/dist/runtime/utils/tool-call-tree.d.ts.map +1 -0
  187. package/dist/runtime/utils/tool-call-tree.js +85 -0
  188. package/dist/runtime/utils/tool-call-tree.js.map +1 -0
  189. package/dist/runtimes/external-store/external-store-adapter.d.ts +29 -2
  190. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  191. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  192. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +21 -27
  193. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  194. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -1
  195. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  196. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +34 -28
  197. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  198. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts +1 -1
  199. package/dist/runtimes/inert/InertThreadRuntimeCore.d.ts.map +1 -1
  200. package/dist/runtimes/inert/InertThreadRuntimeCore.js.map +1 -1
  201. package/dist/runtimes/internal.d.ts +2 -2
  202. package/dist/runtimes/internal.js +2 -2
  203. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  204. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  205. package/dist/runtimes/local/local-thread-runtime-core.js +3 -1
  206. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  207. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts +18 -1
  208. package/dist/runtimes/remote-thread-list/remote-thread-state.d.ts.map +1 -1
  209. package/dist/runtimes/remote-thread-list/remote-thread-state.js +148 -43
  210. package/dist/runtimes/remote-thread-list/remote-thread-state.js.map +1 -1
  211. package/dist/runtimes/remote-thread-list/title-generation.d.ts +49 -0
  212. package/dist/runtimes/remote-thread-list/title-generation.d.ts.map +1 -0
  213. package/dist/runtimes/remote-thread-list/title-generation.js +197 -0
  214. package/dist/runtimes/remote-thread-list/title-generation.js.map +1 -0
  215. package/dist/runtimes/remote-thread-list/title.d.ts +11 -0
  216. package/dist/runtimes/remote-thread-list/title.d.ts.map +1 -0
  217. package/dist/runtimes/remote-thread-list/title.js +14 -0
  218. package/dist/runtimes/remote-thread-list/title.js.map +1 -0
  219. package/dist/runtimes/remote-thread-list/types.d.ts +16 -5
  220. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  221. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts +31 -8
  222. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  223. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +97 -60
  224. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  225. package/dist/store/clients/external-thread.d.ts +1 -1
  226. package/dist/store/clients/external-thread.d.ts.map +1 -1
  227. package/dist/store/clients/external-thread.js +30 -7
  228. package/dist/store/clients/external-thread.js.map +1 -1
  229. package/dist/store/clients/model-context-client.d.ts.map +1 -1
  230. package/dist/store/clients/model-context-client.js +2 -1
  231. package/dist/store/clients/model-context-client.js.map +1 -1
  232. package/dist/store/clients/single-thread-list.d.ts.map +1 -1
  233. package/dist/store/clients/single-thread-list.js +2 -1
  234. package/dist/store/clients/single-thread-list.js.map +1 -1
  235. package/dist/store/clients/suggestions.d.ts.map +1 -1
  236. package/dist/store/clients/suggestions.js +19 -6
  237. package/dist/store/clients/suggestions.js.map +1 -1
  238. package/dist/store/clients/thread-message-client.js +1 -1
  239. package/dist/store/clients/thread-selection-events.js +1 -1
  240. package/dist/store/index.d.ts +2 -1
  241. package/dist/store/index.js +2 -1
  242. package/dist/store/internal.d.ts +2 -2
  243. package/dist/store/internal.js +2 -2
  244. package/dist/store/primitive-predicates.d.ts +4 -1
  245. package/dist/store/primitive-predicates.d.ts.map +1 -1
  246. package/dist/store/primitive-predicates.js +9 -1
  247. package/dist/store/primitive-predicates.js.map +1 -1
  248. package/dist/store/runtime-clients/composer-runtime-client.d.ts +1 -0
  249. package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
  250. package/dist/store/runtime-clients/composer-runtime-client.js +98 -62
  251. package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
  252. package/dist/store/runtime-clients/message-runtime-client.d.ts +1 -0
  253. package/dist/store/runtime-clients/message-runtime-client.d.ts.map +1 -1
  254. package/dist/store/runtime-clients/message-runtime-client.js +221 -144
  255. package/dist/store/runtime-clients/message-runtime-client.js.map +1 -1
  256. package/dist/store/runtime-clients/thread-list-item-runtime-client.d.ts.map +1 -1
  257. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +2 -2
  258. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  259. package/dist/store/runtime-clients/thread-list-runtime-client.d.ts.map +1 -1
  260. package/dist/store/runtime-clients/thread-list-runtime-client.js +128 -107
  261. package/dist/store/runtime-clients/thread-list-runtime-client.js.map +1 -1
  262. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  263. package/dist/store/runtime-clients/thread-runtime-client.js +194 -122
  264. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  265. package/dist/store/runtime-clients/useSubscribable.d.ts +3 -1
  266. package/dist/store/runtime-clients/useSubscribable.d.ts.map +1 -1
  267. package/dist/store/runtime-clients/useSubscribable.js +1 -1
  268. package/dist/store/runtime-clients/useSubscribable.js.map +1 -1
  269. package/dist/store/scopes/composer.d.ts +10 -2
  270. package/dist/store/scopes/composer.d.ts.map +1 -1
  271. package/dist/store/scopes/message.d.ts +30 -1
  272. package/dist/store/scopes/message.d.ts.map +1 -1
  273. package/dist/store/scopes/part.d.ts +6 -3
  274. package/dist/store/scopes/part.d.ts.map +1 -1
  275. package/dist/store/scopes/thread-list-item.d.ts +2 -2
  276. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  277. package/dist/store/scopes/thread.d.ts +8 -0
  278. package/dist/store/scopes/thread.d.ts.map +1 -1
  279. package/dist/store/scopes/threads.d.ts +1 -0
  280. package/dist/store/scopes/threads.d.ts.map +1 -1
  281. package/dist/subscribable/subscribable.d.ts +8 -1
  282. package/dist/subscribable/subscribable.d.ts.map +1 -1
  283. package/dist/subscribable/subscribable.js +24 -16
  284. package/dist/subscribable/subscribable.js.map +1 -1
  285. package/dist/types/attachment.d.ts +2 -1
  286. package/dist/types/attachment.d.ts.map +1 -1
  287. package/dist/types/attachment.js +2 -1
  288. package/dist/types/attachment.js.map +1 -1
  289. package/dist/types/message.d.ts +40 -1
  290. package/dist/types/message.d.ts.map +1 -1
  291. package/dist/types/message.js +7 -1
  292. package/dist/types/message.js.map +1 -1
  293. package/dist/utils/abortable-iterable.d.ts +19 -0
  294. package/dist/utils/abortable-iterable.d.ts.map +1 -0
  295. package/dist/utils/abortable-iterable.js +72 -0
  296. package/dist/utils/abortable-iterable.js.map +1 -0
  297. package/dist/utils/composite-context-provider.d.ts.map +1 -1
  298. package/dist/utils/composite-context-provider.js +20 -2
  299. package/dist/utils/composite-context-provider.js.map +1 -1
  300. package/dist/utils/record.d.ts +11 -0
  301. package/dist/utils/record.d.ts.map +1 -0
  302. package/dist/utils/record.js +12 -0
  303. package/dist/utils/record.js.map +1 -0
  304. package/package.json +12 -17
  305. package/src/adapters/attachment.test.ts +50 -1
  306. package/src/adapters/attachment.ts +7 -4
  307. package/src/index.ts +7 -1
  308. package/src/internal.ts +12 -0
  309. package/src/model-context/frame/host.test.ts +24 -0
  310. package/src/model-context/frame/host.ts +10 -4
  311. package/src/model-context/frame/provider.test.ts +288 -1
  312. package/src/model-context/frame/provider.ts +148 -30
  313. package/src/model-context/interactable-composer-metadata.test.ts +28 -0
  314. package/src/model-context/interactable-composer-metadata.ts +9 -3
  315. package/src/model-context/registry.test.ts +12 -0
  316. package/src/model-context/registry.ts +3 -2
  317. package/src/model-context/tool-call-text.test.ts +67 -0
  318. package/src/model-context/tool-call-text.ts +67 -0
  319. package/src/model-context/types.test.ts +25 -0
  320. package/src/model-context/types.ts +9 -4
  321. package/src/react/AssistantRuntimeProvider.test.tsx +66 -2
  322. package/src/react/RuntimeAdapter.test.ts +34 -0
  323. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +1 -3
  324. package/src/react/client/InMemoryThreadList.ts +1 -0
  325. package/src/react/client/Interactables.test.ts +28 -0
  326. package/src/react/client/Interactables.ts +15 -13
  327. package/src/react/client/RemoteThreadList.background.test.ts +526 -0
  328. package/src/react/client/RemoteThreadList.concurrent.test.tsx +315 -0
  329. package/src/react/client/RemoteThreadList.test.ts +617 -3
  330. package/src/react/client/RemoteThreadList.ts +433 -167
  331. package/src/react/client/Tools.ts +29 -12
  332. package/src/react/index.ts +4 -0
  333. package/src/react/interactables-legacy/Interactables.ts +16 -16
  334. package/src/react/interactables-shared/useInteractablePersistenceQueue.ts +9 -10
  335. package/src/react/model-context/makeAssistantTool.ts +2 -2
  336. package/src/react/model-context/modelContextHooks.test.tsx +131 -0
  337. package/src/react/model-context/toolbox.test.ts +9 -9
  338. package/src/react/model-context/toolbox.ts +9 -36
  339. package/src/react/model-context/useAssistantContext.ts +4 -2
  340. package/src/react/model-context/useAssistantTool.ts +2 -2
  341. package/src/react/model-context/useAuiToolOverrides.ts +4 -2
  342. package/src/react/model-context/useInlineRender.test.tsx +48 -0
  343. package/src/react/model-context/useInlineRender.ts +14 -10
  344. package/src/react/model-context/useToolArgsStatus.test.tsx +30 -0
  345. package/src/react/model-context/useToolArgsStatus.ts +2 -1
  346. package/src/react/primitive-hooks/useMessageError.ts +2 -19
  347. package/src/react/primitive-hooks/useThreadListLoadMore.ts +2 -3
  348. package/src/react/primitives/composer/ComposerAttachments.test.tsx +76 -0
  349. package/src/react/primitives/composer/ComposerAttachments.tsx +9 -4
  350. package/src/react/primitives/composer/ComposerQueue.test.tsx +72 -0
  351. package/src/react/primitives/composer/ComposerQueue.tsx +7 -4
  352. package/src/react/primitives/message/MessageAttachments.test.tsx +107 -37
  353. package/src/react/primitives/message/MessageAttachments.tsx +10 -7
  354. package/src/react/primitives/message/MessageGroupedParts.tsx +2 -2
  355. package/src/react/primitives/message/MessageParts.tsx +3 -3
  356. package/src/react/primitives/threadList/ThreadListItems.test.tsx +99 -0
  357. package/src/react/primitives/threadList/ThreadListItems.tsx +8 -5
  358. package/src/react/runtimes/RemoteThreadListHookInstanceManager.destroy.test.tsx +172 -0
  359. package/src/react/runtimes/RemoteThreadListHookInstanceManager.running.test.tsx +127 -1
  360. package/src/react/runtimes/RemoteThreadListHookInstanceManager.test.tsx +7 -1
  361. package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +99 -35
  362. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.load-error.test.ts +132 -0
  363. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.switch-delete.test.ts +274 -0
  364. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +223 -152
  365. package/src/react/runtimes/RemoteThreadResource.test.ts +9 -0
  366. package/src/react/runtimes/RemoteThreadResource.ts +20 -16
  367. package/src/react/runtimes/assistant-transport/transport-scheduling.test.ts +51 -2
  368. package/src/react/runtimes/assistant-transport/useLatestRef.ts +2 -2
  369. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +45 -0
  370. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +546 -5
  371. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +546 -103
  372. package/src/react/runtimes/cloud/auiV0.ts +5 -0
  373. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +103 -0
  374. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +237 -0
  375. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +90 -1
  376. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +33 -238
  377. package/src/react/runtimes/external-message-converter.ts +1 -0
  378. package/src/react/runtimes/useExternalStoreRuntime.lifecycle.test.tsx +41 -0
  379. package/src/react/runtimes/useExternalStoreRuntime.ts +10 -4
  380. package/src/react/runtimes/useLocalRuntime.test.tsx +20 -0
  381. package/src/react/runtimes/useRemoteThreadListRuntime.concurrent.test.tsx +216 -0
  382. package/src/react/runtimes/useRemoteThreadListRuntime.load-error.test.tsx +108 -0
  383. package/src/react/runtimes/useRemoteThreadListRuntime.ts +57 -6
  384. package/src/react/types/MessagePartComponentTypes.ts +7 -3
  385. package/src/react/types/scopes/tools.ts +2 -0
  386. package/src/runtime/api/message-part-runtime.ts +3 -3
  387. package/src/runtime/api/message-runtime.test.ts +75 -0
  388. package/src/runtime/api/thread-list-item-runtime.ts +10 -3
  389. package/src/runtime/api/thread-list-runtime.ts +46 -12
  390. package/src/runtime/api/thread-runtime.test.ts +78 -0
  391. package/src/runtime/api/thread-runtime.ts +8 -1
  392. package/src/runtime/base/base-composer-runtime-core.ts +36 -8
  393. package/src/runtime/base/base-thread-runtime-core.test.ts +149 -4
  394. package/src/runtime/base/base-thread-runtime-core.ts +16 -8
  395. package/src/runtime/interfaces/composer-runtime-core.ts +10 -5
  396. package/src/runtime/interfaces/thread-list-runtime-core.ts +25 -2
  397. package/src/runtime/interfaces/thread-runtime-core.ts +17 -1
  398. package/src/runtime/utils/auto-status.test.ts +57 -0
  399. package/src/runtime/utils/auto-status.ts +13 -1
  400. package/src/runtime/utils/external-message-conversion.test.ts +165 -0
  401. package/src/runtime/utils/external-message-conversion.ts +18 -2
  402. package/src/runtime/utils/message-repository.ts +29 -17
  403. package/src/runtime/utils/resolveToolApprovalResponse.test.ts +73 -0
  404. package/src/runtime/utils/resolveToolApprovalResponse.ts +27 -6
  405. package/src/runtime/utils/thread-message-like.ts +3 -11
  406. package/src/runtime/utils/tool-call-tree.test.ts +191 -0
  407. package/src/runtime/utils/tool-call-tree.ts +97 -0
  408. package/src/runtimes/external-store/external-store-adapter.ts +38 -2
  409. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +18 -13
  410. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +56 -33
  411. package/src/runtimes/inert/InertThreadRuntimeCore.ts +1 -1
  412. package/src/runtimes/internal.ts +1 -0
  413. package/src/runtimes/local/local-thread-runtime-core.test.ts +29 -3
  414. package/src/runtimes/local/local-thread-runtime-core.ts +5 -1
  415. package/src/runtimes/remote-thread-list/remote-thread-state.test.ts +238 -0
  416. package/src/runtimes/remote-thread-list/remote-thread-state.ts +223 -44
  417. package/src/runtimes/remote-thread-list/title-generation.test.ts +602 -0
  418. package/src/runtimes/remote-thread-list/title-generation.ts +329 -0
  419. package/src/runtimes/remote-thread-list/title.test.ts +62 -0
  420. package/src/runtimes/remote-thread-list/title.ts +16 -0
  421. package/src/runtimes/remote-thread-list/types.ts +16 -5
  422. package/src/runtimes/tool-invocations/EDGE_CASES.md +110 -5
  423. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +750 -136
  424. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +144 -91
  425. package/src/store/clients/external-thread.ts +62 -11
  426. package/src/store/clients/model-context-client.ts +5 -1
  427. package/src/store/clients/single-thread-list.ts +1 -0
  428. package/src/store/clients/suggestions.test.ts +195 -1
  429. package/src/store/clients/suggestions.ts +45 -34
  430. package/src/store/index.ts +4 -0
  431. package/src/store/internal.ts +2 -0
  432. package/src/store/primitive-predicates.ts +35 -0
  433. package/src/store/runtime-clients/composer-runtime-client.ts +42 -9
  434. package/src/store/runtime-clients/message-runtime-client.ts +54 -6
  435. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +4 -2
  436. package/src/store/runtime-clients/thread-list-runtime-client.ts +17 -2
  437. package/src/store/runtime-clients/thread-runtime-client.ts +58 -10
  438. package/src/store/runtime-clients/useSubscribable.ts +8 -2
  439. package/src/store/scopes/composer.ts +16 -4
  440. package/src/store/scopes/message.ts +14 -0
  441. package/src/store/scopes/part.ts +6 -3
  442. package/src/store/scopes/thread-list-item.ts +5 -2
  443. package/src/store/scopes/thread.ts +4 -0
  444. package/src/store/scopes/threads.ts +1 -0
  445. package/src/subscribable/subscribable.test.ts +50 -0
  446. package/src/subscribable/subscribable.ts +33 -21
  447. package/src/tests/MessageRepository.test.ts +116 -0
  448. package/src/tests/OptimisticState-list-race.test.ts +1 -0
  449. package/src/tests/RemoteThreadListThreadListRuntimeCore-initialize-adapter-change.test.ts +38 -0
  450. package/src/tests/RemoteThreadListThreadListRuntimeCore-load-race.test.ts +158 -0
  451. package/src/tests/RemoteThreadListThreadListRuntimeCore-loadMore.test.ts +78 -0
  452. package/src/tests/RemoteThreadListThreadListRuntimeCore-reload.test.ts +52 -0
  453. package/src/tests/RemoteThreadListThreadListRuntimeCore-title-race.test.ts +89 -0
  454. package/src/tests/attachment-adapters.test.ts +14 -0
  455. package/src/tests/base-composer-runtime-core.test.ts +39 -0
  456. package/src/tests/external-store-optimistic-id.test.ts +79 -0
  457. package/src/tests/external-store-repository-instance.test.ts +166 -0
  458. package/src/tests/external-store-thread-list-runtime-core.test.ts +83 -0
  459. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +49 -34
  460. package/src/tests/external-thread-attachments.test.tsx +224 -1
  461. package/src/tests/external-thread-parity.test.tsx +23 -0
  462. package/src/tests/remote-thread-list-adapter-switch.test.ts +66 -1
  463. package/src/tests/remote-thread-list-isLoading.test.ts +1 -0
  464. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
  465. package/src/tests/thread-switch-events.test.tsx +475 -2
  466. package/src/tests/tools-scope-migration.test.tsx +28 -0
  467. package/src/types/attachment.ts +4 -0
  468. package/src/types/message.ts +50 -2
  469. package/src/utils/abortable-iterable.test.ts +213 -0
  470. package/src/utils/abortable-iterable.ts +93 -0
  471. package/src/utils/composite-context-provider.test.ts +25 -0
  472. package/src/utils/composite-context-provider.ts +23 -2
  473. package/src/utils/record.test.ts +48 -0
  474. package/src/utils/record.ts +11 -0
@@ -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","thread","push","_exhaustiveCheck","Error","mappingId","resolve","RemoteThreadState","isLoading","isLoadingMore","cursor","newThreadId","Readonly","createEmptyRemoteThreadState","seedNewThread","state","preserveMidLoadTransitions","priorOrder","Pick","statusAtRequest","ReadonlyMap","regular","Set","archived","rescuedRegular","rescuedArchived","contains","ids","ReadonlySet","data","has","Object","values","before","get","add","length","position","byId","indexOf","byRemoteId","Number","MAX_SAFE_INTEGER","sort","a","b","map","d","statusSnapshot","Map","getThreadData","threadIdOrRemoteId","idx","updateStatusReducer","newStatus","lastStatus","newState","filter","t","fromEntries","entries","key"],"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\ntype ClassifyAccumulator = {\n threadIds: string[];\n archivedThreadIds: string[];\n threadIdMap: Record<string, THREAD_MAPPING_ID>;\n threadData: Record<THREAD_MAPPING_ID, RemoteThreadData>;\n};\n\nexport const classifyThreads = (\n threads: readonly RemoteThreadMetadata[],\n acc: ClassifyAccumulator,\n): ClassifyAccumulator => {\n for (const thread of threads) {\n if (acc.threadIdMap[thread.remoteId] !== undefined) continue;\n\n switch (thread.status) {\n case \"regular\":\n acc.threadIds.push(thread.remoteId);\n break;\n case \"archived\":\n acc.archivedThreadIds.push(thread.remoteId);\n break;\n default: {\n const _exhaustiveCheck: never = thread.status;\n throw new Error(`Unsupported state: ${_exhaustiveCheck}`);\n }\n }\n\n const mappingId = createThreadMappingId(thread.remoteId);\n acc.threadIdMap[thread.remoteId] = mappingId;\n acc.threadData[mappingId] = {\n id: thread.remoteId,\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: 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, remoteId, 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 newState.threadData = Object.fromEntries(\n Object.entries(newState.threadData).filter(([key]) => key !== id),\n );\n newState.threadIdMap = Object.fromEntries(\n Object.entries(newState.threadIdMap).filter(\n ([key]) => key !== id && key !== remoteId,\n ),\n );\n break;\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":"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"}
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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"}
@@ -0,0 +1,11 @@
1
+ import { AssistantMessageStream } from "assistant-stream";
2
+ //#region src/runtimes/remote-thread-list/title.d.ts
3
+ declare const isTitleSourceMessage: (message: {
4
+ status?: {
5
+ type: string;
6
+ } | undefined;
7
+ }) => boolean;
8
+ declare const applyTitleStream: (stream: Parameters<typeof AssistantMessageStream.fromAssistantStream>[0], onTitle: (title: string | undefined) => Promise<void>) => Promise<void>;
9
+ //#endregion
10
+ export { applyTitleStream, isTitleSourceMessage };
11
+ //# sourceMappingURL=title.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,14 @@
1
+ import { AssistantMessageStream } from "assistant-stream";
2
+ //#region src/runtimes/remote-thread-list/title.ts
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
+ };
11
+ //#endregion
12
+ export { applyTitleStream, isTitleSourceMessage };
13
+
14
+ //# sourceMappingURL=title.js.map
@@ -0,0 +1 @@
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
  /**
@@ -60,11 +70,12 @@ type RemoteThreadListAdapter = {
60
70
  */
61
71
  unstable_Provider?: RemoteThreadListProviderComponent | undefined;
62
72
  /**
63
- * Hook the `RemoteThreadList` store entry calls once for the main-thread
64
- * slot, then provides to the `thread` factory. This is not mounted per
65
- * listed thread. `useRemoteThreadListRuntime` also calls it when
66
- * `unstable_Provider` is omitted. Resolve `threadListItem` lazily on each
67
- * adapter call; do not capture it at hook mount. The hook must keep a
73
+ * Hook the `RemoteThreadList` store entry calls once per mounted thread
74
+ * body (the main-thread slot by default; every started thread with
75
+ * `backgroundThreads`), then provides to the `thread` factory. This is not
76
+ * mounted per listed thread. `useRemoteThreadListRuntime` also calls it
77
+ * when `unstable_Provider` is omitted. Resolve `threadListItem` lazily on
78
+ * each adapter call; do not capture it at hook mount. The hook must keep a
68
79
  * stable hook count across adapter swaps; a different count throws.
69
80
  * Memoize the returned object.
70
81
  *
@@ -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;;;;;;;;;;;;;;;EAgBpB,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,4 +1,4 @@
1
- import { ThreadMessage } from "../../types/message.js";
1
+ import { ThreadMessage, ToolCallMessagePart } from "../../types/message.js";
2
2
  import { Tool, ToolModelContentPart } from "assistant-stream";
3
3
  import { ReadonlyJSONValue } from "assistant-stream/utils";
4
4
  //#region src/runtimes/tool-invocations/ToolInvocationTracker.d.ts
@@ -48,9 +48,17 @@ type AddToolResultCommand = {
48
48
  declare class ToolInvocationTracker {
49
49
  private readonly _getTools;
50
50
  private readonly _callbacks;
51
+ private readonly _isClientToolCall;
51
52
  private readonly _entries;
52
53
  private readonly _humanInput;
53
54
  private readonly _executing;
55
+ /**
56
+ * Tool calls whose turn ended before they reached the executor. Held here
57
+ * rather than on the entry because an entry is rebuilt whenever a snapshot
58
+ * re-creates the call, and this is the one reason to skip that no later
59
+ * snapshot carries.
60
+ */
61
+ private readonly _discardedToolCallIds;
54
62
  private readonly _settledResolvers;
55
63
  private _statuses;
56
64
  private _ac;
@@ -62,14 +70,16 @@ declare class ToolInvocationTracker {
62
70
  /**
63
71
  * Set when the assistant-stream pipeline has died (errored out via
64
72
  * `.pipeTo(...).catch(...)`). The next `setState` re-initializes the
65
- * pipeline and demotes all active entries to restored so they survive
66
- * across the restart without re-firing `streamCall` (preserves the
67
- * "exactly once" contract). Capped at a single auto-restart per session
68
- * — repeated failures keep the tracker dead with a more visible error.
73
+ * pipeline and demotes each active entry that reached the executor to
74
+ * restored, so it survives the restart without re-firing `streamCall`.
75
+ * A restart is an execution boundary like `reset()`: an entry that had
76
+ * not reached it starts over and fires once there (F.4). Capped at a
77
+ * single auto-restart per session — repeated failures keep the tracker
78
+ * dead with a more visible error.
69
79
  */
70
80
  private _pipelineDead;
71
81
  private _pipelineRestartUsed;
72
- constructor(getTools: () => Record<string, Tool> | undefined, callbacks: ToolInvocationTracker.Callbacks);
82
+ constructor(getTools: () => Record<string, Tool> | undefined, callbacks: ToolInvocationTracker.Callbacks, isClientToolCall?: (toolCall: ToolCallMessagePart) => boolean | undefined);
73
83
  /**
74
84
  * Build the assistant-stream pipeline. Called once from the constructor
75
85
  * and at most once again if `_pipelineDead` is set (see F.4 in
@@ -90,8 +100,15 @@ declare class ToolInvocationTracker {
90
100
  /**
91
101
  * Abort any in-flight `execute()` invocations. Resolves once all of them
92
102
  * have settled (or immediately if none are running).
103
+ *
104
+ * `discardPending` additionally kills the calls that never reached the
105
+ * executor, for a caller ending the turn rather than interrupting it. The
106
+ * signal cannot reach those: they are waiting on the run to settle (A.10),
107
+ * and the settled snapshot arrives after this installs a fresh controller.
93
108
  */
94
- abort(): Promise<void>;
109
+ abort(options?: {
110
+ discardPending?: boolean;
111
+ }): Promise<void>;
95
112
  /**
96
113
  * Resolve a pending human-input request for the given tool call. Returns
97
114
  * `true` if a pending request was resumed, `false` if the tracker has no
@@ -116,7 +133,13 @@ declare class ToolInvocationTracker {
116
133
  private _invokeOnStatusesChange;
117
134
  private _setStatus;
118
135
  private _deleteStatus;
119
- private _hasExecutableTool;
136
+ private _warnProviderOwnedSkip;
137
+ /**
138
+ * Closing the args stream hands the call to the client executor, so it may
139
+ * only happen once the provider can no longer speak about that call. The run
140
+ * ending is the only universal signal for that; an adapter that reports the
141
+ * call as client-owned has said it earlier, per call.
142
+ */
120
143
  private _shouldCloseArgsStream;
121
144
  private _startActiveEntry;
122
145
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ToolInvocationTracker.d.ts","names":[],"sources":["../../../src/runtimes/tool-invocations/ToolInvocationTracker.ts"],"mappings":";;;;;;;KAuBY;EACN;;EAEA;EACA;IAAW;IAAe;;;KAGpB;WACD;WACA;WACA;WACA,QAAQ;WACR;WACA,WAAW;WACX,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;cA8EtB;mBACM;mBACA;mBAEA;mBACA;mBAQA;mBACA;UAET;UAEA;UACA;;UAGA;UACA;UAEA;;;;;;;;;UAUA;UACA;EAGN,YAAA,gBAAgB,eAAe,mBAC/B,WAAW,sBAAsB;;;;;;UAa3B;;;;;EAsDD,SAAS,UAAU,sBAAsB;;;;;;EAmEzC;;;;;EAwBA,SAAS;;;;;;;EAkCT,OAAO,oBAAoB;;;;;;;EAoB3B,eAAe,oBAAoB;UAMlC;UA6CA;UAaA;UAmCA;UAYA;UA0BA;UAkCA;UAWA;UAaA;UAOA;UAUA;UAKA;UAgBA;;;;;;;;UA4BA;UAWA;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;;kBAmFO;OACH,kBAAkB;OAElB;aACD,mBAAmB;;aAEnB;;;;;;aAMA;;OAGC;;;;;IAKV,WAAW,SAAS;;;;;;IAMpB,mBACE,UAAU,oBAAoB"}