@athenaintel/react 0.43.0 → 0.50.0

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 (746) hide show
  1. package/README.md +258 -8
  2. package/dist/agent-runtime/src/answer-label.cjs +137 -0
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
  4. package/dist/agent-runtime/src/answer-label.d.ts +104 -0
  5. package/dist/agent-runtime/src/answer-label.js +137 -0
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -0
  7. package/dist/agent-runtime/src/answer-rows.cjs +180 -0
  8. package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
  9. package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
  10. package/dist/agent-runtime/src/answer-rows.js +180 -0
  11. package/dist/agent-runtime/src/answer-rows.js.map +1 -0
  12. package/dist/agent-runtime/src/call-recap.cjs +319 -0
  13. package/dist/agent-runtime/src/call-recap.cjs.map +1 -0
  14. package/dist/agent-runtime/src/call-recap.d.ts +142 -0
  15. package/dist/agent-runtime/src/call-recap.js +319 -0
  16. package/dist/agent-runtime/src/call-recap.js.map +1 -0
  17. package/dist/agent-runtime/src/chat-outbox-store.cjs +1 -0
  18. package/dist/agent-runtime/src/chat-outbox-store.cjs.map +1 -1
  19. package/dist/agent-runtime/src/chat-outbox-store.d.ts +7 -0
  20. package/dist/agent-runtime/src/chat-outbox-store.js +1 -0
  21. package/dist/agent-runtime/src/chat-outbox-store.js.map +1 -1
  22. package/dist/agent-runtime/src/chat-outbox.cjs +46 -5
  23. package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -1
  24. package/dist/agent-runtime/src/chat-outbox.d.ts +29 -0
  25. package/dist/agent-runtime/src/chat-outbox.js +46 -5
  26. package/dist/agent-runtime/src/chat-outbox.js.map +1 -1
  27. package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
  28. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  29. package/dist/agent-runtime/src/conversation-index.cjs +8 -8
  30. package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
  31. package/dist/agent-runtime/src/conversation-index.d.ts +7 -0
  32. package/dist/agent-runtime/src/conversation-index.js.map +1 -1
  33. package/dist/agent-runtime/src/conversation-list.cjs +2 -1
  34. package/dist/agent-runtime/src/conversation-list.cjs.map +1 -1
  35. package/dist/agent-runtime/src/conversation-list.d.ts +19 -3
  36. package/dist/agent-runtime/src/conversation-list.js +2 -1
  37. package/dist/agent-runtime/src/conversation-list.js.map +1 -1
  38. package/dist/agent-runtime/src/decision-checks.cjs +207 -0
  39. package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
  40. package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
  41. package/dist/agent-runtime/src/decision-checks.js +207 -0
  42. package/dist/agent-runtime/src/decision-checks.js.map +1 -0
  43. package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
  44. package/dist/agent-runtime/src/errors.cjs +18 -0
  45. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  46. package/dist/agent-runtime/src/errors.d.ts +7 -0
  47. package/dist/agent-runtime/src/errors.js +18 -0
  48. package/dist/agent-runtime/src/errors.js.map +1 -1
  49. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
  50. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  51. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
  52. package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
  53. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  54. package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
  55. package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
  56. package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
  57. package/dist/agent-runtime/src/handoff-arrival.js +60 -0
  58. package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
  59. package/dist/agent-runtime/src/index.d.ts +16 -9
  60. package/dist/agent-runtime/src/interrupts.cjs +71 -19
  61. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  62. package/dist/agent-runtime/src/interrupts.d.ts +40 -3
  63. package/dist/agent-runtime/src/interrupts.js +56 -4
  64. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  65. package/dist/agent-runtime/src/lane-history.cjs +8 -8
  66. package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
  67. package/dist/agent-runtime/src/messages.cjs +43 -8
  68. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  69. package/dist/agent-runtime/src/messages.d.ts +25 -3
  70. package/dist/agent-runtime/src/messages.js +43 -8
  71. package/dist/agent-runtime/src/messages.js.map +1 -1
  72. package/dist/agent-runtime/src/model-context.cjs +3 -2
  73. package/dist/agent-runtime/src/model-context.cjs.map +1 -1
  74. package/dist/agent-runtime/src/model-context.d.ts +6 -1
  75. package/dist/agent-runtime/src/model-context.js +3 -2
  76. package/dist/agent-runtime/src/model-context.js.map +1 -1
  77. package/dist/agent-runtime/src/offline-status.cjs +36 -0
  78. package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
  79. package/dist/agent-runtime/src/offline-status.d.ts +118 -3
  80. package/dist/agent-runtime/src/offline-status.js +36 -0
  81. package/dist/agent-runtime/src/offline-status.js.map +1 -0
  82. package/dist/agent-runtime/src/queue.cjs +0 -9
  83. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  84. package/dist/agent-runtime/src/queue.js +0 -9
  85. package/dist/agent-runtime/src/queue.js.map +1 -1
  86. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
  87. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  88. package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
  89. package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
  90. package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
  91. package/dist/agent-runtime/src/runtime-catalog.js +42 -0
  92. package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
  93. package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
  94. package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
  95. package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
  96. package/dist/agent-runtime/src/runtime.d.ts +41 -0
  97. package/dist/agent-runtime/src/send-recovery.cjs +37 -3
  98. package/dist/agent-runtime/src/send-recovery.cjs.map +1 -1
  99. package/dist/agent-runtime/src/send-recovery.d.ts +19 -0
  100. package/dist/agent-runtime/src/send-recovery.js +37 -3
  101. package/dist/agent-runtime/src/send-recovery.js.map +1 -1
  102. package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
  103. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  104. package/dist/agent-runtime/src/subagents.cjs +32 -2
  105. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  106. package/dist/agent-runtime/src/subagents.d.ts +9 -0
  107. package/dist/agent-runtime/src/subagents.js +30 -0
  108. package/dist/agent-runtime/src/subagents.js.map +1 -1
  109. package/dist/agent-runtime/src/thread-driver.cjs +67 -0
  110. package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
  111. package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
  112. package/dist/agent-runtime/src/thread-driver.js +67 -0
  113. package/dist/agent-runtime/src/thread-driver.js.map +1 -0
  114. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
  115. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +868 -0
  116. package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
  117. package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
  118. package/dist/agent-runtime/src/thread-status.cjs +3 -3
  119. package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
  120. package/dist/agent-runtime/src/tool-metadata.cjs +210 -25
  121. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  122. package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
  123. package/dist/agent-runtime/src/tool-metadata.js +210 -25
  124. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  125. package/dist/agent-runtime/src/tool-names.cjs +2 -0
  126. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  127. package/dist/agent-runtime/src/tool-names.d.ts +2 -0
  128. package/dist/agent-runtime/src/tool-names.js +2 -0
  129. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  130. package/dist/agent-runtime/src/types.d.ts +10 -2
  131. package/dist/agent-runtime/src/use-conversation-list.cjs +14 -13
  132. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  133. package/dist/agent-runtime/src/use-conversation-list.d.ts +6 -0
  134. package/dist/agent-runtime/src/use-conversation-list.js +3 -2
  135. package/dist/agent-runtime/src/use-conversation-list.js.map +1 -1
  136. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +45 -20
  137. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  138. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +10 -3
  139. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +27 -2
  140. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  141. package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
  142. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  143. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
  144. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  145. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +40 -22
  146. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  147. package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +17 -0
  148. package/dist/agent-runtime/src/use-deep-agent-runtime.js +24 -6
  149. package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
  150. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
  151. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  152. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +588 -130
  153. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  154. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +162 -10
  155. package/dist/agent-runtime/src/use-deep-agent-voice.js +529 -71
  156. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  157. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
  158. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  159. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
  160. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
  161. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +34 -26
  162. package/dist/agent-runtime/src/voice-earcon.cjs +139 -0
  163. package/dist/agent-runtime/src/voice-earcon.cjs.map +1 -0
  164. package/dist/agent-runtime/src/voice-earcon.d.ts +38 -0
  165. package/dist/agent-runtime/src/voice-earcon.js +139 -0
  166. package/dist/agent-runtime/src/voice-earcon.js.map +1 -0
  167. package/dist/agent-runtime/src/voice-media.cjs +117 -0
  168. package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
  169. package/dist/agent-runtime/src/voice-media.d.ts +63 -0
  170. package/dist/agent-runtime/src/voice-media.js +117 -0
  171. package/dist/agent-runtime/src/voice-media.js.map +1 -0
  172. package/dist/agent-runtime/src/voice-presentation.cjs +2 -0
  173. package/dist/agent-runtime/src/voice-presentation.cjs.map +1 -1
  174. package/dist/agent-runtime/src/voice-presentation.js +2 -0
  175. package/dist/agent-runtime/src/voice-presentation.js.map +1 -1
  176. package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
  177. package/dist/assets/AssetPanel.cjs +11 -11
  178. package/dist/assets/AssetPanel.cjs.map +1 -1
  179. package/dist/assets/AthenaAssetEmbed.cjs +11 -9
  180. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  181. package/dist/assets/AthenaAssetEmbed.d.ts +18 -5
  182. package/dist/assets/AthenaAssetEmbed.js +4 -2
  183. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  184. package/dist/assets/AthenaLayout.cjs +16 -16
  185. package/dist/assets/AthenaLayout.cjs.map +1 -1
  186. package/dist/assets/use-asset-content.cjs +4 -4
  187. package/dist/assets/use-asset-content.cjs.map +1 -1
  188. package/dist/assets/use-asset-embed.cjs +14 -7
  189. package/dist/assets/use-asset-embed.cjs.map +1 -1
  190. package/dist/assets/use-asset-embed.d.ts +23 -6
  191. package/dist/assets/use-asset-embed.js +10 -3
  192. package/dist/assets/use-asset-embed.js.map +1 -1
  193. package/dist/auth/AthenaAuthContext.cjs +3 -3
  194. package/dist/auth/AthenaAuthContext.cjs.map +1 -1
  195. package/dist/auth/AthenaAuthProvider.cjs +8 -8
  196. package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
  197. package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
  198. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  199. package/dist/auth/AthenaSSOProvider.cjs +14 -14
  200. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  201. package/dist/auth/credential-source.cjs +26 -13
  202. package/dist/auth/credential-source.cjs.map +1 -1
  203. package/dist/auth/credential-source.d.ts +8 -0
  204. package/dist/auth/credential-source.js +26 -13
  205. package/dist/auth/credential-source.js.map +1 -1
  206. package/dist/catalog/agent-model-options.cjs +25 -17
  207. package/dist/catalog/agent-model-options.cjs.map +1 -1
  208. package/dist/catalog/agent-model-options.d.ts +38 -5
  209. package/dist/catalog/agent-model-options.js +25 -17
  210. package/dist/catalog/agent-model-options.js.map +1 -1
  211. package/dist/catalog/channel-refusal.cjs +36 -0
  212. package/dist/catalog/channel-refusal.cjs.map +1 -0
  213. package/dist/catalog/channel-refusal.d.ts +29 -0
  214. package/dist/catalog/channel-refusal.js +36 -0
  215. package/dist/catalog/channel-refusal.js.map +1 -0
  216. package/dist/catalog/chat-pickers.cjs +60 -24
  217. package/dist/catalog/chat-pickers.cjs.map +1 -1
  218. package/dist/catalog/chat-pickers.d.ts +12 -2
  219. package/dist/catalog/chat-pickers.js +56 -20
  220. package/dist/catalog/chat-pickers.js.map +1 -1
  221. package/dist/catalog/runtime-catalog.cjs +89 -23
  222. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  223. package/dist/catalog/runtime-catalog.d.ts +8 -2
  224. package/dist/catalog/runtime-catalog.js +83 -17
  225. package/dist/catalog/runtime-catalog.js.map +1 -1
  226. package/dist/catalog/use-athena-chat-mode.cjs +12 -12
  227. package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
  228. package/dist/chat/AthenaChat.cjs +155 -67
  229. package/dist/chat/AthenaChat.cjs.map +1 -1
  230. package/dist/chat/AthenaChat.d.ts +42 -2
  231. package/dist/chat/AthenaChat.js +106 -18
  232. package/dist/chat/AthenaChat.js.map +1 -1
  233. package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
  234. package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
  235. package/dist/chat/DrivingOnChip.cjs +23 -0
  236. package/dist/chat/DrivingOnChip.cjs.map +1 -0
  237. package/dist/chat/DrivingOnChip.d.ts +17 -0
  238. package/dist/chat/DrivingOnChip.js +23 -0
  239. package/dist/chat/DrivingOnChip.js.map +1 -0
  240. package/dist/chat/StatewireApprovalCard.cjs +166 -37
  241. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  242. package/dist/chat/StatewireApprovalCard.d.ts +91 -2
  243. package/dist/chat/StatewireApprovalCard.js +156 -27
  244. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  245. package/dist/chat/StatewireClientToolBridge.cjs +2 -2
  246. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  247. package/dist/chat/StatewireQueuedMessages.cjs +81 -69
  248. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  249. package/dist/chat/StatewireQueuedMessages.d.ts +25 -13
  250. package/dist/chat/StatewireQueuedMessages.js +73 -61
  251. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  252. package/dist/chat/WaitingOnYouBanner.cjs +9 -5
  253. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
  254. package/dist/chat/WaitingOnYouBanner.js +7 -3
  255. package/dist/chat/WaitingOnYouBanner.js.map +1 -1
  256. package/dist/chat/athena-chat-welcome.cjs +2 -2
  257. package/dist/chat/athena-chat-welcome.cjs.map +1 -1
  258. package/dist/chat/athena-citation-links.cjs +5 -5
  259. package/dist/chat/athena-citation-links.cjs.map +1 -1
  260. package/dist/chat/athena-composer-controls.cjs +26 -16
  261. package/dist/chat/athena-composer-controls.cjs.map +1 -1
  262. package/dist/chat/athena-composer-controls.d.ts +6 -0
  263. package/dist/chat/athena-composer-controls.js +26 -16
  264. package/dist/chat/athena-composer-controls.js.map +1 -1
  265. package/dist/chat/athena-turn-end-status.cjs +42 -0
  266. package/dist/chat/athena-turn-end-status.cjs.map +1 -0
  267. package/dist/chat/athena-turn-end-status.d.ts +24 -0
  268. package/dist/chat/athena-turn-end-status.js +42 -0
  269. package/dist/chat/athena-turn-end-status.js.map +1 -0
  270. package/dist/chat/browser-decision-check.cjs +131 -0
  271. package/dist/chat/browser-decision-check.cjs.map +1 -0
  272. package/dist/chat/browser-decision-check.d.ts +61 -0
  273. package/dist/chat/browser-decision-check.js +131 -0
  274. package/dist/chat/browser-decision-check.js.map +1 -0
  275. package/dist/chat/chat-outbox-rows.cjs +3 -3
  276. package/dist/chat/chat-outbox-rows.cjs.map +1 -1
  277. package/dist/chat/chat-voice-controls.cjs +96 -29
  278. package/dist/chat/chat-voice-controls.cjs.map +1 -1
  279. package/dist/chat/chat-voice-controls.d.ts +42 -3
  280. package/dist/chat/chat-voice-controls.js +92 -25
  281. package/dist/chat/chat-voice-controls.js.map +1 -1
  282. package/dist/chat/composer-keyboard-hint.cjs +5 -5
  283. package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
  284. package/dist/chat/device-operation.cjs +29 -0
  285. package/dist/chat/device-operation.cjs.map +1 -0
  286. package/dist/chat/device-operation.d.ts +34 -0
  287. package/dist/chat/device-operation.js +29 -0
  288. package/dist/chat/device-operation.js.map +1 -0
  289. package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
  290. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  291. package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
  292. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
  293. package/dist/chat/super-grouping/SuperGroupingCard.cjs +52 -36
  294. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  295. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
  296. package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
  297. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  298. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
  299. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  300. package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
  301. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  302. package/dist/chat/super-grouping/ToolTimeline.cjs +73 -40
  303. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  304. package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
  305. package/dist/chat/super-grouping/ToolTimeline.js +69 -36
  306. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  307. package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
  308. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  309. package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
  310. package/dist/chat/super-grouping/activity-timeline.js +47 -12
  311. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  312. package/dist/chat/super-grouping/grouping-function.cjs +4 -0
  313. package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
  314. package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
  315. package/dist/chat/super-grouping/grouping-function.js +5 -1
  316. package/dist/chat/super-grouping/grouping-function.js.map +1 -1
  317. package/dist/chat/super-grouping/index.cjs +6 -0
  318. package/dist/chat/super-grouping/index.cjs.map +1 -1
  319. package/dist/chat/super-grouping/index.d.ts +5 -2
  320. package/dist/chat/super-grouping/index.js +7 -1
  321. package/dist/chat/super-grouping/index.js.map +1 -1
  322. package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
  323. package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
  324. package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
  325. package/dist/chat/super-grouping/tool-part-placement.js +17 -0
  326. package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
  327. package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
  328. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
  329. package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
  330. package/dist/chat/thread-scroll-to-bottom.js +2 -2
  331. package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
  332. package/dist/chat/tooltip-icon-button.cjs +2 -2
  333. package/dist/chat/tooltip-icon-button.cjs.map +1 -1
  334. package/dist/chat/use-athena-voice-live.cjs +11 -0
  335. package/dist/chat/use-athena-voice-live.cjs.map +1 -0
  336. package/dist/chat/use-athena-voice-live.d.ts +11 -0
  337. package/dist/chat/use-athena-voice-live.js +11 -0
  338. package/dist/chat/use-athena-voice-live.js.map +1 -0
  339. package/dist/chat/use-statewire-approval-request.cjs +56 -24
  340. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  341. package/dist/chat/use-statewire-approval-request.d.ts +33 -4
  342. package/dist/chat/use-statewire-approval-request.js +41 -9
  343. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  344. package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
  345. package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
  346. package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
  347. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  348. package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
  349. package/dist/chat-ui/composer/tiptap-composer.js +85 -54
  350. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  351. package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
  352. package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
  353. package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
  354. package/dist/chat-ui/header/conversation-history-panel.js +38 -12
  355. package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
  356. package/dist/chat-ui/index.cjs +21 -0
  357. package/dist/chat-ui/index.cjs.map +1 -1
  358. package/dist/chat-ui/index.d.ts +8 -1
  359. package/dist/chat-ui/index.js +21 -0
  360. package/dist/chat-ui/index.js.map +1 -1
  361. package/dist/chat-ui/mentions/mention-chip.cjs +4 -4
  362. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  363. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
  364. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  365. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
  366. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  367. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
  368. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
  369. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
  370. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  371. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
  372. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
  373. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  374. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
  375. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
  376. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
  377. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
  378. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
  379. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  380. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
  381. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
  382. package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
  383. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
  384. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
  385. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
  386. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  387. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
  388. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
  389. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  390. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
  391. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  392. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
  393. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
  394. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  395. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
  396. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
  397. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
  398. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
  399. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
  400. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
  401. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  402. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
  403. package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
  404. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  405. package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
  406. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
  407. package/dist/chat-ui/mentions/use-mention-asset.cjs +3 -3
  408. package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
  409. package/dist/chat-ui/messages/answer-label.cjs +42 -0
  410. package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
  411. package/dist/chat-ui/messages/answer-label.d.ts +33 -0
  412. package/dist/chat-ui/messages/answer-label.js +42 -0
  413. package/dist/chat-ui/messages/answer-label.js.map +1 -0
  414. package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
  415. package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
  416. package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
  417. package/dist/chat-ui/messages/arrival-animation.js +13 -0
  418. package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
  419. package/dist/chat-ui/messages/continue-pill.cjs +5 -5
  420. package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
  421. package/dist/chat-ui/messages/from-the-call-card.cjs +124 -0
  422. package/dist/chat-ui/messages/from-the-call-card.cjs.map +1 -0
  423. package/dist/chat-ui/messages/from-the-call-card.d.ts +17 -0
  424. package/dist/chat-ui/messages/from-the-call-card.js +124 -0
  425. package/dist/chat-ui/messages/from-the-call-card.js.map +1 -0
  426. package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
  427. package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
  428. package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
  429. package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
  430. package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
  431. package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
  432. package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
  433. package/dist/chat-ui/messages/message-components.cjs +8 -4
  434. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  435. package/dist/chat-ui/messages/message-components.js +5 -1
  436. package/dist/chat-ui/messages/message-components.js.map +1 -1
  437. package/dist/chat-ui/messages/message-images.cjs +66 -0
  438. package/dist/chat-ui/messages/message-images.cjs.map +1 -0
  439. package/dist/chat-ui/messages/message-images.d.ts +16 -0
  440. package/dist/chat-ui/messages/message-images.js +66 -0
  441. package/dist/chat-ui/messages/message-images.js.map +1 -0
  442. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
  443. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  444. package/dist/chat-ui/messages/wake-marker.cjs +3 -3
  445. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
  446. package/dist/chat-ui/rich-text/chat-link.cjs +3 -2
  447. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
  448. package/dist/chat-ui/rich-text/chat-link.d.ts +4 -0
  449. package/dist/chat-ui/rich-text/chat-link.js +4 -3
  450. package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
  451. package/dist/chat-ui/rich-text/chat-message-body.cjs +9 -8
  452. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  453. package/dist/chat-ui/rich-text/chat-message-body.d.ts +12 -0
  454. package/dist/chat-ui/rich-text/chat-message-body.js +2 -1
  455. package/dist/chat-ui/rich-text/chat-message-body.js.map +1 -1
  456. package/dist/chat-ui/rich-text/chat-node-views.cjs +6 -6
  457. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  458. package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
  459. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
  460. package/dist/chat-ui/statewire.cjs +3 -0
  461. package/dist/chat-ui/statewire.cjs.map +1 -1
  462. package/dist/chat-ui/statewire.d.ts +2 -1
  463. package/dist/chat-ui/statewire.js +3 -0
  464. package/dist/chat-ui/statewire.js.map +1 -1
  465. package/dist/chat-ui/thread/chat-thread-shell.cjs +45 -14
  466. package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
  467. package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
  468. package/dist/chat-ui/thread/chat-thread-shell.js +37 -6
  469. package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
  470. package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
  471. package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
  472. package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
  473. package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
  474. package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
  475. package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
  476. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  477. package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
  478. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  479. package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
  480. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
  481. package/dist/collab/client.cjs +52 -3
  482. package/dist/collab/client.cjs.map +1 -1
  483. package/dist/collab/client.d.ts +27 -0
  484. package/dist/collab/client.js +52 -3
  485. package/dist/collab/client.js.map +1 -1
  486. package/dist/collab/document-status.cjs +150 -0
  487. package/dist/collab/document-status.cjs.map +1 -0
  488. package/dist/collab/document-status.d.ts +68 -0
  489. package/dist/collab/document-status.js +150 -0
  490. package/dist/collab/document-status.js.map +1 -0
  491. package/dist/collab/index.cjs +7 -0
  492. package/dist/collab/index.cjs.map +1 -1
  493. package/dist/collab/index.d.ts +6 -1
  494. package/dist/collab/index.js +7 -0
  495. package/dist/collab/index.js.map +1 -1
  496. package/dist/collab/presence-react.cjs +11 -11
  497. package/dist/collab/presence-react.cjs.map +1 -1
  498. package/dist/collab/react.cjs +6 -6
  499. package/dist/collab/react.cjs.map +1 -1
  500. package/dist/composer/AttachmentContext.cjs +24 -11
  501. package/dist/composer/AttachmentContext.cjs.map +1 -1
  502. package/dist/composer/AttachmentContext.js +18 -5
  503. package/dist/composer/AttachmentContext.js.map +1 -1
  504. package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
  505. package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
  506. package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
  507. package/dist/composer/ComposerAttachmentPreview.js +79 -24
  508. package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
  509. package/dist/composer/ComposerDropZone.cjs +7 -7
  510. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  511. package/dist/composer/FileUploadButton.cjs +37 -22
  512. package/dist/composer/FileUploadButton.cjs.map +1 -1
  513. package/dist/composer/FileUploadButton.d.ts +6 -0
  514. package/dist/composer/FileUploadButton.js +34 -19
  515. package/dist/composer/FileUploadButton.js.map +1 -1
  516. package/dist/composer/QuoteContext.cjs +8 -8
  517. package/dist/composer/QuoteContext.cjs.map +1 -1
  518. package/dist/composer/composer-handoff.cjs +4 -4
  519. package/dist/composer/composer-handoff.cjs.map +1 -1
  520. package/dist/composer/index.d.ts +1 -1
  521. package/dist/composer/useAppendToComposer.cjs +4 -4
  522. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  523. package/dist/composer/useAttachFiles.cjs +23 -6
  524. package/dist/composer/useAttachFiles.cjs.map +1 -1
  525. package/dist/composer/useAttachFiles.d.ts +15 -7
  526. package/dist/composer/useAttachFiles.js +22 -5
  527. package/dist/composer/useAttachFiles.js.map +1 -1
  528. package/dist/composer/useComposerAttachment.cjs +4 -4
  529. package/dist/composer/useComposerAttachment.cjs.map +1 -1
  530. package/dist/composer/useFileUpload.cjs +21 -16
  531. package/dist/composer/useFileUpload.cjs.map +1 -1
  532. package/dist/composer/useFileUpload.d.ts +12 -0
  533. package/dist/composer/useFileUpload.js +12 -7
  534. package/dist/composer/useFileUpload.js.map +1 -1
  535. package/dist/composer/useReadComposerDraft.cjs +27 -8
  536. package/dist/composer/useReadComposerDraft.cjs.map +1 -1
  537. package/dist/composer/useReadComposerDraft.d.ts +23 -1
  538. package/dist/composer/useReadComposerDraft.js +27 -8
  539. package/dist/composer/useReadComposerDraft.js.map +1 -1
  540. package/dist/composer/useSendMessage.cjs +4 -4
  541. package/dist/composer/useSendMessage.cjs.map +1 -1
  542. package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
  543. package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
  544. package/dist/dictation/audio-level-history.cjs +3 -3
  545. package/dist/dictation/audio-level-history.cjs.map +1 -1
  546. package/dist/dictation/dictation-controls.cjs +24 -20
  547. package/dist/dictation/dictation-controls.cjs.map +1 -1
  548. package/dist/dictation/dictation-controls.d.ts +6 -1
  549. package/dist/dictation/dictation-controls.js +24 -20
  550. package/dist/dictation/dictation-controls.js.map +1 -1
  551. package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
  552. package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
  553. package/dist/dictation/use-dictation.cjs +22 -22
  554. package/dist/dictation/use-dictation.cjs.map +1 -1
  555. package/dist/index.cjs +29 -2
  556. package/dist/index.cjs.map +1 -1
  557. package/dist/index.d.ts +18 -4
  558. package/dist/index.js +30 -3
  559. package/dist/index.js.map +1 -1
  560. package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
  561. package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
  562. package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
  563. package/dist/keryx-http/src/receive-only-socket.js +40 -0
  564. package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
  565. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs +190 -0
  566. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs.map +1 -0
  567. package/dist/keryx-http/src/unconfirmed-update-attributions.d.ts +132 -0
  568. package/dist/keryx-http/src/unconfirmed-update-attributions.js +190 -0
  569. package/dist/keryx-http/src/unconfirmed-update-attributions.js.map +1 -0
  570. package/dist/keryx-http/src/update-attributions.cjs +141 -0
  571. package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
  572. package/dist/keryx-http/src/update-attributions.d.ts +107 -0
  573. package/dist/keryx-http/src/update-attributions.js +141 -0
  574. package/dist/keryx-http/src/update-attributions.js.map +1 -0
  575. package/dist/lib/owner-document.cjs +6 -6
  576. package/dist/lib/owner-document.cjs.map +1 -1
  577. package/dist/lib/use-athena-rest-query.cjs +4 -4
  578. package/dist/lib/use-athena-rest-query.cjs.map +1 -1
  579. package/dist/lib/use-document-active.cjs +4 -4
  580. package/dist/lib/use-document-active.cjs.map +1 -1
  581. package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
  582. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
  583. package/dist/offline/offline-history.cjs +7 -7
  584. package/dist/offline/offline-history.cjs.map +1 -1
  585. package/dist/provider/AthenaContext.cjs +3 -3
  586. package/dist/provider/AthenaContext.cjs.map +1 -1
  587. package/dist/provider/AthenaProvider.cjs +120 -79
  588. package/dist/provider/AthenaProvider.cjs.map +1 -1
  589. package/dist/provider/AthenaProvider.d.ts +11 -1
  590. package/dist/provider/AthenaProvider.js +44 -3
  591. package/dist/provider/AthenaProvider.js.map +1 -1
  592. package/dist/provider/PostHogProvider.cjs +2 -2
  593. package/dist/provider/PostHogProvider.cjs.map +1 -1
  594. package/dist/provider/agent-selection-context.cjs +2 -2
  595. package/dist/provider/agent-selection-context.cjs.map +1 -1
  596. package/dist/provider/chat-mode-context.cjs +2 -2
  597. package/dist/provider/chat-mode-context.cjs.map +1 -1
  598. package/dist/provider/session-persistence-context.cjs +10 -0
  599. package/dist/provider/session-persistence-context.cjs.map +1 -0
  600. package/dist/provider/session-persistence-context.d.ts +15 -0
  601. package/dist/provider/session-persistence-context.js +10 -0
  602. package/dist/provider/session-persistence-context.js.map +1 -0
  603. package/dist/provider/statewire-history-context.cjs +4 -4
  604. package/dist/provider/statewire-history-context.cjs.map +1 -1
  605. package/dist/provider/statewire-lifecycle-context.cjs +3 -3
  606. package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
  607. package/dist/provider/statewire-window-context.cjs +3 -3
  608. package/dist/provider/statewire-window-context.cjs.map +1 -1
  609. package/dist/provider/theme-style-context.cjs +3 -3
  610. package/dist/provider/theme-style-context.cjs.map +1 -1
  611. package/dist/react/package.json.cjs +1 -1
  612. package/dist/react/package.json.js +1 -1
  613. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
  614. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  615. package/dist/runtime/auth-refusal-restart.cjs +7 -7
  616. package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
  617. package/dist/runtime/auth.cjs +13 -13
  618. package/dist/runtime/auth.cjs.map +1 -1
  619. package/dist/runtime/statewire-lifecycle.cjs +1 -0
  620. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  621. package/dist/runtime/statewire-lifecycle.d.ts +3 -1
  622. package/dist/runtime/statewire-lifecycle.js +2 -1
  623. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  624. package/dist/runtime/statewire-server-lane-context.cjs +2 -2
  625. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
  626. package/dist/runtime/statewire-session-lane.cjs +4 -4
  627. package/dist/runtime/statewire-session-lane.cjs.map +1 -1
  628. package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
  629. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  630. package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
  631. package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
  632. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  633. package/dist/styles.css +1 -1
  634. package/dist/threads/Inbox.cjs +8 -8
  635. package/dist/threads/Inbox.cjs.map +1 -1
  636. package/dist/threads/SessionList.cjs +9 -9
  637. package/dist/threads/SessionList.cjs.map +1 -1
  638. package/dist/threads/SessionsPage.cjs +11 -11
  639. package/dist/threads/SessionsPage.cjs.map +1 -1
  640. package/dist/threads/api.cjs.map +1 -1
  641. package/dist/threads/api.d.ts +15 -0
  642. package/dist/threads/api.js.map +1 -1
  643. package/dist/threads/conversation-list-fetcher.cjs +13 -5
  644. package/dist/threads/conversation-list-fetcher.cjs.map +1 -1
  645. package/dist/threads/conversation-list-fetcher.d.ts +4 -1
  646. package/dist/threads/conversation-list-fetcher.js +13 -5
  647. package/dist/threads/conversation-list-fetcher.js.map +1 -1
  648. package/dist/threads/index-triggered-refresh.cjs +10 -10
  649. package/dist/threads/index-triggered-refresh.cjs.map +1 -1
  650. package/dist/threads/mark-viewed-thread-read.cjs +12 -12
  651. package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
  652. package/dist/threads/offline-session-list.cjs +3 -3
  653. package/dist/threads/offline-session-list.cjs.map +1 -1
  654. package/dist/threads/session-list-tab-share.cjs +5 -5
  655. package/dist/threads/session-list-tab-share.cjs.map +1 -1
  656. package/dist/threads/statewire-thread-list.cjs +79 -57
  657. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  658. package/dist/threads/statewire-thread-list.d.ts +20 -8
  659. package/dist/threads/statewire-thread-list.js +28 -6
  660. package/dist/threads/statewire-thread-list.js.map +1 -1
  661. package/dist/threads/thread-id-context.cjs +5 -5
  662. package/dist/threads/thread-id-context.cjs.map +1 -1
  663. package/dist/threads/use-athena-session-attention.cjs +2 -2
  664. package/dist/threads/use-athena-session-attention.cjs.map +1 -1
  665. package/dist/threads/use-athena-sessions.cjs +37 -15
  666. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  667. package/dist/threads/use-athena-sessions.d.ts +10 -5
  668. package/dist/threads/use-athena-sessions.js +28 -6
  669. package/dist/threads/use-athena-sessions.js.map +1 -1
  670. package/dist/threads/use-athena-thread-model.cjs +3 -3
  671. package/dist/threads/use-athena-thread-model.cjs.map +1 -1
  672. package/dist/threads/use-rest-conversation-history.cjs +3 -3
  673. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  674. package/dist/threads/use-rest-conversation-history.d.ts +1 -0
  675. package/dist/threads/use-statewire-conversation-history.cjs +8 -8
  676. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  677. package/dist/threads/use-thread-archive.cjs +9 -9
  678. package/dist/threads/use-thread-archive.cjs.map +1 -1
  679. package/dist/threads/use-thread-favorite.cjs +2 -2
  680. package/dist/threads/use-thread-favorite.cjs.map +1 -1
  681. package/dist/threads/use-thread-field-override.cjs +20 -20
  682. package/dist/threads/use-thread-field-override.cjs.map +1 -1
  683. package/dist/threads/use-thread-read-state.cjs +4 -4
  684. package/dist/threads/use-thread-read-state.cjs.map +1 -1
  685. package/dist/threads/use-thread-rename.cjs +2 -2
  686. package/dist/threads/use-thread-rename.cjs.map +1 -1
  687. package/dist/threads/useAthenaThreadManager.cjs +2 -2
  688. package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
  689. package/dist/tools/NestedPtcMessages.cjs +6 -6
  690. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  691. package/dist/tools/append-document-tool-ui.cjs +7 -7
  692. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  693. package/dist/tools/file-tool-uis.cjs +2 -2
  694. package/dist/tools/file-tool-uis.cjs.map +1 -1
  695. package/dist/tools/misc-tool-uis.cjs +2 -2
  696. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  697. package/dist/tools/primitives.cjs +6 -6
  698. package/dist/tools/primitives.cjs.map +1 -1
  699. package/dist/tools/read-asset-tool-ui.cjs +6 -6
  700. package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
  701. package/dist/tools/subagent-task-tool-ui.cjs +21 -21
  702. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  703. package/dist/tools/test-recording-tool-uis.cjs +16 -16
  704. package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
  705. package/dist/tools/todo-plan-store.cjs +4 -4
  706. package/dist/tools/todo-plan-store.cjs.map +1 -1
  707. package/dist/tools/tool-appearance.cjs +3 -3
  708. package/dist/tools/tool-appearance.cjs.map +1 -1
  709. package/dist/tools/tool-fallback.cjs +14 -14
  710. package/dist/tools/tool-fallback.cjs.map +1 -1
  711. package/dist/tools/tool-uis.cjs +74 -74
  712. package/dist/tools/tool-uis.cjs.map +1 -1
  713. package/dist/tools/use-elapsed-seconds.cjs +3 -3
  714. package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
  715. package/dist/tools/write-todos-tool-ui.cjs +9 -9
  716. package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
  717. package/dist/ui/image-viewer.cjs +382 -0
  718. package/dist/ui/image-viewer.cjs.map +1 -0
  719. package/dist/ui/image-viewer.d.ts +50 -0
  720. package/dist/ui/image-viewer.js +382 -0
  721. package/dist/ui/image-viewer.js.map +1 -0
  722. package/dist/voice/chat.cjs +6 -0
  723. package/dist/voice/chat.cjs.map +1 -1
  724. package/dist/voice/chat.d.ts +1 -1
  725. package/dist/voice/chat.js +8 -2
  726. package/dist/voice/livekit-join.cjs +52 -101
  727. package/dist/voice/livekit-join.cjs.map +1 -1
  728. package/dist/voice/livekit-join.d.ts +1 -6
  729. package/dist/voice/livekit-join.js +52 -101
  730. package/dist/voice/livekit-join.js.map +1 -1
  731. package/dist/voice/livekit.cjs.map +1 -1
  732. package/dist/voice/livekit.d.ts +11 -1
  733. package/dist/voice/livekit.js.map +1 -1
  734. package/dist/voice/use-athena-voice-session.cjs +34 -34
  735. package/dist/voice/use-athena-voice-session.cjs.map +1 -1
  736. package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
  737. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
  738. package/dist/workbench/SessionWorkbench.cjs +22 -22
  739. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  740. package/dist/workbench/session-workbench-context.cjs +3 -3
  741. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  742. package/dist/workbench/session-workbench-panes.cjs +8 -8
  743. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  744. package/dist/workbench/workbench-layout-context.cjs +3 -3
  745. package/dist/workbench/workbench-layout-context.cjs.map +1 -1
  746. package/package.json +2 -1
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const react$1 = require("@assistant-ui/react");
5
- const react = require("react");
4
+ const react = require("@assistant-ui/react");
5
+ const require$$0 = require("react");
6
6
  const AthenaAuthContext = require("../auth/AthenaAuthContext.cjs");
