@athenaintel/react 0.43.0 → 0.48.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 (661) hide show
  1. package/README.md +215 -3
  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/client-tool-bridge.cjs +15 -15
  13. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  14. package/dist/agent-runtime/src/conversation-index.cjs +8 -8
  15. package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
  16. package/dist/agent-runtime/src/decision-checks.cjs +207 -0
  17. package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
  18. package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
  19. package/dist/agent-runtime/src/decision-checks.js +207 -0
  20. package/dist/agent-runtime/src/decision-checks.js.map +1 -0
  21. package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
  22. package/dist/agent-runtime/src/errors.cjs +18 -0
  23. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  24. package/dist/agent-runtime/src/errors.d.ts +7 -0
  25. package/dist/agent-runtime/src/errors.js +18 -0
  26. package/dist/agent-runtime/src/errors.js.map +1 -1
  27. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
  28. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  29. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
  30. package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
  31. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  32. package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
  33. package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
  34. package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
  35. package/dist/agent-runtime/src/handoff-arrival.js +60 -0
  36. package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
  37. package/dist/agent-runtime/src/index.d.ts +14 -8
  38. package/dist/agent-runtime/src/interrupts.cjs +43 -18
  39. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  40. package/dist/agent-runtime/src/interrupts.d.ts +19 -2
  41. package/dist/agent-runtime/src/interrupts.js +28 -3
  42. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  43. package/dist/agent-runtime/src/lane-history.cjs +8 -8
  44. package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
  45. package/dist/agent-runtime/src/messages.cjs +43 -8
  46. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  47. package/dist/agent-runtime/src/messages.d.ts +25 -3
  48. package/dist/agent-runtime/src/messages.js +43 -8
  49. package/dist/agent-runtime/src/messages.js.map +1 -1
  50. package/dist/agent-runtime/src/offline-status.cjs +36 -0
  51. package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
  52. package/dist/agent-runtime/src/offline-status.d.ts +118 -3
  53. package/dist/agent-runtime/src/offline-status.js +36 -0
  54. package/dist/agent-runtime/src/offline-status.js.map +1 -0
  55. package/dist/agent-runtime/src/queue.cjs +0 -9
  56. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  57. package/dist/agent-runtime/src/queue.js +0 -9
  58. package/dist/agent-runtime/src/queue.js.map +1 -1
  59. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
  60. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  61. package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
  62. package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
  63. package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
  64. package/dist/agent-runtime/src/runtime-catalog.js +42 -0
  65. package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
  66. package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
  67. package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
  68. package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
  69. package/dist/agent-runtime/src/runtime.d.ts +40 -0
  70. package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
  71. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  72. package/dist/agent-runtime/src/subagents.cjs +32 -2
  73. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  74. package/dist/agent-runtime/src/subagents.d.ts +9 -0
  75. package/dist/agent-runtime/src/subagents.js +30 -0
  76. package/dist/agent-runtime/src/subagents.js.map +1 -1
  77. package/dist/agent-runtime/src/thread-driver.cjs +67 -0
  78. package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
  79. package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
  80. package/dist/agent-runtime/src/thread-driver.js +67 -0
  81. package/dist/agent-runtime/src/thread-driver.js.map +1 -0
  82. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
  83. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
  84. package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
  85. package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
  86. package/dist/agent-runtime/src/thread-status.cjs +3 -3
  87. package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
  88. package/dist/agent-runtime/src/tool-metadata.cjs +210 -25
  89. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  90. package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
  91. package/dist/agent-runtime/src/tool-metadata.js +210 -25
  92. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  93. package/dist/agent-runtime/src/tool-names.cjs +2 -0
  94. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  95. package/dist/agent-runtime/src/tool-names.d.ts +2 -0
  96. package/dist/agent-runtime/src/tool-names.js +2 -0
  97. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  98. package/dist/agent-runtime/src/types.d.ts +10 -2
  99. package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
  100. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  101. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
  102. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  103. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +2 -1
  104. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
  105. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  106. package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
  107. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  108. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
  109. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  110. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
  111. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  112. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
  113. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  114. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +547 -124
  115. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  116. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +129 -10
  117. package/dist/agent-runtime/src/use-deep-agent-voice.js +487 -64
  118. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  119. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
  120. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  121. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
  122. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
  123. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
  124. package/dist/agent-runtime/src/voice-media.cjs +117 -0
  125. package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
  126. package/dist/agent-runtime/src/voice-media.d.ts +49 -0
  127. package/dist/agent-runtime/src/voice-media.js +117 -0
  128. package/dist/agent-runtime/src/voice-media.js.map +1 -0
  129. package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
  130. package/dist/assets/AssetPanel.cjs +11 -11
  131. package/dist/assets/AssetPanel.cjs.map +1 -1
  132. package/dist/assets/AthenaAssetEmbed.cjs +11 -9
  133. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  134. package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
  135. package/dist/assets/AthenaAssetEmbed.js +4 -2
  136. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  137. package/dist/assets/AthenaLayout.cjs +16 -16
  138. package/dist/assets/AthenaLayout.cjs.map +1 -1
  139. package/dist/assets/use-asset-content.cjs +4 -4
  140. package/dist/assets/use-asset-content.cjs.map +1 -1
  141. package/dist/assets/use-asset-embed.cjs +14 -7
  142. package/dist/assets/use-asset-embed.cjs.map +1 -1
  143. package/dist/assets/use-asset-embed.d.ts +11 -1
  144. package/dist/assets/use-asset-embed.js +10 -3
  145. package/dist/assets/use-asset-embed.js.map +1 -1
  146. package/dist/auth/AthenaAuthContext.cjs +3 -3
  147. package/dist/auth/AthenaAuthContext.cjs.map +1 -1
  148. package/dist/auth/AthenaAuthProvider.cjs +8 -8
  149. package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
  150. package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
  151. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  152. package/dist/auth/AthenaSSOProvider.cjs +14 -14
  153. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  154. package/dist/auth/credential-source.cjs +26 -13
  155. package/dist/auth/credential-source.cjs.map +1 -1
  156. package/dist/auth/credential-source.d.ts +8 -0
  157. package/dist/auth/credential-source.js +26 -13
  158. package/dist/auth/credential-source.js.map +1 -1
  159. package/dist/catalog/agent-model-options.cjs +25 -17
  160. package/dist/catalog/agent-model-options.cjs.map +1 -1
  161. package/dist/catalog/agent-model-options.d.ts +38 -5
  162. package/dist/catalog/agent-model-options.js +25 -17
  163. package/dist/catalog/agent-model-options.js.map +1 -1
  164. package/dist/catalog/channel-refusal.cjs +36 -0
  165. package/dist/catalog/channel-refusal.cjs.map +1 -0
  166. package/dist/catalog/channel-refusal.d.ts +29 -0
  167. package/dist/catalog/channel-refusal.js +36 -0
  168. package/dist/catalog/channel-refusal.js.map +1 -0
  169. package/dist/catalog/chat-pickers.cjs +60 -24
  170. package/dist/catalog/chat-pickers.cjs.map +1 -1
  171. package/dist/catalog/chat-pickers.d.ts +12 -2
  172. package/dist/catalog/chat-pickers.js +56 -20
  173. package/dist/catalog/chat-pickers.js.map +1 -1
  174. package/dist/catalog/runtime-catalog.cjs +89 -23
  175. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  176. package/dist/catalog/runtime-catalog.d.ts +8 -2
  177. package/dist/catalog/runtime-catalog.js +83 -17
  178. package/dist/catalog/runtime-catalog.js.map +1 -1
  179. package/dist/catalog/use-athena-chat-mode.cjs +12 -12
  180. package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
  181. package/dist/chat/AthenaChat.cjs +155 -67
  182. package/dist/chat/AthenaChat.cjs.map +1 -1
  183. package/dist/chat/AthenaChat.d.ts +42 -2
  184. package/dist/chat/AthenaChat.js +106 -18
  185. package/dist/chat/AthenaChat.js.map +1 -1
  186. package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
  187. package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
  188. package/dist/chat/DrivingOnChip.cjs +23 -0
  189. package/dist/chat/DrivingOnChip.cjs.map +1 -0
  190. package/dist/chat/DrivingOnChip.d.ts +17 -0
  191. package/dist/chat/DrivingOnChip.js +23 -0
  192. package/dist/chat/DrivingOnChip.js.map +1 -0
  193. package/dist/chat/StatewireApprovalCard.cjs +125 -31
  194. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  195. package/dist/chat/StatewireApprovalCard.d.ts +73 -1
  196. package/dist/chat/StatewireApprovalCard.js +115 -21
  197. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  198. package/dist/chat/StatewireClientToolBridge.cjs +2 -2
  199. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  200. package/dist/chat/StatewireQueuedMessages.cjs +25 -63
  201. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  202. package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
  203. package/dist/chat/StatewireQueuedMessages.js +16 -54
  204. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  205. package/dist/chat/WaitingOnYouBanner.cjs +3 -3
  206. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
  207. package/dist/chat/athena-chat-welcome.cjs +2 -2
  208. package/dist/chat/athena-chat-welcome.cjs.map +1 -1
  209. package/dist/chat/athena-citation-links.cjs +5 -5
  210. package/dist/chat/athena-citation-links.cjs.map +1 -1
  211. package/dist/chat/athena-composer-controls.cjs +26 -16
  212. package/dist/chat/athena-composer-controls.cjs.map +1 -1
  213. package/dist/chat/athena-composer-controls.d.ts +6 -0
  214. package/dist/chat/athena-composer-controls.js +26 -16
  215. package/dist/chat/athena-composer-controls.js.map +1 -1
  216. package/dist/chat/athena-turn-end-status.cjs +42 -0
  217. package/dist/chat/athena-turn-end-status.cjs.map +1 -0
  218. package/dist/chat/athena-turn-end-status.d.ts +24 -0
  219. package/dist/chat/athena-turn-end-status.js +42 -0
  220. package/dist/chat/athena-turn-end-status.js.map +1 -0
  221. package/dist/chat/browser-decision-check.cjs +131 -0
  222. package/dist/chat/browser-decision-check.cjs.map +1 -0
  223. package/dist/chat/browser-decision-check.d.ts +61 -0
  224. package/dist/chat/browser-decision-check.js +131 -0
  225. package/dist/chat/browser-decision-check.js.map +1 -0
  226. package/dist/chat/chat-outbox-rows.cjs +3 -3
  227. package/dist/chat/chat-outbox-rows.cjs.map +1 -1
  228. package/dist/chat/chat-voice-controls.cjs +93 -28
  229. package/dist/chat/chat-voice-controls.cjs.map +1 -1
  230. package/dist/chat/chat-voice-controls.d.ts +36 -2
  231. package/dist/chat/chat-voice-controls.js +89 -24
  232. package/dist/chat/chat-voice-controls.js.map +1 -1
  233. package/dist/chat/composer-keyboard-hint.cjs +5 -5
  234. package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
  235. package/dist/chat/device-operation.cjs +29 -0
  236. package/dist/chat/device-operation.cjs.map +1 -0
  237. package/dist/chat/device-operation.d.ts +34 -0
  238. package/dist/chat/device-operation.js +29 -0
  239. package/dist/chat/device-operation.js.map +1 -0
  240. package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
  241. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  242. package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
  243. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
  244. package/dist/chat/super-grouping/SuperGroupingCard.cjs +52 -36
  245. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  246. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
  247. package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
  248. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  249. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
  250. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  251. package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
  252. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  253. package/dist/chat/super-grouping/ToolTimeline.cjs +73 -40
  254. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  255. package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
  256. package/dist/chat/super-grouping/ToolTimeline.js +69 -36
  257. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  258. package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
  259. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  260. package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
  261. package/dist/chat/super-grouping/activity-timeline.js +47 -12
  262. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  263. package/dist/chat/super-grouping/grouping-function.cjs +4 -0
  264. package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
  265. package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
  266. package/dist/chat/super-grouping/grouping-function.js +5 -1
  267. package/dist/chat/super-grouping/grouping-function.js.map +1 -1
  268. package/dist/chat/super-grouping/index.cjs +6 -0
  269. package/dist/chat/super-grouping/index.cjs.map +1 -1
  270. package/dist/chat/super-grouping/index.d.ts +5 -2
  271. package/dist/chat/super-grouping/index.js +7 -1
  272. package/dist/chat/super-grouping/index.js.map +1 -1
  273. package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
  274. package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
  275. package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
  276. package/dist/chat/super-grouping/tool-part-placement.js +17 -0
  277. package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
  278. package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
  279. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
  280. package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
  281. package/dist/chat/thread-scroll-to-bottom.js +2 -2
  282. package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
  283. package/dist/chat/tooltip-icon-button.cjs +2 -2
  284. package/dist/chat/tooltip-icon-button.cjs.map +1 -1
  285. package/dist/chat/use-athena-voice-live.cjs +11 -0
  286. package/dist/chat/use-athena-voice-live.cjs.map +1 -0
  287. package/dist/chat/use-athena-voice-live.d.ts +11 -0
  288. package/dist/chat/use-athena-voice-live.js +11 -0
  289. package/dist/chat/use-athena-voice-live.js.map +1 -0
  290. package/dist/chat/use-statewire-approval-request.cjs +56 -24
  291. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  292. package/dist/chat/use-statewire-approval-request.d.ts +33 -4
  293. package/dist/chat/use-statewire-approval-request.js +41 -9
  294. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  295. package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
  296. package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
  297. package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
  298. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  299. package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
  300. package/dist/chat-ui/composer/tiptap-composer.js +85 -54
  301. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  302. package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
  303. package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
  304. package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
  305. package/dist/chat-ui/header/conversation-history-panel.js +38 -12
  306. package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
  307. package/dist/chat-ui/index.cjs +18 -0
  308. package/dist/chat-ui/index.cjs.map +1 -1
  309. package/dist/chat-ui/index.d.ts +7 -1
  310. package/dist/chat-ui/index.js +18 -0
  311. package/dist/chat-ui/index.js.map +1 -1
  312. package/dist/chat-ui/mentions/mention-chip.cjs +4 -4
  313. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  314. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
  315. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  316. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
  317. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  318. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
  319. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
  320. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
  321. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  322. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
  323. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
  324. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  325. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
  326. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
  327. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
  328. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
  329. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
  330. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  331. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
  332. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
  333. package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
  334. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
  335. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
  336. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
  337. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  338. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
  339. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
  340. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  341. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
  342. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  343. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
  344. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
  345. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  346. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
  347. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
  348. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
  349. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
  350. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
  351. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
  352. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  353. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
  354. package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
  355. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  356. package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
  357. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
  358. package/dist/chat-ui/mentions/use-mention-asset.cjs +3 -3
  359. package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
  360. package/dist/chat-ui/messages/answer-label.cjs +42 -0
  361. package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
  362. package/dist/chat-ui/messages/answer-label.d.ts +33 -0
  363. package/dist/chat-ui/messages/answer-label.js +42 -0
  364. package/dist/chat-ui/messages/answer-label.js.map +1 -0
  365. package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
  366. package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
  367. package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
  368. package/dist/chat-ui/messages/arrival-animation.js +13 -0
  369. package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
  370. package/dist/chat-ui/messages/continue-pill.cjs +5 -5
  371. package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
  372. package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
  373. package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
  374. package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
  375. package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
  376. package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
  377. package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
  378. package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
  379. package/dist/chat-ui/messages/message-components.cjs +8 -4
  380. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  381. package/dist/chat-ui/messages/message-components.js +5 -1
  382. package/dist/chat-ui/messages/message-components.js.map +1 -1
  383. package/dist/chat-ui/messages/message-images.cjs +66 -0
  384. package/dist/chat-ui/messages/message-images.cjs.map +1 -0
  385. package/dist/chat-ui/messages/message-images.d.ts +16 -0
  386. package/dist/chat-ui/messages/message-images.js +66 -0
  387. package/dist/chat-ui/messages/message-images.js.map +1 -0
  388. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
  389. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  390. package/dist/chat-ui/messages/wake-marker.cjs +3 -3
  391. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
  392. package/dist/chat-ui/rich-text/chat-link.cjs +2 -2
  393. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
  394. package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
  395. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  396. package/dist/chat-ui/rich-text/chat-node-views.cjs +6 -6
  397. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  398. package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
  399. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
  400. package/dist/chat-ui/statewire.cjs +3 -0
  401. package/dist/chat-ui/statewire.cjs.map +1 -1
  402. package/dist/chat-ui/statewire.d.ts +2 -1
  403. package/dist/chat-ui/statewire.js +3 -0
  404. package/dist/chat-ui/statewire.js.map +1 -1
  405. package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
  406. package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
  407. package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
  408. package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
  409. package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
  410. package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
  411. package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
  412. package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
  413. package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
  414. package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
  415. package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
  416. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  417. package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
  418. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  419. package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
  420. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
  421. package/dist/collab/client.cjs +40 -3
  422. package/dist/collab/client.cjs.map +1 -1
  423. package/dist/collab/client.d.ts +25 -0
  424. package/dist/collab/client.js +40 -3
  425. package/dist/collab/client.js.map +1 -1
  426. package/dist/collab/document-status.cjs +150 -0
  427. package/dist/collab/document-status.cjs.map +1 -0
  428. package/dist/collab/document-status.d.ts +68 -0
  429. package/dist/collab/document-status.js +150 -0
  430. package/dist/collab/document-status.js.map +1 -0
  431. package/dist/collab/index.cjs +7 -0
  432. package/dist/collab/index.cjs.map +1 -1
  433. package/dist/collab/index.d.ts +6 -1
  434. package/dist/collab/index.js +7 -0
  435. package/dist/collab/index.js.map +1 -1
  436. package/dist/collab/presence-react.cjs +11 -11
  437. package/dist/collab/presence-react.cjs.map +1 -1
  438. package/dist/collab/react.cjs +6 -6
  439. package/dist/collab/react.cjs.map +1 -1
  440. package/dist/composer/AttachmentContext.cjs +24 -11
  441. package/dist/composer/AttachmentContext.cjs.map +1 -1
  442. package/dist/composer/AttachmentContext.js +18 -5
  443. package/dist/composer/AttachmentContext.js.map +1 -1
  444. package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
  445. package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
  446. package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
  447. package/dist/composer/ComposerAttachmentPreview.js +79 -24
  448. package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
  449. package/dist/composer/ComposerDropZone.cjs +7 -7
  450. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  451. package/dist/composer/FileUploadButton.cjs +37 -22
  452. package/dist/composer/FileUploadButton.cjs.map +1 -1
  453. package/dist/composer/FileUploadButton.d.ts +6 -0
  454. package/dist/composer/FileUploadButton.js +34 -19
  455. package/dist/composer/FileUploadButton.js.map +1 -1
  456. package/dist/composer/QuoteContext.cjs +8 -8
  457. package/dist/composer/QuoteContext.cjs.map +1 -1
  458. package/dist/composer/composer-handoff.cjs +4 -4
  459. package/dist/composer/composer-handoff.cjs.map +1 -1
  460. package/dist/composer/useAppendToComposer.cjs +4 -4
  461. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  462. package/dist/composer/useAttachFiles.cjs +23 -6
  463. package/dist/composer/useAttachFiles.cjs.map +1 -1
  464. package/dist/composer/useAttachFiles.d.ts +15 -7
  465. package/dist/composer/useAttachFiles.js +22 -5
  466. package/dist/composer/useAttachFiles.js.map +1 -1
  467. package/dist/composer/useComposerAttachment.cjs +4 -4
  468. package/dist/composer/useComposerAttachment.cjs.map +1 -1
  469. package/dist/composer/useFileUpload.cjs +21 -16
  470. package/dist/composer/useFileUpload.cjs.map +1 -1
  471. package/dist/composer/useFileUpload.d.ts +12 -0
  472. package/dist/composer/useFileUpload.js +12 -7
  473. package/dist/composer/useFileUpload.js.map +1 -1
  474. package/dist/composer/useReadComposerDraft.cjs +2 -2
  475. package/dist/composer/useReadComposerDraft.cjs.map +1 -1
  476. package/dist/composer/useSendMessage.cjs +4 -4
  477. package/dist/composer/useSendMessage.cjs.map +1 -1
  478. package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
  479. package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
  480. package/dist/dictation/audio-level-history.cjs +3 -3
  481. package/dist/dictation/audio-level-history.cjs.map +1 -1
  482. package/dist/dictation/dictation-controls.cjs +24 -20
  483. package/dist/dictation/dictation-controls.cjs.map +1 -1
  484. package/dist/dictation/dictation-controls.d.ts +6 -1
  485. package/dist/dictation/dictation-controls.js +24 -20
  486. package/dist/dictation/dictation-controls.js.map +1 -1
  487. package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
  488. package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
  489. package/dist/dictation/use-dictation.cjs +22 -22
  490. package/dist/dictation/use-dictation.cjs.map +1 -1
  491. package/dist/index.cjs +26 -2
  492. package/dist/index.cjs.map +1 -1
  493. package/dist/index.d.ts +15 -3
  494. package/dist/index.js +26 -2
  495. package/dist/index.js.map +1 -1
  496. package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
  497. package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
  498. package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
  499. package/dist/keryx-http/src/receive-only-socket.js +40 -0
  500. package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
  501. package/dist/keryx-http/src/update-attributions.cjs +111 -0
  502. package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
  503. package/dist/keryx-http/src/update-attributions.d.ts +75 -0
  504. package/dist/keryx-http/src/update-attributions.js +111 -0
  505. package/dist/keryx-http/src/update-attributions.js.map +1 -0
  506. package/dist/lib/owner-document.cjs +6 -6
  507. package/dist/lib/owner-document.cjs.map +1 -1
  508. package/dist/lib/use-athena-rest-query.cjs +4 -4
  509. package/dist/lib/use-athena-rest-query.cjs.map +1 -1
  510. package/dist/lib/use-document-active.cjs +4 -4
  511. package/dist/lib/use-document-active.cjs.map +1 -1
  512. package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
  513. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
  514. package/dist/offline/offline-history.cjs +7 -7
  515. package/dist/offline/offline-history.cjs.map +1 -1
  516. package/dist/provider/AthenaContext.cjs +3 -3
  517. package/dist/provider/AthenaContext.cjs.map +1 -1
  518. package/dist/provider/AthenaProvider.cjs +116 -79
  519. package/dist/provider/AthenaProvider.cjs.map +1 -1
  520. package/dist/provider/AthenaProvider.js +40 -3
  521. package/dist/provider/AthenaProvider.js.map +1 -1
  522. package/dist/provider/PostHogProvider.cjs +2 -2
  523. package/dist/provider/PostHogProvider.cjs.map +1 -1
  524. package/dist/provider/agent-selection-context.cjs +2 -2
  525. package/dist/provider/agent-selection-context.cjs.map +1 -1
  526. package/dist/provider/chat-mode-context.cjs +2 -2
  527. package/dist/provider/chat-mode-context.cjs.map +1 -1
  528. package/dist/provider/session-persistence-context.cjs +10 -0
  529. package/dist/provider/session-persistence-context.cjs.map +1 -0
  530. package/dist/provider/session-persistence-context.d.ts +15 -0
  531. package/dist/provider/session-persistence-context.js +10 -0
  532. package/dist/provider/session-persistence-context.js.map +1 -0
  533. package/dist/provider/statewire-history-context.cjs +4 -4
  534. package/dist/provider/statewire-history-context.cjs.map +1 -1
  535. package/dist/provider/statewire-lifecycle-context.cjs +3 -3
  536. package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
  537. package/dist/provider/statewire-window-context.cjs +3 -3
  538. package/dist/provider/statewire-window-context.cjs.map +1 -1
  539. package/dist/provider/theme-style-context.cjs +3 -3
  540. package/dist/provider/theme-style-context.cjs.map +1 -1
  541. package/dist/react/package.json.cjs +1 -1
  542. package/dist/react/package.json.js +1 -1
  543. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
  544. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  545. package/dist/runtime/auth-refusal-restart.cjs +7 -7
  546. package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
  547. package/dist/runtime/auth.cjs +13 -13
  548. package/dist/runtime/auth.cjs.map +1 -1
  549. package/dist/runtime/statewire-lifecycle.cjs +1 -0
  550. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  551. package/dist/runtime/statewire-lifecycle.d.ts +3 -1
  552. package/dist/runtime/statewire-lifecycle.js +2 -1
  553. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  554. package/dist/runtime/statewire-server-lane-context.cjs +2 -2
  555. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
  556. package/dist/runtime/statewire-session-lane.cjs +4 -4
  557. package/dist/runtime/statewire-session-lane.cjs.map +1 -1
  558. package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
  559. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  560. package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
  561. package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
  562. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  563. package/dist/styles.css +1 -1
  564. package/dist/threads/Inbox.cjs +8 -8
  565. package/dist/threads/Inbox.cjs.map +1 -1
  566. package/dist/threads/SessionList.cjs +9 -9
  567. package/dist/threads/SessionList.cjs.map +1 -1
  568. package/dist/threads/SessionsPage.cjs +11 -11
  569. package/dist/threads/SessionsPage.cjs.map +1 -1
  570. package/dist/threads/index-triggered-refresh.cjs +10 -10
  571. package/dist/threads/index-triggered-refresh.cjs.map +1 -1
  572. package/dist/threads/mark-viewed-thread-read.cjs +12 -12
  573. package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
  574. package/dist/threads/offline-session-list.cjs +3 -3
  575. package/dist/threads/offline-session-list.cjs.map +1 -1
  576. package/dist/threads/session-list-tab-share.cjs +5 -5
  577. package/dist/threads/session-list-tab-share.cjs.map +1 -1
  578. package/dist/threads/statewire-thread-list.cjs +51 -51
  579. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  580. package/dist/threads/thread-id-context.cjs +5 -5
  581. package/dist/threads/thread-id-context.cjs.map +1 -1
  582. package/dist/threads/use-athena-session-attention.cjs +2 -2
  583. package/dist/threads/use-athena-session-attention.cjs.map +1 -1
  584. package/dist/threads/use-athena-sessions.cjs +10 -10
  585. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  586. package/dist/threads/use-athena-thread-model.cjs +3 -3
  587. package/dist/threads/use-athena-thread-model.cjs.map +1 -1
  588. package/dist/threads/use-rest-conversation-history.cjs +3 -3
  589. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  590. package/dist/threads/use-statewire-conversation-history.cjs +8 -8
  591. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  592. package/dist/threads/use-thread-archive.cjs +9 -9
  593. package/dist/threads/use-thread-archive.cjs.map +1 -1
  594. package/dist/threads/use-thread-favorite.cjs +2 -2
  595. package/dist/threads/use-thread-favorite.cjs.map +1 -1
  596. package/dist/threads/use-thread-field-override.cjs +20 -20
  597. package/dist/threads/use-thread-field-override.cjs.map +1 -1
  598. package/dist/threads/use-thread-read-state.cjs +4 -4
  599. package/dist/threads/use-thread-read-state.cjs.map +1 -1
  600. package/dist/threads/use-thread-rename.cjs +2 -2
  601. package/dist/threads/use-thread-rename.cjs.map +1 -1
  602. package/dist/threads/useAthenaThreadManager.cjs +2 -2
  603. package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
  604. package/dist/tools/NestedPtcMessages.cjs +6 -6
  605. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  606. package/dist/tools/append-document-tool-ui.cjs +7 -7
  607. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  608. package/dist/tools/file-tool-uis.cjs +2 -2
  609. package/dist/tools/file-tool-uis.cjs.map +1 -1
  610. package/dist/tools/misc-tool-uis.cjs +2 -2
  611. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  612. package/dist/tools/primitives.cjs +6 -6
  613. package/dist/tools/primitives.cjs.map +1 -1
  614. package/dist/tools/read-asset-tool-ui.cjs +6 -6
  615. package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
  616. package/dist/tools/subagent-task-tool-ui.cjs +21 -21
  617. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  618. package/dist/tools/test-recording-tool-uis.cjs +16 -16
  619. package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
  620. package/dist/tools/todo-plan-store.cjs +4 -4
  621. package/dist/tools/todo-plan-store.cjs.map +1 -1
  622. package/dist/tools/tool-appearance.cjs +3 -3
  623. package/dist/tools/tool-appearance.cjs.map +1 -1
  624. package/dist/tools/tool-fallback.cjs +14 -14
  625. package/dist/tools/tool-fallback.cjs.map +1 -1
  626. package/dist/tools/tool-uis.cjs +74 -74
  627. package/dist/tools/tool-uis.cjs.map +1 -1
  628. package/dist/tools/use-elapsed-seconds.cjs +3 -3
  629. package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
  630. package/dist/tools/write-todos-tool-ui.cjs +9 -9
  631. package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
  632. package/dist/ui/image-viewer.cjs +382 -0
  633. package/dist/ui/image-viewer.cjs.map +1 -0
  634. package/dist/ui/image-viewer.d.ts +50 -0
  635. package/dist/ui/image-viewer.js +382 -0
  636. package/dist/ui/image-viewer.js.map +1 -0
  637. package/dist/voice/chat.cjs +6 -0
  638. package/dist/voice/chat.cjs.map +1 -1
  639. package/dist/voice/chat.d.ts +1 -1
  640. package/dist/voice/chat.js +8 -2
  641. package/dist/voice/livekit-join.cjs +52 -101
  642. package/dist/voice/livekit-join.cjs.map +1 -1
  643. package/dist/voice/livekit-join.d.ts +1 -6
  644. package/dist/voice/livekit-join.js +52 -101
  645. package/dist/voice/livekit-join.js.map +1 -1
  646. package/dist/voice/livekit.cjs.map +1 -1
  647. package/dist/voice/livekit.d.ts +11 -1
  648. package/dist/voice/livekit.js.map +1 -1
  649. package/dist/voice/use-athena-voice-session.cjs +34 -34
  650. package/dist/voice/use-athena-voice-session.cjs.map +1 -1
  651. package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
  652. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
  653. package/dist/workbench/SessionWorkbench.cjs +22 -22
  654. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  655. package/dist/workbench/session-workbench-context.cjs +3 -3
  656. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  657. package/dist/workbench/session-workbench-panes.cjs +8 -8
  658. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  659. package/dist/workbench/workbench-layout-context.cjs +3 -3
  660. package/dist/workbench/workbench-layout-context.cjs.map +1 -1
  661. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SessionsPage.cjs","sources":["../../src/threads/SessionsPage.tsx"],"sourcesContent":["/**\n * `SessionsPage` — a full-page, Devin-style session list: filter chips that\n * the server applies (status, pull requests, unread, pinned, creator, agent,\n * mode, origin, created / updated date), a title search, display options\n * (sort, direction, grouping, columns), an attention-coloured status column\n * that says what the person must do next, row actions (read, pin, archive)\n * and a CSV export of the loaded rows. Live through the thread-list\n * provider's conversation index; renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport {\n ArchiveIcon,\n CheckIcon,\n DownloadIcon,\n FilterIcon,\n MailIcon,\n MailOpenIcon,\n PinIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n SlidersHorizontalIcon,\n XIcon,\n} from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { SessionListSkeleton, type SessionOpenTarget } from './SessionList';\nimport { pullRequestChip, relativeTime, sessionOriginLabel } from './session-list-model';\nimport { FOCUS_RING_CLASS, PullRequestChip, RowIconButton, StatusChip } from './session-row-parts';\nimport {\n agentLabel,\n channelLabel,\n creatorLabel,\n datePresetBounds,\n groupSessionsBy,\n runStatusLabel,\n SESSIONS_COLUMNS,\n SESSIONS_DATE_PRESETS,\n type SessionsColumnId,\n type SessionsDatePreset,\n type SessionsGroupBy,\n type SessionsLabels,\n sessionsCsv,\n sessionsFilterChips,\n plainExcerpt,\n sessionStatusChip,\n} from './sessions-page-model';\nimport {\n readSessionsPageSettings,\n type SessionsPageDisplay,\n writeSessionsPageSettings,\n} from './sessions-page-storage';\nimport {\n type AthenaSessionsQuery,\n type AthenaSessionsQueryField,\n DEFAULT_COLLAB_CHANNEL,\n normalizeSessionsQuery,\n SESSION_RUN_STATUSES,\n type SessionRunStatus,\n sessionsQueryKey,\n} from './sessions-query';\nimport {\n AthenaSessionsLiveContext,\n type AthenaStatewireThreadListState,\n type AthenaStatewireThreadSummary,\n useAthenaStatewireThreadList,\n} from './statewire-thread-list';\nimport { useAthenaSessions } from './use-athena-sessions';\n\nexport interface SessionsPageProps {\n className?: string;\n /** Heading (default \"Sessions\"). */\n title?: string;\n /**\n * Called after a row is selected (the provider's chat switches to it), so\n * a host can navigate to its chat view.\n */\n onOpenSession?: (target: SessionOpenTarget) => void;\n /** Names for collab agents and channels (filters, the Mode column, CSV); ids show otherwise. */\n labels?: SessionsLabels;\n /**\n * Namespaces what this browser remembers — \"Save as default\" and the\n * display options — so a host with several pages keeps them apart\n * (default `\"default\"`).\n */\n storageKey?: string;\n /** The filters before anything is saved as default. */\n defaultQuery?: AthenaSessionsQuery;\n /** Rows per page (default 50). */\n pageSize?: number;\n /** Offer \"New session\" (default `true`). */\n showNewSession?: boolean;\n /** Called after \"New session\" starts a fresh chat, so a host can show its chat view. */\n onNewSession?: () => void;\n}\n\n/** What each query field is called in notices. */\nconst FIELD_LABEL: Record<AthenaSessionsQueryField, string> = {\n search: 'search',\n collabAgentIds: 'agent',\n collabChannelIds: 'mode',\n startChannels: 'origin',\n createdAfter: 'created date',\n createdBefore: 'created date',\n updatedAfter: 'updated date',\n updatedBefore: 'updated date',\n favoritesOnly: 'pinned',\n unreadOnly: 'unread',\n runStatuses: 'status',\n sessionStatuses: 'session status',\n hasPullRequests: 'pull requests',\n createdByMe: 'creator',\n excludeDismissed: 'dismissed',\n excludeTriggered: 'who started it',\n sort: 'sort',\n direction: 'sort direction',\n};\n\n/** \"agent\", \"agent and mode\", \"agent, mode and unread\". */\nfunction fieldList(fields: readonly AthenaSessionsQueryField[]): string {\n const names = [...new Set(fields.map((field) => FIELD_LABEL[field]))];\n return names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names.at(-1)}`;\n}\n\nconst COLUMN_WIDTH: Record<SessionsColumnId, string> = {\n status: 'w-56',\n origin: 'w-24',\n mode: 'w-28',\n pullRequests: 'w-24',\n creator: 'w-32',\n created: 'w-24',\n updated: 'w-24',\n};\n\n/** Save `text` as a file in the browser. */\nfunction downloadText(filename: string, text: string, type: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(new Blob([text], { type }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.rel = 'noopener';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nconst SECTION_HEADING_CLASS =\n 'px-3 pb-1 pt-3 text-left font-medium text-[11px] text-muted-foreground/70 uppercase tracking-wide';\n\n/** A pressable option in a filter or display menu. */\nconst MenuOption: FC<{\n label: string;\n selected: boolean;\n onSelect: () => void;\n disabled?: boolean;\n role?: 'menuitemcheckbox' | 'menuitemradio';\n}> = ({ label, selected, onSelect, disabled = false, role = 'menuitemcheckbox' }) => (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n disabled={disabled}\n onClick={onSelect}\n className={cn(\n 'flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-xs transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50',\n FOCUS_RING_CLASS,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'flex size-3.5 shrink-0 items-center justify-center rounded-sm border border-border',\n selected && 'border-primary bg-primary text-primary-foreground',\n )}\n >\n {selected ? <CheckIcon className=\"size-3\" /> : null}\n </span>\n <span className=\"truncate\">{label}</span>\n </button>\n);\n\nconst MenuSection: FC<{ title: string; hint?: string | null; children: ReactNode }> = ({\n title,\n hint,\n children,\n}) => (\n <section aria-label={title} className=\"py-1\">\n <h4 className=\"px-2 pb-0.5 font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n {title}\n </h4>\n {hint ? <p className=\"px-2 pb-1 text-[11px] text-muted-foreground\">{hint}</p> : null}\n {children}\n </section>\n);\n\nfunction toggleValue<T extends string>(values: readonly T[] | undefined, value: T): T[] {\n const current = values ?? [];\n return current.includes(value) ? current.filter((item) => item !== value) : [...current, value];\n}\n\nfunction datePresetOf(after: string | undefined, before: string | undefined, presets: Record<SessionsDatePreset, { after?: string; before?: string }>): SessionsDatePreset | null {\n for (const preset of SESSIONS_DATE_PRESETS) {\n const bounds = presets[preset.id];\n if ((bounds.after ?? undefined) === after && (bounds.before ?? undefined) === before) {\n return preset.id;\n }\n }\n return null;\n}\n\ninterface FilterMenuProps {\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n unavailable: ReadonlySet<AthenaSessionsQueryField>;\n agentOptions: readonly string[];\n channelOptions: readonly string[];\n originOptions: readonly string[];\n labels: SessionsLabels | undefined;\n}\n\nconst UNAVAILABLE_HINT = 'This Athena server cannot filter by this yet.';\n\n/** Every filter, stacked by kind; each option toggles at once. */\nconst FilterMenu: FC<FilterMenuProps> = ({\n query,\n setQuery,\n unavailable,\n agentOptions,\n channelOptions,\n originOptions,\n labels,\n}) => {\n // The presets' bounds are captured when the menu opens, so a selected\n // preset stays recognisable while it is open.\n const [presetBounds] = useState(() =>\n Object.fromEntries(\n SESSIONS_DATE_PRESETS.map((preset) => [preset.id, datePresetBounds(preset.id)]),\n ) as Record<SessionsDatePreset, { after?: string; before?: string }>,\n );\n const createdPreset = datePresetOf(query.createdAfter, query.createdBefore, presetBounds);\n const updatedPreset = datePresetOf(query.updatedAfter, query.updatedBefore, presetBounds);\n const setPreset = (\n kind: 'created' | 'updated',\n preset: SessionsDatePreset | null,\n ) =>\n setQuery((current) => {\n const bounds = preset ? presetBounds[preset] : {};\n return kind === 'created'\n ? { ...current, createdAfter: bounds.after, createdBefore: bounds.before }\n : { ...current, updatedAfter: bounds.after, updatedBefore: bounds.before };\n });\n const disabledHint = (field: AthenaSessionsQueryField) =>\n unavailable.has(field) ? UNAVAILABLE_HINT : null;\n\n return (\n <div role=\"menu\" aria-label=\"Filters\" className=\"max-h-[70vh] overflow-y-auto p-1\">\n <MenuSection title=\"Status\" hint={disabledHint('runStatuses')}>\n {SESSION_RUN_STATUSES.map((status) => (\n <MenuOption\n key={status}\n label={runStatusLabel(status)}\n selected={query.runStatuses?.includes(status) ?? false}\n disabled={unavailable.has('runStatuses')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n runStatuses: toggleValue<SessionRunStatus>(current.runStatuses, status),\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Pull requests\" hint={disabledHint('hasPullRequests')}>\n {(\n [\n ['Has pull requests', true],\n ['No pull requests', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.hasPullRequests === value}\n disabled={unavailable.has('hasPullRequests')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n hasPullRequests: current.hasPullRequests === value ? undefined : value,\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Read and pinned\">\n <MenuOption\n label=\"Unread\"\n selected={query.unreadOnly === true}\n disabled={unavailable.has('unreadOnly')}\n onSelect={() => setQuery((current) => ({ ...current, unreadOnly: !current.unreadOnly }))}\n />\n <MenuOption\n label=\"Pinned\"\n selected={query.favoritesOnly === true}\n disabled={unavailable.has('favoritesOnly')}\n onSelect={() =>\n setQuery((current) => ({ ...current, favoritesOnly: !current.favoritesOnly }))\n }\n />\n </MenuSection>\n <MenuSection title=\"Creator\" hint={disabledHint('createdByMe')}>\n {(\n [\n ['You', true],\n ['Shared with you', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.createdByMe === value}\n disabled={unavailable.has('createdByMe')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n createdByMe: current.createdByMe === value ? undefined : value,\n }))\n }\n />\n ))}\n <MenuOption\n label=\"Started by a person\"\n selected={query.excludeTriggered === true}\n onSelect={() =>\n setQuery((current) => ({ ...current, excludeTriggered: !current.excludeTriggered }))\n }\n />\n </MenuSection>\n {agentOptions.length > 0 ? (\n <MenuSection title=\"Agent\" hint={disabledHint('collabAgentIds')}>\n {agentOptions.map((agentId) => (\n <MenuOption\n key={agentId}\n label={agentLabel(agentId, labels)}\n selected={query.collabAgentIds?.includes(agentId) ?? false}\n disabled={unavailable.has('collabAgentIds')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabAgentIds: toggleValue(current.collabAgentIds, agentId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {agentOptions.length > 0 ? (\n <MenuSection\n title=\"Mode\"\n hint={\n disabledHint('collabChannelIds') ??\n (query.collabAgentIds?.length ? null : 'Pick an agent first: a mode is one of its channels.')\n }\n >\n {channelOptions.map((channelId) => (\n <MenuOption\n key={channelId}\n label={channelLabel(channelId, labels)}\n selected={query.collabChannelIds?.includes(channelId) ?? false}\n disabled={unavailable.has('collabChannelIds') || !query.collabAgentIds?.length}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabChannelIds: toggleValue(current.collabChannelIds, channelId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {originOptions.length > 0 ? (\n <MenuSection title=\"Origin\" hint={disabledHint('startChannels')}>\n {originOptions.map((channel) => (\n <MenuOption\n key={channel}\n label={sessionOriginLabel({ startChannel: channel, appId: null, triggerType: null }) ?? channel}\n selected={query.startChannels?.includes(channel) ?? false}\n disabled={unavailable.has('startChannels')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n startChannels: toggleValue(current.startChannels, channel),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n <MenuSection title=\"Created\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={createdPreset === preset.id}\n onSelect={() => setPreset('created', createdPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Updated\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={updatedPreset === preset.id}\n onSelect={() => setPreset('updated', updatedPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst DisplayMenu: FC<{\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n display: SessionsPageDisplay;\n setDisplay: (update: (display: SessionsPageDisplay) => SessionsPageDisplay) => void;\n}> = ({ query, setQuery, display, setDisplay }) => {\n const sort = query.sort ?? 'updated';\n const direction = query.direction ?? 'desc';\n return (\n <div role=\"menu\" aria-label=\"Display options\" className=\"p-1\">\n <MenuSection title=\"Sort by\">\n {(\n [\n ['updated', 'Last updated'],\n ['created', 'Created'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={sort === value}\n onSelect={() => setQuery((current) => ({ ...current, sort: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Order\">\n {(\n [\n ['desc', 'Newest first'],\n ['asc', 'Oldest first'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={direction === value}\n onSelect={() => setQuery((current) => ({ ...current, direction: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Group by\">\n {(\n [\n ['attention', 'What it needs'],\n ['status', 'Run status'],\n ['none', 'No grouping'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={display.groupBy === value}\n onSelect={() => setDisplay((current) => ({ ...current, groupBy: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Columns\">\n {SESSIONS_COLUMNS.map((column) => (\n <MenuOption\n key={column.id}\n label={column.label}\n selected={display.columns.includes(column.id)}\n onSelect={() =>\n setDisplay((current) => ({\n ...current,\n columns: current.columns.includes(column.id)\n ? current.columns.filter((id) => id !== column.id)\n : SESSIONS_COLUMNS.map((candidate) => candidate.id).filter(\n (id) => id === column.id || current.columns.includes(id),\n ),\n }))\n }\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst HEADER_BUTTON_CLASS = cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md border border-border/60 px-2.5 font-medium text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50',\n FOCUS_RING_CLASS,\n);\n\nconst SessionsRow: FC<{\n row: AthenaStatewireThreadSummary;\n columns: readonly SessionsColumnId[];\n isActive: boolean;\n labels: SessionsLabels | undefined;\n list: AthenaStatewireThreadListState;\n onOpen: (row: AthenaStatewireThreadSummary) => void;\n}> = ({ row, columns, isActive, labels, list, onOpen }) => {\n const status = sessionStatusChip(row);\n const excerpt = plainExcerpt(row.preview);\n const chip = pullRequestChip(row.pullRequests);\n const origin = sessionOriginLabel(row);\n const cell = (id: SessionsColumnId): ReactNode => {\n switch (id) {\n case 'status':\n return <StatusChip label={status.label} tone={status.tone} detail={status.detail} />;\n case 'origin':\n return origin ? (\n <span className=\"rounded-full border border-border/60 px-1.5 py-px text-[10px] text-muted-foreground\">\n {origin}\n </span>\n ) : null;\n case 'mode':\n return row.collabAgentId ? (\n <span className=\"truncate text-muted-foreground text-xs\">\n {channelLabel(row.collabChannelId, labels)}\n </span>\n ) : null;\n case 'pullRequests':\n return chip ? <PullRequestChip chip={chip} pullRequests={row.pullRequests ?? []} /> : null;\n case 'creator':\n return (\n <span className=\"truncate text-muted-foreground text-xs\">{creatorLabel(row.createdByMe)}</span>\n );\n case 'created':\n return (\n <span className=\"text-muted-foreground text-xs\">\n {row.createdAt ? relativeTime(row.createdAt) : ''}\n </span>\n );\n case 'updated':\n return <span className=\"text-muted-foreground text-xs\">{relativeTime(row.updatedAt)}</span>;\n }\n };\n return (\n <tr\n data-thread-id={row.id}\n data-active={isActive || undefined}\n data-unread={row.isUnread || undefined}\n onClick={() => onOpen(row)}\n className={cn(\n 'group cursor-pointer border-border/40 border-b transition-colors hover:bg-muted/40',\n isActive && 'bg-muted',\n )}\n >\n <td className=\"min-w-0 py-2 pr-2 pl-3 align-top\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span\n role={row.isUnread ? 'img' : undefined}\n aria-label={row.isUnread ? 'Unread' : undefined}\n aria-hidden={row.isUnread ? undefined : true}\n className={cn('size-2 shrink-0 rounded-full', row.isUnread ? 'bg-primary' : 'bg-transparent')}\n />\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row);\n }}\n className={cn(\n 'min-w-0 truncate text-left text-foreground text-sm',\n row.isUnread ? 'font-semibold' : 'font-medium',\n FOCUS_RING_CLASS,\n )}\n >\n {row.title ?? 'Untitled'}\n </button>\n {row.isFavorited ? (\n <PinIcon role=\"img\" aria-label=\"Pinned\" className=\"size-3 shrink-0 fill-current text-muted-foreground\" />\n ) : null}\n </div>\n {excerpt ? <p className=\"mt-0.5 truncate pl-4 text-muted-foreground text-xs\">{excerpt}</p> : null}\n </td>\n {columns.map((id) => (\n <td key={id} data-column={id} className=\"min-w-0 truncate px-2 py-2 align-top\">\n {cell(id)}\n </td>\n ))}\n <td className=\"py-1.5 pr-2 align-top\">\n <div data-row-actions className=\"flex items-center justify-end gap-0.5\">\n <RowIconButton\n label={row.isUnread ? 'Mark read' : 'Mark unread'}\n action=\"read-state\"\n pending={list.readStatePendingThreadIds.has(row.id)}\n onClick={() =>\n list.setReadState({ threadId: row.id, isUnread: !row.isUnread, updatedAt: row.updatedAt })\n }\n >\n {row.isUnread ? <MailOpenIcon className=\"size-3.5\" aria-hidden /> : <MailIcon className=\"size-3.5\" aria-hidden />}\n </RowIconButton>\n {list.favoriteToggleAvailable ? (\n <RowIconButton\n label={row.isFavorited ? 'Unpin session' : 'Pin session'}\n action=\"pin\"\n pressed={row.isFavorited}\n pending={list.favoritePendingThreadIds.has(row.id)}\n onClick={() => list.setFavorited({ threadId: row.id, isFavorited: !row.isFavorited })}\n >\n <PinIcon className={cn('size-3.5', row.isFavorited && 'fill-current')} aria-hidden />\n </RowIconButton>\n ) : null}\n {list.archiveAvailable ? (\n <RowIconButton\n label=\"Archive session\"\n action=\"archive\"\n pending={list.archivePendingThreadIds.has(row.id)}\n onClick={() => list.archiveThread(row.id)}\n >\n <ArchiveIcon className=\"size-3.5\" aria-hidden />\n </RowIconButton>\n ) : null}\n </div>\n </td>\n </tr>\n );\n};\n\nfunction SessionsPageBody({\n className,\n title = 'Sessions',\n onOpenSession,\n labels,\n storageKey = 'default',\n defaultQuery,\n pageSize,\n showNewSession = true,\n onNewSession,\n list,\n}: SessionsPageProps & { list: AthenaStatewireThreadListState }) {\n const [initial] = useState(() => readSessionsPageSettings(storageKey));\n const [savedDefault, setSavedDefault] = useState<AthenaSessionsQuery | null>(initial.defaultQuery);\n const [query, setQueryState] = useState<AthenaSessionsQuery>(\n () => initial.defaultQuery ?? normalizeSessionsQuery(defaultQuery ?? {}),\n );\n const [display, setDisplayState] = useState<SessionsPageDisplay>(initial.display);\n const [searchInput, setSearchInput] = useState(query.search ?? '');\n\n const setQuery = (update: (current: AthenaSessionsQuery) => AthenaSessionsQuery) =>\n setQueryState((current) => normalizeSessionsQuery(update(current)));\n const setDisplay = (update: (current: SessionsPageDisplay) => SessionsPageDisplay) =>\n setDisplayState((current) => {\n const next = update(current);\n writeSessionsPageSettings(storageKey, { defaultQuery: savedDefault, display: next });\n return next;\n });\n\n // The search box types freely; the list follows a beat later.\n useEffect(() => {\n const handle = setTimeout(() => {\n setQueryState((current) => {\n const search = searchInput.trim();\n if ((current.search ?? '') === search) return current;\n return normalizeSessionsQuery({ ...current, search });\n });\n }, 250);\n return () => clearTimeout(handle);\n }, [searchInput]);\n\n const sessions = useAthenaSessions({ query, ...(pageSize ? { pageSize } : {}) });\n const unavailable = useMemo(\n () => new Set([...sessions.unsupportedFields, ...sessions.unavailableFields]),\n [sessions.unsupportedFields, sessions.unavailableFields],\n );\n\n // Filter options: every agent, channel and origin this page has shown, so\n // narrowing the list never hides the option that would widen it again.\n const seenRef = useRef({ agents: new Set<string>(), channels: new Set<string>(), origins: new Set<string>() });\n for (const row of sessions.rows) {\n if (row.collabAgentId) {\n seenRef.current.agents.add(row.collabAgentId);\n seenRef.current.channels.add(row.collabChannelId || DEFAULT_COLLAB_CHANNEL);\n }\n if (row.startChannel) seenRef.current.origins.add(row.startChannel);\n }\n const agentOptions = [\n ...new Set([...Object.keys(labels?.agents ?? {}), ...seenRef.current.agents, ...(query.collabAgentIds ?? [])]),\n ];\n const channelOptions = [\n ...new Set([\n DEFAULT_COLLAB_CHANNEL,\n ...Object.keys(labels?.channels ?? {}),\n ...seenRef.current.channels,\n ...(query.collabChannelIds ?? []),\n ]),\n ];\n const originOptions = [...new Set([...seenRef.current.origins, ...(query.startChannels ?? [])])];\n\n const chips = sessionsFilterChips(query, labels);\n const sections = groupSessionsBy(sessions.rows, display.groupBy);\n const columns = SESSIONS_COLUMNS.map((column) => column.id).filter((id) => display.columns.includes(id));\n const { search: _search, ...queryWithoutSearch } = query;\n const isSavedDefault =\n savedDefault !== null && sessionsQueryKey(savedDefault) === sessionsQueryKey(queryWithoutSearch);\n const hasFilters = chips.length > 0;\n\n const open = (row: AthenaStatewireThreadSummary) => {\n list.selectThread(row.id);\n onOpenSession?.({ threadId: row.id, title: row.title });\n };\n const saveAsDefault = () => {\n const saved = normalizeSessionsQuery(queryWithoutSearch);\n setSavedDefault(saved);\n writeSessionsPageSettings(storageKey, { defaultQuery: saved, display });\n };\n const resetToDefault = () => {\n setQueryState({ ...(savedDefault ?? normalizeSessionsQuery(defaultQuery ?? {})) });\n setSearchInput('');\n };\n const clearFilters = () => {\n setQuery((current) => ({ sort: current.sort, direction: current.direction, search: current.search }));\n };\n const removeChip = (field: AthenaSessionsQueryField) =>\n setQuery((current) => {\n const next: AthenaSessionsQuery = { ...current, [field]: undefined };\n if (field === 'collabAgentIds') next.collabChannelIds = undefined;\n return next;\n });\n const exportCsv = () =>\n downloadText(\n `sessions-${new Date().toISOString().slice(0, 10)}.csv`,\n sessionsCsv(sessions.rows, labels),\n 'text/csv;charset=utf-8',\n );\n\n // Skeletons only while there is nothing to show; a changed query keeps the\n // previous rows (narrowed by it) until its own page answers.\n const showSkeleton =\n sessions.rows.length === 0 && (!sessions.hasResolvedFirstPage || sessions.isFetching);\n\n return (\n <div\n data-testid=\"sessions-page\"\n className={cn('athena-sdk-chrome flex min-h-0 flex-col gap-3 p-4', className)}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"font-semibold text-base text-foreground\">{title}</h2>\n <span data-testid=\"sessions-count\" className=\"text-muted-foreground text-xs\">\n {sessions.rows.length}\n {sessions.hasNextPage ? '+' : ''}\n </span>\n <div className=\"flex-1\" />\n <label className=\"relative block w-64 max-w-full\">\n <SearchIcon className=\"pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n type=\"search\"\n value={searchInput}\n onChange={(event) => setSearchInput(event.target.value)}\n placeholder=\"Search sessions…\"\n className=\"h-8 w-full rounded-md border border-border/60 bg-muted/40 pr-2 pl-8 text-sm outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS} aria-label=\"Display options\">\n <SlidersHorizontalIcon className=\"size-3.5\" aria-hidden />\n Display\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-56\">\n <DisplayMenu query={query} setQuery={setQuery} display={display} setDisplay={setDisplay} />\n </PopoverContent>\n </Popover>\n <button\n type=\"button\"\n onClick={exportCsv}\n disabled={sessions.rows.length === 0}\n className={HEADER_BUTTON_CLASS}\n title=\"Export the loaded sessions as CSV\"\n >\n <DownloadIcon className=\"size-3.5\" aria-hidden />\n Export CSV\n </button>\n <button\n type=\"button\"\n onClick={sessions.refresh}\n disabled={sessions.isFetching}\n className={HEADER_BUTTON_CLASS}\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n >\n <RefreshCwIcon className={cn('size-3.5', sessions.isFetching && 'animate-spin')} aria-hidden />\n </button>\n {showNewSession ? (\n <button\n type=\"button\"\n onClick={() => {\n list.newThread();\n onNewSession?.();\n }}\n className={cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 font-medium text-primary-foreground text-xs transition-colors hover:bg-primary/90',\n FOCUS_RING_CLASS,\n )}\n >\n <PlusIcon className=\"size-3.5\" aria-hidden />\n New session\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid=\"sessions-filters\">\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS}>\n <FilterIcon className=\"size-3.5\" aria-hidden />\n Filter\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64\">\n <FilterMenu\n query={query}\n setQuery={setQuery}\n unavailable={unavailable}\n agentOptions={agentOptions}\n channelOptions={channelOptions}\n originOptions={originOptions}\n labels={labels}\n />\n </PopoverContent>\n </Popover>\n {chips.map((chip) => (\n <span\n key={chip.field + chip.label}\n data-filter-chip={chip.field}\n className=\"inline-flex h-7 items-center gap-1 rounded-full border border-border/60 bg-muted/40 pr-1 pl-2.5 text-foreground text-xs\"\n >\n {chip.label}\n <button\n type=\"button\"\n aria-label={`Remove filter ${chip.label}`}\n onClick={() => removeChip(chip.field)}\n className={cn('rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground', FOCUS_RING_CLASS)}\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </span>\n ))}\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Clear\n </button>\n ) : null}\n <div className=\"flex-1\" />\n {savedDefault !== null && !isSavedDefault ? (\n <button type=\"button\" onClick={resetToDefault} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Reset to default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={saveAsDefault}\n disabled={isSavedDefault}\n className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {isSavedDefault ? 'Saved as default' : 'Save as default'}\n </button>\n </div>\n\n {sessions.degradedFields.length > 0 || sessions.unavailableFields.length > 0 ? (\n <p\n role=\"status\"\n data-testid=\"sessions-degraded\"\n className=\"rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-amber-900 text-xs\"\n >\n {sessions.degradedFields.length > 0\n ? `This Athena server cannot filter by ${fieldList(sessions.degradedFields)} yet, so they apply to the sessions loaded so far. `\n : ''}\n {sessions.unavailableFields.length > 0\n ? `Filtering by ${fieldList(sessions.unavailableFields)} is not available on this server yet and is off.`\n : ''}\n </p>\n ) : null}\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {showSkeleton ? (\n <SessionListSkeleton rows={6} />\n ) : sections.length === 0 ? (\n <div data-testid=\"sessions-empty\" className=\"flex flex-col items-center gap-2 py-12 text-center\">\n <p className=\"text-muted-foreground text-sm\">\n {hasFilters || query.search ? 'No sessions match these filters.' : 'No sessions yet.'}\n </p>\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={HEADER_BUTTON_CLASS}>\n Clear filters\n </button>\n ) : null}\n </div>\n ) : (\n <table className=\"w-full table-fixed border-collapse text-sm\" aria-busy={sessions.isFetching || undefined}>\n <thead>\n <tr className=\"border-border/60 border-b text-left text-[11px] text-muted-foreground uppercase tracking-wide\">\n <th scope=\"col\" className=\"py-2 pl-7 font-medium\">\n Session\n </th>\n {columns.map((id) => (\n <th key={id} scope=\"col\" className={cn('px-2 py-2 font-medium', COLUMN_WIDTH[id])}>\n {SESSIONS_COLUMNS.find((column) => column.id === id)?.label}\n </th>\n ))}\n <th scope=\"col\" className=\"w-24 py-2 pr-2\">\n <span className=\"sr-only\">Actions</span>\n </th>\n </tr>\n </thead>\n {sections.map((section) => (\n <tbody key={section.key} data-group={section.label ?? undefined}>\n {section.label ? (\n <tr>\n <th colSpan={columns.length + 2} scope=\"colgroup\" className={SECTION_HEADING_CLASS}>\n {section.label}\n <span className=\"ml-1.5 font-normal normal-case tracking-normal\">{section.items.length}</span>\n </th>\n </tr>\n ) : null}\n {section.items.map((row) => (\n <SessionsRow\n key={row.id}\n row={row}\n columns={columns}\n isActive={row.id === list.activeThreadId}\n labels={labels}\n list={list}\n onOpen={open}\n />\n ))}\n </tbody>\n ))}\n </table>\n )}\n {sessions.hasNextPage && !showSkeleton ? (\n <button\n type=\"button\"\n onClick={sessions.fetchNextPage}\n disabled={sessions.isFetchingNextPage}\n className={cn('mt-2 w-full rounded-md py-2 text-muted-foreground text-xs transition-colors hover:bg-muted disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {sessions.isFetchingNextPage ? 'Loading…' : sessions.isFetchNextPageError ? 'Retry loading more' : 'Load more'}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * A full-page session list with server-side filters, display options, an\n * attention-coloured status column and CSV export. Renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nexport function SessionsPage(props: SessionsPageProps) {\n const list = useAthenaStatewireThreadList();\n const live = useContext(AthenaSessionsLiveContext);\n if (!list || !live) return null;\n return <SessionsPageBody {...props} list={list} />;\n}\n"],"names":["jsxs","cn","FOCUS_RING_CLASS","jsx","CheckIcon","SESSIONS_DATE_PRESETS","useState","datePresetBounds","SESSION_RUN_STATUSES","runStatusLabel","_a","agentLabel","channelLabel","sessionOriginLabel","SESSIONS_COLUMNS","sessionStatusChip","plainExcerpt","pullRequestChip","StatusChip","PullRequestChip","creatorLabel","relativeTime","PinIcon","RowIconButton","MailOpenIcon","MailIcon","ArchiveIcon","readSessionsPageSettings","normalizeSessionsQuery","writeSessionsPageSettings","useEffect","useAthenaSessions","useMemo","useRef","DEFAULT_COLLAB_CHANNEL","sessionsFilterChips","groupSessionsBy","sessionsQueryKey","sessionsCsv","SearchIcon","Popover","PopoverTrigger","SlidersHorizontalIcon","PopoverContent","DownloadIcon","RefreshCwIcon","PlusIcon","FilterIcon","XIcon","SessionListSkeleton","useAthenaStatewireThreadList","useContext","AthenaSessionsLiveContext"],"mappings":";;;;;;;;;;;;;;;AAmGA,MAAM,cAAwD;AAAA,EAC5D,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,WAAW;AACb;AAGA,SAAS,UAAU,QAAqD;AACtE,QAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC;AACpE,SAAO,MAAM,UAAU,IAAK,MAAM,CAAC,KAAK,KAAM,GAAG,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,QAAQ,MAAM,GAAG,EAAE,CAAC;AACpG;AAEA,MAAM,eAAiD;AAAA,EACrD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,cAAc;AAAA,EACd,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AACX;AAGA,SAAS,aAAa,UAAkB,MAAc,MAAoB;AACxE,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,KAAA,CAAM,CAAC;AAC1D,QAAM,SAAS,SAAS,cAAc,GAAG;AACzC,SAAO,OAAO;AACd,SAAO,WAAW;AAClB,SAAO,MAAM;AACb,WAAS,KAAK,YAAY,MAAM;AAChC,SAAO,MAAA;AACP,SAAO,OAAA;AACP,aAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,CAAC;AAC9C;AAEA,MAAM,wBACJ;AAGF,MAAM,aAMD,CAAC,EAAE,OAAO,UAAU,UAAU,WAAW,OAAO,OAAO,mBAAA,MAC1DA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,MAAK;AAAA,IACL;AAAA,IACA,gBAAc;AAAA,IACd;AAAA,IACA,SAAS;AAAA,IACT,WAAWC,OAAAA;AAAAA,MACT;AAAA,MACAC,gBAAAA;AAAAA,IAAA;AAAA,IAGF,UAAA;AAAA,MAAAC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,eAAY;AAAA,UACZ,WAAWF,OAAAA;AAAAA,YACT;AAAA,YACA,YAAY;AAAA,UAAA;AAAA,UAGb,UAAA,WAAWE,+BAACC,YAAAA,WAAA,EAAU,WAAU,UAAS,IAAK;AAAA,QAAA;AAAA,MAAA;AAAA,MAEjDD,2BAAAA,IAAC,QAAA,EAAK,WAAU,YAAY,UAAA,MAAA,CAAM;AAAA,IAAA;AAAA,EAAA;AACpC;AAGF,MAAM,cAAgF,CAAC;AAAA,EACrF;AAAA,EACA;AAAA,EACA;AACF,MACEH,2BAAAA,KAAC,WAAA,EAAQ,cAAY,OAAO,WAAU,QACpC,UAAA;AAAA,EAAAG,2BAAAA,IAAC,MAAA,EAAG,WAAU,qFACX,UAAA,OACH;AAAA,EACC,OAAOA,2BAAAA,IAAC,KAAA,EAAE,WAAU,+CAA+C,gBAAK,IAAO;AAAA,EAC/E;AAAA,GACH;AAGF,SAAS,YAA8B,QAAkC,OAAe;AACtF,QAAM,UAAU,UAAU,CAAA;AAC1B,SAAO,QAAQ,SAAS,KAAK,IAAI,QAAQ,OAAO,CAAC,SAAS,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,KAAK;AAChG;AAEA,SAAS,aAAa,OAA2B,QAA4B,SAAqG;AAChL,aAAW,UAAUE,yCAAuB;AAC1C,UAAM,SAAS,QAAQ,OAAO,EAAE;AAChC,SAAK,OAAO,SAAS,YAAe,UAAU,OAAO,UAAU,YAAe,QAAQ;AACpF,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAYA,MAAM,mBAAmB;AAGzB,MAAM,aAAkC,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;;AAGJ,QAAM,CAAC,YAAY,IAAIC,MAAAA;AAAAA,IAAS,MAC9B,OAAO;AAAA,MACLD,wCAAsB,IAAI,CAAC,WAAW,CAAC,OAAO,IAAIE,kBAAAA,iBAAiB,OAAO,EAAE,CAAC,CAAC;AAAA,IAAA;AAAA,EAChF;AAEF,QAAM,gBAAgB,aAAa,MAAM,cAAc,MAAM,eAAe,YAAY;AACxF,QAAM,gBAAgB,aAAa,MAAM,cAAc,MAAM,eAAe,YAAY;AACxF,QAAM,YAAY,CAChB,MACA,WAEA,SAAS,CAAC,YAAY;AACpB,UAAM,SAAS,SAAS,aAAa,MAAM,IAAI,CAAA;AAC/C,WAAO,SAAS,YACZ,EAAE,GAAG,SAAS,cAAc,OAAO,OAAO,eAAe,OAAO,WAChE,EAAE,GAAG,SAAS,cAAc,OAAO,OAAO,eAAe,OAAO,OAAA;AAAA,EACtE,CAAC;AACH,QAAM,eAAe,CAAC,UACpB,YAAY,IAAI,KAAK,IAAI,mBAAmB;AAE9C,yCACG,OAAA,EAAI,MAAK,QAAO,cAAW,WAAU,WAAU,oCAC9C,UAAA;AAAA,IAAAJ,2BAAAA,IAAC,aAAA,EAAY,OAAM,UAAS,MAAM,aAAa,aAAa,GACzD,UAAAK,cAAAA,qBAAqB,IAAI,CAAC,WAAA;;AACzBL,wCAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAOM,kBAAAA,eAAe,MAAM;AAAA,UAC5B,YAAUC,MAAA,MAAM,gBAAN,gBAAAA,IAAmB,SAAS,YAAW;AAAA,UACjD,UAAU,YAAY,IAAI,aAAa;AAAA,UACvC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,aAAa,YAA8B,QAAQ,aAAa,MAAM;AAAA,UAAA,EACtE;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH;AAAA,mCACC,aAAA,EAAY,OAAM,iBAAgB,MAAM,aAAa,iBAAiB,GAEnE,UAAA;AAAA,MACE,CAAC,qBAAqB,IAAI;AAAA,MAC1B,CAAC,oBAAoB,KAAK;AAAA,IAAA,EAE5B,IAAI,CAAC,CAAC,OAAO,KAAK,MAClBP,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,MAAM,oBAAoB;AAAA,QACpC,UAAU,YAAY,IAAI,iBAAiB;AAAA,QAC3C,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,UACrB,GAAG;AAAA,UACH,iBAAiB,QAAQ,oBAAoB,QAAQ,SAAY;AAAA,QAAA,EACjE;AAAA,MAAA;AAAA,MATC;AAAA,IAAA,CAYR,GACH;AAAA,IACAH,2BAAAA,KAAC,aAAA,EAAY,OAAM,mBACjB,UAAA;AAAA,MAAAG,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,eAAe;AAAA,UAC/B,UAAU,YAAY,IAAI,YAAY;AAAA,UACtC,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,YAAY,CAAC,QAAQ,aAAa;AAAA,QAAA;AAAA,MAAA;AAAA,MAEzFA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,kBAAkB;AAAA,UAClC,UAAU,YAAY,IAAI,eAAe;AAAA,UACzC,UAAU,MACR,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,eAAe,CAAC,QAAQ,gBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAEjF,GACF;AAAA,oCACC,aAAA,EAAY,OAAM,WAAU,MAAM,aAAa,aAAa,GAEzD,UAAA;AAAA,MAAA;AAAA,QACE,CAAC,OAAO,IAAI;AAAA,QACZ,CAAC,mBAAmB,KAAK;AAAA,MAAA,EAE3B,IAAI,CAAC,CAAC,OAAO,KAAK,MAClBA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL;AAAA,UACA,UAAU,MAAM,gBAAgB;AAAA,UAChC,UAAU,YAAY,IAAI,aAAa;AAAA,UACvC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,aAAa,QAAQ,gBAAgB,QAAQ,SAAY;AAAA,UAAA,EACzD;AAAA,QAAA;AAAA,QATC;AAAA,MAAA,CAYR;AAAA,MACDA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,qBAAqB;AAAA,UACrC,UAAU,MACR,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,kBAAkB,CAAC,QAAQ,mBAAmB;AAAA,QAAA;AAAA,MAAA;AAAA,IAEvF,GACF;AAAA,IACC,aAAa,SAAS,IACrBA,2BAAAA,IAAC,eAAY,OAAM,SAAQ,MAAM,aAAa,gBAAgB,GAC3D,UAAA,aAAa,IAAI,CAAC;;AACjBA,wCAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAOQ,kBAAAA,WAAW,SAAS,MAAM;AAAA,UACjC,YAAUD,MAAA,MAAM,mBAAN,gBAAAA,IAAsB,SAAS,aAAY;AAAA,UACrD,UAAU,YAAY,IAAI,gBAAgB;AAAA,UAC1C,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,gBAAgB,YAAY,QAAQ,gBAAgB,OAAO;AAAA,UAAA,EAC3D;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH,IACE;AAAA,IACH,aAAa,SAAS,IACrBP,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,MACE,aAAa,kBAAkB,QAC9B,WAAM,mBAAN,mBAAsB,UAAS,OAAO;AAAA,QAGxC,UAAA,eAAe,IAAI,CAAC,cAAA;;AACnBA,4CAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC,OAAOS,kBAAAA,aAAa,WAAW,MAAM;AAAA,cACrC,YAAUF,MAAA,MAAM,qBAAN,gBAAAA,IAAwB,SAAS,eAAc;AAAA,cACzD,UAAU,YAAY,IAAI,kBAAkB,KAAK,GAAC,WAAM,mBAAN,mBAAsB;AAAA,cACxE,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,gBACrB,GAAG;AAAA,gBACH,kBAAkB,YAAY,QAAQ,kBAAkB,SAAS;AAAA,cAAA,EACjE;AAAA,YAAA;AAAA,YARC;AAAA,UAAA;AAAA,SAWR;AAAA,MAAA;AAAA,IAAA,IAED;AAAA,IACH,cAAc,SAAS,IACtBP,2BAAAA,IAAC,eAAY,OAAM,UAAS,MAAM,aAAa,eAAe,GAC3D,UAAA,cAAc,IAAI,CAAC;;AAClBA,wCAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAOU,iBAAAA,mBAAmB,EAAE,cAAc,SAAS,OAAO,MAAM,aAAa,KAAA,CAAM,KAAK;AAAA,UACxF,YAAUH,MAAA,MAAM,kBAAN,gBAAAA,IAAqB,SAAS,aAAY;AAAA,UACpD,UAAU,YAAY,IAAI,eAAe;AAAA,UACzC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,eAAe,YAAY,QAAQ,eAAe,OAAO;AAAA,UAAA,EACzD;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH,IACE;AAAA,mCACH,aAAA,EAAY,OAAM,WAChB,UAAAL,wCAAsB,IAAI,CAAC,WAC1BF,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,UAAU,kBAAkB,OAAO;AAAA,QACnC,UAAU,MAAM,UAAU,WAAW,kBAAkB,OAAO,KAAK,OAAO,OAAO,EAAE;AAAA,MAAA;AAAA,MAJ9E,OAAO;AAAA,IAAA,CAMf,GACH;AAAA,mCACC,aAAA,EAAY,OAAM,WAChB,UAAAE,wCAAsB,IAAI,CAAC,WAC1BF,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,UAAU,kBAAkB,OAAO;AAAA,QACnC,UAAU,MAAM,UAAU,WAAW,kBAAkB,OAAO,KAAK,OAAO,OAAO,EAAE;AAAA,MAAA;AAAA,MAJ9E,OAAO;AAAA,IAAA,CAMf,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,MAAM,cAKD,CAAC,EAAE,OAAO,UAAU,SAAS,iBAAiB;AACjD,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,YAAY,MAAM,aAAa;AACrC,yCACG,OAAA,EAAI,MAAK,QAAO,cAAW,mBAAkB,WAAU,OACtD,UAAA;AAAA,IAAAA,2BAAAA,IAAC,aAAA,EAAY,OAAM,WAEf,UAAA;AAAA,MACE,CAAC,WAAW,cAAc;AAAA,MAC1B,CAAC,WAAW,SAAS;AAAA,IAAA,EAEvB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClBA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,SAAS;AAAA,QACnB,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,MAAM,QAAQ;AAAA,MAAA;AAAA,MAJ9D;AAAA,IAAA,CAMR,GACH;AAAA,IACAA,2BAAAA,IAAC,aAAA,EAAY,OAAM,SAEf,UAAA;AAAA,MACE,CAAC,QAAQ,cAAc;AAAA,MACvB,CAAC,OAAO,cAAc;AAAA,IAAA,EAExB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClBA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,cAAc;AAAA,QACxB,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,WAAW,QAAQ;AAAA,MAAA;AAAA,MAJnE;AAAA,IAAA,CAMR,GACH;AAAA,IACAA,2BAAAA,IAAC,aAAA,EAAY,OAAM,YAEf,UAAA;AAAA,MACE,CAAC,aAAa,eAAe;AAAA,MAC7B,CAAC,UAAU,YAAY;AAAA,MACvB,CAAC,QAAQ,aAAa;AAAA,IAAA,EAExB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClBA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,QAAQ,YAAY;AAAA,QAC9B,UAAU,MAAM,WAAW,CAAC,aAAa,EAAE,GAAG,SAAS,SAAS,QAAQ;AAAA,MAAA;AAAA,MAJnE;AAAA,IAAA,CAMR,GACH;AAAA,mCACC,aAAA,EAAY,OAAM,WAChB,UAAAW,mCAAiB,IAAI,CAAC,WACrBX,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAEC,OAAO,OAAO;AAAA,QACd,UAAU,QAAQ,QAAQ,SAAS,OAAO,EAAE;AAAA,QAC5C,UAAU,MACR,WAAW,CAAC,aAAa;AAAA,UACvB,GAAG;AAAA,UACH,SAAS,QAAQ,QAAQ,SAAS,OAAO,EAAE,IACvC,QAAQ,QAAQ,OAAO,CAAC,OAAO,OAAO,OAAO,EAAE,IAC/CW,kBAAAA,iBAAiB,IAAI,CAAC,cAAc,UAAU,EAAE,EAAE;AAAA,YAChD,CAAC,OAAO,OAAO,OAAO,MAAM,QAAQ,QAAQ,SAAS,EAAE;AAAA,UAAA;AAAA,QACzD,EACJ;AAAA,MAAA;AAAA,MAXC,OAAO;AAAA,IAAA,CAcf,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,MAAM,sBAAsBb,OAAAA;AAAAA,EAC1B;AAAA,EACAC,gBAAAA;AACF;AAEA,MAAM,cAOD,CAAC,EAAE,KAAK,SAAS,UAAU,QAAQ,MAAM,aAAa;AACzD,QAAM,SAASa,kBAAAA,kBAAkB,GAAG;AACpC,QAAM,UAAUC,kBAAAA,aAAa,IAAI,OAAO;AACxC,QAAM,OAAOC,iBAAAA,gBAAgB,IAAI,YAAY;AAC7C,QAAM,SAASJ,iBAAAA,mBAAmB,GAAG;AACrC,QAAM,OAAO,CAAC,OAAoC;AAChD,YAAQ,IAAA;AAAA,MACN,KAAK;AACH,eAAOV,2BAAAA,IAACe,gBAAAA,YAAA,EAAW,OAAO,OAAO,OAAO,MAAM,OAAO,MAAM,QAAQ,OAAO,OAAA,CAAQ;AAAA,MACpF,KAAK;AACH,eAAO,SACLf,+BAAC,QAAA,EAAK,WAAU,uFACb,kBACH,IACE;AAAA,MACN,KAAK;AACH,eAAO,IAAI,gBACTA,2BAAAA,IAAC,QAAA,EAAK,WAAU,0CACb,UAAAS,kBAAAA,aAAa,IAAI,iBAAiB,MAAM,EAAA,CAC3C,IACE;AAAA,MACN,KAAK;AACH,eAAO,sCAAQO,gBAAAA,iBAAA,EAAgB,MAAY,cAAc,IAAI,gBAAgB,GAAC,CAAG,IAAK;AAAA,MACxF,KAAK;AACH,8CACG,QAAA,EAAK,WAAU,0CAA0C,UAAAC,+BAAa,IAAI,WAAW,GAAE;AAAA,MAE5F,KAAK;AACH,eACEjB,2BAAAA,IAAC,QAAA,EAAK,WAAU,iCACb,UAAA,IAAI,YAAYkB,iBAAAA,aAAa,IAAI,SAAS,IAAI,GAAA,CACjD;AAAA,MAEJ,KAAK;AACH,8CAAQ,QAAA,EAAK,WAAU,iCAAiC,UAAAA,8BAAa,IAAI,SAAS,GAAE;AAAA,IAAA;AAAA,EAE1F;AACA,SACErB,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,kBAAgB,IAAI;AAAA,MACpB,eAAa,YAAY;AAAA,MACzB,eAAa,IAAI,YAAY;AAAA,MAC7B,SAAS,MAAM,OAAO,GAAG;AAAA,MACzB,WAAWC,OAAAA;AAAAA,QACT;AAAA,QACA,YAAY;AAAA,MAAA;AAAA,MAGd,UAAA;AAAA,QAAAD,2BAAAA,KAAC,MAAA,EAAG,WAAU,oCACZ,UAAA;AAAA,UAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,YAAAG,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAM,IAAI,WAAW,QAAQ;AAAA,gBAC7B,cAAY,IAAI,WAAW,WAAW;AAAA,gBACtC,eAAa,IAAI,WAAW,SAAY;AAAA,gBACxC,WAAWF,OAAAA,GAAG,gCAAgC,IAAI,WAAW,eAAe,gBAAgB;AAAA,cAAA;AAAA,YAAA;AAAA,YAE9FE,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,CAAC,UAAU;AAClB,wBAAM,gBAAA;AACN,yBAAO,GAAG;AAAA,gBACZ;AAAA,gBACA,WAAWF,OAAAA;AAAAA,kBACT;AAAA,kBACA,IAAI,WAAW,kBAAkB;AAAA,kBACjCC,gBAAAA;AAAAA,gBAAA;AAAA,gBAGD,cAAI,SAAS;AAAA,cAAA;AAAA,YAAA;AAAA,YAEf,IAAI,cACHC,+BAACmB,YAAAA,SAAA,EAAQ,MAAK,OAAM,cAAW,UAAS,WAAU,qDAAA,CAAqD,IACrG;AAAA,UAAA,GACN;AAAA,UACC,UAAUnB,2BAAAA,IAAC,KAAA,EAAE,WAAU,sDAAsD,mBAAQ,IAAO;AAAA,QAAA,GAC/F;AAAA,QACC,QAAQ,IAAI,CAAC,sCACX,MAAA,EAAY,eAAa,IAAI,WAAU,wCACrC,UAAA,KAAK,EAAE,EAAA,GADD,EAET,CACD;AAAA,QACDA,2BAAAA,IAAC,QAAG,WAAU,yBACZ,0CAAC,OAAA,EAAI,oBAAgB,MAAC,WAAU,yCAC9B,UAAA;AAAA,UAAAA,2BAAAA;AAAAA,YAACoB,gBAAAA;AAAAA,YAAA;AAAA,cACC,OAAO,IAAI,WAAW,cAAc;AAAA,cACpC,QAAO;AAAA,cACP,SAAS,KAAK,0BAA0B,IAAI,IAAI,EAAE;AAAA,cAClD,SAAS,MACP,KAAK,aAAa,EAAE,UAAU,IAAI,IAAI,UAAU,CAAC,IAAI,UAAU,WAAW,IAAI,WAAW;AAAA,cAG1F,UAAA,IAAI,WAAWpB,2BAAAA,IAACqB,YAAAA,cAAA,EAAa,WAAU,YAAW,eAAW,KAAA,CAAC,IAAKrB,2BAAAA,IAACsB,YAAAA,UAAA,EAAS,WAAU,YAAW,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAEhH,KAAK,0BACJtB,2BAAAA;AAAAA,YAACoB,gBAAAA;AAAAA,YAAA;AAAA,cACC,OAAO,IAAI,cAAc,kBAAkB;AAAA,cAC3C,QAAO;AAAA,cACP,SAAS,IAAI;AAAA,cACb,SAAS,KAAK,yBAAyB,IAAI,IAAI,EAAE;AAAA,cACjD,SAAS,MAAM,KAAK,aAAa,EAAE,UAAU,IAAI,IAAI,aAAa,CAAC,IAAI,YAAA,CAAa;AAAA,cAEpF,UAAApB,2BAAAA,IAACmB,qBAAA,EAAQ,WAAWrB,OAAAA,GAAG,YAAY,IAAI,eAAe,cAAc,GAAG,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA,IAEnF;AAAA,UACH,KAAK,mBACJE,2BAAAA;AAAAA,YAACoB,gBAAAA;AAAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAS,KAAK,wBAAwB,IAAI,IAAI,EAAE;AAAA,cAChD,SAAS,MAAM,KAAK,cAAc,IAAI,EAAE;AAAA,cAExC,UAAApB,2BAAAA,IAACuB,yBAAA,EAAY,WAAU,YAAW,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA,IAE9C;AAAA,QAAA,EAAA,CACN,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAAiE;AAC/D,QAAM,CAAC,OAAO,IAAIpB,MAAAA,SAAS,MAAMqB,oBAAAA,yBAAyB,UAAU,CAAC;AACrE,QAAM,CAAC,cAAc,eAAe,IAAIrB,MAAAA,SAAqC,QAAQ,YAAY;AACjG,QAAM,CAAC,OAAO,aAAa,IAAIA,MAAAA;AAAAA,IAC7B,MAAM,QAAQ,gBAAgBsB,cAAAA,uBAAuB,gBAAgB,CAAA,CAAE;AAAA,EAAA;AAEzE,QAAM,CAAC,SAAS,eAAe,IAAItB,MAAAA,SAA8B,QAAQ,OAAO;AAChF,QAAM,CAAC,aAAa,cAAc,IAAIA,MAAAA,SAAS,MAAM,UAAU,EAAE;AAEjE,QAAM,WAAW,CAAC,WAChB,cAAc,CAAC,YAAYsB,qCAAuB,OAAO,OAAO,CAAC,CAAC;AACpE,QAAM,aAAa,CAAC,WAClB,gBAAgB,CAAC,YAAY;AAC3B,UAAM,OAAO,OAAO,OAAO;AAC3BC,wBAAAA,0BAA0B,YAAY,EAAE,cAAc,cAAc,SAAS,MAAM;AACnF,WAAO;AAAA,EACT,CAAC;AAGHC,QAAAA,UAAU,MAAM;AACd,UAAM,SAAS,WAAW,MAAM;AAC9B,oBAAc,CAAC,YAAY;AACzB,cAAM,SAAS,YAAY,KAAA;AAC3B,aAAK,QAAQ,UAAU,QAAQ,OAAQ,QAAO;AAC9C,eAAOF,qCAAuB,EAAE,GAAG,SAAS,QAAQ;AAAA,MACtD,CAAC;AAAA,IACH,GAAG,GAAG;AACN,WAAO,MAAM,aAAa,MAAM;AAAA,EAClC,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,WAAWG,kBAAAA,kBAAkB,EAAE,OAAO,GAAI,WAAW,EAAE,aAAa,CAAA,GAAK;AAC/E,QAAM,cAAcC,MAAAA;AAAAA,IAClB,MAAM,oBAAI,IAAI,CAAC,GAAG,SAAS,mBAAmB,GAAG,SAAS,iBAAiB,CAAC;AAAA,IAC5E,CAAC,SAAS,mBAAmB,SAAS,iBAAiB;AAAA,EAAA;AAKzD,QAAM,UAAUC,MAAAA,OAAO,EAAE,4BAAY,IAAA,GAAe,UAAU,oBAAI,OAAe,SAAS,oBAAI,IAAA,GAAe;AAC7G,aAAW,OAAO,SAAS,MAAM;AAC/B,QAAI,IAAI,eAAe;AACrB,cAAQ,QAAQ,OAAO,IAAI,IAAI,aAAa;AAC5C,cAAQ,QAAQ,SAAS,IAAI,IAAI,mBAAmBC,oCAAsB;AAAA,IAC5E;AACA,QAAI,IAAI,aAAc,SAAQ,QAAQ,QAAQ,IAAI,IAAI,YAAY;AAAA,EACpE;AACA,QAAM,eAAe;AAAA,IACnB,uBAAO,IAAI,CAAC,GAAG,OAAO,MAAK,iCAAQ,WAAU,CAAA,CAAE,GAAG,GAAG,QAAQ,QAAQ,QAAQ,GAAI,MAAM,kBAAkB,EAAG,CAAC;AAAA,EAAA;AAE/G,QAAM,iBAAiB;AAAA,IACrB,uBAAO,IAAI;AAAA,MACTA,cAAAA;AAAAA,MACA,GAAG,OAAO,MAAK,iCAAQ,aAAY,CAAA,CAAE;AAAA,MACrC,GAAG,QAAQ,QAAQ;AAAA,MACnB,GAAI,MAAM,oBAAoB,CAAA;AAAA,IAAC,CAChC;AAAA,EAAA;AAEH,QAAM,gBAAgB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,QAAQ,QAAQ,SAAS,GAAI,MAAM,iBAAiB,CAAA,CAAG,CAAC,CAAC;AAE/F,QAAM,QAAQC,kBAAAA,oBAAoB,OAAO,MAAM;AAC/C,QAAM,WAAWC,kBAAAA,gBAAgB,SAAS,MAAM,QAAQ,OAAO;AAC/D,QAAM,UAAUtB,kBAAAA,iBAAiB,IAAI,CAAC,WAAW,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,QAAQ,QAAQ,SAAS,EAAE,CAAC;AACvG,QAAM,EAAE,QAAQ,SAAS,GAAG,uBAAuB;AACnD,QAAM,iBACJ,iBAAiB,QAAQuB,cAAAA,iBAAiB,YAAY,MAAMA,cAAAA,iBAAiB,kBAAkB;AACjG,QAAM,aAAa,MAAM,SAAS;AAElC,QAAM,OAAO,CAAC,QAAsC;AAClD,SAAK,aAAa,IAAI,EAAE;AACxB,mDAAgB,EAAE,UAAU,IAAI,IAAI,OAAO,IAAI;EACjD;AACA,QAAM,gBAAgB,MAAM;AAC1B,UAAM,QAAQT,cAAAA,uBAAuB,kBAAkB;AACvD,oBAAgB,KAAK;AACrBC,wBAAAA,0BAA0B,YAAY,EAAE,cAAc,OAAO,SAAS;AAAA,EACxE;AACA,QAAM,iBAAiB,MAAM;AAC3B,kBAAc,EAAE,GAAI,gBAAgBD,cAAAA,uBAAuB,gBAAgB,CAAA,CAAE,GAAI;AACjF,mBAAe,EAAE;AAAA,EACnB;AACA,QAAM,eAAe,MAAM;AACzB,aAAS,CAAC,aAAa,EAAE,MAAM,QAAQ,MAAM,WAAW,QAAQ,WAAW,QAAQ,QAAQ,OAAA,EAAS;AAAA,EACtG;AACA,QAAM,aAAa,CAAC,UAClB,SAAS,CAAC,YAAY;AACpB,UAAM,OAA4B,EAAE,GAAG,SAAS,CAAC,KAAK,GAAG,OAAA;AACzD,QAAI,UAAU,iBAAkB,MAAK,mBAAmB;AACxD,WAAO;AAAA,EACT,CAAC;AACH,QAAM,YAAY,MAChB;AAAA,IACE,iCAAgB,QAAO,cAAc,MAAM,GAAG,EAAE,CAAC;AAAA,IACjDU,8BAAY,SAAS,MAAM,MAAM;AAAA,IACjC;AAAA,EAAA;AAKJ,QAAM,eACJ,SAAS,KAAK,WAAW,MAAM,CAAC,SAAS,wBAAwB,SAAS;AAE5E,SACEtC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAWC,OAAAA,GAAG,qDAAqD,SAAS;AAAA,MAE5E,UAAA;AAAA,QAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,UAAAG,2BAAAA,IAAC,MAAA,EAAG,WAAU,2CAA2C,UAAA,OAAM;AAAA,UAC/DH,2BAAAA,KAAC,QAAA,EAAK,eAAY,kBAAiB,WAAU,iCAC1C,UAAA;AAAA,YAAA,SAAS,KAAK;AAAA,YACd,SAAS,cAAc,MAAM;AAAA,UAAA,GAChC;AAAA,UACAG,2BAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,UACxBH,2BAAAA,KAAC,SAAA,EAAM,WAAU,kCACf,UAAA;AAAA,YAAAG,2BAAAA,IAACoC,YAAAA,YAAA,EAAW,WAAU,gGAAA,CAAgG;AAAA,YACtHpC,2BAAAA,IAAC,QAAA,EAAK,WAAU,WAAU,UAAA,mBAAe;AAAA,YACzCA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,UAAU,CAAC,UAAU,eAAe,MAAM,OAAO,KAAK;AAAA,gBACtD,aAAY;AAAA,gBACZ,WAAU;AAAA,cAAA;AAAA,YAAA;AAAA,UACZ,GACF;AAAA,0CACCqC,QAAAA,SAAA,EACC,UAAA;AAAA,YAAArC,2BAAAA,IAACsC,QAAAA,gBAAA,EAAe,SAAO,MACrB,UAAAzC,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,WAAW,qBAAqB,cAAW,mBAC/D,UAAA;AAAA,cAAAG,2BAAAA,IAACuC,YAAAA,uBAAA,EAAsB,WAAU,YAAW,eAAW,MAAC;AAAA,cAAE;AAAA,YAAA,EAAA,CAE5D,EAAA,CACF;AAAA,YACAvC,2BAAAA,IAACwC,QAAAA,gBAAA,EAAe,OAAM,OAAM,WAAU,QACpC,UAAAxC,2BAAAA,IAAC,aAAA,EAAY,OAAc,UAAoB,SAAkB,WAAA,CAAwB,EAAA,CAC3F;AAAA,UAAA,GACF;AAAA,UACAH,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU,SAAS,KAAK,WAAW;AAAA,cACnC,WAAW;AAAA,cACX,OAAM;AAAA,cAEN,UAAA;AAAA,gBAAAG,2BAAAA,IAACyC,YAAAA,cAAA,EAAa,WAAU,YAAW,eAAW,MAAC;AAAA,gBAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGnDzC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,SAAS;AAAA,cAClB,UAAU,SAAS;AAAA,cACnB,WAAW;AAAA,cACX,cAAW;AAAA,cACX,OAAM;AAAA,cAEN,UAAAA,2BAAAA,IAAC0C,2BAAA,EAAc,WAAW5C,OAAAA,GAAG,YAAY,SAAS,cAAc,cAAc,GAAG,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAE9F,iBACCD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM;AACb,qBAAK,UAAA;AACL;AAAA,cACF;AAAA,cACA,WAAWC,OAAAA;AAAAA,gBACT;AAAA,gBACAC,gBAAAA;AAAAA,cAAA;AAAA,cAGF,UAAA;AAAA,gBAAAC,2BAAAA,IAAC2C,YAAAA,UAAA,EAAS,WAAU,YAAW,eAAW,MAAC;AAAA,gBAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,IAG7C;AAAA,QAAA,GACN;AAAA,QAEA9C,2BAAAA,KAAC,OAAA,EAAI,WAAU,uCAAsC,eAAY,oBAC/D,UAAA;AAAA,UAAAA,gCAACwC,QAAAA,SAAA,EACC,UAAA;AAAA,YAAArC,2BAAAA,IAACsC,QAAAA,gBAAA,EAAe,SAAO,MACrB,UAAAzC,2BAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,qBAC/B,UAAA;AAAA,cAAAG,2BAAAA,IAAC4C,YAAAA,YAAA,EAAW,WAAU,YAAW,eAAW,MAAC;AAAA,cAAE;AAAA,YAAA,EAAA,CAEjD,EAAA,CACF;AAAA,YACA5C,2BAAAA,IAACwC,QAAAA,gBAAA,EAAe,OAAM,SAAQ,WAAU,QACtC,UAAAxC,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,YAAA,EACF,CACF;AAAA,UAAA,GACF;AAAA,UACC,MAAM,IAAI,CAAC,SACVH,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC,oBAAkB,KAAK;AAAA,cACvB,WAAU;AAAA,cAET,UAAA;AAAA,gBAAA,KAAK;AAAA,gBACNG,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,cAAY,iBAAiB,KAAK,KAAK;AAAA,oBACvC,SAAS,MAAM,WAAW,KAAK,KAAK;AAAA,oBACpC,WAAWF,OAAAA,GAAG,iFAAiFC,gCAAgB;AAAA,oBAE/G,UAAAC,2BAAAA,IAAC6C,mBAAA,EAAM,WAAU,UAAS,eAAW,KAAA,CAAC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACxC;AAAA,YAAA;AAAA,YAZK,KAAK,QAAQ,KAAK;AAAA,UAAA,CAc1B;AAAA,UACA,aACC7C,2BAAAA,IAAC,UAAA,EAAO,MAAK,UAAS,SAAS,cAAc,WAAWF,OAAAA,GAAG,8DAA8DC,gBAAAA,gBAAgB,GAAG,mBAE5I,IACE;AAAA,UACJC,2BAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,UACvB,iBAAiB,QAAQ,CAAC,iBACzBA,2BAAAA,IAAC,YAAO,MAAK,UAAS,SAAS,gBAAgB,WAAWF,OAAAA,GAAG,8DAA8DC,gBAAAA,gBAAgB,GAAG,8BAE9I,IACE;AAAA,UACJC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAWF,OAAAA,GAAG,kFAAkFC,gCAAgB;AAAA,cAE/G,2BAAiB,qBAAqB;AAAA,YAAA;AAAA,UAAA;AAAA,QACzC,GACF;AAAA,QAEC,SAAS,eAAe,SAAS,KAAK,SAAS,kBAAkB,SAAS,IACzEF,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,YAET,UAAA;AAAA,cAAA,SAAS,eAAe,SAAS,IAC9B,uCAAuC,UAAU,SAAS,cAAc,CAAC,wDACzE;AAAA,cACH,SAAS,kBAAkB,SAAS,IACjC,gBAAgB,UAAU,SAAS,iBAAiB,CAAC,qDACrD;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,IAEJ;AAAA,QAEJA,2BAAAA,KAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,UAAA,eACCG,2BAAAA,IAAC8C,iCAAA,EAAoB,MAAM,EAAA,CAAG,IAC5B,SAAS,WAAW,IACtBjD,2BAAAA,KAAC,OAAA,EAAI,eAAY,kBAAiB,WAAU,sDAC1C,UAAA;AAAA,YAAAG,2BAAAA,IAAC,OAAE,WAAU,iCACV,wBAAc,MAAM,SAAS,qCAAqC,mBAAA,CACrE;AAAA,YACC,aACCA,2BAAAA,IAAC,UAAA,EAAO,MAAK,UAAS,SAAS,cAAc,WAAW,qBAAqB,UAAA,gBAAA,CAE7E,IACE;AAAA,UAAA,EAAA,CACN,oCAEC,SAAA,EAAM,WAAU,8CAA6C,aAAW,SAAS,cAAc,QAC9F,UAAA;AAAA,YAAAA,+BAAC,SAAA,EACC,UAAAH,2BAAAA,KAAC,MAAA,EAAG,WAAU,iGACZ,UAAA;AAAA,cAAAG,+BAAC,MAAA,EAAG,OAAM,OAAM,WAAU,yBAAwB,UAAA,WAElD;AAAA,cACC,QAAQ,IAAI,CAAC,OAAA;;AACZA,kDAAAA,IAAC,QAAY,OAAM,OAAM,WAAWF,OAAAA,GAAG,yBAAyB,aAAa,EAAE,CAAC,GAC7E,WAAAa,wCAAiB,KAAK,CAAC,WAAW,OAAO,OAAO,EAAE,MAAlDA,mBAAqD,MAAA,GAD/C,EAET;AAAA,eACD;AAAA,cACDX,2BAAAA,IAAC,MAAA,EAAG,OAAM,OAAM,WAAU,kBACxB,UAAAA,2BAAAA,IAAC,QAAA,EAAK,WAAU,WAAU,UAAA,UAAA,CAAO,EAAA,CACnC;AAAA,YAAA,EAAA,CACF,EAAA,CACF;AAAA,YACC,SAAS,IAAI,CAAC,4CACZ,SAAA,EAAwB,cAAY,QAAQ,SAAS,QACnD,UAAA;AAAA,cAAA,QAAQ,QACPA,+BAAC,MAAA,EACC,UAAAH,2BAAAA,KAAC,MAAA,EAAG,SAAS,QAAQ,SAAS,GAAG,OAAM,YAAW,WAAW,uBAC1D,UAAA;AAAA,gBAAA,QAAQ;AAAA,+CACR,QAAA,EAAK,WAAU,kDAAkD,UAAA,QAAQ,MAAM,OAAA,CAAO;AAAA,cAAA,EAAA,CACzF,GACF,IACE;AAAA,cACH,QAAQ,MAAM,IAAI,CAAC,QAClBG,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC;AAAA,kBACA;AAAA,kBACA,UAAU,IAAI,OAAO,KAAK;AAAA,kBAC1B;AAAA,kBACA;AAAA,kBACA,QAAQ;AAAA,gBAAA;AAAA,gBANH,IAAI;AAAA,cAAA,CAQZ;AAAA,YAAA,EAAA,GAnBS,QAAQ,GAoBpB,CACD;AAAA,UAAA,GACH;AAAA,UAED,SAAS,eAAe,CAAC,eACxBA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,SAAS;AAAA,cAClB,UAAU,SAAS;AAAA,cACnB,WAAWF,OAAAA,GAAG,kHAAkHC,gCAAgB;AAAA,cAE/I,UAAA,SAAS,qBAAqB,aAAa,SAAS,uBAAuB,uBAAuB;AAAA,YAAA;AAAA,UAAA,IAEnG;AAAA,QAAA,EAAA,CACN;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAOO,SAAS,aAAa,OAA0B;AACrD,QAAM,OAAOgD,oBAAAA,6BAAA;AACb,QAAM,OAAOC,MAAAA,WAAWC,6CAAyB;AACjD,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAOjD,2BAAAA,IAAC,kBAAA,EAAkB,GAAG,OAAO,KAAA,CAAY;AAClD;;"}
1
+ {"version":3,"file":"SessionsPage.cjs","sources":["../../src/threads/SessionsPage.tsx"],"sourcesContent":["/**\n * `SessionsPage` — a full-page, Devin-style session list: filter chips that\n * the server applies (status, pull requests, unread, pinned, creator, agent,\n * mode, origin, created / updated date), a title search, display options\n * (sort, direction, grouping, columns), an attention-coloured status column\n * that says what the person must do next, row actions (read, pin, archive)\n * and a CSV export of the loaded rows. Live through the thread-list\n * provider's conversation index; renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport {\n ArchiveIcon,\n CheckIcon,\n DownloadIcon,\n FilterIcon,\n MailIcon,\n MailOpenIcon,\n PinIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n SlidersHorizontalIcon,\n XIcon,\n} from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { SessionListSkeleton, type SessionOpenTarget } from './SessionList';\nimport { pullRequestChip, relativeTime, sessionOriginLabel } from './session-list-model';\nimport { FOCUS_RING_CLASS, PullRequestChip, RowIconButton, StatusChip } from './session-row-parts';\nimport {\n agentLabel,\n channelLabel,\n creatorLabel,\n datePresetBounds,\n groupSessionsBy,\n runStatusLabel,\n SESSIONS_COLUMNS,\n SESSIONS_DATE_PRESETS,\n type SessionsColumnId,\n type SessionsDatePreset,\n type SessionsGroupBy,\n type SessionsLabels,\n sessionsCsv,\n sessionsFilterChips,\n plainExcerpt,\n sessionStatusChip,\n} from './sessions-page-model';\nimport {\n readSessionsPageSettings,\n type SessionsPageDisplay,\n writeSessionsPageSettings,\n} from './sessions-page-storage';\nimport {\n type AthenaSessionsQuery,\n type AthenaSessionsQueryField,\n DEFAULT_COLLAB_CHANNEL,\n normalizeSessionsQuery,\n SESSION_RUN_STATUSES,\n type SessionRunStatus,\n sessionsQueryKey,\n} from './sessions-query';\nimport {\n AthenaSessionsLiveContext,\n type AthenaStatewireThreadListState,\n type AthenaStatewireThreadSummary,\n useAthenaStatewireThreadList,\n} from './statewire-thread-list';\nimport { useAthenaSessions } from './use-athena-sessions';\n\nexport interface SessionsPageProps {\n className?: string;\n /** Heading (default \"Sessions\"). */\n title?: string;\n /**\n * Called after a row is selected (the provider's chat switches to it), so\n * a host can navigate to its chat view.\n */\n onOpenSession?: (target: SessionOpenTarget) => void;\n /** Names for collab agents and channels (filters, the Mode column, CSV); ids show otherwise. */\n labels?: SessionsLabels;\n /**\n * Namespaces what this browser remembers — \"Save as default\" and the\n * display options — so a host with several pages keeps them apart\n * (default `\"default\"`).\n */\n storageKey?: string;\n /** The filters before anything is saved as default. */\n defaultQuery?: AthenaSessionsQuery;\n /** Rows per page (default 50). */\n pageSize?: number;\n /** Offer \"New session\" (default `true`). */\n showNewSession?: boolean;\n /** Called after \"New session\" starts a fresh chat, so a host can show its chat view. */\n onNewSession?: () => void;\n}\n\n/** What each query field is called in notices. */\nconst FIELD_LABEL: Record<AthenaSessionsQueryField, string> = {\n search: 'search',\n collabAgentIds: 'agent',\n collabChannelIds: 'mode',\n startChannels: 'origin',\n createdAfter: 'created date',\n createdBefore: 'created date',\n updatedAfter: 'updated date',\n updatedBefore: 'updated date',\n favoritesOnly: 'pinned',\n unreadOnly: 'unread',\n runStatuses: 'status',\n sessionStatuses: 'session status',\n hasPullRequests: 'pull requests',\n createdByMe: 'creator',\n excludeDismissed: 'dismissed',\n excludeTriggered: 'who started it',\n sort: 'sort',\n direction: 'sort direction',\n};\n\n/** \"agent\", \"agent and mode\", \"agent, mode and unread\". */\nfunction fieldList(fields: readonly AthenaSessionsQueryField[]): string {\n const names = [...new Set(fields.map((field) => FIELD_LABEL[field]))];\n return names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names.at(-1)}`;\n}\n\nconst COLUMN_WIDTH: Record<SessionsColumnId, string> = {\n status: 'w-56',\n origin: 'w-24',\n mode: 'w-28',\n pullRequests: 'w-24',\n creator: 'w-32',\n created: 'w-24',\n updated: 'w-24',\n};\n\n/** Save `text` as a file in the browser. */\nfunction downloadText(filename: string, text: string, type: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(new Blob([text], { type }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.rel = 'noopener';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nconst SECTION_HEADING_CLASS =\n 'px-3 pb-1 pt-3 text-left font-medium text-[11px] text-muted-foreground/70 uppercase tracking-wide';\n\n/** A pressable option in a filter or display menu. */\nconst MenuOption: FC<{\n label: string;\n selected: boolean;\n onSelect: () => void;\n disabled?: boolean;\n role?: 'menuitemcheckbox' | 'menuitemradio';\n}> = ({ label, selected, onSelect, disabled = false, role = 'menuitemcheckbox' }) => (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n disabled={disabled}\n onClick={onSelect}\n className={cn(\n 'flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-xs transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50',\n FOCUS_RING_CLASS,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'flex size-3.5 shrink-0 items-center justify-center rounded-sm border border-border',\n selected && 'border-primary bg-primary text-primary-foreground',\n )}\n >\n {selected ? <CheckIcon className=\"size-3\" /> : null}\n </span>\n <span className=\"truncate\">{label}</span>\n </button>\n);\n\nconst MenuSection: FC<{ title: string; hint?: string | null; children: ReactNode }> = ({\n title,\n hint,\n children,\n}) => (\n <section aria-label={title} className=\"py-1\">\n <h4 className=\"px-2 pb-0.5 font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n {title}\n </h4>\n {hint ? <p className=\"px-2 pb-1 text-[11px] text-muted-foreground\">{hint}</p> : null}\n {children}\n </section>\n);\n\nfunction toggleValue<T extends string>(values: readonly T[] | undefined, value: T): T[] {\n const current = values ?? [];\n return current.includes(value) ? current.filter((item) => item !== value) : [...current, value];\n}\n\nfunction datePresetOf(after: string | undefined, before: string | undefined, presets: Record<SessionsDatePreset, { after?: string; before?: string }>): SessionsDatePreset | null {\n for (const preset of SESSIONS_DATE_PRESETS) {\n const bounds = presets[preset.id];\n if ((bounds.after ?? undefined) === after && (bounds.before ?? undefined) === before) {\n return preset.id;\n }\n }\n return null;\n}\n\ninterface FilterMenuProps {\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n unavailable: ReadonlySet<AthenaSessionsQueryField>;\n agentOptions: readonly string[];\n channelOptions: readonly string[];\n originOptions: readonly string[];\n labels: SessionsLabels | undefined;\n}\n\nconst UNAVAILABLE_HINT = 'This Athena server cannot filter by this yet.';\n\n/** Every filter, stacked by kind; each option toggles at once. */\nconst FilterMenu: FC<FilterMenuProps> = ({\n query,\n setQuery,\n unavailable,\n agentOptions,\n channelOptions,\n originOptions,\n labels,\n}) => {\n // The presets' bounds are captured when the menu opens, so a selected\n // preset stays recognisable while it is open.\n const [presetBounds] = useState(() =>\n Object.fromEntries(\n SESSIONS_DATE_PRESETS.map((preset) => [preset.id, datePresetBounds(preset.id)]),\n ) as Record<SessionsDatePreset, { after?: string; before?: string }>,\n );\n const createdPreset = datePresetOf(query.createdAfter, query.createdBefore, presetBounds);\n const updatedPreset = datePresetOf(query.updatedAfter, query.updatedBefore, presetBounds);\n const setPreset = (\n kind: 'created' | 'updated',\n preset: SessionsDatePreset | null,\n ) =>\n setQuery((current) => {\n const bounds = preset ? presetBounds[preset] : {};\n return kind === 'created'\n ? { ...current, createdAfter: bounds.after, createdBefore: bounds.before }\n : { ...current, updatedAfter: bounds.after, updatedBefore: bounds.before };\n });\n const disabledHint = (field: AthenaSessionsQueryField) =>\n unavailable.has(field) ? UNAVAILABLE_HINT : null;\n\n return (\n <div role=\"menu\" aria-label=\"Filters\" className=\"max-h-[70vh] overflow-y-auto p-1\">\n <MenuSection title=\"Status\" hint={disabledHint('runStatuses')}>\n {SESSION_RUN_STATUSES.map((status) => (\n <MenuOption\n key={status}\n label={runStatusLabel(status)}\n selected={query.runStatuses?.includes(status) ?? false}\n disabled={unavailable.has('runStatuses')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n runStatuses: toggleValue<SessionRunStatus>(current.runStatuses, status),\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Pull requests\" hint={disabledHint('hasPullRequests')}>\n {(\n [\n ['Has pull requests', true],\n ['No pull requests', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.hasPullRequests === value}\n disabled={unavailable.has('hasPullRequests')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n hasPullRequests: current.hasPullRequests === value ? undefined : value,\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Read and pinned\">\n <MenuOption\n label=\"Unread\"\n selected={query.unreadOnly === true}\n disabled={unavailable.has('unreadOnly')}\n onSelect={() => setQuery((current) => ({ ...current, unreadOnly: !current.unreadOnly }))}\n />\n <MenuOption\n label=\"Pinned\"\n selected={query.favoritesOnly === true}\n disabled={unavailable.has('favoritesOnly')}\n onSelect={() =>\n setQuery((current) => ({ ...current, favoritesOnly: !current.favoritesOnly }))\n }\n />\n </MenuSection>\n <MenuSection title=\"Creator\" hint={disabledHint('createdByMe')}>\n {(\n [\n ['You', true],\n ['Shared with you', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.createdByMe === value}\n disabled={unavailable.has('createdByMe')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n createdByMe: current.createdByMe === value ? undefined : value,\n }))\n }\n />\n ))}\n <MenuOption\n label=\"Started by a person\"\n selected={query.excludeTriggered === true}\n onSelect={() =>\n setQuery((current) => ({ ...current, excludeTriggered: !current.excludeTriggered }))\n }\n />\n </MenuSection>\n {agentOptions.length > 0 ? (\n <MenuSection title=\"Agent\" hint={disabledHint('collabAgentIds')}>\n {agentOptions.map((agentId) => (\n <MenuOption\n key={agentId}\n label={agentLabel(agentId, labels)}\n selected={query.collabAgentIds?.includes(agentId) ?? false}\n disabled={unavailable.has('collabAgentIds')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabAgentIds: toggleValue(current.collabAgentIds, agentId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {agentOptions.length > 0 ? (\n <MenuSection\n title=\"Mode\"\n hint={\n disabledHint('collabChannelIds') ??\n (query.collabAgentIds?.length ? null : 'Pick an agent first: a mode is one of its channels.')\n }\n >\n {channelOptions.map((channelId) => (\n <MenuOption\n key={channelId}\n label={channelLabel(channelId, labels)}\n selected={query.collabChannelIds?.includes(channelId) ?? false}\n disabled={unavailable.has('collabChannelIds') || !query.collabAgentIds?.length}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabChannelIds: toggleValue(current.collabChannelIds, channelId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {originOptions.length > 0 ? (\n <MenuSection title=\"Origin\" hint={disabledHint('startChannels')}>\n {originOptions.map((channel) => (\n <MenuOption\n key={channel}\n label={sessionOriginLabel({ startChannel: channel, appId: null, triggerType: null }) ?? channel}\n selected={query.startChannels?.includes(channel) ?? false}\n disabled={unavailable.has('startChannels')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n startChannels: toggleValue(current.startChannels, channel),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n <MenuSection title=\"Created\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={createdPreset === preset.id}\n onSelect={() => setPreset('created', createdPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Updated\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={updatedPreset === preset.id}\n onSelect={() => setPreset('updated', updatedPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst DisplayMenu: FC<{\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n display: SessionsPageDisplay;\n setDisplay: (update: (display: SessionsPageDisplay) => SessionsPageDisplay) => void;\n}> = ({ query, setQuery, display, setDisplay }) => {\n const sort = query.sort ?? 'updated';\n const direction = query.direction ?? 'desc';\n return (\n <div role=\"menu\" aria-label=\"Display options\" className=\"p-1\">\n <MenuSection title=\"Sort by\">\n {(\n [\n ['updated', 'Last updated'],\n ['created', 'Created'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={sort === value}\n onSelect={() => setQuery((current) => ({ ...current, sort: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Order\">\n {(\n [\n ['desc', 'Newest first'],\n ['asc', 'Oldest first'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={direction === value}\n onSelect={() => setQuery((current) => ({ ...current, direction: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Group by\">\n {(\n [\n ['attention', 'What it needs'],\n ['status', 'Run status'],\n ['none', 'No grouping'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={display.groupBy === value}\n onSelect={() => setDisplay((current) => ({ ...current, groupBy: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Columns\">\n {SESSIONS_COLUMNS.map((column) => (\n <MenuOption\n key={column.id}\n label={column.label}\n selected={display.columns.includes(column.id)}\n onSelect={() =>\n setDisplay((current) => ({\n ...current,\n columns: current.columns.includes(column.id)\n ? current.columns.filter((id) => id !== column.id)\n : SESSIONS_COLUMNS.map((candidate) => candidate.id).filter(\n (id) => id === column.id || current.columns.includes(id),\n ),\n }))\n }\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst HEADER_BUTTON_CLASS = cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md border border-border/60 px-2.5 font-medium text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50',\n FOCUS_RING_CLASS,\n);\n\nconst SessionsRow: FC<{\n row: AthenaStatewireThreadSummary;\n columns: readonly SessionsColumnId[];\n isActive: boolean;\n labels: SessionsLabels | undefined;\n list: AthenaStatewireThreadListState;\n onOpen: (row: AthenaStatewireThreadSummary) => void;\n}> = ({ row, columns, isActive, labels, list, onOpen }) => {\n const status = sessionStatusChip(row);\n const excerpt = plainExcerpt(row.preview);\n const chip = pullRequestChip(row.pullRequests);\n const origin = sessionOriginLabel(row);\n const cell = (id: SessionsColumnId): ReactNode => {\n switch (id) {\n case 'status':\n return <StatusChip label={status.label} tone={status.tone} detail={status.detail} />;\n case 'origin':\n return origin ? (\n <span className=\"rounded-full border border-border/60 px-1.5 py-px text-[10px] text-muted-foreground\">\n {origin}\n </span>\n ) : null;\n case 'mode':\n return row.collabAgentId ? (\n <span className=\"truncate text-muted-foreground text-xs\">\n {channelLabel(row.collabChannelId, labels)}\n </span>\n ) : null;\n case 'pullRequests':\n return chip ? <PullRequestChip chip={chip} pullRequests={row.pullRequests ?? []} /> : null;\n case 'creator':\n return (\n <span className=\"truncate text-muted-foreground text-xs\">{creatorLabel(row.createdByMe)}</span>\n );\n case 'created':\n return (\n <span className=\"text-muted-foreground text-xs\">\n {row.createdAt ? relativeTime(row.createdAt) : ''}\n </span>\n );\n case 'updated':\n return <span className=\"text-muted-foreground text-xs\">{relativeTime(row.updatedAt)}</span>;\n }\n };\n return (\n <tr\n data-thread-id={row.id}\n data-active={isActive || undefined}\n data-unread={row.isUnread || undefined}\n onClick={() => onOpen(row)}\n className={cn(\n 'group cursor-pointer border-border/40 border-b transition-colors hover:bg-muted/40',\n isActive && 'bg-muted',\n )}\n >\n <td className=\"min-w-0 py-2 pr-2 pl-3 align-top\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span\n role={row.isUnread ? 'img' : undefined}\n aria-label={row.isUnread ? 'Unread' : undefined}\n aria-hidden={row.isUnread ? undefined : true}\n className={cn('size-2 shrink-0 rounded-full', row.isUnread ? 'bg-primary' : 'bg-transparent')}\n />\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row);\n }}\n className={cn(\n 'min-w-0 truncate text-left text-foreground text-sm',\n row.isUnread ? 'font-semibold' : 'font-medium',\n FOCUS_RING_CLASS,\n )}\n >\n {row.title ?? 'Untitled'}\n </button>\n {row.isFavorited ? (\n <PinIcon role=\"img\" aria-label=\"Pinned\" className=\"size-3 shrink-0 fill-current text-muted-foreground\" />\n ) : null}\n </div>\n {excerpt ? <p className=\"mt-0.5 truncate pl-4 text-muted-foreground text-xs\">{excerpt}</p> : null}\n </td>\n {columns.map((id) => (\n <td key={id} data-column={id} className=\"min-w-0 truncate px-2 py-2 align-top\">\n {cell(id)}\n </td>\n ))}\n <td className=\"py-1.5 pr-2 align-top\">\n <div data-row-actions className=\"flex items-center justify-end gap-0.5\">\n <RowIconButton\n label={row.isUnread ? 'Mark read' : 'Mark unread'}\n action=\"read-state\"\n pending={list.readStatePendingThreadIds.has(row.id)}\n onClick={() =>\n list.setReadState({ threadId: row.id, isUnread: !row.isUnread, updatedAt: row.updatedAt })\n }\n >\n {row.isUnread ? <MailOpenIcon className=\"size-3.5\" aria-hidden /> : <MailIcon className=\"size-3.5\" aria-hidden />}\n </RowIconButton>\n {list.favoriteToggleAvailable ? (\n <RowIconButton\n label={row.isFavorited ? 'Unpin session' : 'Pin session'}\n action=\"pin\"\n pressed={row.isFavorited}\n pending={list.favoritePendingThreadIds.has(row.id)}\n onClick={() => list.setFavorited({ threadId: row.id, isFavorited: !row.isFavorited })}\n >\n <PinIcon className={cn('size-3.5', row.isFavorited && 'fill-current')} aria-hidden />\n </RowIconButton>\n ) : null}\n {list.archiveAvailable ? (\n <RowIconButton\n label=\"Archive session\"\n action=\"archive\"\n pending={list.archivePendingThreadIds.has(row.id)}\n onClick={() => list.archiveThread(row.id)}\n >\n <ArchiveIcon className=\"size-3.5\" aria-hidden />\n </RowIconButton>\n ) : null}\n </div>\n </td>\n </tr>\n );\n};\n\nfunction SessionsPageBody({\n className,\n title = 'Sessions',\n onOpenSession,\n labels,\n storageKey = 'default',\n defaultQuery,\n pageSize,\n showNewSession = true,\n onNewSession,\n list,\n}: SessionsPageProps & { list: AthenaStatewireThreadListState }) {\n const [initial] = useState(() => readSessionsPageSettings(storageKey));\n const [savedDefault, setSavedDefault] = useState<AthenaSessionsQuery | null>(initial.defaultQuery);\n const [query, setQueryState] = useState<AthenaSessionsQuery>(\n () => initial.defaultQuery ?? normalizeSessionsQuery(defaultQuery ?? {}),\n );\n const [display, setDisplayState] = useState<SessionsPageDisplay>(initial.display);\n const [searchInput, setSearchInput] = useState(query.search ?? '');\n\n const setQuery = (update: (current: AthenaSessionsQuery) => AthenaSessionsQuery) =>\n setQueryState((current) => normalizeSessionsQuery(update(current)));\n const setDisplay = (update: (current: SessionsPageDisplay) => SessionsPageDisplay) =>\n setDisplayState((current) => {\n const next = update(current);\n writeSessionsPageSettings(storageKey, { defaultQuery: savedDefault, display: next });\n return next;\n });\n\n // The search box types freely; the list follows a beat later.\n useEffect(() => {\n const handle = setTimeout(() => {\n setQueryState((current) => {\n const search = searchInput.trim();\n if ((current.search ?? '') === search) return current;\n return normalizeSessionsQuery({ ...current, search });\n });\n }, 250);\n return () => clearTimeout(handle);\n }, [searchInput]);\n\n const sessions = useAthenaSessions({ query, ...(pageSize ? { pageSize } : {}) });\n const unavailable = useMemo(\n () => new Set([...sessions.unsupportedFields, ...sessions.unavailableFields]),\n [sessions.unsupportedFields, sessions.unavailableFields],\n );\n\n // Filter options: every agent, channel and origin this page has shown, so\n // narrowing the list never hides the option that would widen it again.\n const seenRef = useRef({ agents: new Set<string>(), channels: new Set<string>(), origins: new Set<string>() });\n for (const row of sessions.rows) {\n if (row.collabAgentId) {\n seenRef.current.agents.add(row.collabAgentId);\n seenRef.current.channels.add(row.collabChannelId || DEFAULT_COLLAB_CHANNEL);\n }\n if (row.startChannel) seenRef.current.origins.add(row.startChannel);\n }\n const agentOptions = [\n ...new Set([...Object.keys(labels?.agents ?? {}), ...seenRef.current.agents, ...(query.collabAgentIds ?? [])]),\n ];\n const channelOptions = [\n ...new Set([\n DEFAULT_COLLAB_CHANNEL,\n ...Object.keys(labels?.channels ?? {}),\n ...seenRef.current.channels,\n ...(query.collabChannelIds ?? []),\n ]),\n ];\n const originOptions = [...new Set([...seenRef.current.origins, ...(query.startChannels ?? [])])];\n\n const chips = sessionsFilterChips(query, labels);\n const sections = groupSessionsBy(sessions.rows, display.groupBy);\n const columns = SESSIONS_COLUMNS.map((column) => column.id).filter((id) => display.columns.includes(id));\n const { search: _search, ...queryWithoutSearch } = query;\n const isSavedDefault =\n savedDefault !== null && sessionsQueryKey(savedDefault) === sessionsQueryKey(queryWithoutSearch);\n const hasFilters = chips.length > 0;\n\n const open = (row: AthenaStatewireThreadSummary) => {\n list.selectThread(row.id);\n onOpenSession?.({ threadId: row.id, title: row.title });\n };\n const saveAsDefault = () => {\n const saved = normalizeSessionsQuery(queryWithoutSearch);\n setSavedDefault(saved);\n writeSessionsPageSettings(storageKey, { defaultQuery: saved, display });\n };\n const resetToDefault = () => {\n setQueryState({ ...(savedDefault ?? normalizeSessionsQuery(defaultQuery ?? {})) });\n setSearchInput('');\n };\n const clearFilters = () => {\n setQuery((current) => ({ sort: current.sort, direction: current.direction, search: current.search }));\n };\n const removeChip = (field: AthenaSessionsQueryField) =>\n setQuery((current) => {\n const next: AthenaSessionsQuery = { ...current, [field]: undefined };\n if (field === 'collabAgentIds') next.collabChannelIds = undefined;\n return next;\n });\n const exportCsv = () =>\n downloadText(\n `sessions-${new Date().toISOString().slice(0, 10)}.csv`,\n sessionsCsv(sessions.rows, labels),\n 'text/csv;charset=utf-8',\n );\n\n // Skeletons only while there is nothing to show; a changed query keeps the\n // previous rows (narrowed by it) until its own page answers.\n const showSkeleton =\n sessions.rows.length === 0 && (!sessions.hasResolvedFirstPage || sessions.isFetching);\n\n return (\n <div\n data-testid=\"sessions-page\"\n className={cn('athena-sdk-chrome flex min-h-0 flex-col gap-3 p-4', className)}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"font-semibold text-base text-foreground\">{title}</h2>\n <span data-testid=\"sessions-count\" className=\"text-muted-foreground text-xs\">\n {sessions.rows.length}\n {sessions.hasNextPage ? '+' : ''}\n </span>\n <div className=\"flex-1\" />\n <label className=\"relative block w-64 max-w-full\">\n <SearchIcon className=\"pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n type=\"search\"\n value={searchInput}\n onChange={(event) => setSearchInput(event.target.value)}\n placeholder=\"Search sessions…\"\n className=\"h-8 w-full rounded-md border border-border/60 bg-muted/40 pr-2 pl-8 text-sm outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS} aria-label=\"Display options\">\n <SlidersHorizontalIcon className=\"size-3.5\" aria-hidden />\n Display\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-56\">\n <DisplayMenu query={query} setQuery={setQuery} display={display} setDisplay={setDisplay} />\n </PopoverContent>\n </Popover>\n <button\n type=\"button\"\n onClick={exportCsv}\n disabled={sessions.rows.length === 0}\n className={HEADER_BUTTON_CLASS}\n title=\"Export the loaded sessions as CSV\"\n >\n <DownloadIcon className=\"size-3.5\" aria-hidden />\n Export CSV\n </button>\n <button\n type=\"button\"\n onClick={sessions.refresh}\n disabled={sessions.isFetching}\n className={HEADER_BUTTON_CLASS}\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n >\n <RefreshCwIcon className={cn('size-3.5', sessions.isFetching && 'animate-spin')} aria-hidden />\n </button>\n {showNewSession ? (\n <button\n type=\"button\"\n onClick={() => {\n list.newThread();\n onNewSession?.();\n }}\n className={cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 font-medium text-primary-foreground text-xs transition-colors hover:bg-primary/90',\n FOCUS_RING_CLASS,\n )}\n >\n <PlusIcon className=\"size-3.5\" aria-hidden />\n New session\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid=\"sessions-filters\">\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS}>\n <FilterIcon className=\"size-3.5\" aria-hidden />\n Filter\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64\">\n <FilterMenu\n query={query}\n setQuery={setQuery}\n unavailable={unavailable}\n agentOptions={agentOptions}\n channelOptions={channelOptions}\n originOptions={originOptions}\n labels={labels}\n />\n </PopoverContent>\n </Popover>\n {chips.map((chip) => (\n <span\n key={chip.field + chip.label}\n data-filter-chip={chip.field}\n className=\"inline-flex h-7 items-center gap-1 rounded-full border border-border/60 bg-muted/40 pr-1 pl-2.5 text-foreground text-xs\"\n >\n {chip.label}\n <button\n type=\"button\"\n aria-label={`Remove filter ${chip.label}`}\n onClick={() => removeChip(chip.field)}\n className={cn('rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground', FOCUS_RING_CLASS)}\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </span>\n ))}\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Clear\n </button>\n ) : null}\n <div className=\"flex-1\" />\n {savedDefault !== null && !isSavedDefault ? (\n <button type=\"button\" onClick={resetToDefault} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Reset to default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={saveAsDefault}\n disabled={isSavedDefault}\n className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {isSavedDefault ? 'Saved as default' : 'Save as default'}\n </button>\n </div>\n\n {sessions.degradedFields.length > 0 || sessions.unavailableFields.length > 0 ? (\n <p\n role=\"status\"\n data-testid=\"sessions-degraded\"\n className=\"rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-amber-900 text-xs\"\n >\n {sessions.degradedFields.length > 0\n ? `This Athena server cannot filter by ${fieldList(sessions.degradedFields)} yet, so they apply to the sessions loaded so far. `\n : ''}\n {sessions.unavailableFields.length > 0\n ? `Filtering by ${fieldList(sessions.unavailableFields)} is not available on this server yet and is off.`\n : ''}\n </p>\n ) : null}\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {showSkeleton ? (\n <SessionListSkeleton rows={6} />\n ) : sections.length === 0 ? (\n <div data-testid=\"sessions-empty\" className=\"flex flex-col items-center gap-2 py-12 text-center\">\n <p className=\"text-muted-foreground text-sm\">\n {hasFilters || query.search ? 'No sessions match these filters.' : 'No sessions yet.'}\n </p>\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={HEADER_BUTTON_CLASS}>\n Clear filters\n </button>\n ) : null}\n </div>\n ) : (\n <table className=\"w-full table-fixed border-collapse text-sm\" aria-busy={sessions.isFetching || undefined}>\n <thead>\n <tr className=\"border-border/60 border-b text-left text-[11px] text-muted-foreground uppercase tracking-wide\">\n <th scope=\"col\" className=\"py-2 pl-7 font-medium\">\n Session\n </th>\n {columns.map((id) => (\n <th key={id} scope=\"col\" className={cn('px-2 py-2 font-medium', COLUMN_WIDTH[id])}>\n {SESSIONS_COLUMNS.find((column) => column.id === id)?.label}\n </th>\n ))}\n <th scope=\"col\" className=\"w-24 py-2 pr-2\">\n <span className=\"sr-only\">Actions</span>\n </th>\n </tr>\n </thead>\n {sections.map((section) => (\n <tbody key={section.key} data-group={section.label ?? undefined}>\n {section.label ? (\n <tr>\n <th colSpan={columns.length + 2} scope=\"colgroup\" className={SECTION_HEADING_CLASS}>\n {section.label}\n <span className=\"ml-1.5 font-normal normal-case tracking-normal\">{section.items.length}</span>\n </th>\n </tr>\n ) : null}\n {section.items.map((row) => (\n <SessionsRow\n key={row.id}\n row={row}\n columns={columns}\n isActive={row.id === list.activeThreadId}\n labels={labels}\n list={list}\n onOpen={open}\n />\n ))}\n </tbody>\n ))}\n </table>\n )}\n {sessions.hasNextPage && !showSkeleton ? (\n <button\n type=\"button\"\n onClick={sessions.fetchNextPage}\n disabled={sessions.isFetchingNextPage}\n className={cn('mt-2 w-full rounded-md py-2 text-muted-foreground text-xs transition-colors hover:bg-muted disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {sessions.isFetchingNextPage ? 'Loading…' : sessions.isFetchNextPageError ? 'Retry loading more' : 'Load more'}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * A full-page session list with server-side filters, display options, an\n * attention-coloured status column and CSV export. Renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nexport function SessionsPage(props: SessionsPageProps) {\n const list = useAthenaStatewireThreadList();\n const live = useContext(AthenaSessionsLiveContext);\n if (!list || !live) return null;\n return <SessionsPageBody {...props} list={list} />;\n}\n"],"names":["jsxs","cn","FOCUS_RING_CLASS","jsx","CheckIcon","SESSIONS_DATE_PRESETS","useState","datePresetBounds","SESSION_RUN_STATUSES","runStatusLabel","_a","agentLabel","channelLabel","sessionOriginLabel","SESSIONS_COLUMNS","sessionStatusChip","plainExcerpt","pullRequestChip","StatusChip","PullRequestChip","creatorLabel","relativeTime","PinIcon","RowIconButton","MailOpenIcon","MailIcon","ArchiveIcon","readSessionsPageSettings","normalizeSessionsQuery","writeSessionsPageSettings","useEffect","useAthenaSessions","useMemo","useRef","DEFAULT_COLLAB_CHANNEL","sessionsFilterChips","groupSessionsBy","sessionsQueryKey","sessionsCsv","SearchIcon","Popover","PopoverTrigger","SlidersHorizontalIcon","PopoverContent","DownloadIcon","RefreshCwIcon","PlusIcon","FilterIcon","XIcon","SessionListSkeleton","useAthenaStatewireThreadList","useContext","AthenaSessionsLiveContext"],"mappings":"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"}
@@ -3,7 +3,7 @@ var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
5
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
- const react = require("react");
6
+ const require$$0 = require("react");
7
7
  const INDEX_REFRESH_DEBOUNCE_MS = 750;
