@assistant-ui/core 0.3.18 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/dist/adapters/speech.d.ts.map +1 -1
  2. package/dist/adapters/speech.js +13 -3
  3. package/dist/adapters/speech.js.map +1 -1
  4. package/dist/adapters/thread-history.d.ts +4 -0
  5. package/dist/adapters/thread-history.d.ts.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/internal.d.ts +1 -1
  9. package/dist/model-context/frame/host.d.ts.map +1 -1
  10. package/dist/model-context/frame/host.js +26 -11
  11. package/dist/model-context/frame/host.js.map +1 -1
  12. package/dist/model-context/interactable-composer-metadata.js +11 -9
  13. package/dist/model-context/interactable-composer-metadata.js.map +1 -1
  14. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  15. package/dist/react/adapters/LocalStorageThreadListAdapter.js +45 -7
  16. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  17. package/dist/react/client/DataRenderers.d.ts.map +1 -1
  18. package/dist/react/client/DataRenderers.js +20 -15
  19. package/dist/react/client/DataRenderers.js.map +1 -1
  20. package/dist/react/client/Interactables.d.ts.map +1 -1
  21. package/dist/react/client/Interactables.js +11 -5
  22. package/dist/react/client/Interactables.js.map +1 -1
  23. package/dist/react/client/RemoteThreadList.d.ts.map +1 -1
  24. package/dist/react/client/RemoteThreadList.js +3 -2
  25. package/dist/react/client/RemoteThreadList.js.map +1 -1
  26. package/dist/react/client/interactable-model-context.d.ts.map +1 -1
  27. package/dist/react/client/interactable-model-context.js +3 -2
  28. package/dist/react/client/interactable-model-context.js.map +1 -1
  29. package/dist/react/index.d.ts +2 -2
  30. package/dist/react/index.js +2 -2
  31. package/dist/react/interactables-legacy/useAssistantInteractable.d.ts.map +1 -1
  32. package/dist/react/interactables-legacy/useAssistantInteractable.js +3 -0
  33. package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
  34. package/dist/react/model-context/useInteractable.d.ts.map +1 -1
  35. package/dist/react/model-context/useInteractable.js +4 -1
  36. package/dist/react/model-context/useInteractable.js.map +1 -1
  37. package/dist/react/model-context/useInteractableVersions.js +1 -1
  38. package/dist/react/primitives/message/MessageGroupedParts.d.ts +11 -2
  39. package/dist/react/primitives/message/MessageGroupedParts.d.ts.map +1 -1
  40. package/dist/react/primitives/message/MessageGroupedParts.js +3 -2
  41. package/dist/react/primitives/message/MessageGroupedParts.js.map +1 -1
  42. package/dist/react/primitives/part/PartMessages.d.ts +1 -0
  43. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  44. package/dist/react/primitives/part/PartMessages.js +1 -0
  45. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  46. package/dist/react/primitives/thread/ThreadMessages.d.ts.map +1 -1
  47. package/dist/react/primitives/thread/ThreadMessages.js +6 -5
  48. package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
  49. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  50. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +2 -1
  51. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  52. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts +2 -24
  53. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
  54. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +135 -374
  55. package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
  56. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts +1 -0
  57. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.d.ts.map +1 -1
  58. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js +22 -2
  59. package/dist/react/runtimes/cloud/CloudFileAttachmentAdapter.js.map +1 -1
  60. package/dist/react/runtimes/cloud/auiV0.d.ts +40 -15
  61. package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
  62. package/dist/react/runtimes/cloud/auiV0.js +62 -15
  63. package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
  64. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts +2 -1
  65. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.d.ts.map +1 -1
  66. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js +4 -0
  67. package/dist/react/runtimes/cloud/createCloudThreadListAdapter.js.map +1 -1
  68. package/dist/react/runtimes/cloud/sdkIdentity.d.ts +6 -0
  69. package/dist/react/runtimes/cloud/sdkIdentity.d.ts.map +1 -0
  70. package/dist/react/runtimes/cloud/sdkIdentity.js +9 -0
  71. package/dist/react/runtimes/cloud/sdkIdentity.js.map +1 -0
  72. package/dist/react/runtimes/external-message-converter.d.ts +12 -2
  73. package/dist/react/runtimes/external-message-converter.d.ts.map +1 -1
  74. package/dist/react/runtimes/external-message-converter.js +26 -61
  75. package/dist/react/runtimes/external-message-converter.js.map +1 -1
  76. package/dist/react/runtimes/useRemoteThreadListRuntime.js +1 -1
  77. package/dist/react/runtimes/useRemoteThreadListRuntime.js.map +1 -1
  78. package/dist/react/utils/groupParts.d.ts +6 -1
  79. package/dist/react/utils/groupParts.d.ts.map +1 -1
  80. package/dist/react/utils/groupParts.js +6 -0
  81. package/dist/react/utils/groupParts.js.map +1 -1
  82. package/dist/react/utils/useJSONEqual.d.ts +3 -1
  83. package/dist/react/utils/useJSONEqual.d.ts.map +1 -1
  84. package/dist/react/utils/useJSONEqual.js +6 -1
  85. package/dist/react/utils/useJSONEqual.js.map +1 -1
  86. package/dist/react/utils/useJSONSchemaDependency.d.ts +7 -0
  87. package/dist/react/utils/useJSONSchemaDependency.d.ts.map +1 -0
  88. package/dist/react/utils/useJSONSchemaDependency.js +20 -0
  89. package/dist/react/utils/useJSONSchemaDependency.js.map +1 -0
  90. package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
  91. package/dist/runtime/api/thread-runtime.js +2 -5
  92. package/dist/runtime/api/thread-runtime.js.map +1 -1
  93. package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
  94. package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
  95. package/dist/runtime/base/base-composer-runtime-core.js +46 -10
  96. package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
  97. package/dist/runtime/base/base-thread-runtime-core.d.ts +2 -0
  98. package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
  99. package/dist/runtime/base/base-thread-runtime-core.js +155 -64
  100. package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
  101. package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
  102. package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
  103. package/dist/runtime/queue/message-queue.d.ts +5 -0
  104. package/dist/runtime/queue/message-queue.d.ts.map +1 -1
  105. package/dist/runtime/queue/message-queue.js +61 -6
  106. package/dist/runtime/queue/message-queue.js.map +1 -1
  107. package/dist/runtime/utils/auto-status.d.ts +6 -2
  108. package/dist/runtime/utils/auto-status.d.ts.map +1 -1
  109. package/dist/runtime/utils/auto-status.js +12 -4
  110. package/dist/runtime/utils/auto-status.js.map +1 -1
  111. package/dist/runtime/utils/external-message-conversion.d.ts +16 -4
  112. package/dist/runtime/utils/external-message-conversion.d.ts.map +1 -1
  113. package/dist/runtime/utils/external-message-conversion.js +48 -12
  114. package/dist/runtime/utils/external-message-conversion.js.map +1 -1
  115. package/dist/runtime/utils/message-repository.js +3 -3
  116. package/dist/runtime/utils/message-repository.js.map +1 -1
  117. package/dist/runtime/utils/thread-message-like.d.ts +2 -1
  118. package/dist/runtime/utils/thread-message-like.d.ts.map +1 -1
  119. package/dist/runtime/utils/thread-message-like.js +4 -2
  120. package/dist/runtime/utils/thread-message-like.js.map +1 -1
  121. package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
  122. package/dist/runtimes/external-store/external-store-thread-runtime-core.js +8 -1
  123. package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
  124. package/dist/runtimes/internal.d.ts +1 -1
  125. package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -1
  126. package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
  127. package/dist/runtimes/local/local-thread-runtime-core.js +4 -1
  128. package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
  129. package/dist/runtimes/tool-invocations/ToolInvocationTracker.d.ts.map +1 -1
  130. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js +2 -1
  131. package/dist/runtimes/tool-invocations/ToolInvocationTracker.js.map +1 -1
  132. package/dist/store/clients/external-thread.d.ts.map +1 -1
  133. package/dist/store/clients/external-thread.js +241 -200
  134. package/dist/store/clients/external-thread.js.map +1 -1
  135. package/dist/store/clients/thread-tasks.d.ts +13 -0
  136. package/dist/store/clients/thread-tasks.d.ts.map +1 -0
  137. package/dist/store/clients/thread-tasks.js +69 -0
  138. package/dist/store/clients/thread-tasks.js.map +1 -0
  139. package/dist/store/index.d.ts +3 -2
  140. package/dist/store/index.js +3 -3
  141. package/dist/store/primitive-predicates.d.ts.map +1 -1
  142. package/dist/store/primitive-predicates.js +4 -4
  143. package/dist/store/primitive-predicates.js.map +1 -1
  144. package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
  145. package/dist/store/runtime-clients/thread-runtime-client.js +176 -128
  146. package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
  147. package/dist/store/scope-registration.d.ts +2 -0
  148. package/dist/store/scope-registration.d.ts.map +1 -1
  149. package/dist/store/scopes/task.d.ts +36 -0
  150. package/dist/store/scopes/task.d.ts.map +1 -0
  151. package/dist/store/scopes/task.js +0 -0
  152. package/dist/store/scopes/thread.d.ts +20 -0
  153. package/dist/store/scopes/thread.d.ts.map +1 -1
  154. package/dist/subscribable/subscribable.d.ts +2 -1
  155. package/dist/subscribable/subscribable.d.ts.map +1 -1
  156. package/dist/subscribable/subscribable.js +23 -15
  157. package/dist/subscribable/subscribable.js.map +1 -1
  158. package/dist/types/index.d.ts +2 -2
  159. package/dist/types/message.d.ts +8 -1
  160. package/dist/types/message.d.ts.map +1 -1
  161. package/dist/types/message.js.map +1 -1
  162. package/dist/utils/abortable-iterable.d.ts.map +1 -1
  163. package/dist/utils/abortable-iterable.js +30 -14
  164. package/dist/utils/abortable-iterable.js.map +1 -1
  165. package/dist/utils/getGroupStatus.d.ts +18 -2
  166. package/dist/utils/getGroupStatus.d.ts.map +1 -1
  167. package/dist/utils/getGroupStatus.js +32 -7
  168. package/dist/utils/getGroupStatus.js.map +1 -1
  169. package/dist/utils/wire-media.d.ts.map +1 -1
  170. package/dist/utils/wire-media.js +2 -2
  171. package/dist/utils/wire-media.js.map +1 -1
  172. package/package.json +6 -6
  173. package/src/adapters/speech.test.ts +236 -0
  174. package/src/adapters/speech.ts +17 -10
  175. package/src/adapters/thread-history.ts +3 -0
  176. package/src/index.ts +1 -0
  177. package/src/model-context/frame/host.test.ts +113 -1
  178. package/src/model-context/frame/host.ts +39 -12
  179. package/src/model-context/interactable-composer-metadata.test.ts +30 -0
  180. package/src/model-context/interactable-composer-metadata.ts +10 -10
  181. package/src/react/adapters/LocalStorageThreadListAdapter.test.ts +244 -0
  182. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +104 -7
  183. package/src/react/client/DataRenderers.test.tsx +45 -0
  184. package/src/react/client/DataRenderers.ts +13 -9
  185. package/src/react/client/Interactables.test.ts +44 -1
  186. package/src/react/client/Interactables.ts +7 -1
  187. package/src/react/client/RemoteThreadList.test.ts +41 -1
  188. package/src/react/client/RemoteThreadList.ts +15 -2
  189. package/src/react/client/interactable-model-context.test.ts +44 -0
  190. package/src/react/client/interactable-model-context.ts +3 -2
  191. package/src/react/index.ts +5 -1
  192. package/src/react/interactables-legacy/useAssistantInteractable.test.tsx +132 -0
  193. package/src/react/interactables-legacy/useAssistantInteractable.ts +10 -1
  194. package/src/react/model-context/useInteractable.test.tsx +177 -0
  195. package/src/react/model-context/useInteractable.ts +3 -0
  196. package/src/react/primitive-hooks/useActionBarCopy.test.ts +0 -1
  197. package/src/react/primitive-hooks/useSuggestionTrigger.test.ts +0 -1
  198. package/src/react/primitives/message/MessageGroupedParts.test.tsx +96 -0
  199. package/src/react/primitives/message/MessageGroupedParts.tsx +15 -4
  200. package/src/react/primitives/part/PartMessages.test.tsx +104 -1
  201. package/src/react/primitives/part/PartMessages.tsx +1 -0
  202. package/src/react/primitives/thread/ThreadMessages.test.tsx +142 -0
  203. package/src/react/primitives/thread/ThreadMessages.tsx +8 -5
  204. package/src/react/providers/ReadonlyThreadProvider.test.tsx +56 -0
  205. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +7 -1
  206. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.ts +20 -14
  207. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +221 -1
  208. package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +166 -512
  209. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.test.ts +77 -0
  210. package/src/react/runtimes/cloud/CloudFileAttachmentAdapter.ts +27 -1
  211. package/src/react/runtimes/cloud/auiV0.ts +160 -25
  212. package/src/react/runtimes/cloud/createCloudThreadListAdapter.test.ts +21 -0
  213. package/src/react/runtimes/cloud/createCloudThreadListAdapter.ts +7 -1
  214. package/src/react/runtimes/cloud/sdkIdentity.ts +9 -0
  215. package/src/react/runtimes/cloud/useCloudThreadListAdapter.test.tsx +18 -4
  216. package/src/react/runtimes/external-message-converter.test.ts +136 -1
  217. package/src/react/runtimes/external-message-converter.ts +39 -93
  218. package/src/react/runtimes/useRemoteThreadListRuntime.ts +1 -1
  219. package/src/react/utils/groupParts.ts +12 -1
  220. package/src/react/utils/useJSONEqual.ts +9 -0
  221. package/src/react/utils/useJSONSchemaDependency.ts +22 -0
  222. package/src/runtime/api/thread-runtime.test.ts +58 -0
  223. package/src/runtime/api/thread-runtime.ts +2 -4
  224. package/src/runtime/base/base-composer-runtime-core.ts +69 -16
  225. package/src/runtime/base/base-thread-runtime-core.test.ts +1008 -1
  226. package/src/runtime/base/base-thread-runtime-core.ts +222 -83
  227. package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
  228. package/src/runtime/queue/message-queue.ts +68 -6
  229. package/src/runtime/utils/auto-status.test.ts +112 -1
  230. package/src/runtime/utils/auto-status.ts +31 -5
  231. package/src/runtime/utils/external-message-conversion.test.ts +134 -0
  232. package/src/runtime/utils/external-message-conversion.ts +122 -31
  233. package/src/runtime/utils/message-repository.test.ts +49 -0
  234. package/src/runtime/utils/message-repository.ts +3 -3
  235. package/src/runtime/utils/thread-message-like.test.ts +52 -0
  236. package/src/runtime/utils/thread-message-like.ts +4 -0
  237. package/src/runtimes/external-store/external-store-thread-runtime-core.ts +31 -1
  238. package/src/runtimes/local/local-thread-runtime-core.test.ts +21 -0
  239. package/src/runtimes/local/local-thread-runtime-core.ts +11 -1
  240. package/src/runtimes/tool-invocations/EDGE_CASES.md +2 -6
  241. package/src/runtimes/tool-invocations/ToolInvocationTracker.test.ts +133 -0
  242. package/src/runtimes/tool-invocations/ToolInvocationTracker.ts +10 -6
  243. package/src/store/clients/external-thread.ts +19 -1
  244. package/src/store/clients/thread-tasks.test.ts +274 -0
  245. package/src/store/clients/thread-tasks.ts +138 -0
  246. package/src/store/index.ts +8 -0
  247. package/src/store/primitive-predicates.test.ts +48 -5
  248. package/src/store/primitive-predicates.ts +7 -2
  249. package/src/store/runtime-clients/thread-runtime-client.ts +31 -1
  250. package/src/store/scope-registration.ts +2 -0
  251. package/src/store/scopes/task.ts +34 -0
  252. package/src/store/scopes/thread.ts +16 -0
  253. package/src/store/thread-tasks.test.tsx +209 -0
  254. package/src/subscribable/subscribable.test.ts +156 -1
  255. package/src/subscribable/subscribable.ts +25 -15
  256. package/src/tests/MessageRepository.test.ts +1 -5
  257. package/src/tests/auiV0Encode.test.ts +300 -0
  258. package/src/tests/base-composer-runtime-core-send.test.ts +51 -0
  259. package/src/tests/base-composer-runtime-core.test.ts +314 -2
  260. package/src/tests/external-store-thread-runtime-core-adapter.test.ts +151 -0
  261. package/src/tests/external-thread-attachments.test.tsx +69 -0
  262. package/src/tests/external-thread-parity.test.tsx +34 -0
  263. package/src/tests/groupParts.test.ts +71 -0
  264. package/src/tests/message-queue.test.ts +253 -0
  265. package/src/tests/remote-thread-list-reactive-threadId.test.ts +51 -0
  266. package/src/tests/useRemoteThreadListRuntime-controlled.test.tsx +43 -0
  267. package/src/types/index.ts +1 -0
  268. package/src/types/message.ts +8 -0
  269. package/src/utils/abortable-iterable.test.ts +115 -0
  270. package/src/utils/abortable-iterable.ts +34 -23
  271. package/src/utils/getGroupStatus.test.ts +70 -4
  272. package/src/utils/getGroupStatus.ts +35 -12
  273. package/src/utils/wire-media.test.ts +10 -0
  274. package/src/utils/wire-media.ts +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"interactable-composer-metadata.js","names":["isJSONValueEqual","isJSONValue","isRecord","Unstable_InteractableSnapshotEntry","id","name","state","partial","SnapshotCarrierMessage","role","metadata","content","unstable_getInteractableSnapshots","message","undefined","custom","Record","items","interactables","Array","isArray","unstable_formatInteractableSnapshot","entry","JSON","stringify","interactableToolName","replace","getArrayItemId","item","applyArrayUpdate","prev","update","mintId","next","set","clear","remove","length","ids","Set","filter","has","patches","patchesById","Map","candidate","Number","isNaN","map","patch","get","add","added","shallowMergeInteractableState","options","arrayBaseline","idFactory","field","idKeyedFields","ReadonlySet","baseline","key","value","Object","entries","baseValue","shallowDiffInteractableState","known","keys","diff","changed","ToolCallLikePart","type","toolCallId","toolName","args","result","asToolCallPart","part","p","updateCallTargets","success","argsId","createAddedItemIdFactory","addedItemIds","idsByField","stringIds","size","shift","Unstable_InteractableVersion","origin","versionsCache","WeakMap","unstable_getInteractableVersions","messages","byName","byId","cached","versions","current","msg","find","it","push","_id","findModelKnownState","last","gateInteractableComposerMetadata","meta","rest","gated","pending","process","env","NODE_ENV","console","warn"],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"sourcesContent":["import { isJSONValueEqual } from \"../utils/json/is-json-equal\";\nimport { isJSONValue, isRecord } from \"../utils/json/is-json\";\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableSnapshotEntry = {\n id: string;\n name: string;\n state: unknown;\n /**\n * When true, `state` carries only the top-level fields that changed since\n * the model's last known state; omitted fields are unchanged. The first\n * snapshot of an instance is always full.\n */\n partial?: boolean | undefined;\n};\n\n/**\n * Minimal message shape needed to read snapshots and `update_*` tool calls out\n * of history. Structurally compatible with both `ThreadMessage` and the AI\n * SDK's `UIMessage`.\n */\ntype SnapshotCarrierMessage = {\n role: string;\n metadata?: unknown;\n content?: readonly unknown[] | undefined;\n};\n\n/**\n * Reads the interactable snapshots stamped on a message's\n * `metadata.custom.interactables`, or `undefined` if none. This is the read\n * half of the snapshot channel — integrations use it to surface interactable\n * state to the model (see `unstable_injectInteractableContext` in\n * `@assistant-ui/ai-sdk` for the AI SDK implementation).\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableSnapshots(message: {\n metadata?: unknown;\n}): Unstable_InteractableSnapshotEntry[] | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n const items = (custom as Record<string, unknown>).interactables;\n return Array.isArray(items)\n ? (items as Unstable_InteractableSnapshotEntry[])\n : undefined;\n}\n\n/**\n * Canonical model-facing wording for one snapshot entry.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_formatInteractableSnapshot(\n entry: Unstable_InteractableSnapshotEntry,\n): string {\n if (entry.partial) {\n return `[State of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}) changed — updated fields: ${JSON.stringify(entry.state)}; fields not listed are unchanged]`;\n }\n return `[Current state of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}): ${JSON.stringify(entry.state)}]`;\n}\n\n/** The model-facing tool name for an interactable `name`. One tool per name. */\nexport function interactableToolName(name: string): string {\n return `update_${name.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n}\n\nconst getArrayItemId = (item: unknown): string | number | undefined => {\n if (!isRecord(item)) return undefined;\n const id = item.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n};\n\nfunction applyArrayUpdate(\n prev: unknown[],\n update: Record<string, unknown>,\n mintId?: () => string | undefined,\n) {\n let next = Array.isArray(update.set) ? [...update.set] : [...prev];\n\n if (update.clear === true) next = [];\n\n if (Array.isArray(update.remove) && update.remove.length > 0) {\n const ids = new Set(update.remove);\n next = next.filter((item) => {\n const id = getArrayItemId(item);\n return id !== undefined ? !ids.has(id) : !ids.has(item);\n });\n }\n\n const patches = update.update;\n if (Array.isArray(patches) && patches.length > 0) {\n const patchesById = new Map<string | number, Record<string, unknown>>();\n for (const candidate of patches) {\n const id = getArrayItemId(candidate);\n if (id !== undefined && !Number.isNaN(id) && !patchesById.has(id)) {\n patchesById.set(id, candidate as Record<string, unknown>);\n }\n }\n\n next = next.map((item) => {\n const id = getArrayItemId(item);\n if (id === undefined || !isRecord(item)) return item;\n const patch = patchesById.get(id);\n return patch ? { ...item, ...patch } : item;\n });\n }\n\n if (Array.isArray(update.add) && update.add.length > 0) {\n const added = mintId\n ? update.add.map((item) => {\n if (!isRecord(item) || item.id !== undefined) return item;\n const id = mintId();\n return id === undefined ? item : { ...item, id };\n })\n : update.add;\n next = [...next, ...added];\n }\n\n return next;\n}\n\n/**\n * The merge `update_*` tools apply: top-level keys replace, rest preserved.\n * Array fields also accept operation objects (`add`, `update`, `remove`,\n * `clear`, `set`) so collection edits do not need a companion manage_* tool.\n */\nexport function shallowMergeInteractableState(\n prev: unknown,\n partial: unknown,\n options?:\n | {\n arrayBaseline?: unknown;\n /**\n * Supplies ids for added items in id-keyed array fields. The live\n * execute path mints fresh ids; history folds replay ids previously\n * returned by execute.\n */\n idFactory?: (field: string) => string | undefined;\n idKeyedFields?: ReadonlySet<string>;\n }\n | undefined,\n): unknown {\n if (!isRecord(prev) || !isRecord(partial)) return partial;\n const baseline = isRecord(options?.arrayBaseline)\n ? options.arrayBaseline\n : prev;\n const next = { ...prev };\n for (const [key, value] of Object.entries(partial)) {\n const baseValue = baseline[key];\n if (Array.isArray(baseValue) && isRecord(value)) {\n const mintId =\n options?.idFactory &&\n (options.idKeyedFields === undefined || options.idKeyedFields.has(key))\n ? () => options.idFactory?.(key)\n : undefined;\n next[key] = applyArrayUpdate(baseValue, value, mintId);\n } else {\n next[key] = value;\n }\n }\n return next;\n}\n\n/**\n * The top-level fields of `next` that differ from `known`, for stamping a\n * partial snapshot. Returns `undefined` when a partial stamp has no benefit:\n * the change is not expressible as a shallow merge (non-object states, or a\n * top-level key was removed), or every field changed anyway — the caller\n * falls back to a full snapshot.\n */\nfunction shallowDiffInteractableState(\n known: unknown,\n next: unknown,\n): Record<string, unknown> | undefined {\n if (!isRecord(known) || !isRecord(next)) return undefined;\n for (const key of Object.keys(known)) {\n if (!(key in next)) return undefined;\n }\n const diff: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(next)) {\n if (!(key in known) || !isJSONValueEqual(known[key], value)) {\n diff[key] = value;\n }\n }\n const changed = Object.keys(diff).length;\n if (changed === 0 || changed === Object.keys(next).length) return undefined;\n return diff;\n}\n\ntype ToolCallLikePart = {\n type?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n};\n\nconst asToolCallPart = (part: unknown): ToolCallLikePart | undefined => {\n if (!part || typeof part !== \"object\") return undefined;\n const p = part as ToolCallLikePart;\n return p.type === \"tool-call\" ? p : undefined;\n};\n\n/** Whether an accepted `update_*` call addressed instance `id`. */\nconst updateCallTargets = (p: ToolCallLikePart, id: string): boolean => {\n if (!p.args || typeof p.args !== \"object\") return false;\n const result = isRecord(p.result) ? p.result : undefined;\n if (result?.success === false) return false;\n if (typeof result?.id === \"string\") return result.id === id;\n const argsId = (p.args as Record<string, unknown>).id;\n return argsId === id || argsId === undefined;\n};\n\nconst createAddedItemIdFactory = (result: unknown) => {\n const value = isRecord(result) ? result.addedItemIds : undefined;\n if (!isRecord(value)) return undefined;\n\n const idsByField = new Map<string, string[]>();\n for (const [field, ids] of Object.entries(value)) {\n if (!Array.isArray(ids)) continue;\n const stringIds = ids.filter(\n (item): item is string => typeof item === \"string\",\n );\n if (stringIds.length > 0) idsByField.set(field, stringIds);\n }\n if (idsByField.size === 0) return undefined;\n\n return (field: string) => idsByField.get(field)?.shift();\n};\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableVersion = {\n /** The full state as of this version. */\n state: unknown;\n origin: \"create\" | \"update\" | \"user-edit\";\n /** For create/update versions, the tool call that produced this version. */\n toolCallId?: string | undefined;\n};\n\n// Without this, every mounted anchor re-folds the whole thread on each streaming\n// token, since the repository hands out a new messages array per token.\nconst versionsCache = new WeakMap<\n readonly SnapshotCarrierMessage[],\n Map<string, Map<string, Unstable_InteractableVersion[]>>\n>();\n\n/**\n * Every version of interactable `id` recorded in the thread, oldest first,\n * folded chronologically:\n *\n * - the tool call whose `toolCallId` equals `id` seeds the baseline with its\n * args (`origin: \"create\"`) — the `id: toolCallId` convention for\n * tool-created interactables,\n * - a snapshot stamped on a user message is a `\"user-edit\"` version (a full\n * snapshot replaces the state; a partial one shallow-merges),\n * - each accepted `update_*` call shallow-merges an `\"update\"` version.\n *\n * The last entry is the state the model knows. Partial snapshots and update\n * calls with no baseline to merge into are skipped.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableVersions(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): Unstable_InteractableVersion[] {\n let byName = versionsCache.get(messages);\n if (!byName) {\n byName = new Map();\n versionsCache.set(messages, byName);\n }\n let byId = byName.get(name);\n if (!byId) {\n byId = new Map();\n byName.set(name, byId);\n }\n const cached = byId.get(id);\n if (cached) return cached;\n\n const toolName = interactableToolName(name);\n const versions: Unstable_InteractableVersion[] = [];\n const current = () => versions[versions.length - 1];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const entry = unstable_getInteractableSnapshots(msg)?.find(\n (it) => it.id === id,\n );\n if (!entry) continue;\n if (entry.partial) {\n const prev = current();\n if (prev) {\n versions.push({\n state: shallowMergeInteractableState(prev.state, entry.state),\n origin: \"user-edit\",\n });\n }\n } else {\n versions.push({ state: entry.state, origin: \"user-edit\" });\n }\n continue;\n }\n\n if (msg.role !== \"assistant\") continue;\n for (const part of msg.content ?? []) {\n const p = asToolCallPart(part);\n if (!p) continue;\n if (p.toolCallId === id && p.toolName === name) {\n if (p.args && typeof p.args === \"object\") {\n versions.push({ state: p.args, origin: \"create\", toolCallId: id });\n }\n } else if (p.toolName === toolName && updateCallTargets(p, id)) {\n const prev = current();\n if (prev) {\n const { id: _id, ...partial } = p.args as Record<string, unknown>;\n const idFactory = createAddedItemIdFactory(p.result);\n versions.push({\n state: idFactory\n ? shallowMergeInteractableState(prev.state, partial, {\n idFactory,\n })\n : shallowMergeInteractableState(prev.state, partial),\n origin: \"update\",\n toolCallId: p.toolCallId,\n });\n }\n }\n }\n }\n byId.set(id, versions);\n return versions;\n}\n\n/**\n * The state the model knows for interactable `id` — its latest recorded\n * version, or `undefined` when no baseline exists yet.\n */\nexport function findModelKnownState(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): { state: unknown } | undefined {\n const versions = unstable_getInteractableVersions(messages, id, name);\n const last = versions[versions.length - 1];\n return last ? { state: last.state } : undefined;\n}\n\n/**\n * Snapshot gate. Stamps an interactable only when the model doesn't already\n * know its state (no baseline yet, or the live state differs from the folded\n * thread record). A change that fits a shallow merge is stamped as a partial\n * snapshot carrying just the changed fields; otherwise the full state is\n * stamped. Other metadata keys pass through untouched.\n */\nexport function gateInteractableComposerMetadata(\n meta: Record<string, unknown> | undefined,\n messages: readonly SnapshotCarrierMessage[],\n): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n const { interactables, ...rest } = meta as {\n interactables?: Unstable_InteractableSnapshotEntry[];\n } & Record<string, unknown>;\n\n const gated: Record<string, unknown> = { ...rest };\n if (Array.isArray(interactables)) {\n const pending: Unstable_InteractableSnapshotEntry[] = [];\n for (const it of interactables) {\n if (process.env.NODE_ENV !== \"production\" && !isJSONValue(it.state)) {\n console.warn(\n `[Interactables] state for \"${it.name}\" (${it.id}) is not JSON-equatable ` +\n `(an undefined, NaN, Infinity, function, or symbol value?). It will be ` +\n `re-snapshotted on every send, recreating per-message growth. Use plain ` +\n `JSON values.`,\n );\n }\n const known = findModelKnownState(messages, it.id, it.name);\n if (!known) {\n pending.push({ id: it.id, name: it.name, state: it.state });\n continue;\n }\n if (isJSONValueEqual(it.state, known.state)) continue;\n const diff = shallowDiffInteractableState(known.state, it.state);\n pending.push(\n diff\n ? { id: it.id, name: it.name, state: diff, partial: true }\n : { id: it.id, name: it.name, state: it.state },\n );\n }\n if (pending.length) gated.interactables = pending;\n }\n return Object.keys(gated).length ? gated : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"interactable-composer-metadata.js","names":["isJSONValueEqual","isJSONValue","isRecord","Unstable_InteractableSnapshotEntry","id","name","state","partial","SnapshotCarrierMessage","role","metadata","content","unstable_getInteractableSnapshots","message","undefined","custom","Record","items","interactables","Array","isArray","unstable_formatInteractableSnapshot","entry","JSON","stringify","interactableToolName","replace","getArrayItemId","item","applyArrayUpdate","prev","update","mintId","next","set","clear","remove","length","ids","Set","filter","has","patches","patchesById","Map","candidate","Number","isNaN","map","patch","get","add","added","shallowMergeInteractableState","options","arrayBaseline","idFactory","field","idKeyedFields","ReadonlySet","baseline","Object","entries","key","value","baseValue","push","fromEntries","shallowDiffInteractableState","known","keys","hasOwn","diff","changed","ToolCallLikePart","type","toolCallId","toolName","args","result","asToolCallPart","part","p","updateCallTargets","success","argsId","createAddedItemIdFactory","addedItemIds","idsByField","stringIds","size","shift","Unstable_InteractableVersion","origin","versionsCache","WeakMap","unstable_getInteractableVersions","messages","byName","byId","cached","versions","current","msg","find","it","_id","findModelKnownState","last","gateInteractableComposerMetadata","meta","rest","gated","pending","process","env","NODE_ENV","console","warn"],"sources":["../../src/model-context/interactable-composer-metadata.ts"],"sourcesContent":["import { isJSONValueEqual } from \"../utils/json/is-json-equal\";\nimport { isJSONValue, isRecord } from \"../utils/json/is-json\";\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableSnapshotEntry = {\n id: string;\n name: string;\n state: unknown;\n /**\n * When true, `state` carries only the top-level fields that changed since\n * the model's last known state; omitted fields are unchanged. The first\n * snapshot of an instance is always full.\n */\n partial?: boolean | undefined;\n};\n\n/**\n * Minimal message shape needed to read snapshots and `update_*` tool calls out\n * of history. Structurally compatible with both `ThreadMessage` and the AI\n * SDK's `UIMessage`.\n */\ntype SnapshotCarrierMessage = {\n role: string;\n metadata?: unknown;\n content?: readonly unknown[] | undefined;\n};\n\n/**\n * Reads the interactable snapshots stamped on a message's\n * `metadata.custom.interactables`, or `undefined` if none. This is the read\n * half of the snapshot channel — integrations use it to surface interactable\n * state to the model (see `unstable_injectInteractableContext` in\n * `@assistant-ui/ai-sdk` for the AI SDK implementation).\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableSnapshots(message: {\n metadata?: unknown;\n}): Unstable_InteractableSnapshotEntry[] | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n const items = (custom as Record<string, unknown>).interactables;\n return Array.isArray(items)\n ? (items as Unstable_InteractableSnapshotEntry[])\n : undefined;\n}\n\n/**\n * Canonical model-facing wording for one snapshot entry.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_formatInteractableSnapshot(\n entry: Unstable_InteractableSnapshotEntry,\n): string {\n if (entry.partial) {\n return `[State of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}) changed — updated fields: ${JSON.stringify(entry.state)}; fields not listed are unchanged]`;\n }\n return `[Current state of \"${entry.name}\" (id: ${JSON.stringify(entry.id)}): ${JSON.stringify(entry.state)}]`;\n}\n\n/** The model-facing tool name for an interactable `name`. One tool per name. */\nexport function interactableToolName(name: string): string {\n return `update_${name.replace(/[^a-zA-Z0-9_-]/g, \"_\")}`;\n}\n\nconst getArrayItemId = (item: unknown): string | number | undefined => {\n if (!isRecord(item)) return undefined;\n const id = item.id;\n return typeof id === \"string\" || typeof id === \"number\" ? id : undefined;\n};\n\nfunction applyArrayUpdate(\n prev: unknown[],\n update: Record<string, unknown>,\n mintId?: () => string | undefined,\n) {\n let next = Array.isArray(update.set) ? [...update.set] : [...prev];\n\n if (update.clear === true) next = [];\n\n if (Array.isArray(update.remove) && update.remove.length > 0) {\n const ids = new Set(update.remove);\n next = next.filter((item) => {\n const id = getArrayItemId(item);\n return id !== undefined ? !ids.has(id) : !ids.has(item);\n });\n }\n\n const patches = update.update;\n if (Array.isArray(patches) && patches.length > 0) {\n const patchesById = new Map<string | number, Record<string, unknown>>();\n for (const candidate of patches) {\n const id = getArrayItemId(candidate);\n if (id !== undefined && !Number.isNaN(id) && !patchesById.has(id)) {\n patchesById.set(id, candidate as Record<string, unknown>);\n }\n }\n\n next = next.map((item) => {\n const id = getArrayItemId(item);\n if (id === undefined || !isRecord(item)) return item;\n const patch = patchesById.get(id);\n return patch ? { ...item, ...patch } : item;\n });\n }\n\n if (Array.isArray(update.add) && update.add.length > 0) {\n const added = mintId\n ? update.add.map((item) => {\n if (!isRecord(item) || item.id !== undefined) return item;\n const id = mintId();\n return id === undefined ? item : { ...item, id };\n })\n : update.add;\n next = [...next, ...added];\n }\n\n return next;\n}\n\n/**\n * The merge `update_*` tools apply: top-level keys replace, rest preserved.\n * Array fields also accept operation objects (`add`, `update`, `remove`,\n * `clear`, `set`) so collection edits do not need a companion manage_* tool.\n */\nexport function shallowMergeInteractableState(\n prev: unknown,\n partial: unknown,\n options?:\n | {\n arrayBaseline?: unknown;\n /**\n * Supplies ids for added items in id-keyed array fields. The live\n * execute path mints fresh ids; history folds replay ids previously\n * returned by execute.\n */\n idFactory?: (field: string) => string | undefined;\n idKeyedFields?: ReadonlySet<string>;\n }\n | undefined,\n): unknown {\n if (!isRecord(prev) || !isRecord(partial)) return partial;\n const baseline = isRecord(options?.arrayBaseline)\n ? options.arrayBaseline\n : prev;\n const next = Object.entries(prev);\n for (const [key, value] of Object.entries(partial)) {\n const baseValue = baseline[key];\n if (Array.isArray(baseValue) && isRecord(value)) {\n const mintId =\n options?.idFactory &&\n (options.idKeyedFields === undefined || options.idKeyedFields.has(key))\n ? () => options.idFactory?.(key)\n : undefined;\n next.push([key, applyArrayUpdate(baseValue, value, mintId)]);\n } else {\n next.push([key, value]);\n }\n }\n return Object.fromEntries(next);\n}\n\n/**\n * The top-level fields of `next` that differ from `known`, for stamping a\n * partial snapshot. Returns `undefined` when a partial stamp has no benefit:\n * the change is not expressible as a shallow merge (non-object states, or a\n * top-level key was removed), or every field changed anyway — the caller\n * falls back to a full snapshot.\n */\nfunction shallowDiffInteractableState(\n known: unknown,\n next: unknown,\n): Record<string, unknown> | undefined {\n if (!isRecord(known) || !isRecord(next)) return undefined;\n for (const key of Object.keys(known)) {\n if (!Object.hasOwn(next, key)) return undefined;\n }\n const diff: [string, unknown][] = [];\n for (const [key, value] of Object.entries(next)) {\n if (!Object.hasOwn(known, key) || !isJSONValueEqual(known[key], value)) {\n diff.push([key, value]);\n }\n }\n const changed = diff.length;\n if (changed === 0 || changed === Object.keys(next).length) return undefined;\n return Object.fromEntries(diff);\n}\n\ntype ToolCallLikePart = {\n type?: string;\n toolCallId?: string;\n toolName?: string;\n args?: unknown;\n result?: unknown;\n};\n\nconst asToolCallPart = (part: unknown): ToolCallLikePart | undefined => {\n if (!part || typeof part !== \"object\") return undefined;\n const p = part as ToolCallLikePart;\n return p.type === \"tool-call\" ? p : undefined;\n};\n\n/** Whether an accepted `update_*` call addressed instance `id`. */\nconst updateCallTargets = (p: ToolCallLikePart, id: string): boolean => {\n if (!p.args || typeof p.args !== \"object\") return false;\n const result = isRecord(p.result) ? p.result : undefined;\n if (result?.success === false) return false;\n if (typeof result?.id === \"string\") return result.id === id;\n const argsId = (p.args as Record<string, unknown>).id;\n return argsId === id || argsId === undefined;\n};\n\nconst createAddedItemIdFactory = (result: unknown) => {\n const value = isRecord(result) ? result.addedItemIds : undefined;\n if (!isRecord(value)) return undefined;\n\n const idsByField = new Map<string, string[]>();\n for (const [field, ids] of Object.entries(value)) {\n if (!Array.isArray(ids)) continue;\n const stringIds = ids.filter(\n (item): item is string => typeof item === \"string\",\n );\n if (stringIds.length > 0) idsByField.set(field, stringIds);\n }\n if (idsByField.size === 0) return undefined;\n\n return (field: string) => idsByField.get(field)?.shift();\n};\n\n/**\n * Unstable / Experimental — the interactables API is still evolving and may change in any release.\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport type Unstable_InteractableVersion = {\n /** The full state as of this version. */\n state: unknown;\n origin: \"create\" | \"update\" | \"user-edit\";\n /** For create/update versions, the tool call that produced this version. */\n toolCallId?: string | undefined;\n};\n\n// Without this, every mounted anchor re-folds the whole thread on each streaming\n// token, since the repository hands out a new messages array per token.\nconst versionsCache = new WeakMap<\n readonly SnapshotCarrierMessage[],\n Map<string, Map<string, Unstable_InteractableVersion[]>>\n>();\n\n/**\n * Every version of interactable `id` recorded in the thread, oldest first,\n * folded chronologically:\n *\n * - the tool call whose `toolCallId` equals `id` seeds the baseline with its\n * args (`origin: \"create\"`) — the `id: toolCallId` convention for\n * tool-created interactables,\n * - a snapshot stamped on a user message is a `\"user-edit\"` version (a full\n * snapshot replaces the state; a partial one shallow-merges),\n * - each accepted `update_*` call shallow-merges an `\"update\"` version.\n *\n * The last entry is the state the model knows. Partial snapshots and update\n * calls with no baseline to merge into are skipped.\n *\n * @deprecated Unstable / Experimental (not actually removed).\n */\nexport function unstable_getInteractableVersions(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): Unstable_InteractableVersion[] {\n let byName = versionsCache.get(messages);\n if (!byName) {\n byName = new Map();\n versionsCache.set(messages, byName);\n }\n let byId = byName.get(name);\n if (!byId) {\n byId = new Map();\n byName.set(name, byId);\n }\n const cached = byId.get(id);\n if (cached) return cached;\n\n const toolName = interactableToolName(name);\n const versions: Unstable_InteractableVersion[] = [];\n const current = () => versions[versions.length - 1];\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const entry = unstable_getInteractableSnapshots(msg)?.find(\n (it) => it.id === id,\n );\n if (!entry) continue;\n if (entry.partial) {\n const prev = current();\n if (prev) {\n versions.push({\n state: shallowMergeInteractableState(prev.state, entry.state),\n origin: \"user-edit\",\n });\n }\n } else {\n versions.push({ state: entry.state, origin: \"user-edit\" });\n }\n continue;\n }\n\n if (msg.role !== \"assistant\") continue;\n for (const part of msg.content ?? []) {\n const p = asToolCallPart(part);\n if (!p) continue;\n if (p.toolCallId === id && p.toolName === name) {\n if (p.args && typeof p.args === \"object\") {\n versions.push({ state: p.args, origin: \"create\", toolCallId: id });\n }\n } else if (p.toolName === toolName && updateCallTargets(p, id)) {\n const prev = current();\n if (prev) {\n const { id: _id, ...partial } = p.args as Record<string, unknown>;\n const idFactory = createAddedItemIdFactory(p.result);\n versions.push({\n state: idFactory\n ? shallowMergeInteractableState(prev.state, partial, {\n idFactory,\n })\n : shallowMergeInteractableState(prev.state, partial),\n origin: \"update\",\n toolCallId: p.toolCallId,\n });\n }\n }\n }\n }\n byId.set(id, versions);\n return versions;\n}\n\n/**\n * The state the model knows for interactable `id` — its latest recorded\n * version, or `undefined` when no baseline exists yet.\n */\nexport function findModelKnownState(\n messages: readonly SnapshotCarrierMessage[],\n id: string,\n name: string,\n): { state: unknown } | undefined {\n const versions = unstable_getInteractableVersions(messages, id, name);\n const last = versions[versions.length - 1];\n return last ? { state: last.state } : undefined;\n}\n\n/**\n * Snapshot gate. Stamps an interactable only when the model doesn't already\n * know its state (no baseline yet, or the live state differs from the folded\n * thread record). A change that fits a shallow merge is stamped as a partial\n * snapshot carrying just the changed fields; otherwise the full state is\n * stamped. Other metadata keys pass through untouched.\n */\nexport function gateInteractableComposerMetadata(\n meta: Record<string, unknown> | undefined,\n messages: readonly SnapshotCarrierMessage[],\n): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n const { interactables, ...rest } = meta as {\n interactables?: Unstable_InteractableSnapshotEntry[];\n } & Record<string, unknown>;\n\n const gated: Record<string, unknown> = { ...rest };\n if (Array.isArray(interactables)) {\n const pending: Unstable_InteractableSnapshotEntry[] = [];\n for (const it of interactables) {\n if (process.env.NODE_ENV !== \"production\" && !isJSONValue(it.state)) {\n console.warn(\n `[Interactables] state for \"${it.name}\" (${it.id}) is not JSON-equatable ` +\n `(an undefined, NaN, Infinity, function, or symbol value?). It will be ` +\n `re-snapshotted on every send, recreating per-message growth. Use plain ` +\n `JSON values.`,\n );\n }\n const known = findModelKnownState(messages, it.id, it.name);\n if (!known) {\n pending.push({ id: it.id, name: it.name, state: it.state });\n continue;\n }\n if (isJSONValueEqual(it.state, known.state)) continue;\n const diff = shallowDiffInteractableState(known.state, it.state);\n pending.push(\n diff\n ? { id: it.id, name: it.name, state: diff, partial: true }\n : { id: it.id, name: it.name, state: it.state },\n );\n }\n if (pending.length) gated.interactables = pending;\n }\n return Object.keys(gated).length ? gated : undefined;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LocalStorageThreadListAdapter.d.ts","names":[],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"mappings":";;;;;;KA8BY;EACV,QAAQ,cAAc;EACtB,QAAQ,aAAa,gBAAgB;EACrC,WAAW,cAAc;;KAkCtB;EACH,SAAS;EACT;EACA,iBAAiB;;KAGd;EACH;EACA;EACA;EACA;EACA,SAAS;;cAqIE,4BACX,uBACC;cAoCU,+BACX,uBACC;cAqIU,4BACX,SAAS,+BACR"}