7
7
  const lib_ownerDocument = require("../lib/owner-document.cjs");
8
8
  const useDocumentActive = require("../lib/use-document-active.cjs");
@@ -14,8 +14,8 @@ function lastMessageKey(messages) {
14
14
  return last ? `${last.id}#${last.content.length}` : null;
15
15
  }
16
16
  function useOnScreen(element) {
17
- const [onScreen, setOnScreen] = react.useState(true);
18
- react.useEffect(() => {
17
+ const [onScreen, setOnScreen] = require$$0.useState(true);
18
+ require$$0.useEffect(() => {
19
19
  var _a;
20
20
  const Observer = (_a = element == null ? void 0 : element.ownerDocument.defaultView) == null ? void 0 : _a.IntersectionObserver;
21
21
  if (!element || !Observer) return;
@@ -33,18 +33,18 @@ function MarkViewedThreadRead({
33
33
  }) {
34
34
  var _a, _b, _c;
35
35
  const list = statewireThreadList.useAthenaStatewireThreadList();
36
- const threadId = react.useContext(threadIdContext.AthenaStatewireThreadIdContext);
37
- const principal = ((_b = (_a = react.useContext(AthenaAuthContext.AthenaAuthContext)) == null ? void 0 : _a.user) == null ? void 0 : _b.userId) ?? "";
38
- const messageKey = react$1.useAuiState((s) => {
36
+ const threadId = require$$0.useContext(threadIdContext.AthenaStatewireThreadIdContext);
37
+ const principal = ((_b = (_a = require$$0.useContext(AthenaAuthContext.AthenaAuthContext)) == null ? void 0 : _a.user) == null ? void 0 : _b.userId) ?? "";
38
+ const messageKey = react.useAuiState((s) => {
39
39
  var _a2;
40
40
  return lastMessageKey((_a2 = s.optional.thread) == null ? void 0 : _a2.messages);
41
41
  });
42
- const isRunning = react$1.useAuiState((s) => {
42
+ const isRunning = react.useAuiState((s) => {
43
43
  var _a2;
44
44
  return ((_a2 = s.optional.thread) == null ? void 0 : _a2.isRunning) ?? false;
45
45
  });
46
46
  const windowActive = useDocumentActive.useDocumentActive(lib_ownerDocument.useOwnerDocument());
47
- const [sentinel, setSentinel] = react.useState(null);
47
+ const [sentinel, setSentinel] = require$$0.useState(null);
48
48
  const onScreen = useOnScreen(sentinel);
49
49
  const inView = windowActive && onScreen;
50
50
  const row = threadId !== null && ((_c = list == null ? void 0 : list.activeThread) == null ? void 0 : _c.id) === threadId ? list.activeThread : null;
@@ -52,14 +52,14 @@ function MarkViewedThreadRead({
52
52
  const writeInFlight = threadId !== null && ((list == null ? void 0 : list.readStatePendingThreadIds.has(threadId)) ?? false);
53
53
  const setReadState = list == null ? void 0 : list.setReadState;
54
54
  const visitKey = `${principal}\0${threadId ?? ""}`;
55
- const rowRef = react.useRef(row);
55
+ const rowRef = require$$0.useRef(row);
56
56
  rowRef.current = row;
57
- const visitRef = react.useRef({
57
+ const visitRef = require$$0.useRef({
58
58
  key: visitKey,
59
59
  settledMessageKey: null,
60
60
  inFlightMessageKey: null
61
61
  });
62
- react.useEffect(() => {
62
+ require$$0.useEffect(() => {
63
63
  if (visitRef.current.key !== visitKey) {
64
64
  visitRef.current = { key: visitKey, settledMessageKey: null, inFlightMessageKey: null };
65
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mark-viewed-thread-read.cjs","sources":["../../src/threads/mark-viewed-thread-read.tsx"],"sourcesContent":["/**\n * `MarkViewedThreadRead` — the session `AthenaChat` shows is marked read for\n * the viewer, as Olympus marks every session it shows\n * (`useMarkCurrentThreadAsRead`) and Devin clears a session's unread dot when\n * it is opened. Without it, a session opened from the session list or a link\n * stayed unread for good: only the inbox's own open and its Mark read wrote\n * the receipt, so unread dots and the inbox's Unread count only grew.\n *\n * The open session is marked read once all of these hold:\n *\n * - the transcript is in front of the person: its window is visible and\n * focused (the window it renders into, a pop-out's included), and the chat\n * itself is on screen (not hidden, as `AthenaLayout` hides it behind a\n * maximized workbench, nor scrolled out of the page);\n * - its history is on screen (the thread has a last message);\n * - no run is going (a running session is marked when its run ends, never per\n * streamed chunk);\n * - its row is unread (a read row is never written).\n *\n * They must hold for {@link MARK_VIEWED_THREAD_READ_DELAY_MS}; the write is\n * the thread list's `setReadState` (`POST /api/conversations/threads/read-state`),\n * with the row's `updatedAt`, so the next message ends the override and shows\n * the row unread again. One write per (viewer, session, last message as it\n * stands — its id and how many parts it has, since the agent's further\n * messages in a turn join that turn's message): what arrives while the person\n * watches is marked too, nothing polls, and a failed write is not repeated\n * for the same message. A read-state write in flight for the open session\n * (this one's, or the person's own Mark read / Mark unread) settles the\n * message that was on screen when it began, so the person's choice stands\n * until something new arrives or they open the session again.\n *\n * Renders an invisible, inert sentinel over the chat panel (it must sit in\n * the panel, which is `relative`); nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport { useAuiState } from '@assistant-ui/react';\nimport { type ReactNode, useContext, useEffect, useRef, useState } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport { useOwnerDocument } from '../lib/owner-document';\nimport { useDocumentActive } from '../lib/use-document-active';\nimport { useAthenaStatewireThreadList } from './statewire-thread-list';\nimport { AthenaStatewireThreadIdContext } from './thread-id-context';\n\n/** How long the open session must stay unread and in view before it is marked read. */\nexport const MARK_VIEWED_THREAD_READ_DELAY_MS = 1_000;\n\ninterface ViewedThreadVisit {\n /** Who views which session: the provider's read state is scoped to the viewer. */\n key: string;\n /** The last message (as {@link lastMessageKey} reads it) this visit has settled. */\n settledMessageKey: string | null;\n /** The message on screen when the read-state write now in flight began. */\n inFlightMessageKey: string | null;\n}\n\n/**\n * The thread's last message as it stands: its id and part count. A turn's\n * further assistant messages join that turn's message, so its id alone does\n * not move when the agent writes more; the part count does — once per part,\n * never per streamed token. `null` until the history is on screen.\n */\nfunction lastMessageKey(\n messages: readonly { readonly id: string; readonly content: readonly unknown[] }[] | undefined,\n): string | null {\n const last = messages?.at(-1);\n return last ? `${last.id}#${last.content.length}` : null;\n}\n\n/**\n * Whether `element` is on screen: laid out (no `display: none` on it or an\n * ancestor) and inside the viewport, read by an IntersectionObserver of the\n * element's own window. `true` until the observer's first answer, which\n * arrives within a frame, and where there is no observer.\n */\nfunction useOnScreen(element: Element | null): boolean {\n const [onScreen, setOnScreen] = useState(true);\n useEffect(() => {\n const Observer = element?.ownerDocument.defaultView?.IntersectionObserver;\n if (!element || !Observer) return;\n const observer = new Observer((entries) => {\n const latest = entries.at(-1);\n if (latest) setOnScreen(latest.isIntersecting);\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [element]);\n return onScreen;\n}\n\nexport function MarkViewedThreadRead({\n delayMs = MARK_VIEWED_THREAD_READ_DELAY_MS,\n}: {\n /** How long the conditions must hold before the write. */\n delayMs?: number;\n}): ReactNode {\n const list = useAthenaStatewireThreadList();\n // The thread the statewire scope publishes WITH its client, so the messages\n // read here are always this thread's: the list's selection runs one commit\n // ahead of the client during a switch.\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const principal = useContext(AthenaAuthContext)?.user?.userId ?? '';\n // Primitive reads: a streamed token changes neither, so it never re-renders this.\n const messageKey = useAuiState((s) => lastMessageKey(s.optional.thread?.messages));\n const isRunning = useAuiState((s) => s.optional.thread?.isRunning ?? false);\n const windowActive = useDocumentActive(useOwnerDocument());\n const [sentinel, setSentinel] = useState<HTMLSpanElement | null>(null);\n const onScreen = useOnScreen(sentinel);\n const inView = windowActive && onScreen;\n\n const row = threadId !== null && list?.activeThread?.id === threadId ? list.activeThread : null;\n const isUnread = row?.isUnread ?? false;\n const writeInFlight = threadId !== null && (list?.readStatePendingThreadIds.has(threadId) ?? false);\n const setReadState = list?.setReadState;\n const visitKey = `${principal}\\u0000${threadId ?? ''}`;\n\n // The row as it stands when the wait ends: the receipt covers its `updatedAt`.\n const rowRef = useRef(row);\n rowRef.current = row;\n const visitRef = useRef<ViewedThreadVisit>({\n key: visitKey,\n settledMessageKey: null,\n inFlightMessageKey: null,\n });\n\n useEffect(() => {\n if (visitRef.current.key !== visitKey) {\n visitRef.current = { key: visitKey, settledMessageKey: null, inFlightMessageKey: null };\n }\n const visit = visitRef.current;\n if (threadId === null || setReadState === undefined || messageKey === null) return;\n if (writeInFlight) {\n // A write settles the message on screen when it began. One that arrives\n // while it is in flight is weighed once it has answered.\n if (visit.inFlightMessageKey === null) visit.inFlightMessageKey = messageKey;\n visit.settledMessageKey = visit.inFlightMessageKey;\n return;\n }\n visit.inFlightMessageKey = null;\n if (visit.settledMessageKey === messageKey) return;\n if (!inView || isRunning || !isUnread) return;\n const timer = setTimeout(() => {\n // Read again: a render may have taken the row away or marked it read\n // before React ran this effect's cleanup.\n const current = rowRef.current;\n if (current === null || !current.isUnread) return;\n visit.settledMessageKey = messageKey;\n setReadState({ threadId, isUnread: false, updatedAt: current.updatedAt });\n }, delayMs);\n return () => clearTimeout(timer);\n }, [visitKey, threadId, messageKey, writeInFlight, inView, isRunning, isUnread, setReadState, delayMs]);\n\n if (list === null) return null;\n return (\n <span\n ref={setSentinel}\n aria-hidden=\"true\"\n data-slot=\"viewed-thread-sentinel\"\n className=\"pointer-events-none absolute inset-0\"\n />\n );\n}\n"],"names":["useState","useEffect","useAthenaStatewireThreadList","useContext","AthenaStatewireThreadIdContext","AthenaAuthContext","useAuiState","_a","useDocumentActive","useOwnerDocument","useRef","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"mark-viewed-thread-read.cjs","sources":["../../src/threads/mark-viewed-thread-read.tsx"],"sourcesContent":["/**\n * `MarkViewedThreadRead` — the session `AthenaChat` shows is marked read for\n * the viewer, as Olympus marks every session it shows\n * (`useMarkCurrentThreadAsRead`) and Devin clears a session's unread dot when\n * it is opened. Without it, a session opened from the session list or a link\n * stayed unread for good: only the inbox's own open and its Mark read wrote\n * the receipt, so unread dots and the inbox's Unread count only grew.\n *\n * The open session is marked read once all of these hold:\n *\n * - the transcript is in front of the person: its window is visible and\n * focused (the window it renders into, a pop-out's included), and the chat\n * itself is on screen (not hidden, as `AthenaLayout` hides it behind a\n * maximized workbench, nor scrolled out of the page);\n * - its history is on screen (the thread has a last message);\n * - no run is going (a running session is marked when its run ends, never per\n * streamed chunk);\n * - its row is unread (a read row is never written).\n *\n * They must hold for {@link MARK_VIEWED_THREAD_READ_DELAY_MS}; the write is\n * the thread list's `setReadState` (`POST /api/conversations/threads/read-state`),\n * with the row's `updatedAt`, so the next message ends the override and shows\n * the row unread again. One write per (viewer, session, last message as it\n * stands — its id and how many parts it has, since the agent's further\n * messages in a turn join that turn's message): what arrives while the person\n * watches is marked too, nothing polls, and a failed write is not repeated\n * for the same message. A read-state write in flight for the open session\n * (this one's, or the person's own Mark read / Mark unread) settles the\n * message that was on screen when it began, so the person's choice stands\n * until something new arrives or they open the session again.\n *\n * Renders an invisible, inert sentinel over the chat panel (it must sit in\n * the panel, which is `relative`); nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport { useAuiState } from '@assistant-ui/react';\nimport { type ReactNode, useContext, useEffect, useRef, useState } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport { useOwnerDocument } from '../lib/owner-document';\nimport { useDocumentActive } from '../lib/use-document-active';\nimport { useAthenaStatewireThreadList } from './statewire-thread-list';\nimport { AthenaStatewireThreadIdContext } from './thread-id-context';\n\n/** How long the open session must stay unread and in view before it is marked read. */\nexport const MARK_VIEWED_THREAD_READ_DELAY_MS = 1_000;\n\ninterface ViewedThreadVisit {\n /** Who views which session: the provider's read state is scoped to the viewer. */\n key: string;\n /** The last message (as {@link lastMessageKey} reads it) this visit has settled. */\n settledMessageKey: string | null;\n /** The message on screen when the read-state write now in flight began. */\n inFlightMessageKey: string | null;\n}\n\n/**\n * The thread's last message as it stands: its id and part count. A turn's\n * further assistant messages join that turn's message, so its id alone does\n * not move when the agent writes more; the part count does — once per part,\n * never per streamed token. `null` until the history is on screen.\n */\nfunction lastMessageKey(\n messages: readonly { readonly id: string; readonly content: readonly unknown[] }[] | undefined,\n): string | null {\n const last = messages?.at(-1);\n return last ? `${last.id}#${last.content.length}` : null;\n}\n\n/**\n * Whether `element` is on screen: laid out (no `display: none` on it or an\n * ancestor) and inside the viewport, read by an IntersectionObserver of the\n * element's own window. `true` until the observer's first answer, which\n * arrives within a frame, and where there is no observer.\n */\nfunction useOnScreen(element: Element | null): boolean {\n const [onScreen, setOnScreen] = useState(true);\n useEffect(() => {\n const Observer = element?.ownerDocument.defaultView?.IntersectionObserver;\n if (!element || !Observer) return;\n const observer = new Observer((entries) => {\n const latest = entries.at(-1);\n if (latest) setOnScreen(latest.isIntersecting);\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [element]);\n return onScreen;\n}\n\nexport function MarkViewedThreadRead({\n delayMs = MARK_VIEWED_THREAD_READ_DELAY_MS,\n}: {\n /** How long the conditions must hold before the write. */\n delayMs?: number;\n}): ReactNode {\n const list = useAthenaStatewireThreadList();\n // The thread the statewire scope publishes WITH its client, so the messages\n // read here are always this thread's: the list's selection runs one commit\n // ahead of the client during a switch.\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const principal = useContext(AthenaAuthContext)?.user?.userId ?? '';\n // Primitive reads: a streamed token changes neither, so it never re-renders this.\n const messageKey = useAuiState((s) => lastMessageKey(s.optional.thread?.messages));\n const isRunning = useAuiState((s) => s.optional.thread?.isRunning ?? false);\n const windowActive = useDocumentActive(useOwnerDocument());\n const [sentinel, setSentinel] = useState<HTMLSpanElement | null>(null);\n const onScreen = useOnScreen(sentinel);\n const inView = windowActive && onScreen;\n\n const row = threadId !== null && list?.activeThread?.id === threadId ? list.activeThread : null;\n const isUnread = row?.isUnread ?? false;\n const writeInFlight = threadId !== null && (list?.readStatePendingThreadIds.has(threadId) ?? false);\n const setReadState = list?.setReadState;\n const visitKey = `${principal}\\u0000${threadId ?? ''}`;\n\n // The row as it stands when the wait ends: the receipt covers its `updatedAt`.\n const rowRef = useRef(row);\n rowRef.current = row;\n const visitRef = useRef<ViewedThreadVisit>({\n key: visitKey,\n settledMessageKey: null,\n inFlightMessageKey: null,\n });\n\n useEffect(() => {\n if (visitRef.current.key !== visitKey) {\n visitRef.current = { key: visitKey, settledMessageKey: null, inFlightMessageKey: null };\n }\n const visit = visitRef.current;\n if (threadId === null || setReadState === undefined || messageKey === null) return;\n if (writeInFlight) {\n // A write settles the message on screen when it began. One that arrives\n // while it is in flight is weighed once it has answered.\n if (visit.inFlightMessageKey === null) visit.inFlightMessageKey = messageKey;\n visit.settledMessageKey = visit.inFlightMessageKey;\n return;\n }\n visit.inFlightMessageKey = null;\n if (visit.settledMessageKey === messageKey) return;\n if (!inView || isRunning || !isUnread) return;\n const timer = setTimeout(() => {\n // Read again: a render may have taken the row away or marked it read\n // before React ran this effect's cleanup.\n const current = rowRef.current;\n if (current === null || !current.isUnread) return;\n visit.settledMessageKey = messageKey;\n setReadState({ threadId, isUnread: false, updatedAt: current.updatedAt });\n }, delayMs);\n return () => clearTimeout(timer);\n }, [visitKey, threadId, messageKey, writeInFlight, inView, isRunning, isUnread, setReadState, delayMs]);\n\n if (list === null) return null;\n return (\n <span\n ref={setSentinel}\n aria-hidden=\"true\"\n data-slot=\"viewed-thread-sentinel\"\n className=\"pointer-events-none absolute inset-0\"\n />\n );\n}\n"],"names":["useState","useEffect","useAthenaStatewireThreadList","useContext","AthenaStatewireThreadIdContext","AthenaAuthContext","useAuiState","_a","useDocumentActive","useOwnerDocument","useRef","jsx"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
3
+ const require$$0 = require("react");
4
4
  const conversationList = require("../agent-runtime/src/conversation-list.cjs");
5
5
  const OFFLINE_SESSION_LIST_KEY = "session-list";
6
6
  const MAX_OFFLINE_SESSION_LIST_PAGES = 4;
@@ -32,8 +32,8 @@ function useOfflineSessionList({
32
32
  }) {
33
33
  const mirror = offlineList == null ? void 0 : offlineList.mirror;
34
34
  const ownerId = offlineList == null ? void 0 : offlineList.ownerId;
35
- const boundOwner = react.useRef(null);
36
- react.useEffect(() => {
35
+ const boundOwner = require$$0.useRef(null);
36
+ require$$0.useEffect(() => {
37
37
  if (!mirror || !ownerId) return;
38
38
  if (boundOwner.current !== null && boundOwner.current !== ownerId) {
39
39
  void queryClient.cancelQueries({ queryKey: [conversationList.CONVERSATION_LIST_QUERY_KEY_ROOT] });
@@ -1 +1 @@
1
- {"version":3,"file":"offline-session-list.cjs","sources":["../../src/threads/offline-session-list.ts"],"sourcesContent":["import {\n CONVERSATION_LIST_QUERY_KEY_ROOT,\n type ConversationListPage,\n type ThreadSnapshotMirror,\n} from '@athenaintel/agent-runtime';\nimport type { QueryClient, QueryKey } from '@tanstack/react-query';\nimport { useEffect, useRef } from 'react';\n\n/** Under this name the list's pages are kept, per owner. */\nexport const OFFLINE_SESSION_LIST_KEY = 'session-list';\n/** The first pages kept: one per filter the list was read with, the newest first. */\nexport const MAX_OFFLINE_SESSION_LIST_PAGES = 4;\n/**\n * Restored pages are stamped this old, so they paint at once and are read again on mount whenever\n * Athena can be reached (and never replace a page already read in this provider).\n */\nconst RESTORED_UPDATED_AT = 1;\n\ninterface KeptPage {\n queryKey: QueryKey;\n data: ConversationListPage;\n}\n\n/** A conversation list's live first page (`conversationListQueryKeys.firstPage`). */\nexport function isSessionListFirstPage(queryKey: QueryKey): boolean {\n return queryKey[0] === CONVERSATION_LIST_QUERY_KEY_ROOT && queryKey[4] === 'first-page';\n}\n\n/** Exactly `conversationListQueryKeys.firstPage(scopeKey, filterKey, pageSize)`. */\nfunction isFirstPageKey(queryKey: unknown): queryKey is QueryKey {\n return (\n Array.isArray(queryKey) &&\n queryKey.length === 5 &&\n isSessionListFirstPage(queryKey) &&\n typeof queryKey[1] === 'string' &&\n typeof queryKey[2] === 'string' &&\n typeof queryKey[3] === 'number'\n );\n}\n\nfunction isConversationRow(row: unknown): boolean {\n if (typeof row !== 'object' || row === null) return false;\n const { threadId, title, updatedAt } = row as Record<string, unknown>;\n return typeof threadId === 'string' && typeof title === 'string' && typeof updatedAt === 'string';\n}\n\n/** A page the list can render: its rows carry the fields every row reads. */\nfunction isConversationListPage(value: unknown): value is ConversationListPage {\n if (typeof value !== 'object' || value === null) return false;\n const { items, hasMore, totalCount } = value as Record<string, unknown>;\n return (\n Array.isArray(items) &&\n items.every(isConversationRow) &&\n typeof hasMore === 'boolean' &&\n (totalCount === null || typeof totalCount === 'number')\n );\n}\n\nfunction isKeptPage(value: unknown): value is KeptPage {\n if (typeof value !== 'object' || value === null) return false;\n const { queryKey, data } = value as Record<string, unknown>;\n return isFirstPageKey(queryKey) && isConversationListPage(data);\n}\n\n/**\n * The session list's first pages, kept on this device sealed under the host's key\n * (`offlineList`'s mirror, `AthenaProvider`'s `offlineHistory`): restored into the list's own query\n * client before it is read, so the list paints at once and reads while Athena can't be reached,\n * and written back (debounced by the mirror) each time a first page is read. Without `offlineList`,\n * nothing.\n *\n * Owner-bound. A list kept for one owner is never restored for another, and a change of owner\n * drops every page of the list's cache before the new owner's are restored (in API-key mode two\n * people read the same list keys); only pages read since the owner was bound are kept for them. A\n * restored page that is not a list page the rows can render is left out.\n */\nexport function useOfflineSessionList({\n queryClient,\n offlineList,\n}: {\n queryClient: QueryClient;\n offlineList: { mirror: ThreadSnapshotMirror; ownerId: string } | undefined;\n}): void {\n const mirror = offlineList?.mirror;\n const ownerId = offlineList?.ownerId;\n const boundOwner = useRef<string | null>(null);\n useEffect(() => {\n if (!mirror || !ownerId) return;\n if (boundOwner.current !== null && boundOwner.current !== ownerId) {\n void queryClient.cancelQueries({ queryKey: [CONVERSATION_LIST_QUERY_KEY_ROOT] });\n queryClient.removeQueries({ queryKey: [CONVERSATION_LIST_QUERY_KEY_ROOT] });\n }\n boundOwner.current = ownerId;\n const boundAt = Date.now();\n let stopped = false;\n void mirror.loadList({ ownerId, listKey: OFFLINE_SESSION_LIST_KEY }).then((kept) => {\n if (stopped || !kept || !Array.isArray(kept.value)) return;\n for (const page of kept.value) {\n if (!isKeptPage(page)) continue;\n if (queryClient.getQueryData(page.queryKey) !== undefined) continue;\n queryClient.setQueryData(page.queryKey, page.data, { updatedAt: RESTORED_UPDATED_AT });\n }\n });\n const write = (): void => {\n const pages: KeptPage[] = queryClient\n .getQueryCache()\n .findAll({ predicate: (query) => isSessionListFirstPage(query.queryKey) })\n .filter(\n (query) =>\n query.state.status === 'success' &&\n query.state.dataUpdatedAt >= boundAt &&\n isConversationListPage(query.state.data),\n )\n .sort((a, b) => b.state.dataUpdatedAt - a.state.dataUpdatedAt)\n .slice(0, MAX_OFFLINE_SESSION_LIST_PAGES)\n .map((query) => ({ queryKey: query.queryKey, data: query.state.data as ConversationListPage }));\n if (pages.length > 0) mirror.writeList({ ownerId, listKey: OFFLINE_SESSION_LIST_KEY, value: pages });\n };\n const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n if (event.type !== 'updated' || event.action.type !== 'success') return;\n if (!isSessionListFirstPage(event.query.queryKey)) return;\n // A page restored from the device is not news to write back.\n if (event.query.state.dataUpdatedAt === RESTORED_UPDATED_AT) return;\n write();\n });\n return () => {\n stopped = true;\n unsubscribe();\n };\n }, [queryClient, mirror, ownerId]);\n}\n"],"names":["CONVERSATION_LIST_QUERY_KEY_ROOT","useRef","useEffect"],"mappings":"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"}
1
+ {"version":3,"file":"offline-session-list.cjs","sources":["../../src/threads/offline-session-list.ts"],"sourcesContent":["import {\n CONVERSATION_LIST_QUERY_KEY_ROOT,\n type ConversationListPage,\n type ThreadSnapshotMirror,\n} from '@athenaintel/agent-runtime';\nimport type { QueryClient, QueryKey } from '@tanstack/react-query';\nimport { useEffect, useRef } from 'react';\n\n/** Under this name the list's pages are kept, per owner. */\nexport const OFFLINE_SESSION_LIST_KEY = 'session-list';\n/** The first pages kept: one per filter the list was read with, the newest first. */\nexport const MAX_OFFLINE_SESSION_LIST_PAGES = 4;\n/**\n * Restored pages are stamped this old, so they paint at once and are read again on mount whenever\n * Athena can be reached (and never replace a page already read in this provider).\n */\nconst RESTORED_UPDATED_AT = 1;\n\ninterface KeptPage {\n queryKey: QueryKey;\n data: ConversationListPage;\n}\n\n/** A conversation list's live first page (`conversationListQueryKeys.firstPage`). */\nexport function isSessionListFirstPage(queryKey: QueryKey): boolean {\n return queryKey[0] === CONVERSATION_LIST_QUERY_KEY_ROOT && queryKey[4] === 'first-page';\n}\n\n/** Exactly `conversationListQueryKeys.firstPage(scopeKey, filterKey, pageSize)`. */\nfunction isFirstPageKey(queryKey: unknown): queryKey is QueryKey {\n return (\n Array.isArray(queryKey) &&\n queryKey.length === 5 &&\n isSessionListFirstPage(queryKey) &&\n typeof queryKey[1] === 'string' &&\n typeof queryKey[2] === 'string' &&\n typeof queryKey[3] === 'number'\n );\n}\n\nfunction isConversationRow(row: unknown): boolean {\n if (typeof row !== 'object' || row === null) return false;\n const { threadId, title, updatedAt } = row as Record<string, unknown>;\n return typeof threadId === 'string' && typeof title === 'string' && typeof updatedAt === 'string';\n}\n\n/** A page the list can render: its rows carry the fields every row reads. */\nfunction isConversationListPage(value: unknown): value is ConversationListPage {\n if (typeof value !== 'object' || value === null) return false;\n const { items, hasMore, totalCount } = value as Record<string, unknown>;\n return (\n Array.isArray(items) &&\n items.every(isConversationRow) &&\n typeof hasMore === 'boolean' &&\n (totalCount === null || typeof totalCount === 'number')\n );\n}\n\nfunction isKeptPage(value: unknown): value is KeptPage {\n if (typeof value !== 'object' || value === null) return false;\n const { queryKey, data } = value as Record<string, unknown>;\n return isFirstPageKey(queryKey) && isConversationListPage(data);\n}\n\n/**\n * The session list's first pages, kept on this device sealed under the host's key\n * (`offlineList`'s mirror, `AthenaProvider`'s `offlineHistory`): restored into the list's own query\n * client before it is read, so the list paints at once and reads while Athena can't be reached,\n * and written back (debounced by the mirror) each time a first page is read. Without `offlineList`,\n * nothing.\n *\n * Owner-bound. A list kept for one owner is never restored for another, and a change of owner\n * drops every page of the list's cache before the new owner's are restored (in API-key mode two\n * people read the same list keys); only pages read since the owner was bound are kept for them. A\n * restored page that is not a list page the rows can render is left out.\n */\nexport function useOfflineSessionList({\n queryClient,\n offlineList,\n}: {\n queryClient: QueryClient;\n offlineList: { mirror: ThreadSnapshotMirror; ownerId: string } | undefined;\n}): void {\n const mirror = offlineList?.mirror;\n const ownerId = offlineList?.ownerId;\n const boundOwner = useRef<string | null>(null);\n useEffect(() => {\n if (!mirror || !ownerId) return;\n if (boundOwner.current !== null && boundOwner.current !== ownerId) {\n void queryClient.cancelQueries({ queryKey: [CONVERSATION_LIST_QUERY_KEY_ROOT] });\n queryClient.removeQueries({ queryKey: [CONVERSATION_LIST_QUERY_KEY_ROOT] });\n }\n boundOwner.current = ownerId;\n const boundAt = Date.now();\n let stopped = false;\n void mirror.loadList({ ownerId, listKey: OFFLINE_SESSION_LIST_KEY }).then((kept) => {\n if (stopped || !kept || !Array.isArray(kept.value)) return;\n for (const page of kept.value) {\n if (!isKeptPage(page)) continue;\n if (queryClient.getQueryData(page.queryKey) !== undefined) continue;\n queryClient.setQueryData(page.queryKey, page.data, { updatedAt: RESTORED_UPDATED_AT });\n }\n });\n const write = (): void => {\n const pages: KeptPage[] = queryClient\n .getQueryCache()\n .findAll({ predicate: (query) => isSessionListFirstPage(query.queryKey) })\n .filter(\n (query) =>\n query.state.status === 'success' &&\n query.state.dataUpdatedAt >= boundAt &&\n isConversationListPage(query.state.data),\n )\n .sort((a, b) => b.state.dataUpdatedAt - a.state.dataUpdatedAt)\n .slice(0, MAX_OFFLINE_SESSION_LIST_PAGES)\n .map((query) => ({ queryKey: query.queryKey, data: query.state.data as ConversationListPage }));\n if (pages.length > 0) mirror.writeList({ ownerId, listKey: OFFLINE_SESSION_LIST_KEY, value: pages });\n };\n const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n if (event.type !== 'updated' || event.action.type !== 'success') return;\n if (!isSessionListFirstPage(event.query.queryKey)) return;\n // A page restored from the device is not news to write back.\n if (event.query.state.dataUpdatedAt === RESTORED_UPDATED_AT) return;\n write();\n });\n return () => {\n stopped = true;\n unsubscribe();\n };\n }, [queryClient, mirror, ownerId]);\n}\n"],"names":["CONVERSATION_LIST_QUERY_KEY_ROOT","useRef","useEffect"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
3
+ const require$$0 = require("react");
4
4
  const useAthenaRestQuery = require("../lib/use-athena-rest-query.cjs");
5
5
  const conversationList = require("../agent-runtime/src/conversation-list.cjs");
6
6
  const TAB_SHARE_CLAIM_MS = 5e3;
@@ -52,10 +52,10 @@ function useSessionListTabShare({
52
52
  const channelName = identity ? `${CHANNEL_PREFIX}${useAthenaRestQuery.keyPartFingerprint(
53
53
  [identity.backendUrl, identity.userId, identity.workspaceId].join("\0")
54
54
  )}` : null;
55
- const claims = react.useMemo(() => /* @__PURE__ */ new Map(), [channelName]);
56
- const channelRef = react.useRef(null);
55
+ const claims = require$$0.useMemo(() => /* @__PURE__ */ new Map(), [channelName]);
56
+ const channelRef = require$$0.useRef(null);
57
57
  const isSupported = channelName !== null && typeof BroadcastChannel !== "undefined";
58
- react.useEffect(() => {
58
+ require$$0.useEffect(() => {
59
59
  if (!channelName || typeof BroadcastChannel === "undefined") return;
60
60
  let channel;
61
61
  try {
@@ -116,7 +116,7 @@ function useSessionListTabShare({
116
116
  channel.close();
117
117
  };
118
118
  }, [channelName, claims, queryClient]);
119
- return react.useMemo(() => {
119
+ return require$$0.useMemo(() => {
120
120
  if (!isSupported) return NO_SHARE;
121
121
  return {
122
122
  claimedUntil: (key) => {
@@ -1 +1 @@
1
- {"version":3,"file":"session-list-tab-share.cjs","sources":["../../src/threads/session-list-tab-share.ts"],"sourcesContent":["/**\n * Open tabs of one signed-in user share their session-list reads.\n *\n * A pushed conversation-index change reaches every open tab at once, and each\n * one used to re-read the same lists. With this in place:\n *\n * - **Pages are shared.** Whenever a tab reads a list's first page, it posts\n * the page on a `BroadcastChannel` named for the backend, the user and the\n * workspace. A tab that holds the same list (same query key) and has an\n * older copy takes it, so the new row appears there without a request.\n * - **One tab reads for the others.** Before an index-triggered refresh, a tab\n * claims the list on the channel. The other tabs hold their own refresh for\n * that list for {@link TAB_SHARE_CLAIM_MS}; the claimer's page normally\n * lands well before then. If it does not (the claimer failed or closed),\n * they refresh themselves.\n *\n * Only same-origin tabs can hear a `BroadcastChannel`, and only tabs signed in\n * as the same user to the same workspace and backend use the same channel, so\n * a page never reaches another account. Without a signed-in user, a\n * workspace, or `BroadcastChannel` (older browsers, SSR, tests), every call is\n * a no-op and each tab reads for itself, as before.\n */\nimport {\n type ConversationListPage,\n CONVERSATION_LIST_QUERY_KEY_ROOT,\n} from '@athenaintel/agent-runtime';\nimport type { QueryClient, QueryKey } from '@tanstack/react-query';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { keyPartFingerprint } from '../lib/use-athena-rest-query';\n\n/** How long a claim by another tab holds this tab's own refresh of that list. */\nexport const TAB_SHARE_CLAIM_MS = 5_000;\n\nconst CHANNEL_PREFIX = 'athena-sdk:session-list:';\nconst MESSAGE_VERSION = 1;\n\ntype TabShareMessage =\n | { v: number; kind: 'page'; key: string; queryKey: QueryKey; data: ConversationListPage; updatedAt: number }\n | { v: number; kind: 'claim'; key: string };\n\nexport interface SessionListTabShare {\n /**\n * Whether another tab has claimed the list with this query key and its\n * claim still stands: when it lapses (epoch ms), or `null`.\n */\n claimedUntil(key: string): number | null;\n /** Tell the other tabs this one is reading the list now. */\n claim(key: string): void;\n}\n\nconst NO_SHARE: SessionListTabShare = {\n claimedUntil: () => null,\n claim: () => undefined,\n};\n\n/** A list's first-page query key, as the stable string the channel names it by. */\nexport function sessionListShareKey(queryKey: QueryKey): string {\n return JSON.stringify(queryKey);\n}\n\nfunction isFirstPageKey(queryKey: unknown): queryKey is QueryKey {\n return (\n Array.isArray(queryKey) &&\n queryKey[0] === CONVERSATION_LIST_QUERY_KEY_ROOT &&\n queryKey[queryKey.length - 1] === 'first-page'\n );\n}\n\nfunction isPage(value: unknown): value is ConversationListPage {\n if (typeof value !== 'object' || value === null) return false;\n const { items, hasMore } = value as Record<string, unknown>;\n return Array.isArray(items) && typeof hasMore === 'boolean';\n}\n\n/** Parse a channel message, or `null` for anything this version does not send. Exported for tests. */\nexport function parseTabShareMessage(raw: unknown): TabShareMessage | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const message = raw as Record<string, unknown>;\n if (message.v !== MESSAGE_VERSION || typeof message.key !== 'string') return null;\n if (message.kind === 'claim') return { v: MESSAGE_VERSION, kind: 'claim', key: message.key };\n if (\n message.kind === 'page' &&\n isFirstPageKey(message.queryKey) &&\n sessionListShareKey(message.queryKey) === message.key &&\n isPage(message.data) &&\n typeof message.updatedAt === 'number'\n ) {\n return {\n v: MESSAGE_VERSION,\n kind: 'page',\n key: message.key,\n queryKey: message.queryKey,\n data: message.data,\n updatedAt: message.updatedAt,\n };\n }\n return null;\n}\n\n/**\n * Take a page another tab read: only into a list this tab holds, and only\n * when it is newer than this tab's copy. Returns whether it was taken.\n * Exported for tests.\n */\nexport function applySharedPage(\n queryClient: QueryClient,\n message: Extract<TabShareMessage, { kind: 'page' }>,\n): boolean {\n const state = queryClient.getQueryState(message.queryKey);\n if (!state) return false;\n if (state.dataUpdatedAt >= message.updatedAt) return false;\n queryClient.setQueryData(message.queryKey, message.data, { updatedAt: message.updatedAt });\n return true;\n}\n\n/**\n * Share this provider's session-list first pages with the user's other open\n * tabs, and hear theirs. `identity` is `null` when sharing must stay off (no\n * signed-in user or workspace known yet).\n */\nexport function useSessionListTabShare({\n queryClient,\n identity,\n}: {\n queryClient: QueryClient;\n identity: { backendUrl: string; userId: string; workspaceId: string } | null;\n}): SessionListTabShare {\n const channelName = identity\n ? `${CHANNEL_PREFIX}${keyPartFingerprint(\n [identity.backendUrl, identity.userId, identity.workspaceId].join('\\u0000'),\n )}`\n : null;\n const claims = useMemo(() => new Map<string, number>(), [channelName]);\n // The channel is opened by the effect that closes it, so each setup has its\n // own (StrictMode's setup, cleanup, setup included), and `claim` posts on\n // whichever one is open now.\n const channelRef = useRef<BroadcastChannel | null>(null);\n const isSupported = channelName !== null && typeof BroadcastChannel !== 'undefined';\n\n useEffect(() => {\n if (!channelName || typeof BroadcastChannel === 'undefined') return;\n let channel: BroadcastChannel;\n try {\n channel = new BroadcastChannel(channelName);\n } catch {\n return;\n }\n channelRef.current = channel;\n const post = (message: TabShareMessage) => {\n try {\n channel.postMessage(message);\n } catch {\n // A page that cannot be cloned or a closed channel: the other tabs read for themselves.\n }\n };\n channel.onmessage = (event: MessageEvent) => {\n const message = parseTabShareMessage(event.data);\n if (!message) return;\n if (message.kind === 'claim') {\n claims.set(message.key, Date.now() + TAB_SHARE_CLAIM_MS);\n return;\n }\n // The claim stands until it lapses: a tab whose rows the page still\n // leaves out reads for itself once it does, not all of them at once.\n applySharedPage(queryClient, message);\n };\n // Only a read that STARTED while this channel was open is shared on it.\n // The channel is named for the workspace the current credential resolved\n // to; a read started before (under the previous credential, perhaps for\n // another workspace) may still land after the switch, and its rows must\n // never reach this workspace's tabs.\n const startedHere = new Set<string>();\n const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n if (event.type === 'removed') {\n startedHere.delete(event.query.queryHash);\n return;\n }\n if (event.type !== 'updated') return;\n const { queryKey, queryHash } = event.query;\n if (!isFirstPageKey(queryKey)) return;\n if (event.action.type === 'fetch') {\n startedHere.add(queryHash);\n return;\n }\n if (event.action.type === 'error') {\n startedHere.delete(queryHash);\n return;\n }\n if (event.action.type !== 'success') return;\n // A page set by hand (one another tab shared, an optimistic patch) is not news to them.\n if ((event.action as { manual?: boolean }).manual) return;\n if (!startedHere.delete(queryHash)) return;\n if (!isPage(event.query.state.data)) return;\n post({\n v: MESSAGE_VERSION,\n kind: 'page',\n key: sessionListShareKey(queryKey),\n queryKey,\n data: event.query.state.data,\n updatedAt: event.query.state.dataUpdatedAt,\n });\n });\n return () => {\n unsubscribe();\n if (channelRef.current === channel) channelRef.current = null;\n channel.onmessage = null;\n channel.close();\n };\n }, [channelName, claims, queryClient]);\n\n return useMemo<SessionListTabShare>(() => {\n if (!isSupported) return NO_SHARE;\n return {\n claimedUntil: (key) => {\n const until = claims.get(key);\n if (until === undefined) return null;\n if (until <= Date.now()) {\n claims.delete(key);\n return null;\n }\n return until;\n },\n claim: (key) => {\n try {\n channelRef.current?.postMessage({\n v: MESSAGE_VERSION,\n kind: 'claim',\n key,\n } satisfies TabShareMessage);\n } catch {\n // Closed: nothing to coordinate with.\n }\n },\n };\n }, [isSupported, claims]);\n}\n"],"names":["CONVERSATION_LIST_QUERY_KEY_ROOT","keyPartFingerprint","useMemo","useRef","useEffect"],"mappings":"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"}
1
+ {"version":3,"file":"session-list-tab-share.cjs","sources":["../../src/threads/session-list-tab-share.ts"],"sourcesContent":["/**\n * Open tabs of one signed-in user share their session-list reads.\n *\n * A pushed conversation-index change reaches every open tab at once, and each\n * one used to re-read the same lists. With this in place:\n *\n * - **Pages are shared.** Whenever a tab reads a list's first page, it posts\n * the page on a `BroadcastChannel` named for the backend, the user and the\n * workspace. A tab that holds the same list (same query key) and has an\n * older copy takes it, so the new row appears there without a request.\n * - **One tab reads for the others.** Before an index-triggered refresh, a tab\n * claims the list on the channel. The other tabs hold their own refresh for\n * that list for {@link TAB_SHARE_CLAIM_MS}; the claimer's page normally\n * lands well before then. If it does not (the claimer failed or closed),\n * they refresh themselves.\n *\n * Only same-origin tabs can hear a `BroadcastChannel`, and only tabs signed in\n * as the same user to the same workspace and backend use the same channel, so\n * a page never reaches another account. Without a signed-in user, a\n * workspace, or `BroadcastChannel` (older browsers, SSR, tests), every call is\n * a no-op and each tab reads for itself, as before.\n */\nimport {\n type ConversationListPage,\n CONVERSATION_LIST_QUERY_KEY_ROOT,\n} from '@athenaintel/agent-runtime';\nimport type { QueryClient, QueryKey } from '@tanstack/react-query';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { keyPartFingerprint } from '../lib/use-athena-rest-query';\n\n/** How long a claim by another tab holds this tab's own refresh of that list. */\nexport const TAB_SHARE_CLAIM_MS = 5_000;\n\nconst CHANNEL_PREFIX = 'athena-sdk:session-list:';\nconst MESSAGE_VERSION = 1;\n\ntype TabShareMessage =\n | { v: number; kind: 'page'; key: string; queryKey: QueryKey; data: ConversationListPage; updatedAt: number }\n | { v: number; kind: 'claim'; key: string };\n\nexport interface SessionListTabShare {\n /**\n * Whether another tab has claimed the list with this query key and its\n * claim still stands: when it lapses (epoch ms), or `null`.\n */\n claimedUntil(key: string): number | null;\n /** Tell the other tabs this one is reading the list now. */\n claim(key: string): void;\n}\n\nconst NO_SHARE: SessionListTabShare = {\n claimedUntil: () => null,\n claim: () => undefined,\n};\n\n/** A list's first-page query key, as the stable string the channel names it by. */\nexport function sessionListShareKey(queryKey: QueryKey): string {\n return JSON.stringify(queryKey);\n}\n\nfunction isFirstPageKey(queryKey: unknown): queryKey is QueryKey {\n return (\n Array.isArray(queryKey) &&\n queryKey[0] === CONVERSATION_LIST_QUERY_KEY_ROOT &&\n queryKey[queryKey.length - 1] === 'first-page'\n );\n}\n\nfunction isPage(value: unknown): value is ConversationListPage {\n if (typeof value !== 'object' || value === null) return false;\n const { items, hasMore } = value as Record<string, unknown>;\n return Array.isArray(items) && typeof hasMore === 'boolean';\n}\n\n/** Parse a channel message, or `null` for anything this version does not send. Exported for tests. */\nexport function parseTabShareMessage(raw: unknown): TabShareMessage | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const message = raw as Record<string, unknown>;\n if (message.v !== MESSAGE_VERSION || typeof message.key !== 'string') return null;\n if (message.kind === 'claim') return { v: MESSAGE_VERSION, kind: 'claim', key: message.key };\n if (\n message.kind === 'page' &&\n isFirstPageKey(message.queryKey) &&\n sessionListShareKey(message.queryKey) === message.key &&\n isPage(message.data) &&\n typeof message.updatedAt === 'number'\n ) {\n return {\n v: MESSAGE_VERSION,\n kind: 'page',\n key: message.key,\n queryKey: message.queryKey,\n data: message.data,\n updatedAt: message.updatedAt,\n };\n }\n return null;\n}\n\n/**\n * Take a page another tab read: only into a list this tab holds, and only\n * when it is newer than this tab's copy. Returns whether it was taken.\n * Exported for tests.\n */\nexport function applySharedPage(\n queryClient: QueryClient,\n message: Extract<TabShareMessage, { kind: 'page' }>,\n): boolean {\n const state = queryClient.getQueryState(message.queryKey);\n if (!state) return false;\n if (state.dataUpdatedAt >= message.updatedAt) return false;\n queryClient.setQueryData(message.queryKey, message.data, { updatedAt: message.updatedAt });\n return true;\n}\n\n/**\n * Share this provider's session-list first pages with the user's other open\n * tabs, and hear theirs. `identity` is `null` when sharing must stay off (no\n * signed-in user or workspace known yet).\n */\nexport function useSessionListTabShare({\n queryClient,\n identity,\n}: {\n queryClient: QueryClient;\n identity: { backendUrl: string; userId: string; workspaceId: string } | null;\n}): SessionListTabShare {\n const channelName = identity\n ? `${CHANNEL_PREFIX}${keyPartFingerprint(\n [identity.backendUrl, identity.userId, identity.workspaceId].join('\\u0000'),\n )}`\n : null;\n const claims = useMemo(() => new Map<string, number>(), [channelName]);\n // The channel is opened by the effect that closes it, so each setup has its\n // own (StrictMode's setup, cleanup, setup included), and `claim` posts on\n // whichever one is open now.\n const channelRef = useRef<BroadcastChannel | null>(null);\n const isSupported = channelName !== null && typeof BroadcastChannel !== 'undefined';\n\n useEffect(() => {\n if (!channelName || typeof BroadcastChannel === 'undefined') return;\n let channel: BroadcastChannel;\n try {\n channel = new BroadcastChannel(channelName);\n } catch {\n return;\n }\n channelRef.current = channel;\n const post = (message: TabShareMessage) => {\n try {\n channel.postMessage(message);\n } catch {\n // A page that cannot be cloned or a closed channel: the other tabs read for themselves.\n }\n };\n channel.onmessage = (event: MessageEvent) => {\n const message = parseTabShareMessage(event.data);\n if (!message) return;\n if (message.kind === 'claim') {\n claims.set(message.key, Date.now() + TAB_SHARE_CLAIM_MS);\n return;\n }\n // The claim stands until it lapses: a tab whose rows the page still\n // leaves out reads for itself once it does, not all of them at once.\n applySharedPage(queryClient, message);\n };\n // Only a read that STARTED while this channel was open is shared on it.\n // The channel is named for the workspace the current credential resolved\n // to; a read started before (under the previous credential, perhaps for\n // another workspace) may still land after the switch, and its rows must\n // never reach this workspace's tabs.\n const startedHere = new Set<string>();\n const unsubscribe = queryClient.getQueryCache().subscribe((event) => {\n if (event.type === 'removed') {\n startedHere.delete(event.query.queryHash);\n return;\n }\n if (event.type !== 'updated') return;\n const { queryKey, queryHash } = event.query;\n if (!isFirstPageKey(queryKey)) return;\n if (event.action.type === 'fetch') {\n startedHere.add(queryHash);\n return;\n }\n if (event.action.type === 'error') {\n startedHere.delete(queryHash);\n return;\n }\n if (event.action.type !== 'success') return;\n // A page set by hand (one another tab shared, an optimistic patch) is not news to them.\n if ((event.action as { manual?: boolean }).manual) return;\n if (!startedHere.delete(queryHash)) return;\n if (!isPage(event.query.state.data)) return;\n post({\n v: MESSAGE_VERSION,\n kind: 'page',\n key: sessionListShareKey(queryKey),\n queryKey,\n data: event.query.state.data,\n updatedAt: event.query.state.dataUpdatedAt,\n });\n });\n return () => {\n unsubscribe();\n if (channelRef.current === channel) channelRef.current = null;\n channel.onmessage = null;\n channel.close();\n };\n }, [channelName, claims, queryClient]);\n\n return useMemo<SessionListTabShare>(() => {\n if (!isSupported) return NO_SHARE;\n return {\n claimedUntil: (key) => {\n const until = claims.get(key);\n if (until === undefined) return null;\n if (until <= Date.now()) {\n claims.delete(key);\n return null;\n }\n return until;\n },\n claim: (key) => {\n try {\n channelRef.current?.postMessage({\n v: MESSAGE_VERSION,\n kind: 'claim',\n key,\n } satisfies TabShareMessage);\n } catch {\n // Closed: nothing to coordinate with.\n }\n },\n };\n }, [isSupported, claims]);\n}\n"],"names":["CONVERSATION_LIST_QUERY_KEY_ROOT","keyPartFingerprint","useMemo","useRef","useEffect"],"mappings":"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"}