8
8
  const INDEX_REFRESH_MAX_WAIT_MS = 3e3;
9
9
  const INDEX_REFRESH_HIDDEN_TAB_DELAY_MS = 1500;
@@ -84,28 +84,28 @@ function useIndexTriggeredRefresh({
84
84
  timing
85
85
  }) {
86
86
  const resolvedTiming = { ...DEFAULT_TIMING, ...timing };
87
- const timingRef = react.useRef(resolvedTiming);
87
+ const timingRef = require$$0.useRef(resolvedTiming);
88
88
  timingRef.current = resolvedTiming;
89
- const ledgerRef = react.useRef(null);
89
+ const ledgerRef = require$$0.useRef(null);
90
90
  ledgerRef.current ?? (ledgerRef.current = new IndexRefreshLedger(resolvedTiming));
91
- const refreshRef = react.useRef(refresh);
91
+ const refreshRef = require$$0.useRef(refresh);
92
92
  refreshRef.current = refresh;
93
- const tabShareRef = react.useRef(tabShare);
93
+ const tabShareRef = require$$0.useRef(tabShare);
94
94
  tabShareRef.current = tabShare;
95
- const firstDueAtRef = react.useRef(null);
96
- const mountedRef = react.useRef(true);
97
- react.useEffect(() => {
95
+ const firstDueAtRef = require$$0.useRef(null);
96
+ const mountedRef = require$$0.useRef(true);
97
+ require$$0.useEffect(() => {
98
98
  mountedRef.current = true;
99
99
  return () => {
100
100
  mountedRef.current = false;
101
101
  };
102
102
  }, []);
103
- const [tick, setTick] = react.useState(0);
103
+ const [tick, setTick] = require$$0.useState(0);
104
104
  const bump = () => {
105
105
  if (mountedRef.current) setTick((value) => value + 1);
106
106
  };
107
107
  const pendingKey = JSON.stringify(pending);
108
- react.useEffect(() => {
108
+ require$$0.useEffect(() => {
109
109
  var _a;
110
110
  if (!enabled) return;
111
111
  const ledger = ledgerRef.current;
@@ -1 +1 @@
1
- {"version":3,"file":"index-triggered-refresh.cjs","sources":["../../src/threads/index-triggered-refresh.ts"],"sourcesContent":["/**\n * The refresh a list runs when the pushed conversation index knows a thread\n * the list does not show yet (a session just started here or in another tab,\n * or one that just came to match a filter). Shared by the sidebar provider\n * and `useAthenaSessions`.\n *\n * - **Coalesced.** One push rarely comes alone (a new session is created,\n * titled and starts running within a second), and every open tab hears\n * each one. Keys that become due are gathered for\n * {@link INDEX_REFRESH_DEBOUNCE_MS} after the last change (at most\n * {@link INDEX_REFRESH_MAX_WAIT_MS} after the first), and nothing is sent\n * while the list is already fetching: that fetch may list the row, and the\n * keys are looked at again once it lands.\n * - **One tab for all.** With a `tabShare`, the tab that is about to refresh\n * claims the list first; the user's other tabs hold their own refresh\n * while the claim stands and take the page it shares\n * (`session-list-tab-share.ts`). A claim that lapses without a page lets\n * them refresh themselves.\n * - **Retried.** A key is settled only by a refresh that SUCCEEDED. A refused\n * one (429, network, a deploy restart) is tried again after\n * {@link INDEX_REFRESH_RETRY_BASE_MS}, doubling, at most\n * {@link INDEX_REFRESH_MAX_ATTEMPTS} times, so a thread the list\n * legitimately never shows (another app, a search) cannot loop.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport type { SessionListTabShare } from './session-list-tab-share';\n\n/** Quiet time gathered after the last change before the refresh is sent. */\nexport const INDEX_REFRESH_DEBOUNCE_MS = 750;\n/** The longest a due key waits for quiet before its refresh is sent anyway. */\nexport const INDEX_REFRESH_MAX_WAIT_MS = 3_000;\n/**\n * Extra wait for a tab nobody is looking at, so the visible tab is usually the\n * one that claims a list and reads it for the others.\n */\nexport const INDEX_REFRESH_HIDDEN_TAB_DELAY_MS = 1_500;\n/** Up to this much random wait on top, so tabs that heard the same push do not flush together. */\nexport const INDEX_REFRESH_JITTER_MS = 300;\n/** Refreshes tried per key before it is given up on. */\nexport const INDEX_REFRESH_MAX_ATTEMPTS = 3;\n/**\n * Wait before the first retry; each later retry waits twice as long. Long enough that a refusal\n * from the per-minute request window has a chance to clear (the list query has already retried\n * on its own by then).\n */\nexport const INDEX_REFRESH_RETRY_BASE_MS = 10_000;\n\nexport interface IndexRefreshTiming {\n debounceMs: number;\n hiddenTabDelayMs: number;\n jitterMs: number;\n maxWaitMs: number;\n maxAttempts: number;\n retryBaseMs: number;\n}\n\nconst DEFAULT_TIMING: IndexRefreshTiming = {\n debounceMs: INDEX_REFRESH_DEBOUNCE_MS,\n hiddenTabDelayMs: INDEX_REFRESH_HIDDEN_TAB_DELAY_MS,\n jitterMs: INDEX_REFRESH_JITTER_MS,\n maxWaitMs: INDEX_REFRESH_MAX_WAIT_MS,\n maxAttempts: INDEX_REFRESH_MAX_ATTEMPTS,\n retryBaseMs: INDEX_REFRESH_RETRY_BASE_MS,\n};\n\n/**\n * What each key has cost so far: settled (a refresh succeeded, or it ran out\n * of attempts), in flight, or failed N times and next due at an instant.\n * Exported for tests.\n */\nexport class IndexRefreshLedger {\n private readonly settled = new Set<string>();\n private readonly inFlight = new Set<string>();\n private readonly failures = new Map<string, { attempts: number; retryAt: number }>();\n\n constructor(private readonly timing: Pick<IndexRefreshTiming, 'maxAttempts' | 'retryBaseMs'>) {}\n\n /** The keys a refresh should be sent for now. */\n due(keys: readonly string[], now: number): string[] {\n return keys.filter((key) => {\n if (this.settled.has(key) || this.inFlight.has(key)) return false;\n const failure = this.failures.get(key);\n return failure === undefined || failure.retryAt <= now;\n });\n }\n\n /** When the earliest of these keys that failed is due again; `null` if none waits. */\n nextRetryAt(keys: readonly string[]): number | null {\n let next: number | null = null;\n for (const key of keys) {\n if (this.settled.has(key) || this.inFlight.has(key)) continue;\n const failure = this.failures.get(key);\n if (failure && (next === null || failure.retryAt < next)) next = failure.retryAt;\n }\n return next;\n }\n\n begin(keys: readonly string[]): void {\n for (const key of keys) this.inFlight.add(key);\n }\n\n succeed(keys: readonly string[]): void {\n for (const key of keys) {\n this.inFlight.delete(key);\n this.failures.delete(key);\n this.settled.add(key);\n }\n }\n\n fail(keys: readonly string[], now: number): void {\n for (const key of keys) {\n this.inFlight.delete(key);\n const attempts = (this.failures.get(key)?.attempts ?? 0) + 1;\n if (attempts >= this.timing.maxAttempts) {\n this.failures.delete(key);\n this.settled.add(key);\n continue;\n }\n this.failures.set(key, {\n attempts,\n retryAt: now + this.timing.retryBaseMs * 2 ** (attempts - 1),\n });\n }\n }\n}\n\n/**\n * Whether a list refresh answered. `useConversationList().refresh` resolves\n * with the query result rather than throwing, so a refused fetch shows as\n * `status: 'error'`. Exported for tests.\n */\nexport function refreshSucceeded(result: unknown): boolean {\n if (result === null || typeof result !== 'object') return true;\n const { status, isError } = result as { status?: unknown; isError?: unknown };\n return status !== 'error' && isError !== true;\n}\n\n/**\n * Run `refresh` for the `pending` keys (the threads, or thread versions, the\n * index knows and the list does not show), coalesced and retried as described\n * above. `enabled` false holds everything (no index yet, the first page not\n * read, or a fetch of the list already in flight); pending keys are looked at\n * again when it turns true.\n */\nexport function useIndexTriggeredRefresh({\n pending,\n refresh,\n enabled,\n tabShare,\n shareKey,\n timing,\n}: {\n pending: readonly string[];\n refresh: () => Promise<unknown>;\n enabled: boolean;\n /** The user's other open tabs, and this list's name among them (its first-page query key). */\n tabShare?: SessionListTabShare;\n shareKey?: string;\n /** Overrides for tests. */\n timing?: Partial<IndexRefreshTiming>;\n}): void {\n const resolvedTiming = { ...DEFAULT_TIMING, ...timing };\n const timingRef = useRef(resolvedTiming);\n timingRef.current = resolvedTiming;\n const ledgerRef = useRef<IndexRefreshLedger | null>(null);\n ledgerRef.current ??= new IndexRefreshLedger(resolvedTiming);\n const refreshRef = useRef(refresh);\n refreshRef.current = refresh;\n const tabShareRef = useRef(tabShare);\n tabShareRef.current = tabShare;\n // When the oldest key now waiting for quiet first became due.\n const firstDueAtRef = useRef<number | null>(null);\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n // Bumped when a refresh settles or a retry falls due, so the keys are looked at again.\n const [tick, setTick] = useState(0);\n const bump = () => {\n if (mountedRef.current) setTick((value) => value + 1);\n };\n\n // A stable key, so a fresh array with the same keys does not restart the wait.\n const pendingKey = JSON.stringify(pending);\n useEffect(() => {\n if (!enabled) return;\n const ledger = ledgerRef.current;\n if (!ledger) return;\n const { debounceMs, maxWaitMs, hiddenTabDelayMs, jitterMs } = timingRef.current;\n const keys = JSON.parse(pendingKey) as string[];\n const now = Date.now();\n const due = ledger.due(keys, now);\n if (due.length === 0) {\n firstDueAtRef.current = null;\n const retryAt = ledger.nextRetryAt(keys);\n if (retryAt === null) return;\n const retryId = setTimeout(bump, Math.max(0, retryAt - now));\n return () => clearTimeout(retryId);\n }\n // Another tab is reading this list: its page will be shared here. Look\n // again once its claim lapses, in case it never arrives.\n const claimedUntil = shareKey ? (tabShareRef.current?.claimedUntil(shareKey) ?? null) : null;\n if (claimedUntil !== null) {\n const claimId = setTimeout(bump, Math.max(0, claimedUntil - now));\n return () => clearTimeout(claimId);\n }\n firstDueAtRef.current ??= now;\n const isHidden = typeof document !== 'undefined' && document.visibilityState === 'hidden';\n const stagger = (isHidden ? hiddenTabDelayMs : 0) + Math.random() * jitterMs;\n const delay =\n Math.max(0, Math.min(debounceMs, firstDueAtRef.current + maxWaitMs - now)) + stagger;\n const flushId = setTimeout(() => {\n firstDueAtRef.current = null;\n const sending = ledger.due(keys, Date.now());\n if (sending.length === 0) return;\n if (shareKey && tabShareRef.current?.claimedUntil(shareKey) != null) {\n bump();\n return;\n }\n if (shareKey) tabShareRef.current?.claim(shareKey);\n ledger.begin(sending);\n void Promise.resolve()\n .then(() => refreshRef.current())\n .then(\n (result) => {\n if (refreshSucceeded(result)) ledger.succeed(sending);\n else ledger.fail(sending, Date.now());\n },\n () => ledger.fail(sending, Date.now()),\n )\n .finally(bump);\n }, delay);\n return () => clearTimeout(flushId);\n // `bump` only sets state; `tick` re-runs this after a settle or a retry falls due.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, pendingKey, shareKey, tick]);\n}\n"],"names":["useRef","useEffect","useState","_a"],"mappings":"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"}
1
+ {"version":3,"file":"index-triggered-refresh.cjs","sources":["../../src/threads/index-triggered-refresh.ts"],"sourcesContent":["/**\n * The refresh a list runs when the pushed conversation index knows a thread\n * the list does not show yet (a session just started here or in another tab,\n * or one that just came to match a filter). Shared by the sidebar provider\n * and `useAthenaSessions`.\n *\n * - **Coalesced.** One push rarely comes alone (a new session is created,\n * titled and starts running within a second), and every open tab hears\n * each one. Keys that become due are gathered for\n * {@link INDEX_REFRESH_DEBOUNCE_MS} after the last change (at most\n * {@link INDEX_REFRESH_MAX_WAIT_MS} after the first), and nothing is sent\n * while the list is already fetching: that fetch may list the row, and the\n * keys are looked at again once it lands.\n * - **One tab for all.** With a `tabShare`, the tab that is about to refresh\n * claims the list first; the user's other tabs hold their own refresh\n * while the claim stands and take the page it shares\n * (`session-list-tab-share.ts`). A claim that lapses without a page lets\n * them refresh themselves.\n * - **Retried.** A key is settled only by a refresh that SUCCEEDED. A refused\n * one (429, network, a deploy restart) is tried again after\n * {@link INDEX_REFRESH_RETRY_BASE_MS}, doubling, at most\n * {@link INDEX_REFRESH_MAX_ATTEMPTS} times, so a thread the list\n * legitimately never shows (another app, a search) cannot loop.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport type { SessionListTabShare } from './session-list-tab-share';\n\n/** Quiet time gathered after the last change before the refresh is sent. */\nexport const INDEX_REFRESH_DEBOUNCE_MS = 750;\n/** The longest a due key waits for quiet before its refresh is sent anyway. */\nexport const INDEX_REFRESH_MAX_WAIT_MS = 3_000;\n/**\n * Extra wait for a tab nobody is looking at, so the visible tab is usually the\n * one that claims a list and reads it for the others.\n */\nexport const INDEX_REFRESH_HIDDEN_TAB_DELAY_MS = 1_500;\n/** Up to this much random wait on top, so tabs that heard the same push do not flush together. */\nexport const INDEX_REFRESH_JITTER_MS = 300;\n/** Refreshes tried per key before it is given up on. */\nexport const INDEX_REFRESH_MAX_ATTEMPTS = 3;\n/**\n * Wait before the first retry; each later retry waits twice as long. Long enough that a refusal\n * from the per-minute request window has a chance to clear (the list query has already retried\n * on its own by then).\n */\nexport const INDEX_REFRESH_RETRY_BASE_MS = 10_000;\n\nexport interface IndexRefreshTiming {\n debounceMs: number;\n hiddenTabDelayMs: number;\n jitterMs: number;\n maxWaitMs: number;\n maxAttempts: number;\n retryBaseMs: number;\n}\n\nconst DEFAULT_TIMING: IndexRefreshTiming = {\n debounceMs: INDEX_REFRESH_DEBOUNCE_MS,\n hiddenTabDelayMs: INDEX_REFRESH_HIDDEN_TAB_DELAY_MS,\n jitterMs: INDEX_REFRESH_JITTER_MS,\n maxWaitMs: INDEX_REFRESH_MAX_WAIT_MS,\n maxAttempts: INDEX_REFRESH_MAX_ATTEMPTS,\n retryBaseMs: INDEX_REFRESH_RETRY_BASE_MS,\n};\n\n/**\n * What each key has cost so far: settled (a refresh succeeded, or it ran out\n * of attempts), in flight, or failed N times and next due at an instant.\n * Exported for tests.\n */\nexport class IndexRefreshLedger {\n private readonly settled = new Set<string>();\n private readonly inFlight = new Set<string>();\n private readonly failures = new Map<string, { attempts: number; retryAt: number }>();\n\n constructor(private readonly timing: Pick<IndexRefreshTiming, 'maxAttempts' | 'retryBaseMs'>) {}\n\n /** The keys a refresh should be sent for now. */\n due(keys: readonly string[], now: number): string[] {\n return keys.filter((key) => {\n if (this.settled.has(key) || this.inFlight.has(key)) return false;\n const failure = this.failures.get(key);\n return failure === undefined || failure.retryAt <= now;\n });\n }\n\n /** When the earliest of these keys that failed is due again; `null` if none waits. */\n nextRetryAt(keys: readonly string[]): number | null {\n let next: number | null = null;\n for (const key of keys) {\n if (this.settled.has(key) || this.inFlight.has(key)) continue;\n const failure = this.failures.get(key);\n if (failure && (next === null || failure.retryAt < next)) next = failure.retryAt;\n }\n return next;\n }\n\n begin(keys: readonly string[]): void {\n for (const key of keys) this.inFlight.add(key);\n }\n\n succeed(keys: readonly string[]): void {\n for (const key of keys) {\n this.inFlight.delete(key);\n this.failures.delete(key);\n this.settled.add(key);\n }\n }\n\n fail(keys: readonly string[], now: number): void {\n for (const key of keys) {\n this.inFlight.delete(key);\n const attempts = (this.failures.get(key)?.attempts ?? 0) + 1;\n if (attempts >= this.timing.maxAttempts) {\n this.failures.delete(key);\n this.settled.add(key);\n continue;\n }\n this.failures.set(key, {\n attempts,\n retryAt: now + this.timing.retryBaseMs * 2 ** (attempts - 1),\n });\n }\n }\n}\n\n/**\n * Whether a list refresh answered. `useConversationList().refresh` resolves\n * with the query result rather than throwing, so a refused fetch shows as\n * `status: 'error'`. Exported for tests.\n */\nexport function refreshSucceeded(result: unknown): boolean {\n if (result === null || typeof result !== 'object') return true;\n const { status, isError } = result as { status?: unknown; isError?: unknown };\n return status !== 'error' && isError !== true;\n}\n\n/**\n * Run `refresh` for the `pending` keys (the threads, or thread versions, the\n * index knows and the list does not show), coalesced and retried as described\n * above. `enabled` false holds everything (no index yet, the first page not\n * read, or a fetch of the list already in flight); pending keys are looked at\n * again when it turns true.\n */\nexport function useIndexTriggeredRefresh({\n pending,\n refresh,\n enabled,\n tabShare,\n shareKey,\n timing,\n}: {\n pending: readonly string[];\n refresh: () => Promise<unknown>;\n enabled: boolean;\n /** The user's other open tabs, and this list's name among them (its first-page query key). */\n tabShare?: SessionListTabShare;\n shareKey?: string;\n /** Overrides for tests. */\n timing?: Partial<IndexRefreshTiming>;\n}): void {\n const resolvedTiming = { ...DEFAULT_TIMING, ...timing };\n const timingRef = useRef(resolvedTiming);\n timingRef.current = resolvedTiming;\n const ledgerRef = useRef<IndexRefreshLedger | null>(null);\n ledgerRef.current ??= new IndexRefreshLedger(resolvedTiming);\n const refreshRef = useRef(refresh);\n refreshRef.current = refresh;\n const tabShareRef = useRef(tabShare);\n tabShareRef.current = tabShare;\n // When the oldest key now waiting for quiet first became due.\n const firstDueAtRef = useRef<number | null>(null);\n const mountedRef = useRef(true);\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n // Bumped when a refresh settles or a retry falls due, so the keys are looked at again.\n const [tick, setTick] = useState(0);\n const bump = () => {\n if (mountedRef.current) setTick((value) => value + 1);\n };\n\n // A stable key, so a fresh array with the same keys does not restart the wait.\n const pendingKey = JSON.stringify(pending);\n useEffect(() => {\n if (!enabled) return;\n const ledger = ledgerRef.current;\n if (!ledger) return;\n const { debounceMs, maxWaitMs, hiddenTabDelayMs, jitterMs } = timingRef.current;\n const keys = JSON.parse(pendingKey) as string[];\n const now = Date.now();\n const due = ledger.due(keys, now);\n if (due.length === 0) {\n firstDueAtRef.current = null;\n const retryAt = ledger.nextRetryAt(keys);\n if (retryAt === null) return;\n const retryId = setTimeout(bump, Math.max(0, retryAt - now));\n return () => clearTimeout(retryId);\n }\n // Another tab is reading this list: its page will be shared here. Look\n // again once its claim lapses, in case it never arrives.\n const claimedUntil = shareKey ? (tabShareRef.current?.claimedUntil(shareKey) ?? null) : null;\n if (claimedUntil !== null) {\n const claimId = setTimeout(bump, Math.max(0, claimedUntil - now));\n return () => clearTimeout(claimId);\n }\n firstDueAtRef.current ??= now;\n const isHidden = typeof document !== 'undefined' && document.visibilityState === 'hidden';\n const stagger = (isHidden ? hiddenTabDelayMs : 0) + Math.random() * jitterMs;\n const delay =\n Math.max(0, Math.min(debounceMs, firstDueAtRef.current + maxWaitMs - now)) + stagger;\n const flushId = setTimeout(() => {\n firstDueAtRef.current = null;\n const sending = ledger.due(keys, Date.now());\n if (sending.length === 0) return;\n if (shareKey && tabShareRef.current?.claimedUntil(shareKey) != null) {\n bump();\n return;\n }\n if (shareKey) tabShareRef.current?.claim(shareKey);\n ledger.begin(sending);\n void Promise.resolve()\n .then(() => refreshRef.current())\n .then(\n (result) => {\n if (refreshSucceeded(result)) ledger.succeed(sending);\n else ledger.fail(sending, Date.now());\n },\n () => ledger.fail(sending, Date.now()),\n )\n .finally(bump);\n }, delay);\n return () => clearTimeout(flushId);\n // `bump` only sets state; `tick` re-runs this after a settle or a retry falls due.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, pendingKey, shareKey, tick]);\n}\n"],"names":["useRef","useEffect","useState","_a"],"mappings":"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"}
@@ -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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"}