1
+ {"version":3,"file":"LocalStorageThreadListAdapter.d.ts","names":[],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"mappings":";;;;;;KAiCY;EACV,QAAQ,cAAc;EACtB,QAAQ,aAAa,gBAAgB;EACrC,WAAW,cAAc;;KAkCtB;EACH,SAAS;EACT;EACA,iBAAiB;;KAGd;EACH;EACA;EACA;EACA;EACA,SAAS;;cAmOE,4BACX,uBACC;cAoCU,+BACX,uBACC;cAqIU,4BACX,SAAS,+BACR"}
@@ -55,7 +55,41 @@ const parseDate = (value) => {
55
55
  return Number.isNaN(date.getTime()) ? null : date;
56
56
  };
57
57
  const isMessageRole = (value) => value === "system" || value === "user" || value === "assistant";
58
- const parseStoredThreadMessage = (value) => {
58
+ const MAX_STORED_MESSAGE_DEPTH = 100;
59
+ const storedPartGuards = {
60
+ text: (part) => typeof part.text === "string",
61
+ reasoning: (part) => typeof part.text === "string" || typeof part.unstable_summary === "string",
62
+ image: (part) => typeof part.image === "string",
63
+ file: (part) => typeof part.data === "string" && typeof part.mimeType === "string",
64
+ audio: (part) => isRecord(part.audio) && typeof part.audio.data === "string" && typeof part.audio.format === "string",
65
+ data: (part) => typeof part.name === "string",
66
+ source: (part) => typeof part.id === "string" && (part.sourceType === "url" ? typeof part.url === "string" : part.sourceType === "document" && typeof part.title === "string" && typeof part.mediaType === "string"),
67
+ "generative-ui": (part) => isRecord(part.spec),
68
+ "tool-call": (part) => typeof part.toolCallId === "string" && typeof part.toolName === "string" && isRecord(part.args) && typeof part.argsText === "string"
69
+ };
70
+ const isStoredMessagePart = (value) => isRecord(value) && typeof value.type === "string" && (!Object.hasOwn(storedPartGuards, value.type) || storedPartGuards[value.type](value));
71
+ const parseStoredMessageParts = (content, depth) => content.flatMap((part) => {
72
+ if (!isStoredMessagePart(part)) return [];
73
+ if (part.type !== "tool-call" || part.messages === void 0) return [part];
74
+ const { messages, ...toolCall } = part;
75
+ if (!Array.isArray(messages)) return [toolCall];
76
+ return [{
77
+ ...toolCall,
78
+ messages: messages.flatMap((item) => {
79
+ const message = parseStoredThreadMessage(item, depth + 1);
80
+ return message ? [message] : [];
81
+ })
82
+ }];
83
+ });
84
+ const parseStoredAttachment = (value) => {
85
+ if (!isRecord(value) || typeof value.id !== "string" || typeof value.type !== "string" || typeof value.name !== "string" || !isRecord(value.status) || value.status.type !== "complete" || !Array.isArray(value.content)) return null;
86
+ return {
87
+ ...value,
88
+ content: value.content.filter(isStoredMessagePart)
89
+ };
90
+ };
91
+ const parseStoredThreadMessage = (value, depth) => {
92
+ if (depth > MAX_STORED_MESSAGE_DEPTH) return null;
59
93
  if (!isRecord(value) || typeof value.id !== "string") return null;
60
94
  if (!isMessageRole(value.role)) return null;
61
95
  if (!Array.isArray(value.content)) return null;
@@ -70,7 +104,7 @@ const parseStoredThreadMessage = (value) => {
70
104
  return {
71
105
  id: value.id,
72
106
  role: "assistant",
73
- content: value.content,
107
+ content: parseStoredMessageParts(value.content, depth),
74
108
  status,
75
109
  createdAt,
76
110
  metadata: {
@@ -88,16 +122,20 @@ const parseStoredThreadMessage = (value) => {
88
122
  if (value.role === "user") return {
89
123
  id: value.id,
90
124
  role: "user",
91
- content: value.content,
92
- attachments: Array.isArray(value.attachments) ? value.attachments : [],
125
+ content: parseStoredMessageParts(value.content, depth),
126
+ attachments: Array.isArray(value.attachments) ? value.attachments.flatMap((item) => {
127
+ const attachment = parseStoredAttachment(item);
128
+ return attachment ? [attachment] : [];
129
+ }) : [],
93
130
  createdAt,
94
131
  metadata: { custom: metadata.custom }
95
132
  };
96
- if (value.content.length !== 1) return null;
133
+ const content = parseStoredMessageParts(value.content, depth);
134
+ if (content.length !== 1) return null;
97
135
  return {
98
136
  id: value.id,
99
137
  role: "system",
100
- content: [value.content[0]],
138
+ content: [content[0]],
101
139
  createdAt,
102
140
  metadata: { custom: metadata.custom }
103
141
  };
@@ -112,7 +150,7 @@ const parseStoredThreadMetadata = (raw) => {
112
150
  };
113
151
  const parseStoredMessageRepositoryItem = (value) => {
114
152
  if (!isRecord(value)) return null;
115
- const message = parseStoredThreadMessage(value.message);
153
+ const message = parseStoredThreadMessage(value.message, 0);
116
154
  if (!message) return null;
117
155
  const parentId = value.parentId;
118
156
  if (parentId !== void 0 && parentId !== null && typeof parentId !== "string") return null;
@@ -1 +1 @@
1
- {"version":3,"file":"LocalStorageThreadListAdapter.js","names":["AssistantStream","createAssistantStream","FC","PropsWithChildren","useEffect","useMemo","useRef","useState","useAui","RemoteThreadInitializeResponse","RemoteThreadListAdapter","RemoteThreadListResponse","RemoteThreadMetadata","ThreadHistoryAdapter","ThreadMessage","RunConfig","ExportedMessageRepository","ExportedMessageRepositoryItem","isRecord","RuntimeAdapterProvider","RuntimeAdapters","TitleGenerationAdapter","AsyncStorageLike","getItem","key","Promise","setItem","value","removeItem","KeyedMutationQueue","tails","Map","run","mutation","T","previous","get","result","then","tail","undefined","set","delete","mutationQueues","WeakMap","getMutationQueue","storage","queue","LocalStorageAdapterOptions","prefix","titleGenerator","StoredThreadMetadata","remoteId","externalId","status","title","custom","Record","StoredSystemMessage","Extract","role","StoredUserMessage","StoredAssistantMessage","parseJSON","raw","JSON","parse","parseStoredThread","parseDate","Date","Number","isNaN","getTime","date","isMessageRole","parseStoredThreadMessage","id","Array","isArray","content","createdAt","metadata","type","submittedFeedback","submittedFeedbackType","unstable_state","unstable_annotations","unstable_data","steps","timing","NonNullable","isOptimistic","attachments","length","parseStoredThreadMetadata","parsed","flatMap","item","thread","parseStoredMessageRepositoryItem","message","parentId","runConfig","parseStoredMessageRepository","messages","candidateMessages","parsedItem","acceptedIds","Set","has","add","headId","some","AsyncStorageHistoryAdapter","getAui","ReturnType","mutationQueue","constructor","aui","_messagesKey","load","threadListItem","getState","append","initialize","repo","idx","findIndex","m","push","stringify","useLocalStorageThreadAdapters","auiRef","current","history","createHistoryProvider","Provider","t0","$","_c","children","adapters","t1","createLocalStorageAdapter","options","threadsKey","messagesKey","threadId","loadThreadMetadata","saveThreadMetadata","threads","updateThreadMetadata","update","find","adapter","unstable_Provider","unstable_useAdapters","useLocalStorageAdapters","list","map","t","unshift","rename","newTitle","updateCustom","archive","unarchive","filtered","filter","fetch","Error","generateTitle","controller","appendText"],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"sourcesContent":["import { type AssistantStream, createAssistantStream } from \"assistant-stream\";\nimport {\n type FC,\n type PropsWithChildren,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n ThreadHistoryAdapter,\n ThreadMessage,\n RunConfig,\n} from \"../../index\";\nimport type {\n ExportedMessageRepository,\n ExportedMessageRepositoryItem,\n} from \"../../internal\";\nimport { isRecord } from \"../../utils/json/is-json\";\nimport {\n RuntimeAdapterProvider,\n type RuntimeAdapters,\n} from \"../runtimes/RuntimeAdapterProvider\";\nimport type { TitleGenerationAdapter } from \"./TitleGenerationAdapter\";\n\nexport type AsyncStorageLike = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\nclass KeyedMutationQueue {\n private readonly tails = new Map<string, Promise<void>>();\n\n run<T>(key: string, mutation: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n const result = previous ? previous.then(mutation) : mutation();\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n\n this.tails.set(key, tail);\n void tail.then(() => {\n if (this.tails.get(key) === tail) this.tails.delete(key);\n });\n\n return result;\n }\n}\n\nconst mutationQueues = new WeakMap<AsyncStorageLike, KeyedMutationQueue>();\n\nconst getMutationQueue = (storage: AsyncStorageLike): KeyedMutationQueue => {\n let queue = mutationQueues.get(storage);\n if (!queue) {\n queue = new KeyedMutationQueue();\n mutationQueues.set(storage, queue);\n }\n return queue;\n};\n\ntype LocalStorageAdapterOptions = {\n storage: AsyncStorageLike;\n prefix?: string | undefined;\n titleGenerator?: TitleGenerationAdapter | undefined;\n};\n\ntype StoredThreadMetadata = {\n remoteId: string;\n externalId?: string;\n status: \"regular\" | \"archived\";\n title?: string;\n custom?: Record<string, unknown> | undefined;\n};\n\ntype StoredSystemMessage = Extract<ThreadMessage, { role: \"system\" }>;\ntype StoredUserMessage = Extract<ThreadMessage, { role: \"user\" }>;\ntype StoredAssistantMessage = Extract<ThreadMessage, { role: \"assistant\" }>;\n\nconst parseJSON = (raw: string | null): unknown => {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n};\n\nconst parseStoredThread = (value: unknown): StoredThreadMetadata | null => {\n if (!isRecord(value) || typeof value.remoteId !== \"string\") return null;\n\n const status = value.status ?? \"regular\";\n if (status !== \"regular\" && status !== \"archived\") return null;\n\n return {\n remoteId: value.remoteId,\n status,\n ...(typeof value.externalId === \"string\"\n ? { externalId: value.externalId }\n : undefined),\n ...(typeof value.title === \"string\" ? { title: value.title } : undefined),\n ...(isRecord(value.custom) ? { custom: value.custom } : undefined),\n };\n};\n\nconst parseDate = (value: unknown): Date | null => {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value;\n if (typeof value !== \"string\" && typeof value !== \"number\") return null;\n\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\nconst isMessageRole = (value: unknown): value is ThreadMessage[\"role\"] =>\n value === \"system\" || value === \"user\" || value === \"assistant\";\n\nconst parseStoredThreadMessage = (value: unknown): ThreadMessage | null => {\n if (!isRecord(value) || typeof value.id !== \"string\") return null;\n if (!isMessageRole(value.role)) return null;\n if (!Array.isArray(value.content)) return null;\n\n const createdAt = parseDate(value.createdAt);\n if (!createdAt) return null;\n\n const metadata = value.metadata;\n if (!isRecord(metadata) || !isRecord(metadata.custom)) return null;\n\n if (value.role === \"assistant\") {\n const status = value.status;\n if (!isRecord(status) || typeof status.type !== \"string\") return null;\n\n const submittedFeedback = isRecord(metadata.submittedFeedback)\n ? metadata.submittedFeedback\n : undefined;\n const submittedFeedbackType = submittedFeedback?.type;\n\n return {\n id: value.id,\n role: \"assistant\",\n content: value.content as StoredAssistantMessage[\"content\"],\n status: status as StoredAssistantMessage[\"status\"],\n createdAt,\n metadata: {\n unstable_state: (metadata.unstable_state ??\n null) as StoredAssistantMessage[\"metadata\"][\"unstable_state\"],\n unstable_annotations: Array.isArray(metadata.unstable_annotations)\n ? (metadata.unstable_annotations as StoredAssistantMessage[\"metadata\"][\"unstable_annotations\"])\n : [],\n unstable_data: Array.isArray(metadata.unstable_data)\n ? (metadata.unstable_data as StoredAssistantMessage[\"metadata\"][\"unstable_data\"])\n : [],\n steps: Array.isArray(metadata.steps)\n ? (metadata.steps as StoredAssistantMessage[\"metadata\"][\"steps\"])\n : [],\n ...(submittedFeedbackType === \"positive\" ||\n submittedFeedbackType === \"negative\"\n ? {\n submittedFeedback: {\n type: submittedFeedbackType,\n },\n }\n : undefined),\n ...(metadata.timing !== undefined\n ? {\n timing: metadata.timing as NonNullable<\n StoredAssistantMessage[\"metadata\"][\"timing\"]\n >,\n }\n : undefined),\n ...(metadata.isOptimistic === true\n ? { isOptimistic: true }\n : undefined),\n custom: metadata.custom,\n },\n };\n }\n\n if (value.role === \"user\") {\n return {\n id: value.id,\n role: \"user\",\n content: value.content as StoredUserMessage[\"content\"],\n attachments: Array.isArray(value.attachments)\n ? (value.attachments as StoredUserMessage[\"attachments\"])\n : [],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n }\n\n if (value.content.length !== 1) return null;\n\n return {\n id: value.id,\n role: \"system\",\n content: [value.content[0] as StoredSystemMessage[\"content\"][0]],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n};\n\nexport const parseStoredThreadMetadata = (\n raw: string | null,\n): StoredThreadMetadata[] => {\n const parsed = parseJSON(raw);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.flatMap((item) => {\n const thread = parseStoredThread(item);\n return thread ? [thread] : [];\n });\n};\n\nconst parseStoredMessageRepositoryItem = (\n value: unknown,\n): ExportedMessageRepositoryItem | null => {\n if (!isRecord(value)) return null;\n\n const message = parseStoredThreadMessage(value.message);\n if (!message) return null;\n\n const parentId = value.parentId;\n if (\n parentId !== undefined &&\n parentId !== null &&\n typeof parentId !== \"string\"\n ) {\n return null;\n }\n\n return {\n message,\n parentId: parentId ?? null,\n ...(isRecord(value.runConfig)\n ? { runConfig: value.runConfig as RunConfig }\n : undefined),\n };\n};\n\nexport const parseStoredMessageRepository = (\n raw: string | null,\n): ExportedMessageRepository => {\n const parsed = parseJSON(raw);\n if (!isRecord(parsed) || !Array.isArray(parsed.messages)) {\n return { messages: [] };\n }\n\n const candidateMessages = parsed.messages.flatMap((item) => {\n const parsedItem = parseStoredMessageRepositoryItem(item);\n return parsedItem ? [parsedItem] : [];\n });\n\n const acceptedIds = new Set<string>();\n const messages = candidateMessages.flatMap((item) => {\n if (acceptedIds.has(item.message.id)) return [];\n if (item.parentId !== null && !acceptedIds.has(item.parentId)) return [];\n\n acceptedIds.add(item.message.id);\n return [item];\n });\n\n const headId =\n parsed.headId === null ||\n (typeof parsed.headId === \"string\" &&\n messages.some((item) => item.message.id === parsed.headId))\n ? parsed.headId\n : undefined;\n\n return {\n ...(headId !== undefined ? { headId } : undefined),\n messages,\n };\n};\n\nclass AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {\n private storage: AsyncStorageLike;\n private getAui: () => ReturnType<typeof useAui>;\n private prefix: string;\n private mutationQueue: KeyedMutationQueue;\n\n constructor(\n storage: AsyncStorageLike,\n getAui: () => ReturnType<typeof useAui>,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n ) {\n this.storage = storage;\n this.getAui = getAui;\n this.prefix = prefix;\n this.mutationQueue = mutationQueue;\n }\n\n private get aui(): ReturnType<typeof useAui> {\n return this.getAui();\n }\n\n private _messagesKey(remoteId: string) {\n return `${this.prefix}messages:${remoteId}`;\n }\n\n async load(): Promise<ExportedMessageRepository> {\n const remoteId = this.aui.threadListItem.getState().remoteId;\n if (!remoteId) return { messages: [] };\n\n const raw = await this.storage.getItem(this._messagesKey(remoteId));\n return parseStoredMessageRepository(raw);\n }\n\n async append(item: ExportedMessageRepositoryItem): Promise<void> {\n const { remoteId } = await this.aui.threadListItem.initialize();\n\n const key = this._messagesKey(remoteId);\n await this.mutationQueue.run(key, async () => {\n const raw = await this.storage.getItem(key);\n const repo = parseStoredMessageRepository(raw);\n\n const idx = repo.messages.findIndex(\n (m) => m.message.id === item.message.id,\n );\n if (idx >= 0) {\n repo.messages[idx] = item;\n } else {\n repo.messages.push(item);\n }\n repo.headId = item.message.id;\n\n await this.storage.setItem(key, JSON.stringify(repo));\n });\n }\n}\n\nconst useLocalStorageThreadAdapters = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): RuntimeAdapters => {\n const aui = useAui();\n // Not useEffectEvent: history adapter methods run during render (SSR load).\n const auiRef = useRef(aui);\n useEffect(() => {\n auiRef.current = aui;\n });\n const [history] = useState(\n () =>\n new AsyncStorageHistoryAdapter(\n storage,\n () => auiRef.current,\n prefix,\n mutationQueue,\n ),\n );\n return useMemo(() => ({ history }), [history]);\n};\n\nconst createHistoryProvider = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): FC<PropsWithChildren> => {\n const Provider: FC<PropsWithChildren> = ({ children }) => {\n const adapters = useLocalStorageThreadAdapters(\n storage,\n prefix,\n mutationQueue,\n );\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n };\n return Provider;\n};\n\nexport const createLocalStorageAdapter = (\n options: LocalStorageAdapterOptions,\n): RemoteThreadListAdapter => {\n const { storage, prefix = \"@assistant-ui:\", titleGenerator } = options;\n\n const threadsKey = `${prefix}threads`;\n const messagesKey = (threadId: string) => `${prefix}messages:${threadId}`;\n const mutationQueue = getMutationQueue(storage);\n\n const loadThreadMetadata = async (): Promise<StoredThreadMetadata[]> => {\n const raw = await storage.getItem(threadsKey);\n return parseStoredThreadMetadata(raw);\n };\n\n const saveThreadMetadata = async (\n threads: StoredThreadMetadata[],\n ): Promise<void> => {\n await storage.setItem(threadsKey, JSON.stringify(threads));\n };\n\n const updateThreadMetadata = async (\n remoteId: string,\n update: (thread: StoredThreadMetadata) => void,\n ): Promise<void> => {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const thread = threads.find((item) => item.remoteId === remoteId);\n if (thread) {\n update(thread);\n await saveThreadMetadata(threads);\n }\n });\n };\n\n const adapter: RemoteThreadListAdapter = {\n unstable_Provider: createHistoryProvider(storage, prefix, mutationQueue),\n unstable_useAdapters: function useLocalStorageAdapters() {\n return useLocalStorageThreadAdapters(storage, prefix, mutationQueue);\n },\n\n async list(): Promise<RemoteThreadListResponse> {\n const threads = await loadThreadMetadata();\n return {\n threads: threads.map((t) => ({\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: t.status,\n title: t.title,\n custom: t.custom,\n })),\n };\n },\n\n async initialize(\n threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const remoteId = threadId;\n return mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n\n // Only add if not already present\n if (!threads.some((t) => t.remoteId === remoteId)) {\n threads.unshift({\n remoteId,\n status: \"regular\",\n });\n await saveThreadMetadata(threads);\n }\n\n return { remoteId, externalId: undefined };\n });\n },\n\n async rename(remoteId: string, newTitle: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = newTitle;\n });\n },\n\n async updateCustom(\n remoteId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.custom = custom;\n });\n },\n\n async archive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"archived\";\n });\n },\n\n async unarchive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"regular\";\n });\n },\n\n async delete(remoteId: string): Promise<void> {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const filtered = threads.filter((t) => t.remoteId !== remoteId);\n await saveThreadMetadata(filtered);\n });\n const key = messagesKey(remoteId);\n await mutationQueue.run(key, () => storage.removeItem(key));\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const threads = await loadThreadMetadata();\n const thread = threads.find((t) => t.remoteId === threadId);\n if (!thread)\n throw new Error(\n `Stored thread \"${threadId}\" not found while fetching thread metadata.`,\n );\n return {\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n custom: thread.custom,\n };\n },\n\n async generateTitle(\n remoteId: string,\n messages: readonly ThreadMessage[],\n ): Promise<AssistantStream> {\n if (titleGenerator) {\n const title = await titleGenerator.generateTitle(messages);\n\n // Update the stored title\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = title;\n });\n\n // Return a stream with a single text part\n return createAssistantStream((controller) => {\n controller.appendText(title);\n });\n }\n\n // No title generator — return empty stream\n return createAssistantStream(() => {});\n },\n };\n\n return adapter;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"LocalStorageThreadListAdapter.js","names":["AssistantStream","createAssistantStream","FC","PropsWithChildren","useEffect","useMemo","useRef","useState","useAui","CompleteAttachment","RemoteThreadInitializeResponse","RemoteThreadListAdapter","RemoteThreadListResponse","RemoteThreadMetadata","ThreadAssistantMessagePart","ThreadHistoryAdapter","ThreadMessage","ThreadUserMessagePart","RunConfig","ExportedMessageRepository","ExportedMessageRepositoryItem","isRecord","RuntimeAdapterProvider","RuntimeAdapters","TitleGenerationAdapter","AsyncStorageLike","getItem","key","Promise","setItem","value","removeItem","KeyedMutationQueue","tails","Map","run","mutation","T","previous","get","result","then","tail","undefined","set","delete","mutationQueues","WeakMap","getMutationQueue","storage","queue","LocalStorageAdapterOptions","prefix","titleGenerator","StoredThreadMetadata","remoteId","externalId","status","title","custom","Record","StoredSystemMessage","Extract","role","StoredUserMessage","StoredAssistantMessage","parseJSON","raw","JSON","parse","parseStoredThread","parseDate","Date","Number","isNaN","getTime","date","isMessageRole","MAX_STORED_MESSAGE_DEPTH","storedPartGuards","text","part","reasoning","unstable_summary","image","file","data","mimeType","audio","format","name","source","id","sourceType","url","mediaType","spec","toolCallId","toolName","args","argsText","isStoredMessagePart","type","Object","hasOwn","parseStoredMessageParts","content","depth","flatMap","messages","toolCall","Array","isArray","item","message","parseStoredThreadMessage","parseStoredAttachment","filter","createdAt","metadata","submittedFeedback","submittedFeedbackType","unstable_state","unstable_annotations","unstable_data","steps","timing","NonNullable","isOptimistic","attachments","attachment","length","parseStoredThreadMetadata","parsed","thread","parseStoredMessageRepositoryItem","parentId","runConfig","parseStoredMessageRepository","candidateMessages","parsedItem","acceptedIds","Set","has","add","headId","some","AsyncStorageHistoryAdapter","getAui","ReturnType","mutationQueue","constructor","aui","_messagesKey","load","threadListItem","getState","append","initialize","repo","idx","findIndex","m","push","stringify","useLocalStorageThreadAdapters","auiRef","current","history","createHistoryProvider","Provider","t0","$","_c","children","adapters","t1","createLocalStorageAdapter","options","threadsKey","messagesKey","threadId","loadThreadMetadata","saveThreadMetadata","threads","updateThreadMetadata","update","find","adapter","unstable_Provider","unstable_useAdapters","useLocalStorageAdapters","list","map","t","unshift","rename","newTitle","updateCustom","archive","unarchive","filtered","fetch","Error","generateTitle","controller","appendText"],"sources":["../../../src/react/adapters/LocalStorageThreadListAdapter.tsx"],"sourcesContent":["import { type AssistantStream, createAssistantStream } from \"assistant-stream\";\nimport {\n type FC,\n type PropsWithChildren,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAui } from \"@assistant-ui/store\";\nimport type {\n CompleteAttachment,\n RemoteThreadInitializeResponse,\n RemoteThreadListAdapter,\n RemoteThreadListResponse,\n RemoteThreadMetadata,\n ThreadAssistantMessagePart,\n ThreadHistoryAdapter,\n ThreadMessage,\n ThreadUserMessagePart,\n RunConfig,\n} from \"../../index\";\nimport type {\n ExportedMessageRepository,\n ExportedMessageRepositoryItem,\n} from \"../../internal\";\nimport { isRecord } from \"../../utils/json/is-json\";\nimport {\n RuntimeAdapterProvider,\n type RuntimeAdapters,\n} from \"../runtimes/RuntimeAdapterProvider\";\nimport type { TitleGenerationAdapter } from \"./TitleGenerationAdapter\";\n\nexport type AsyncStorageLike = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\nclass KeyedMutationQueue {\n private readonly tails = new Map<string, Promise<void>>();\n\n run<T>(key: string, mutation: () => Promise<T>): Promise<T> {\n const previous = this.tails.get(key);\n const result = previous ? previous.then(mutation) : mutation();\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n\n this.tails.set(key, tail);\n void tail.then(() => {\n if (this.tails.get(key) === tail) this.tails.delete(key);\n });\n\n return result;\n }\n}\n\nconst mutationQueues = new WeakMap<AsyncStorageLike, KeyedMutationQueue>();\n\nconst getMutationQueue = (storage: AsyncStorageLike): KeyedMutationQueue => {\n let queue = mutationQueues.get(storage);\n if (!queue) {\n queue = new KeyedMutationQueue();\n mutationQueues.set(storage, queue);\n }\n return queue;\n};\n\ntype LocalStorageAdapterOptions = {\n storage: AsyncStorageLike;\n prefix?: string | undefined;\n titleGenerator?: TitleGenerationAdapter | undefined;\n};\n\ntype StoredThreadMetadata = {\n remoteId: string;\n externalId?: string;\n status: \"regular\" | \"archived\";\n title?: string;\n custom?: Record<string, unknown> | undefined;\n};\n\ntype StoredSystemMessage = Extract<ThreadMessage, { role: \"system\" }>;\ntype StoredUserMessage = Extract<ThreadMessage, { role: \"user\" }>;\ntype StoredAssistantMessage = Extract<ThreadMessage, { role: \"assistant\" }>;\n\nconst parseJSON = (raw: string | null): unknown => {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n};\n\nconst parseStoredThread = (value: unknown): StoredThreadMetadata | null => {\n if (!isRecord(value) || typeof value.remoteId !== \"string\") return null;\n\n const status = value.status ?? \"regular\";\n if (status !== \"regular\" && status !== \"archived\") return null;\n\n return {\n remoteId: value.remoteId,\n status,\n ...(typeof value.externalId === \"string\"\n ? { externalId: value.externalId }\n : undefined),\n ...(typeof value.title === \"string\" ? { title: value.title } : undefined),\n ...(isRecord(value.custom) ? { custom: value.custom } : undefined),\n };\n};\n\nconst parseDate = (value: unknown): Date | null => {\n if (value instanceof Date && !Number.isNaN(value.getTime())) return value;\n if (typeof value !== \"string\" && typeof value !== \"number\") return null;\n\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n};\n\nconst isMessageRole = (value: unknown): value is ThreadMessage[\"role\"] =>\n value === \"system\" || value === \"user\" || value === \"assistant\";\n\nconst MAX_STORED_MESSAGE_DEPTH = 100;\n\nconst storedPartGuards = {\n text: (part) => typeof part.text === \"string\",\n reasoning: (part) =>\n typeof part.text === \"string\" || typeof part.unstable_summary === \"string\",\n image: (part) => typeof part.image === \"string\",\n file: (part) =>\n typeof part.data === \"string\" && typeof part.mimeType === \"string\",\n audio: (part) =>\n isRecord(part.audio) &&\n typeof part.audio.data === \"string\" &&\n typeof part.audio.format === \"string\",\n data: (part) => typeof part.name === \"string\",\n source: (part) =>\n typeof part.id === \"string\" &&\n (part.sourceType === \"url\"\n ? typeof part.url === \"string\"\n : part.sourceType === \"document\" &&\n typeof part.title === \"string\" &&\n typeof part.mediaType === \"string\"),\n \"generative-ui\": (part) => isRecord(part.spec),\n \"tool-call\": (part) =>\n typeof part.toolCallId === \"string\" &&\n typeof part.toolName === \"string\" &&\n isRecord(part.args) &&\n typeof part.argsText === \"string\",\n} satisfies Record<\n (ThreadUserMessagePart | ThreadAssistantMessagePart)[\"type\"],\n (part: Record<string, unknown>) => boolean\n>;\n\nconst isStoredMessagePart = (\n value: unknown,\n): value is Record<string, unknown> & { type: string } =>\n isRecord(value) &&\n typeof value.type === \"string\" &&\n (!Object.hasOwn(storedPartGuards, value.type) ||\n storedPartGuards[value.type as keyof typeof storedPartGuards](value));\n\nconst parseStoredMessageParts = (\n content: unknown[],\n depth: number,\n): unknown[] =>\n content.flatMap((part) => {\n if (!isStoredMessagePart(part)) return [];\n if (part.type !== \"tool-call\" || part.messages === undefined) return [part];\n\n const { messages, ...toolCall } = part;\n if (!Array.isArray(messages)) return [toolCall];\n return [\n {\n ...toolCall,\n messages: messages.flatMap((item) => {\n const message = parseStoredThreadMessage(item, depth + 1);\n return message ? [message] : [];\n }),\n },\n ];\n });\n\nconst parseStoredAttachment = (value: unknown): CompleteAttachment | null => {\n if (\n !isRecord(value) ||\n typeof value.id !== \"string\" ||\n typeof value.type !== \"string\" ||\n typeof value.name !== \"string\" ||\n !isRecord(value.status) ||\n value.status.type !== \"complete\" ||\n !Array.isArray(value.content)\n ) {\n return null;\n }\n\n return {\n ...value,\n content: value.content.filter(isStoredMessagePart),\n } as CompleteAttachment;\n};\n\nconst parseStoredThreadMessage = (\n value: unknown,\n depth: number,\n): ThreadMessage | null => {\n if (depth > MAX_STORED_MESSAGE_DEPTH) return null;\n if (!isRecord(value) || typeof value.id !== \"string\") return null;\n if (!isMessageRole(value.role)) return null;\n if (!Array.isArray(value.content)) return null;\n\n const createdAt = parseDate(value.createdAt);\n if (!createdAt) return null;\n\n const metadata = value.metadata;\n if (!isRecord(metadata) || !isRecord(metadata.custom)) return null;\n\n if (value.role === \"assistant\") {\n const status = value.status;\n if (!isRecord(status) || typeof status.type !== \"string\") return null;\n\n const submittedFeedback = isRecord(metadata.submittedFeedback)\n ? metadata.submittedFeedback\n : undefined;\n const submittedFeedbackType = submittedFeedback?.type;\n\n return {\n id: value.id,\n role: \"assistant\",\n content: parseStoredMessageParts(\n value.content,\n depth,\n ) as StoredAssistantMessage[\"content\"],\n status: status as StoredAssistantMessage[\"status\"],\n createdAt,\n metadata: {\n unstable_state: (metadata.unstable_state ??\n null) as StoredAssistantMessage[\"metadata\"][\"unstable_state\"],\n unstable_annotations: Array.isArray(metadata.unstable_annotations)\n ? (metadata.unstable_annotations as StoredAssistantMessage[\"metadata\"][\"unstable_annotations\"])\n : [],\n unstable_data: Array.isArray(metadata.unstable_data)\n ? (metadata.unstable_data as StoredAssistantMessage[\"metadata\"][\"unstable_data\"])\n : [],\n steps: Array.isArray(metadata.steps)\n ? (metadata.steps as StoredAssistantMessage[\"metadata\"][\"steps\"])\n : [],\n ...(submittedFeedbackType === \"positive\" ||\n submittedFeedbackType === \"negative\"\n ? {\n submittedFeedback: {\n type: submittedFeedbackType,\n },\n }\n : undefined),\n ...(metadata.timing !== undefined\n ? {\n timing: metadata.timing as NonNullable<\n StoredAssistantMessage[\"metadata\"][\"timing\"]\n >,\n }\n : undefined),\n ...(metadata.isOptimistic === true\n ? { isOptimistic: true }\n : undefined),\n custom: metadata.custom,\n },\n };\n }\n\n if (value.role === \"user\") {\n return {\n id: value.id,\n role: \"user\",\n content: parseStoredMessageParts(\n value.content,\n depth,\n ) as StoredUserMessage[\"content\"],\n attachments: Array.isArray(value.attachments)\n ? value.attachments.flatMap((item) => {\n const attachment = parseStoredAttachment(item);\n return attachment ? [attachment] : [];\n })\n : [],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n }\n\n const content = parseStoredMessageParts(value.content, depth);\n if (content.length !== 1) return null;\n\n return {\n id: value.id,\n role: \"system\",\n content: [content[0] as StoredSystemMessage[\"content\"][0]],\n createdAt,\n metadata: {\n custom: metadata.custom,\n },\n };\n};\n\nexport const parseStoredThreadMetadata = (\n raw: string | null,\n): StoredThreadMetadata[] => {\n const parsed = parseJSON(raw);\n if (!Array.isArray(parsed)) return [];\n\n return parsed.flatMap((item) => {\n const thread = parseStoredThread(item);\n return thread ? [thread] : [];\n });\n};\n\nconst parseStoredMessageRepositoryItem = (\n value: unknown,\n): ExportedMessageRepositoryItem | null => {\n if (!isRecord(value)) return null;\n\n const message = parseStoredThreadMessage(value.message, 0);\n if (!message) return null;\n\n const parentId = value.parentId;\n if (\n parentId !== undefined &&\n parentId !== null &&\n typeof parentId !== \"string\"\n ) {\n return null;\n }\n\n return {\n message,\n parentId: parentId ?? null,\n ...(isRecord(value.runConfig)\n ? { runConfig: value.runConfig as RunConfig }\n : undefined),\n };\n};\n\nexport const parseStoredMessageRepository = (\n raw: string | null,\n): ExportedMessageRepository => {\n const parsed = parseJSON(raw);\n if (!isRecord(parsed) || !Array.isArray(parsed.messages)) {\n return { messages: [] };\n }\n\n const candidateMessages = parsed.messages.flatMap((item) => {\n const parsedItem = parseStoredMessageRepositoryItem(item);\n return parsedItem ? [parsedItem] : [];\n });\n\n const acceptedIds = new Set<string>();\n const messages = candidateMessages.flatMap((item) => {\n if (acceptedIds.has(item.message.id)) return [];\n if (item.parentId !== null && !acceptedIds.has(item.parentId)) return [];\n\n acceptedIds.add(item.message.id);\n return [item];\n });\n\n const headId =\n parsed.headId === null ||\n (typeof parsed.headId === \"string\" &&\n messages.some((item) => item.message.id === parsed.headId))\n ? parsed.headId\n : undefined;\n\n return {\n ...(headId !== undefined ? { headId } : undefined),\n messages,\n };\n};\n\nclass AsyncStorageHistoryAdapter implements ThreadHistoryAdapter {\n private storage: AsyncStorageLike;\n private getAui: () => ReturnType<typeof useAui>;\n private prefix: string;\n private mutationQueue: KeyedMutationQueue;\n\n constructor(\n storage: AsyncStorageLike,\n getAui: () => ReturnType<typeof useAui>,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n ) {\n this.storage = storage;\n this.getAui = getAui;\n this.prefix = prefix;\n this.mutationQueue = mutationQueue;\n }\n\n private get aui(): ReturnType<typeof useAui> {\n return this.getAui();\n }\n\n private _messagesKey(remoteId: string) {\n return `${this.prefix}messages:${remoteId}`;\n }\n\n async load(): Promise<ExportedMessageRepository> {\n const remoteId = this.aui.threadListItem.getState().remoteId;\n if (!remoteId) return { messages: [] };\n\n const raw = await this.storage.getItem(this._messagesKey(remoteId));\n return parseStoredMessageRepository(raw);\n }\n\n async append(item: ExportedMessageRepositoryItem): Promise<void> {\n const { remoteId } = await this.aui.threadListItem.initialize();\n\n const key = this._messagesKey(remoteId);\n await this.mutationQueue.run(key, async () => {\n const raw = await this.storage.getItem(key);\n const repo = parseStoredMessageRepository(raw);\n\n const idx = repo.messages.findIndex(\n (m) => m.message.id === item.message.id,\n );\n if (idx >= 0) {\n repo.messages[idx] = item;\n } else {\n repo.messages.push(item);\n }\n repo.headId = item.message.id;\n\n await this.storage.setItem(key, JSON.stringify(repo));\n });\n }\n}\n\nconst useLocalStorageThreadAdapters = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): RuntimeAdapters => {\n const aui = useAui();\n // Not useEffectEvent: history adapter methods run during render (SSR load).\n const auiRef = useRef(aui);\n useEffect(() => {\n auiRef.current = aui;\n });\n const [history] = useState(\n () =>\n new AsyncStorageHistoryAdapter(\n storage,\n () => auiRef.current,\n prefix,\n mutationQueue,\n ),\n );\n return useMemo(() => ({ history }), [history]);\n};\n\nconst createHistoryProvider = (\n storage: AsyncStorageLike,\n prefix: string,\n mutationQueue: KeyedMutationQueue,\n): FC<PropsWithChildren> => {\n const Provider: FC<PropsWithChildren> = ({ children }) => {\n const adapters = useLocalStorageThreadAdapters(\n storage,\n prefix,\n mutationQueue,\n );\n return (\n <RuntimeAdapterProvider adapters={adapters}>\n {children}\n </RuntimeAdapterProvider>\n );\n };\n return Provider;\n};\n\nexport const createLocalStorageAdapter = (\n options: LocalStorageAdapterOptions,\n): RemoteThreadListAdapter => {\n const { storage, prefix = \"@assistant-ui:\", titleGenerator } = options;\n\n const threadsKey = `${prefix}threads`;\n const messagesKey = (threadId: string) => `${prefix}messages:${threadId}`;\n const mutationQueue = getMutationQueue(storage);\n\n const loadThreadMetadata = async (): Promise<StoredThreadMetadata[]> => {\n const raw = await storage.getItem(threadsKey);\n return parseStoredThreadMetadata(raw);\n };\n\n const saveThreadMetadata = async (\n threads: StoredThreadMetadata[],\n ): Promise<void> => {\n await storage.setItem(threadsKey, JSON.stringify(threads));\n };\n\n const updateThreadMetadata = async (\n remoteId: string,\n update: (thread: StoredThreadMetadata) => void,\n ): Promise<void> => {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const thread = threads.find((item) => item.remoteId === remoteId);\n if (thread) {\n update(thread);\n await saveThreadMetadata(threads);\n }\n });\n };\n\n const adapter: RemoteThreadListAdapter = {\n unstable_Provider: createHistoryProvider(storage, prefix, mutationQueue),\n unstable_useAdapters: function useLocalStorageAdapters() {\n return useLocalStorageThreadAdapters(storage, prefix, mutationQueue);\n },\n\n async list(): Promise<RemoteThreadListResponse> {\n const threads = await loadThreadMetadata();\n return {\n threads: threads.map((t) => ({\n remoteId: t.remoteId,\n externalId: t.externalId,\n status: t.status,\n title: t.title,\n custom: t.custom,\n })),\n };\n },\n\n async initialize(\n threadId: string,\n ): Promise<RemoteThreadInitializeResponse> {\n const remoteId = threadId;\n return mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n\n // Only add if not already present\n if (!threads.some((t) => t.remoteId === remoteId)) {\n threads.unshift({\n remoteId,\n status: \"regular\",\n });\n await saveThreadMetadata(threads);\n }\n\n return { remoteId, externalId: undefined };\n });\n },\n\n async rename(remoteId: string, newTitle: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = newTitle;\n });\n },\n\n async updateCustom(\n remoteId: string,\n custom: Record<string, unknown> | undefined,\n ): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.custom = custom;\n });\n },\n\n async archive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"archived\";\n });\n },\n\n async unarchive(remoteId: string): Promise<void> {\n await updateThreadMetadata(remoteId, (thread) => {\n thread.status = \"regular\";\n });\n },\n\n async delete(remoteId: string): Promise<void> {\n await mutationQueue.run(threadsKey, async () => {\n const threads = await loadThreadMetadata();\n const filtered = threads.filter((t) => t.remoteId !== remoteId);\n await saveThreadMetadata(filtered);\n });\n const key = messagesKey(remoteId);\n await mutationQueue.run(key, () => storage.removeItem(key));\n },\n\n async fetch(threadId: string): Promise<RemoteThreadMetadata> {\n const threads = await loadThreadMetadata();\n const thread = threads.find((t) => t.remoteId === threadId);\n if (!thread)\n throw new Error(\n `Stored thread \"${threadId}\" not found while fetching thread metadata.`,\n );\n return {\n remoteId: thread.remoteId,\n externalId: thread.externalId,\n status: thread.status,\n title: thread.title,\n custom: thread.custom,\n };\n },\n\n async generateTitle(\n remoteId: string,\n messages: readonly ThreadMessage[],\n ): Promise<AssistantStream> {\n if (titleGenerator) {\n const title = await titleGenerator.generateTitle(messages);\n\n // Update the stored title\n await updateThreadMetadata(remoteId, (thread) => {\n thread.title = title;\n });\n\n // Return a stream with a single text part\n return createAssistantStream((controller) => {\n controller.appendText(title);\n });\n }\n\n // No title generator — return empty stream\n return createAssistantStream(() => {});\n },\n };\n\n return adapter;\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DataRenderers.d.ts","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"mappings":";;cAmEa,2CAAa,SAAA"}
1
+ {"version":3,"file":"DataRenderers.d.ts","names":[],"sources":["../../../src/react/client/DataRenderers.ts"],"mappings":";;cAuEa,2CAAa,SAAA"}
@@ -1,3 +1,4 @@
1
+ import { nullProtoRecord } from "../../utils/record.js";
1
2
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
2
3
  import { useState } from "@assistant-ui/tap/react-shim";
3
4
  import { resource } from "@assistant-ui/tap";
@@ -15,21 +16,25 @@ const useDataRenderers = () => {
15
16
  let t0;
16
17
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
17
18
  t0 = (name, render) => {
18
- setState((prev) => ({
19
- ...prev,
20
- renderers: {
21
- ...prev.renderers,
22
- [name]: [...prev.renderers[name] ?? [], render]
23
- }
24
- }));
19
+ setState((prev) => {
20
+ const renderers = nullProtoRecord(prev.renderers);
21
+ renderers[name] = [...renderers[name] ?? [], render];
22
+ return {
23
+ ...prev,
24
+ renderers
25
+ };
26
+ });
25
27
  return () => {
26
- setState((prev_0) => ({
27
- ...prev_0,
28
- renderers: {
29
- ...prev_0.renderers,
30
- [name]: prev_0.renderers[name]?.filter((r) => r !== render) ?? []
31
- }
32
- }));
28
+ setState((prev_0) => {
29
+ const renderers_0 = nullProtoRecord(prev_0.renderers);
30
+ const remaining = renderers_0[name]?.filter((r) => r !== render) ?? [];
31
+ if (remaining.length > 0) renderers_0[name] = remaining;
32
+ else delete renderers_0[name];
33
+ return {
34
+ ...prev_0,
35
+ renderers: renderers_0
36
+ };
37
+ });
33
38
  };
34
39
  };
35
40
  $[0] = t0;
@@ -67,7 +72,7 @@ const useDataRenderers = () => {
67
72
  const DataRenderers = resource(useDataRenderers);
68
73
  function _temp() {
69
74
  return {
70
- renderers: {},
75
+ renderers: nullProtoRecord(),
71
76
  fallbacks: []
72
77
  };
73
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataRenderers.js","names":["useState","useCallback","resource","ClientOutput","DataRenderersState","DataMessagePartComponent","useDataRenderers","$","_c","state","setState","_temp","t0","Symbol","for","name","render","prev","renderers","prev_0","filter","r","setDataUI","t1","render_0","prev_1","fallbacks","prev_2","r_0","setFallbackDataUI","t2","getState","DataRenderers"],"sources":["../../../src/react/client/DataRenderers.ts"],"sourcesContent":["import { useState, useCallback } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport type { DataRenderersState } from \"../types/scopes/dataRenderers\";\nimport type { DataMessagePartComponent } from \"../types/MessagePartComponentTypes\";\n\n/**\n * Registers renderers for `data` message parts.\n *\n * Data renderers are looked up by the part's `name` field. Use this resource\n * directly for a renderer scope, or prefer {@link useAssistantDataUI} /\n * {@link makeAssistantDataUI} when registering from React components.\n */\nconst useDataRenderers = (): ClientOutput<\"dataRenderers\"> => {\n const [state, setState] = useState<DataRenderersState>(() => ({\n renderers: {},\n fallbacks: [],\n }));\n\n const setDataUI = useCallback(\n (name: string, render: DataMessagePartComponent) => {\n setState((prev) => {\n return {\n ...prev,\n renderers: {\n ...prev.renderers,\n [name]: [...(prev.renderers[name] ?? []), render],\n },\n };\n });\n\n return () => {\n setState((prev) => {\n return {\n ...prev,\n renderers: {\n ...prev.renderers,\n [name]: prev.renderers[name]?.filter((r) => r !== render) ?? [],\n },\n };\n });\n };\n },\n [],\n );\n\n const setFallbackDataUI = useCallback((render: DataMessagePartComponent) => {\n setState((prev) => ({\n ...prev,\n fallbacks: [...prev.fallbacks, render],\n }));\n\n return () => {\n setState((prev) => ({\n ...prev,\n fallbacks: prev.fallbacks.filter((r) => r !== render),\n }));\n };\n }, []);\n\n return {\n getState: () => state,\n setDataUI,\n setFallbackDataUI,\n };\n};\n\nexport const DataRenderers = resource(useDataRenderers);\n"],"mappings":";;;;;;;;;;;AAaA,MAAMM,yBAAmB;CAAA,MAAAC,IAAAC,EAAA,CAAA;CACvB,MAAA,CAAAC,OAAAC,YAA0BV,SAA6BW,KAGrD;CAAE,IAAAC;CAAA,IAAAL,EAAA,OAAAM,OAAAC,IAAA,2BAAA,GAAA;EAGFF,MAAAG,MAAAC,WAAA;GACEN,UAASO,UACA;IAAA,GACFA;IAAIC,WACI;KAAA,GACND,KAAIC;MACNH,OAAO,CAAA,GAAKE,KAAIC,UAAWH,SAAf,CAAA,GAA6BC,MAAM;IAClD;GACF,EACD;GAAC,aAEK;IACLN,UAASS,YACA;KAAA,GACFF;KAAIC,WACI;MAAA,GACND,OAAIC;OACNH,OAAOE,OAAIC,UAAWH,KAAa,EAAAK,QAACC,MAAOA,MAAML,MAAY,KAAtD,CAAA;KACV;IACF,EACD;GAAC;EACH;EACFT,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAvBH,MAAAe,YAAkBV;CAyBhB,IAAAW;CAAA,IAAAhB,EAAA,OAAAM,OAAAC,IAAA,2BAAA,GAAA;EAEoCS,MAAAC,aAAA;GACpCd,UAASe,YAAW;IAAA,GACfR;IAAIS,WACI,CAAA,GAAIT,OAAIS,WAAYV,QAAM;GACvC,EAAE;GAAC,aAEI;IACLN,UAASiB,YAAW;KAAA,GACfV;KAAIS,WACIT,OAAIS,UAAUN,QAAQQ,QAAOP,QAAML,QAAM;IACtD,EAAE;GAAC;EACJ;EACFT,EAAA,KAAAgB;CAAA,OAAAA,KAAAhB,EAAA;CAZD,MAAAsB,oBAA0BN;CAYnB,IAAAO;CAAA,IAAAvB,EAAA,OAAAE,OAAA;EAEAqB,KAAA;GAAAC,gBACWtB;GAAKa;GAAAO;EAGvB;EAACtB,EAAA,KAAAE;EAAAF,EAAA,KAAAuB;CAAA,OAAAA,KAAAvB,EAAA;CAAA,OAJMuB;AAIN;AAGH,MAAaE,gBAAgB9B,SAASI,gBAAgB;AAtD7B,SAAAK,QAAA;CAAA,OACuC;EAAAO,WACjD,CAAC;EAACQ,WACF,CAAA;CACb;AAAC"}
1
+ {"version":3,"file":"DataRenderers.js","names":["useState","useCallback","resource","ClientOutput","DataRenderersState","DataMessagePartComponent","nullProtoRecord","useDataRenderers","$","_c","state","setState","_temp","t0","Symbol","for","name","render","prev","renderers","prev_0","renderers_0","remaining","filter","r","length","setDataUI","t1","render_0","prev_1","fallbacks","prev_2","r_0","setFallbackDataUI","t2","getState","DataRenderers"],"sources":["../../../src/react/client/DataRenderers.ts"],"sourcesContent":["import { useState, useCallback } from \"react\";\nimport { resource } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport type { DataRenderersState } from \"../types/scopes/dataRenderers\";\nimport type { DataMessagePartComponent } from \"../types/MessagePartComponentTypes\";\nimport { nullProtoRecord } from \"../../utils/record\";\n\n/**\n * Registers renderers for `data` message parts.\n *\n * Data renderers are looked up by the part's `name` field. Use this resource\n * directly for a renderer scope, or prefer {@link useAssistantDataUI} /\n * {@link makeAssistantDataUI} when registering from React components.\n */\nconst useDataRenderers = (): ClientOutput<\"dataRenderers\"> => {\n const [state, setState] = useState<DataRenderersState>(() => ({\n renderers: nullProtoRecord(),\n fallbacks: [],\n }));\n\n const setDataUI = useCallback(\n (name: string, render: DataMessagePartComponent) => {\n setState((prev) => {\n const renderers = nullProtoRecord(prev.renderers);\n renderers[name] = [...(renderers[name] ?? []), render];\n return {\n ...prev,\n renderers,\n };\n });\n\n return () => {\n setState((prev) => {\n const renderers = nullProtoRecord(prev.renderers);\n const remaining = renderers[name]?.filter((r) => r !== render) ?? [];\n if (remaining.length > 0) {\n renderers[name] = remaining;\n } else {\n delete renderers[name];\n }\n return {\n ...prev,\n renderers,\n };\n });\n };\n },\n [],\n );\n\n const setFallbackDataUI = useCallback((render: DataMessagePartComponent) => {\n setState((prev) => ({\n ...prev,\n fallbacks: [...prev.fallbacks, render],\n }));\n\n return () => {\n setState((prev) => ({\n ...prev,\n fallbacks: prev.fallbacks.filter((r) => r !== render),\n }));\n };\n }, []);\n\n return {\n getState: () => state,\n setDataUI,\n setFallbackDataUI,\n };\n};\n\nexport const DataRenderers = resource(useDataRenderers);\n"],"mappings":";;;;;;;;;;;;AAcA,MAAMO,yBAAmB;CAAA,MAAAC,IAAAC,EAAA,CAAA;CACvB,MAAA,CAAAC,OAAAC,YAA0BX,SAA6BY,KAGrD;CAAE,IAAAC;CAAA,IAAAL,EAAA,OAAAM,OAAAC,IAAA,2BAAA,GAAA;EAGFF,MAAAG,MAAAC,WAAA;GACEN,UAASO,SAAA;IACP,MAAAC,YAAkBb,gBAAgBY,KAAIC,SAAU;IAChDA,UAAUH,QAAQ,CAAA,GAAKG,UAAUH,SAAV,CAAA,GAAwBC,MAAM;IAAtC,OACR;KAAA,GACFC;KAAIC;IAET;GAAC,CACF;GAAC,aAEK;IACLR,UAASS,WAAA;KACP,MAAAC,cAAkBf,gBAAgBY,OAAIC,SAAU;KAChD,MAAAG,YAAkBH,YAAUH,KAAa,EAAAO,QAACC,MAAOA,MAAMP,MAAY,KAAjD,CAAA;KAClB,IAAIK,UAASG,SAAU,GACrBN,YAAUH,QAAQM;UAElB,OAAOH,YAAUH;KAClB,OACM;MAAA,GACFE;MAAIC,WACPA;KACF;IAAC,CACF;GAAC;EACH;EACFX,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CA1BH,MAAAkB,YAAkBb;CA4BhB,IAAAc;CAAA,IAAAnB,EAAA,OAAAM,OAAAC,IAAA,2BAAA,GAAA;EAEoCY,MAAAC,aAAA;GACpCjB,UAASkB,YAAW;IAAA,GACfX;IAAIY,WACI,CAAA,GAAIZ,OAAIY,WAAYb,QAAM;GACvC,EAAE;GAAC,aAEI;IACLN,UAASoB,YAAW;KAAA,GACfb;KAAIY,WACIZ,OAAIY,UAAUP,QAAQS,QAAOR,QAAMP,QAAM;IACtD,EAAE;GAAC;EACJ;EACFT,EAAA,KAAAmB;CAAA,OAAAA,KAAAnB,EAAA;CAZD,MAAAyB,oBAA0BN;CAYnB,IAAAO;CAAA,IAAA1B,EAAA,OAAAE,OAAA;EAEAwB,KAAA;GAAAC,gBACWzB;GAAKgB;GAAAO;EAGvB;EAACzB,EAAA,KAAAE;EAAAF,EAAA,KAAA0B;CAAA,OAAAA,KAAA1B,EAAA;CAAA,OAJM0B;AAIN;AAGH,MAAaE,gBAAgBlC,SAASK,gBAAgB;AAzD7B,SAAAK,QAAA;CAAA,OACuC;EAAAO,WACjDb,gBAAgB;EAACwB,WACjB,CAAA;CACb;AAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;;;;;;cAqhBa,oDAAsB,SAAA,0CAAA"}
1
+ {"version":3,"file":"Interactables.d.ts","names":[],"sources":["../../../src/react/client/Interactables.ts"],"mappings":";;;;;;;;cA2hBa,oDAAsB,SAAA,0CAAA"}
@@ -23,6 +23,7 @@ const useInteractablesResource = ({ persistence } = {}) => {
23
23
  const stateRef = useRef(state);
24
24
  const subscribersRef = useRef(/* @__PURE__ */ new Set());
25
25
  const partialSchemaCacheRef = useRef(/* @__PURE__ */ new Map());
26
+ const partialSchemaSourceRef = useRef(/* @__PURE__ */ new Map());
26
27
  const streamBaselinesRef = useRef(/* @__PURE__ */ new Map());
27
28
  const detachedAppStateRef = useRef(/* @__PURE__ */ new Map());
28
29
  const detachedThreadStateRef = useRef(/* @__PURE__ */ new Map());
@@ -203,11 +204,15 @@ const useInteractablesResource = ({ persistence } = {}) => {
203
204
  }
204
205
  };
205
206
  }
206
- if (!partialSchemaCacheRef.current.has(def_2.id)) try {
207
- const jsonSchema = toJSONSchema(def_2.stateSchema);
208
- partialSchemaCacheRef.current.set(def_2.id, toPartialJSONSchema(jsonSchema));
209
- } catch (e_0) {
210
- console.warn(`[Interactables] Failed to create partial schema for "${def_2.name}". The update tool will accept arbitrary fields without validation.`, e_0);
207
+ if (partialSchemaSourceRef.current.get(def_2.id) !== def_2.stateSchema) {
208
+ partialSchemaSourceRef.current.set(def_2.id, def_2.stateSchema);
209
+ partialSchemaCacheRef.current.delete(def_2.id);
210
+ try {
211
+ const jsonSchema = toJSONSchema(def_2.stateSchema);
212
+ partialSchemaCacheRef.current.set(def_2.id, toPartialJSONSchema(jsonSchema));
213
+ } catch (e_0) {
214
+ console.warn(`[Interactables] Failed to create partial schema for "${def_2.name}". The update tool will accept arbitrary fields without validation.`, e_0);
215
+ }
211
216
  }
212
217
  const threadId = scope === "thread" ? getCurrentThreadId() : void 0;
213
218
  const detached = scope === "thread" ? threadId ? detachedThreadStateRef.current.get(threadId)?.get(def_2.id) : void 0 : detachedAppStateRef.current.get(def_2.id);
@@ -252,6 +257,7 @@ const useInteractablesResource = ({ persistence } = {}) => {
252
257
  }
253
258
  } else detachedAppStateRef.current.set(def_2.id, existing_1.state);
254
259
  }
260
+ partialSchemaSourceRef.current.delete(def_2.id);
255
261
  partialSchemaCacheRef.current.delete(def_2.id);
256
262
  const definitions_0 = nullProtoRecord(prev_3.definitions);
257
263
  const persistence_1 = nullProtoRecord(prev_3.persistence);