@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,25 +1,42 @@
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
+ const offlineStatus = require("../agent-runtime/src/offline-status.cjs");
4
5
  const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
5
6
  const AttachmentContext = require("./AttachmentContext.cjs");
6
7
  const useFileUpload = require("./useFileUpload.cjs");
7
8
  const useDeepAgentChatOutbox = require("../agent-runtime/src/use-deep-agent-chat-outbox.cjs");
8
- const OFFLINE_FILE_ATTACH_MESSAGE = "Files can't be attached while Athena can't be reached. Messages you send now go out when it's back — attach the file then.";
9
9
  const ATTACH_FAILURE_MESSAGE = {
10
10
  paperclip: "Failed to attach the selected files",
11
11
  drop: "Failed to attach the dropped files",
12
12
  paste: "Failed to attach the pasted images"
13
13
  };
14
+ function withPicturePreviews({
15
+ assets,
16
+ files
17
+ }) {
18
+ if (typeof URL === "undefined" || typeof URL.createObjectURL !== "function") return assets;
19
+ const unclaimed = [...files];
20
+ const positional = assets.length === files.length;
21
+ const claim = (file) => {
22
+ const at = file === void 0 ? -1 : unclaimed.indexOf(file);
23
+ return at === -1 ? void 0 : unclaimed.splice(at, 1)[0];
24
+ };
25
+ return assets.map((asset, index) => {
26
+ const file = asset.fileIndex !== void 0 ? claim(files[asset.fileIndex]) : claim(unclaimed.find((candidate) => candidate.name === asset.fileName)) ?? (positional ? claim(files[index]) : void 0);
27
+ if (!file || !file.type.startsWith("image/")) return asset;
28
+ return { ...asset, previewUrl: URL.createObjectURL(file) };
29
+ });
30
+ }
14
31
  function useAttachFiles() {
15
32
  const { upload, isUploading, error, clearError } = useFileUpload.useFileUpload();
16
33
  const { addAttachments, setIsUploading, setNotice } = AttachmentContext.useAttachments();
17
34
  const outbox = useDeepAgentChatOutbox.useDeepAgentChatOutboxContext();
18
- const attachFiles = react.useCallback(
35
+ const attachFiles = require$$0.useCallback(
19
36
  async (files, source) => {
20
37
  if (files.length === 0) return [];
21
38
  if (outbox && !outbox.reachability.get()) {
22
- setNotice(OFFLINE_FILE_ATTACH_MESSAGE);
39
+ setNotice(offlineStatus.attachmentNeedsConnection({ kind: "file", messagesWait: true }));
23
40
  athenaDiagnostics.athenaDiagnostics.emit("composer.attachment.refused_offline", {
24
41
  level: "info",
25
42
  data: { source, count: files.length }
@@ -29,7 +46,7 @@ function useAttachFiles() {
29
46
  setNotice(null);
30
47
  setIsUploading(true);
31
48
  try {
32
- const assets = await upload([...files]);
49
+ const assets = withPicturePreviews({ assets: await upload([...files]), files });
33
50
  if (assets.length > 0) addAttachments(assets);
34
51
  return assets;
35
52
  } catch (error2) {
@@ -48,6 +65,6 @@ function useAttachFiles() {
48
65
  );
49
66
  return { attachFiles, isUploading, error, clearError };
50
67
  }
51
- exports.OFFLINE_FILE_ATTACH_MESSAGE = OFFLINE_FILE_ATTACH_MESSAGE;
52
68
  exports.useAttachFiles = useAttachFiles;
69
+ exports.withPicturePreviews = withPicturePreviews;
53
70
  //# sourceMappingURL=useAttachFiles.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAttachFiles.cjs","sources":["../../src/composer/useAttachFiles.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useDeepAgentChatOutboxContext } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useAttachments } from './AttachmentContext';\nimport { useFileUpload, type UploadedAsset } from './useFileUpload';\n\n/**\n * What the composer says when a file is picked, pasted or dropped while Athena can't be reached\n * (the same words as Olympus's): the upload cannot happen, and a message sent now waits in the chat\n * outbox with only the files that were already uploaded.\n */\nexport const OFFLINE_FILE_ATTACH_MESSAGE =\n \"Files can't be attached while Athena can't be reached. Messages you send now go out when it's back — attach the file then.\";\n\n/** Which intake the files came through — carried on the diagnostics event. */\nexport type AttachFilesSource = 'paperclip' | 'drop' | 'paste';\n\nconst ATTACH_FAILURE_MESSAGE: Record<AttachFilesSource, string> = {\n paperclip: 'Failed to attach the selected files',\n drop: 'Failed to attach the dropped files',\n paste: 'Failed to attach the pasted images',\n};\n\nexport interface UseAttachFilesReturn {\n /**\n * Upload files as Athena assets and add them to the attachment pills.\n * Resolves to the assets attached; a failed upload resolves to `[]` after\n * recording `composer.attachment.error` on the diagnostics bus (and in\n * `error`).\n */\n attachFiles: (files: readonly File[], source: AttachFilesSource) => Promise<UploadedAsset[]>;\n /** This intake's own upload in flight. */\n isUploading: boolean;\n /** Last failure of this intake, for its own affordance. */\n error: string | null;\n clearError: () => void;\n}\n\n/**\n * The one intake path for the attachment pills: the paperclip, the drop zone\n * and the composer's paste all upload through here, so a failure reaches the\n * diagnostics bus the same way and the shared `isUploading` flag — which\n * parks every submit path — is set for exactly the upload's duration.\n *\n * While the chat's outbox (a host's `chatOutbox`) says Athena can't be\n * reached, a file is not attached: its upload could only fail, and a message\n * that waits to be sent carries only files already uploaded. The composer\n * says so (`notice`, {@link OFFLINE_FILE_ATTACH_MESSAGE}).\n */\nexport function useAttachFiles(): UseAttachFilesReturn {\n const { upload, isUploading, error, clearError } = useFileUpload();\n const { addAttachments, setIsUploading, setNotice } = useAttachments();\n const outbox = useDeepAgentChatOutboxContext();\n\n const attachFiles = useCallback(\n async (files: readonly File[], source: AttachFilesSource): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n if (outbox && !outbox.reachability.get()) {\n setNotice(OFFLINE_FILE_ATTACH_MESSAGE);\n athenaDiagnostics.emit('composer.attachment.refused_offline', {\n level: 'info',\n data: { source, count: files.length },\n });\n return [];\n }\n setNotice(null);\n setIsUploading(true);\n try {\n const assets = await upload([...files]);\n if (assets.length > 0) addAttachments(assets);\n return assets;\n } catch (error) {\n athenaDiagnostics.error(\n 'composer.attachment.error',\n error,\n { code: 'attachment_failed', message: ATTACH_FAILURE_MESSAGE[source] },\n { source, count: files.length },\n );\n return [];\n } finally {\n setIsUploading(false);\n }\n },\n [addAttachments, outbox, setIsUploading, setNotice, upload],\n );\n\n return { attachFiles, isUploading, error, clearError };\n}\n"],"names":["useFileUpload","useAttachments","useDeepAgentChatOutboxContext","useCallback","athenaDiagnostics","error"],"mappings":";;;;;;;AAWO,MAAM,8BACX;AAKF,MAAM,yBAA4D;AAAA,EAChE,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AACT;AA4BO,SAAS,iBAAuC;AACrD,QAAM,EAAE,QAAQ,aAAa,OAAO,WAAA,IAAeA,cAAAA,cAAA;AACnD,QAAM,EAAE,gBAAgB,gBAAgB,UAAA,IAAcC,kBAAAA,eAAA;AACtD,QAAM,SAASC,uBAAAA,8BAAA;AAEf,QAAM,cAAcC,MAAAA;AAAAA,IAClB,OAAO,OAAwB,WAAwD;AACrF,UAAI,MAAM,WAAW,EAAG,QAAO,CAAA;AAC/B,UAAI,UAAU,CAAC,OAAO,aAAa,OAAO;AACxC,kBAAU,2BAA2B;AACrCC,0BAAAA,kBAAkB,KAAK,uCAAuC;AAAA,UAC5D,OAAO;AAAA,UACP,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO,CACrC;AACD,eAAO,CAAA;AAAA,MACT;AACA,gBAAU,IAAI;AACd,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,CAAC,GAAG,KAAK,CAAC;AACtC,YAAI,OAAO,SAAS,EAAG,gBAAe,MAAM;AAC5C,eAAO;AAAA,MACT,SAASC,QAAO;AACdD,0BAAAA,kBAAkB;AAAA,UAChB;AAAA,UACAC;AAAAA,UACA,EAAE,MAAM,qBAAqB,SAAS,uBAAuB,MAAM,EAAA;AAAA,UACnE,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO;AAEhC,eAAO,CAAA;AAAA,MACT,UAAA;AACE,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,QAAQ,gBAAgB,WAAW,MAAM;AAAA,EAAA;AAG5D,SAAO,EAAE,aAAa,aAAa,OAAO,WAAA;AAC5C;;;"}
1
+ {"version":3,"file":"useAttachFiles.cjs","sources":["../../src/composer/useAttachFiles.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useDeepAgentChatOutboxContext } from '@athenaintel/agent-runtime';\nimport { attachmentNeedsConnection } from '@athenaintel/agent-runtime/offline-status';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useAttachments } from './AttachmentContext';\nimport { useFileUpload, type UploadedAsset } from './useFileUpload';\n\n/** Which intake the files came through — carried on the diagnostics event. */\nexport type AttachFilesSource = 'paperclip' | 'drop' | 'paste';\n\nconst ATTACH_FAILURE_MESSAGE: Record<AttachFilesSource, string> = {\n paperclip: 'Failed to attach the selected files',\n drop: 'Failed to attach the dropped files',\n paste: 'Failed to attach the pasted images',\n};\n\nexport interface UseAttachFilesReturn {\n /**\n * Upload files as Athena assets and add them to the attachment pills.\n * Resolves to the assets attached; a failed upload resolves to `[]` after\n * recording `composer.attachment.error` on the diagnostics bus (and in\n * `error`).\n */\n attachFiles: (files: readonly File[], source: AttachFilesSource) => Promise<UploadedAsset[]>;\n /** This intake's own upload in flight. */\n isUploading: boolean;\n /** Last failure of this intake, for its own affordance. */\n error: string | null;\n clearError: () => void;\n}\n\n/**\n * `assets` with a local preview of each picture among `files`, so the draft\n * shows the picture itself and opens it full screen before anything is sent.\n * Each asset takes the file the upload says it came from (`fileIndex`); from a\n * server that does not say, the file of the same name, else the one at the\n * same position when every file came back. Other files, and a browser without\n * object URLs, keep the name pill.\n */\nexport function withPicturePreviews({\n assets,\n files,\n}: {\n assets: UploadedAsset[];\n files: readonly File[];\n}): UploadedAsset[] {\n if (typeof URL === 'undefined' || typeof URL.createObjectURL !== 'function') return assets;\n const unclaimed = [...files];\n const positional = assets.length === files.length;\n const claim = (file: File | undefined): File | undefined => {\n const at = file === undefined ? -1 : unclaimed.indexOf(file);\n return at === -1 ? undefined : unclaimed.splice(at, 1)[0];\n };\n return assets.map((asset, index) => {\n const file =\n asset.fileIndex !== undefined\n ? claim(files[asset.fileIndex])\n : (claim(unclaimed.find((candidate) => candidate.name === asset.fileName)) ??\n (positional ? claim(files[index]) : undefined));\n if (!file || !file.type.startsWith('image/')) return asset;\n return { ...asset, previewUrl: URL.createObjectURL(file) };\n });\n}\n\n/**\n * The one intake path for the attachment pills: the paperclip, the drop zone\n * and the composer's paste all upload through here, so a failure reaches the\n * diagnostics bus the same way and the shared `isUploading` flag — which\n * parks every submit path — is set for exactly the upload's duration.\n *\n * While the chat's outbox (a host's `chatOutbox`) says Athena can't be\n * reached, a file is not attached: its upload could only fail, and a message\n * that waits to be sent carries only files already uploaded. The composer\n * says so (`notice`) in the words every Athena app uses\n * (`attachmentNeedsConnection`, `@athenaintel/agent-runtime/offline-status`):\n * the message still goes, since the outbox keeps it.\n */\nexport function useAttachFiles(): UseAttachFilesReturn {\n const { upload, isUploading, error, clearError } = useFileUpload();\n const { addAttachments, setIsUploading, setNotice } = useAttachments();\n const outbox = useDeepAgentChatOutboxContext();\n\n const attachFiles = useCallback(\n async (files: readonly File[], source: AttachFilesSource): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n if (outbox && !outbox.reachability.get()) {\n setNotice(attachmentNeedsConnection({ kind: 'file', messagesWait: true }));\n athenaDiagnostics.emit('composer.attachment.refused_offline', {\n level: 'info',\n data: { source, count: files.length },\n });\n return [];\n }\n setNotice(null);\n setIsUploading(true);\n try {\n const assets = withPicturePreviews({ assets: await upload([...files]), files });\n if (assets.length > 0) addAttachments(assets);\n return assets;\n } catch (error) {\n athenaDiagnostics.error(\n 'composer.attachment.error',\n error,\n { code: 'attachment_failed', message: ATTACH_FAILURE_MESSAGE[source] },\n { source, count: files.length },\n );\n return [];\n } finally {\n setIsUploading(false);\n }\n },\n [addAttachments, outbox, setIsUploading, setNotice, upload],\n );\n\n return { attachFiles, isUploading, error, clearError };\n}\n"],"names":["useFileUpload","useAttachments","useDeepAgentChatOutboxContext","useCallback","attachmentNeedsConnection","athenaDiagnostics","error"],"mappings":";;;;;;;;AAUA,MAAM,yBAA4D;AAAA,EAChE,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AACT;AAyBO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGoB;AAClB,MAAI,OAAO,QAAQ,eAAe,OAAO,IAAI,oBAAoB,WAAY,QAAO;AACpF,QAAM,YAAY,CAAC,GAAG,KAAK;AAC3B,QAAM,aAAa,OAAO,WAAW,MAAM;AAC3C,QAAM,QAAQ,CAAC,SAA6C;AAC1D,UAAM,KAAK,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI;AAC3D,WAAO,OAAO,KAAK,SAAY,UAAU,OAAO,IAAI,CAAC,EAAE,CAAC;AAAA,EAC1D;AACA,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,OACJ,MAAM,cAAc,SAChB,MAAM,MAAM,MAAM,SAAS,CAAC,IAC3B,MAAM,UAAU,KAAK,CAAC,cAAc,UAAU,SAAS,MAAM,QAAQ,CAAC,MACtE,aAAa,MAAM,MAAM,KAAK,CAAC,IAAI;AAC1C,QAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,WAAW,QAAQ,EAAG,QAAO;AACrD,WAAO,EAAE,GAAG,OAAO,YAAY,IAAI,gBAAgB,IAAI,EAAA;AAAA,EACzD,CAAC;AACH;AAeO,SAAS,iBAAuC;AACrD,QAAM,EAAE,QAAQ,aAAa,OAAO,WAAA,IAAeA,cAAAA,cAAA;AACnD,QAAM,EAAE,gBAAgB,gBAAgB,UAAA,IAAcC,kBAAAA,eAAA;AACtD,QAAM,SAASC,uBAAAA,8BAAA;AAEf,QAAM,cAAcC,WAAAA;AAAAA,IAClB,OAAO,OAAwB,WAAwD;AACrF,UAAI,MAAM,WAAW,EAAG,QAAO,CAAA;AAC/B,UAAI,UAAU,CAAC,OAAO,aAAa,OAAO;AACxC,kBAAUC,cAAAA,0BAA0B,EAAE,MAAM,QAAQ,cAAc,KAAA,CAAM,CAAC;AACzEC,0BAAAA,kBAAkB,KAAK,uCAAuC;AAAA,UAC5D,OAAO;AAAA,UACP,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO,CACrC;AACD,eAAO,CAAA;AAAA,MACT;AACA,gBAAU,IAAI;AACd,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,SAAS,oBAAoB,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO;AAC9E,YAAI,OAAO,SAAS,EAAG,gBAAe,MAAM;AAC5C,eAAO;AAAA,MACT,SAASC,QAAO;AACdD,0BAAAA,kBAAkB;AAAA,UAChB;AAAA,UACAC;AAAAA,UACA,EAAE,MAAM,qBAAqB,SAAS,uBAAuB,MAAM,EAAA;AAAA,UACnE,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO;AAEhC,eAAO,CAAA;AAAA,MACT,UAAA;AACE,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,QAAQ,gBAAgB,WAAW,MAAM;AAAA,EAAA;AAG5D,SAAO,EAAE,aAAa,aAAa,OAAO,WAAA;AAC5C;;;"}
@@ -1,10 +1,4 @@
1
1
  import { type UploadedAsset } from './useFileUpload';
2
- /**
3
- * What the composer says when a file is picked, pasted or dropped while Athena can't be reached
4
- * (the same words as Olympus's): the upload cannot happen, and a message sent now waits in the chat
5
- * outbox with only the files that were already uploaded.
6
- */
7
- export declare const OFFLINE_FILE_ATTACH_MESSAGE = "Files can't be attached while Athena can't be reached. Messages you send now go out when it's back \u2014 attach the file then.";
8
2
  /** Which intake the files came through — carried on the diagnostics event. */
9
3
  export type AttachFilesSource = 'paperclip' | 'drop' | 'paste';
10
4
  export interface UseAttachFilesReturn {
@@ -21,6 +15,18 @@ export interface UseAttachFilesReturn {
21
15
  error: string | null;
22
16
  clearError: () => void;
23
17
  }
18
+ /**
19
+ * `assets` with a local preview of each picture among `files`, so the draft
20
+ * shows the picture itself and opens it full screen before anything is sent.
21
+ * Each asset takes the file the upload says it came from (`fileIndex`); from a
22
+ * server that does not say, the file of the same name, else the one at the
23
+ * same position when every file came back. Other files, and a browser without
24
+ * object URLs, keep the name pill.
25
+ */
26
+ export declare function withPicturePreviews({ assets, files, }: {
27
+ assets: UploadedAsset[];
28
+ files: readonly File[];
29
+ }): UploadedAsset[];
24
30
  /**
25
31
  * The one intake path for the attachment pills: the paperclip, the drop zone
26
32
  * and the composer's paste all upload through here, so a failure reaches the
@@ -30,6 +36,8 @@ export interface UseAttachFilesReturn {
30
36
  * While the chat's outbox (a host's `chatOutbox`) says Athena can't be
31
37
  * reached, a file is not attached: its upload could only fail, and a message
32
38
  * that waits to be sent carries only files already uploaded. The composer
33
- * says so (`notice`, {@link OFFLINE_FILE_ATTACH_MESSAGE}).
39
+ * says so (`notice`) in the words every Athena app uses
40
+ * (`attachmentNeedsConnection`, `@athenaintel/agent-runtime/offline-status`):
41
+ * the message still goes, since the outbox keeps it.
34
42
  */
35
43
  export declare function useAttachFiles(): UseAttachFilesReturn;
@@ -1,14 +1,31 @@
1
1
  import { useCallback } from "react";
2
+ import { attachmentNeedsConnection } from "../agent-runtime/src/offline-status.js";
2
3
  import { athenaDiagnostics } from "../diagnostics/athena-diagnostics.js";
3
4
  import { useAttachments } from "./AttachmentContext.js";
4
5
  import { useFileUpload } from "./useFileUpload.js";
5
6
  import { useDeepAgentChatOutboxContext } from "../agent-runtime/src/use-deep-agent-chat-outbox.js";
6
- const OFFLINE_FILE_ATTACH_MESSAGE = "Files can't be attached while Athena can't be reached. Messages you send now go out when it's back — attach the file then.";
7
7
  const ATTACH_FAILURE_MESSAGE = {
8
8
  paperclip: "Failed to attach the selected files",
9
9
  drop: "Failed to attach the dropped files",
10
10
  paste: "Failed to attach the pasted images"
11
11
  };
12
+ function withPicturePreviews({
13
+ assets,
14
+ files
15
+ }) {
16
+ if (typeof URL === "undefined" || typeof URL.createObjectURL !== "function") return assets;
17
+ const unclaimed = [...files];
18
+ const positional = assets.length === files.length;
19
+ const claim = (file) => {
20
+ const at = file === void 0 ? -1 : unclaimed.indexOf(file);
21
+ return at === -1 ? void 0 : unclaimed.splice(at, 1)[0];
22
+ };
23
+ return assets.map((asset, index) => {
24
+ const file = asset.fileIndex !== void 0 ? claim(files[asset.fileIndex]) : claim(unclaimed.find((candidate) => candidate.name === asset.fileName)) ?? (positional ? claim(files[index]) : void 0);
25
+ if (!file || !file.type.startsWith("image/")) return asset;
26
+ return { ...asset, previewUrl: URL.createObjectURL(file) };
27
+ });
28
+ }
12
29
  function useAttachFiles() {
13
30
  const { upload, isUploading, error, clearError } = useFileUpload();
14
31
  const { addAttachments, setIsUploading, setNotice } = useAttachments();
@@ -17,7 +34,7 @@ function useAttachFiles() {
17
34
  async (files, source) => {
18
35
  if (files.length === 0) return [];
19
36
  if (outbox && !outbox.reachability.get()) {
20
- setNotice(OFFLINE_FILE_ATTACH_MESSAGE);
37
+ setNotice(attachmentNeedsConnection({ kind: "file", messagesWait: true }));
21
38
  athenaDiagnostics.emit("composer.attachment.refused_offline", {
22
39
  level: "info",
23
40
  data: { source, count: files.length }
@@ -27,7 +44,7 @@ function useAttachFiles() {
27
44
  setNotice(null);
28
45
  setIsUploading(true);
29
46
  try {
30
- const assets = await upload([...files]);
47
+ const assets = withPicturePreviews({ assets: await upload([...files]), files });
31
48
  if (assets.length > 0) addAttachments(assets);
32
49
  return assets;
33
50
  } catch (error2) {
@@ -47,7 +64,7 @@ function useAttachFiles() {
47
64
  return { attachFiles, isUploading, error, clearError };
48
65
  }
49
66
  export {
50
- OFFLINE_FILE_ATTACH_MESSAGE,
51
- useAttachFiles
67
+ useAttachFiles,
68
+ withPicturePreviews
52
69
  };
53
70
  //# sourceMappingURL=useAttachFiles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAttachFiles.js","sources":["../../src/composer/useAttachFiles.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useDeepAgentChatOutboxContext } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useAttachments } from './AttachmentContext';\nimport { useFileUpload, type UploadedAsset } from './useFileUpload';\n\n/**\n * What the composer says when a file is picked, pasted or dropped while Athena can't be reached\n * (the same words as Olympus's): the upload cannot happen, and a message sent now waits in the chat\n * outbox with only the files that were already uploaded.\n */\nexport const OFFLINE_FILE_ATTACH_MESSAGE =\n \"Files can't be attached while Athena can't be reached. Messages you send now go out when it's back — attach the file then.\";\n\n/** Which intake the files came through — carried on the diagnostics event. */\nexport type AttachFilesSource = 'paperclip' | 'drop' | 'paste';\n\nconst ATTACH_FAILURE_MESSAGE: Record<AttachFilesSource, string> = {\n paperclip: 'Failed to attach the selected files',\n drop: 'Failed to attach the dropped files',\n paste: 'Failed to attach the pasted images',\n};\n\nexport interface UseAttachFilesReturn {\n /**\n * Upload files as Athena assets and add them to the attachment pills.\n * Resolves to the assets attached; a failed upload resolves to `[]` after\n * recording `composer.attachment.error` on the diagnostics bus (and in\n * `error`).\n */\n attachFiles: (files: readonly File[], source: AttachFilesSource) => Promise<UploadedAsset[]>;\n /** This intake's own upload in flight. */\n isUploading: boolean;\n /** Last failure of this intake, for its own affordance. */\n error: string | null;\n clearError: () => void;\n}\n\n/**\n * The one intake path for the attachment pills: the paperclip, the drop zone\n * and the composer's paste all upload through here, so a failure reaches the\n * diagnostics bus the same way and the shared `isUploading` flag — which\n * parks every submit path — is set for exactly the upload's duration.\n *\n * While the chat's outbox (a host's `chatOutbox`) says Athena can't be\n * reached, a file is not attached: its upload could only fail, and a message\n * that waits to be sent carries only files already uploaded. The composer\n * says so (`notice`, {@link OFFLINE_FILE_ATTACH_MESSAGE}).\n */\nexport function useAttachFiles(): UseAttachFilesReturn {\n const { upload, isUploading, error, clearError } = useFileUpload();\n const { addAttachments, setIsUploading, setNotice } = useAttachments();\n const outbox = useDeepAgentChatOutboxContext();\n\n const attachFiles = useCallback(\n async (files: readonly File[], source: AttachFilesSource): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n if (outbox && !outbox.reachability.get()) {\n setNotice(OFFLINE_FILE_ATTACH_MESSAGE);\n athenaDiagnostics.emit('composer.attachment.refused_offline', {\n level: 'info',\n data: { source, count: files.length },\n });\n return [];\n }\n setNotice(null);\n setIsUploading(true);\n try {\n const assets = await upload([...files]);\n if (assets.length > 0) addAttachments(assets);\n return assets;\n } catch (error) {\n athenaDiagnostics.error(\n 'composer.attachment.error',\n error,\n { code: 'attachment_failed', message: ATTACH_FAILURE_MESSAGE[source] },\n { source, count: files.length },\n );\n return [];\n } finally {\n setIsUploading(false);\n }\n },\n [addAttachments, outbox, setIsUploading, setNotice, upload],\n );\n\n return { attachFiles, isUploading, error, clearError };\n}\n"],"names":["error"],"mappings":";;;;;AAWO,MAAM,8BACX;AAKF,MAAM,yBAA4D;AAAA,EAChE,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AACT;AA4BO,SAAS,iBAAuC;AACrD,QAAM,EAAE,QAAQ,aAAa,OAAO,WAAA,IAAe,cAAA;AACnD,QAAM,EAAE,gBAAgB,gBAAgB,UAAA,IAAc,eAAA;AACtD,QAAM,SAAS,8BAAA;AAEf,QAAM,cAAc;AAAA,IAClB,OAAO,OAAwB,WAAwD;AACrF,UAAI,MAAM,WAAW,EAAG,QAAO,CAAA;AAC/B,UAAI,UAAU,CAAC,OAAO,aAAa,OAAO;AACxC,kBAAU,2BAA2B;AACrC,0BAAkB,KAAK,uCAAuC;AAAA,UAC5D,OAAO;AAAA,UACP,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO,CACrC;AACD,eAAO,CAAA;AAAA,MACT;AACA,gBAAU,IAAI;AACd,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,CAAC,GAAG,KAAK,CAAC;AACtC,YAAI,OAAO,SAAS,EAAG,gBAAe,MAAM;AAC5C,eAAO;AAAA,MACT,SAASA,QAAO;AACd,0BAAkB;AAAA,UAChB;AAAA,UACAA;AAAAA,UACA,EAAE,MAAM,qBAAqB,SAAS,uBAAuB,MAAM,EAAA;AAAA,UACnE,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO;AAEhC,eAAO,CAAA;AAAA,MACT,UAAA;AACE,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,QAAQ,gBAAgB,WAAW,MAAM;AAAA,EAAA;AAG5D,SAAO,EAAE,aAAa,aAAa,OAAO,WAAA;AAC5C;"}
1
+ {"version":3,"file":"useAttachFiles.js","sources":["../../src/composer/useAttachFiles.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useDeepAgentChatOutboxContext } from '@athenaintel/agent-runtime';\nimport { attachmentNeedsConnection } from '@athenaintel/agent-runtime/offline-status';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { useAttachments } from './AttachmentContext';\nimport { useFileUpload, type UploadedAsset } from './useFileUpload';\n\n/** Which intake the files came through — carried on the diagnostics event. */\nexport type AttachFilesSource = 'paperclip' | 'drop' | 'paste';\n\nconst ATTACH_FAILURE_MESSAGE: Record<AttachFilesSource, string> = {\n paperclip: 'Failed to attach the selected files',\n drop: 'Failed to attach the dropped files',\n paste: 'Failed to attach the pasted images',\n};\n\nexport interface UseAttachFilesReturn {\n /**\n * Upload files as Athena assets and add them to the attachment pills.\n * Resolves to the assets attached; a failed upload resolves to `[]` after\n * recording `composer.attachment.error` on the diagnostics bus (and in\n * `error`).\n */\n attachFiles: (files: readonly File[], source: AttachFilesSource) => Promise<UploadedAsset[]>;\n /** This intake's own upload in flight. */\n isUploading: boolean;\n /** Last failure of this intake, for its own affordance. */\n error: string | null;\n clearError: () => void;\n}\n\n/**\n * `assets` with a local preview of each picture among `files`, so the draft\n * shows the picture itself and opens it full screen before anything is sent.\n * Each asset takes the file the upload says it came from (`fileIndex`); from a\n * server that does not say, the file of the same name, else the one at the\n * same position when every file came back. Other files, and a browser without\n * object URLs, keep the name pill.\n */\nexport function withPicturePreviews({\n assets,\n files,\n}: {\n assets: UploadedAsset[];\n files: readonly File[];\n}): UploadedAsset[] {\n if (typeof URL === 'undefined' || typeof URL.createObjectURL !== 'function') return assets;\n const unclaimed = [...files];\n const positional = assets.length === files.length;\n const claim = (file: File | undefined): File | undefined => {\n const at = file === undefined ? -1 : unclaimed.indexOf(file);\n return at === -1 ? undefined : unclaimed.splice(at, 1)[0];\n };\n return assets.map((asset, index) => {\n const file =\n asset.fileIndex !== undefined\n ? claim(files[asset.fileIndex])\n : (claim(unclaimed.find((candidate) => candidate.name === asset.fileName)) ??\n (positional ? claim(files[index]) : undefined));\n if (!file || !file.type.startsWith('image/')) return asset;\n return { ...asset, previewUrl: URL.createObjectURL(file) };\n });\n}\n\n/**\n * The one intake path for the attachment pills: the paperclip, the drop zone\n * and the composer's paste all upload through here, so a failure reaches the\n * diagnostics bus the same way and the shared `isUploading` flag — which\n * parks every submit path — is set for exactly the upload's duration.\n *\n * While the chat's outbox (a host's `chatOutbox`) says Athena can't be\n * reached, a file is not attached: its upload could only fail, and a message\n * that waits to be sent carries only files already uploaded. The composer\n * says so (`notice`) in the words every Athena app uses\n * (`attachmentNeedsConnection`, `@athenaintel/agent-runtime/offline-status`):\n * the message still goes, since the outbox keeps it.\n */\nexport function useAttachFiles(): UseAttachFilesReturn {\n const { upload, isUploading, error, clearError } = useFileUpload();\n const { addAttachments, setIsUploading, setNotice } = useAttachments();\n const outbox = useDeepAgentChatOutboxContext();\n\n const attachFiles = useCallback(\n async (files: readonly File[], source: AttachFilesSource): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n if (outbox && !outbox.reachability.get()) {\n setNotice(attachmentNeedsConnection({ kind: 'file', messagesWait: true }));\n athenaDiagnostics.emit('composer.attachment.refused_offline', {\n level: 'info',\n data: { source, count: files.length },\n });\n return [];\n }\n setNotice(null);\n setIsUploading(true);\n try {\n const assets = withPicturePreviews({ assets: await upload([...files]), files });\n if (assets.length > 0) addAttachments(assets);\n return assets;\n } catch (error) {\n athenaDiagnostics.error(\n 'composer.attachment.error',\n error,\n { code: 'attachment_failed', message: ATTACH_FAILURE_MESSAGE[source] },\n { source, count: files.length },\n );\n return [];\n } finally {\n setIsUploading(false);\n }\n },\n [addAttachments, outbox, setIsUploading, setNotice, upload],\n );\n\n return { attachFiles, isUploading, error, clearError };\n}\n"],"names":["error"],"mappings":";;;;;;AAUA,MAAM,yBAA4D;AAAA,EAChE,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AACT;AAyBO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AACF,GAGoB;AAClB,MAAI,OAAO,QAAQ,eAAe,OAAO,IAAI,oBAAoB,WAAY,QAAO;AACpF,QAAM,YAAY,CAAC,GAAG,KAAK;AAC3B,QAAM,aAAa,OAAO,WAAW,MAAM;AAC3C,QAAM,QAAQ,CAAC,SAA6C;AAC1D,UAAM,KAAK,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI;AAC3D,WAAO,OAAO,KAAK,SAAY,UAAU,OAAO,IAAI,CAAC,EAAE,CAAC;AAAA,EAC1D;AACA,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,UAAM,OACJ,MAAM,cAAc,SAChB,MAAM,MAAM,MAAM,SAAS,CAAC,IAC3B,MAAM,UAAU,KAAK,CAAC,cAAc,UAAU,SAAS,MAAM,QAAQ,CAAC,MACtE,aAAa,MAAM,MAAM,KAAK,CAAC,IAAI;AAC1C,QAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,WAAW,QAAQ,EAAG,QAAO;AACrD,WAAO,EAAE,GAAG,OAAO,YAAY,IAAI,gBAAgB,IAAI,EAAA;AAAA,EACzD,CAAC;AACH;AAeO,SAAS,iBAAuC;AACrD,QAAM,EAAE,QAAQ,aAAa,OAAO,WAAA,IAAe,cAAA;AACnD,QAAM,EAAE,gBAAgB,gBAAgB,UAAA,IAAc,eAAA;AACtD,QAAM,SAAS,8BAAA;AAEf,QAAM,cAAc;AAAA,IAClB,OAAO,OAAwB,WAAwD;AACrF,UAAI,MAAM,WAAW,EAAG,QAAO,CAAA;AAC/B,UAAI,UAAU,CAAC,OAAO,aAAa,OAAO;AACxC,kBAAU,0BAA0B,EAAE,MAAM,QAAQ,cAAc,KAAA,CAAM,CAAC;AACzE,0BAAkB,KAAK,uCAAuC;AAAA,UAC5D,OAAO;AAAA,UACP,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO,CACrC;AACD,eAAO,CAAA;AAAA,MACT;AACA,gBAAU,IAAI;AACd,qBAAe,IAAI;AACnB,UAAI;AACF,cAAM,SAAS,oBAAoB,EAAE,QAAQ,MAAM,OAAO,CAAC,GAAG,KAAK,CAAC,GAAG,OAAO;AAC9E,YAAI,OAAO,SAAS,EAAG,gBAAe,MAAM;AAC5C,eAAO;AAAA,MACT,SAASA,QAAO;AACd,0BAAkB;AAAA,UAChB;AAAA,UACAA;AAAAA,UACA,EAAE,MAAM,qBAAqB,SAAS,uBAAuB,MAAM,EAAA;AAAA,UACnE,EAAE,QAAQ,OAAO,MAAM,OAAA;AAAA,QAAO;AAEhC,eAAO,CAAA;AAAA,MACT,UAAA;AACE,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA,CAAC,gBAAgB,QAAQ,gBAAgB,WAAW,MAAM;AAAA,EAAA;AAG5D,SAAO,EAAE,aAAa,aAAa,OAAO,WAAA;AAC5C;"}
@@ -1,22 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react$1 = require("react");
3
+ const require$$0 = require("react");
4
4
  const react = require("@assistant-ui/react");
5
5
  function useComposerAttachment() {
6
6
  const aui = react.useAui();
7
- const addFile = react$1.useCallback(
7
+ const addFile = require$$0.useCallback(
8
8
  (file) => {
9
9
  aui.composer.addAttachment(file);
10
10
  },
11
11
  [aui]
12
12
  );
13
- const addContent = react$1.useCallback(
13
+ const addContent = require$$0.useCallback(
14
14
  (name, content) => {
15
15
  aui.composer.addAttachment({ name, content });
16
16
  },
17
17
  [aui]
18
18
  );
19
- const clear = react$1.useCallback(() => {
19
+ const clear = require$$0.useCallback(() => {
20
20
  aui.composer.clearAttachments();
21
21
  }, [aui]);
22
22
  return { addFile, addContent, clear };
@@ -1 +1 @@
1
- {"version":3,"file":"useComposerAttachment.cjs","sources":["../../src/composer/useComposerAttachment.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useAui } from '@assistant-ui/react';\n\n/**\n * Hook for programmatic composer file attachment control.\n *\n * Usage:\n * const { addFile, addContent, clear } = useComposerAttachment();\n * addFile(fileObject);\n * addContent(\"data.csv\", \"col1,col2\\n1,2\");\n * clear();\n */\nexport function useComposerAttachment() {\n const aui = useAui();\n\n const addFile = useCallback(\n (file: File) => {\n aui.composer.addAttachment(file);\n },\n [aui],\n );\n\n const addContent = useCallback(\n (name: string, content: string) => {\n aui.composer.addAttachment({ name, content } as unknown as File);\n },\n [aui],\n );\n\n const clear = useCallback(() => {\n aui.composer.clearAttachments();\n }, [aui]);\n\n return { addFile, addContent, clear };\n}\n"],"names":["useAui","useCallback"],"mappings":";;;;AAYO,SAAS,wBAAwB;AACtC,QAAM,MAAMA,MAAAA,OAAA;AAEZ,QAAM,UAAUC,QAAAA;AAAAA,IACd,CAAC,SAAe;AACd,UAAI,SAAS,cAAc,IAAI;AAAA,IACjC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAGN,QAAM,aAAaA,QAAAA;AAAAA,IACjB,CAAC,MAAc,YAAoB;AACjC,UAAI,SAAS,cAAc,EAAE,MAAM,SAA4B;AAAA,IACjE;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAGN,QAAM,QAAQA,QAAAA,YAAY,MAAM;AAC9B,QAAI,SAAS,iBAAA;AAAA,EACf,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,SAAS,YAAY,MAAA;AAChC;;"}
1
+ {"version":3,"file":"useComposerAttachment.cjs","sources":["../../src/composer/useComposerAttachment.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useAui } from '@assistant-ui/react';\n\n/**\n * Hook for programmatic composer file attachment control.\n *\n * Usage:\n * const { addFile, addContent, clear } = useComposerAttachment();\n * addFile(fileObject);\n * addContent(\"data.csv\", \"col1,col2\\n1,2\");\n * clear();\n */\nexport function useComposerAttachment() {\n const aui = useAui();\n\n const addFile = useCallback(\n (file: File) => {\n aui.composer.addAttachment(file);\n },\n [aui],\n );\n\n const addContent = useCallback(\n (name: string, content: string) => {\n aui.composer.addAttachment({ name, content } as unknown as File);\n },\n [aui],\n );\n\n const clear = useCallback(() => {\n aui.composer.clearAttachments();\n }, [aui]);\n\n return { addFile, addContent, clear };\n}\n"],"names":["useAui","useCallback"],"mappings":";;;;AAYO,SAAS,wBAAwB;AACtC,QAAM,MAAMA,MAAAA,OAAA;AAEZ,QAAM,UAAUC,WAAAA;AAAAA,IACd,CAAC,SAAe;AACd,UAAI,SAAS,cAAc,IAAI;AAAA,IACjC;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAGN,QAAM,aAAaA,WAAAA;AAAAA,IACjB,CAAC,MAAc,YAAoB;AACjC,UAAI,SAAS,cAAc,EAAE,MAAM,SAA4B;AAAA,IACjE;AAAA,IACA,CAAC,GAAG;AAAA,EAAA;AAGN,QAAM,QAAQA,WAAAA,YAAY,MAAM;AAC9B,QAAI,SAAS,iBAAA;AAAA,EACf,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,EAAE,SAAS,YAAY,MAAA;AAChC;;"}
@@ -1,25 +1,25 @@
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 AthenaContext = require("../provider/AthenaContext.cjs");
5
5
  const MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024;
6
6
  function useFileUpload() {
7
7
  const config = AthenaContext.useAthenaConfig();
8
- const configRef = react.useRef(config);
8
+ const configRef = require$$0.useRef(config);
9
9
  configRef.current = config;
10
10
  const { backendUrl, apiKey } = config;
11
- const [isUploading, setIsUploading] = react.useState(false);
12
- const [progress, setProgress] = react.useState(null);
13
- const [error, setError] = react.useState(null);
14
- const xhrRef = react.useRef(null);
15
- react.useEffect(() => {
11
+ const [isUploading, setIsUploading] = require$$0.useState(false);
12
+ const [progress, setProgress] = require$$0.useState(null);
13
+ const [error, setError] = require$$0.useState(null);
14
+ const xhrRef = require$$0.useRef(null);
15
+ require$$0.useEffect(() => {
16
16
  return () => {
17
17
  var _a;
18
18
  (_a = xhrRef.current) == null ? void 0 : _a.abort();
19
19
  };
20
20
  }, []);
21
- const clearError = react.useCallback(() => setError(null), []);
22
- const upload = react.useCallback(
21
+ const clearError = require$$0.useCallback(() => setError(null), []);
22
+ const upload = require$$0.useCallback(
23
23
  async (files) => {
24
24
  var _a;
25
25
  if (files.length === 0) return [];
@@ -70,13 +70,18 @@ function useFileUpload() {
70
70
  if (xhr.status >= 200 && xhr.status < 300) {
71
71
  try {
72
72
  const data = JSON.parse(xhr.responseText);
73
- const assets = (data.success ?? []).map((a) => ({
74
- id: a.id,
75
- title: a.title ?? a.file_name,
76
- fileName: a.file_name,
77
- fileSize: a.file_size,
78
- mediaType: a.media_type
79
- }));
73
+ const fileIndexes = data.success_file_indexes;
74
+ const assets = (data.success ?? []).map((a, at) => {
75
+ const fileIndex = Array.isArray(fileIndexes) ? fileIndexes[at] : void 0;
76
+ return {
77
+ id: a.id,
78
+ title: a.title ?? a.file_name,
79
+ fileName: a.file_name,
80
+ fileSize: a.file_size,
81
+ mediaType: a.media_type,
82
+ ...typeof fileIndex === "number" && { fileIndex }
83
+ };
84
+ });
80
85
  resolve({ success: assets, errors: data.errors ?? [] });
81
86
  } catch {
82
87
  reject(new Error("Failed to parse upload response"));
@@ -1 +1 @@
1
- {"version":3,"file":"useFileUpload.cjs","sources":["../../src/composer/useFileUpload.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAthenaConfig } from '../provider/AthenaContext';\n\nexport interface UploadedAsset {\n id: string;\n title: string;\n fileName: string;\n fileSize: number;\n mediaType: string;\n}\n\nexport interface UploadProgress {\n current: number;\n total: number;\n fileName: string;\n /** 0–1 normalized progress for the current file */\n percent: number;\n}\n\nexport interface UseFileUploadReturn {\n /** Upload one or more files to Athena. Returns the created asset(s). */\n upload: (files: File[]) => Promise<UploadedAsset[]>;\n /** Whether an upload is currently in progress. */\n isUploading: boolean;\n /** Upload progress info (null when idle). */\n progress: UploadProgress | null;\n /** Last upload error (null when no error). */\n error: string | null;\n /** Clear the error state. */\n clearError: () => void;\n}\n\nconst MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB\n\n/**\n * Hook for uploading files to the Athena platform via the Athena upload endpoint.\n * Files become Athena assets (documents, spreadsheets, PDFs, images, etc.).\n *\n * Usage:\n * const { upload, isUploading, progress, error } = useFileUpload();\n * const assets = await upload(fileList);\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const config = useAthenaConfig();\n // Keep config in a ref so upload() always reads the latest token at call\n // time. AthenaConfig's token is a getter that returns the current value\n // from PropelAuth, and reading via the ref avoids capturing stale\n // destructured values in the useCallback closure.\n const configRef = useRef(config);\n configRef.current = config;\n const { backendUrl, apiKey } = config;\n const [isUploading, setIsUploading] = useState(false);\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n const [error, setError] = useState<string | null>(null);\n const xhrRef = useRef<XMLHttpRequest | null>(null);\n\n // Abort any in-flight upload when the component unmounts\n useEffect(() => {\n return () => {\n xhrRef.current?.abort();\n };\n }, []);\n\n const clearError = useCallback(() => setError(null), []);\n\n const upload = useCallback(\n async (files: File[]): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n\n // Validate file sizes\n for (const file of files) {\n if (file.size > MAX_FILE_SIZE) {\n const msg = `File \"${file.name}\" exceeds the maximum size of 5 GB.`;\n setError(msg);\n throw new Error(msg);\n }\n }\n\n setIsUploading(true);\n setError(null);\n setProgress({ current: 0, total: files.length, fileName: files[0]?.name ?? '', percent: 0 });\n\n try {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file, file.name);\n }\n\n // Derive the upload URL from the configured Athena backend URL.\n // If backendUrl points at a nested Athena endpoint, trim it back to the API base first.\n const baseUrl = backendUrl.replace(/\\/api\\/assistant-ui\\/?$/, '');\n const uploadUrl = `${baseUrl}/api/upload/`;\n\n // Read the current token at call time so rotated tokens are picked up.\n const currentToken = configRef.current.token;\n const headers: Record<string, string> = {};\n if (currentToken) {\n headers['Authorization'] = `Bearer ${currentToken}`;\n } else if (apiKey) {\n headers['X-API-KEY'] = apiKey;\n }\n\n const xhr = new XMLHttpRequest();\n xhrRef.current = xhr;\n\n const result = await new Promise<{ success: UploadedAsset[]; errors: Array<{ file: { filename: string }; error: string }> }>((resolve, reject) => {\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n const percent = e.loaded / e.total;\n // Estimate which file we're on based on progress\n const fileIndex = Math.min(\n Math.floor(percent * files.length),\n files.length - 1,\n );\n setProgress({\n current: fileIndex + 1,\n total: files.length,\n fileName: files[fileIndex]?.name ?? '',\n percent,\n });\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const data = JSON.parse(xhr.responseText);\n const assets: UploadedAsset[] = (data.success ?? []).map((a: Record<string, unknown>) => ({\n id: a.id as string,\n title: (a.title ?? a.file_name) as string,\n fileName: a.file_name as string,\n fileSize: a.file_size as number,\n mediaType: a.media_type as string,\n }));\n resolve({ success: assets, errors: data.errors ?? [] });\n } catch {\n reject(new Error('Failed to parse upload response'));\n }\n } else if (xhr.status === 401 || xhr.status === 403) {\n reject(new Error('Authentication failed. Check your API key or token.'));\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => reject(new Error('Network error during upload')));\n xhr.addEventListener('abort', () => reject(new Error('Upload was cancelled')));\n\n xhr.open('POST', uploadUrl);\n for (const [key, value] of Object.entries(headers)) {\n xhr.setRequestHeader(key, value);\n }\n xhr.withCredentials = !currentToken && !apiKey;\n xhr.send(formData);\n });\n\n if (result.errors.length > 0) {\n const errMsg = result.errors.map((e) => `${e.file.filename}: ${e.error}`).join('; ');\n if (result.success.length === 0) {\n setError(errMsg);\n throw new Error(errMsg);\n }\n // Partial success — set error but still return successful uploads\n setError(errMsg);\n }\n\n return result.success;\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Upload failed';\n setError(msg);\n throw err;\n } finally {\n xhrRef.current = null;\n setIsUploading(false);\n setProgress(null);\n }\n },\n [backendUrl, apiKey],\n );\n\n return { upload, isUploading, progress, error, clearError };\n}\n"],"names":["useAthenaConfig","useRef","useState","useEffect","useCallback","_a"],"mappings":"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"}
1
+ {"version":3,"file":"useFileUpload.cjs","sources":["../../src/composer/useFileUpload.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAthenaConfig } from '../provider/AthenaContext';\n\nexport interface UploadedAsset {\n id: string;\n title: string;\n fileName: string;\n fileSize: number;\n mediaType: string;\n /**\n * The position, in the batch `upload` was given, of the file this asset was\n * uploaded from (the upload's `success_file_indexes`; absent from a server\n * that does not send them).\n */\n fileIndex?: number;\n /**\n * A local `blob:` URL of the picture this attachment was uploaded from, for\n * the composer's thumbnail and full-screen viewer. Set by the composer's\n * intake for image files, and revoked when the draft lets the attachment go.\n */\n previewUrl?: string;\n}\n\nexport interface UploadProgress {\n current: number;\n total: number;\n fileName: string;\n /** 0–1 normalized progress for the current file */\n percent: number;\n}\n\nexport interface UseFileUploadReturn {\n /** Upload one or more files to Athena. Returns the created asset(s). */\n upload: (files: File[]) => Promise<UploadedAsset[]>;\n /** Whether an upload is currently in progress. */\n isUploading: boolean;\n /** Upload progress info (null when idle). */\n progress: UploadProgress | null;\n /** Last upload error (null when no error). */\n error: string | null;\n /** Clear the error state. */\n clearError: () => void;\n}\n\nconst MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB\n\n/**\n * Hook for uploading files to the Athena platform via the Athena upload endpoint.\n * Files become Athena assets (documents, spreadsheets, PDFs, images, etc.).\n *\n * Usage:\n * const { upload, isUploading, progress, error } = useFileUpload();\n * const assets = await upload(fileList);\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const config = useAthenaConfig();\n // Keep config in a ref so upload() always reads the latest token at call\n // time. AthenaConfig's token is a getter that returns the current value\n // from PropelAuth, and reading via the ref avoids capturing stale\n // destructured values in the useCallback closure.\n const configRef = useRef(config);\n configRef.current = config;\n const { backendUrl, apiKey } = config;\n const [isUploading, setIsUploading] = useState(false);\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n const [error, setError] = useState<string | null>(null);\n const xhrRef = useRef<XMLHttpRequest | null>(null);\n\n // Abort any in-flight upload when the component unmounts\n useEffect(() => {\n return () => {\n xhrRef.current?.abort();\n };\n }, []);\n\n const clearError = useCallback(() => setError(null), []);\n\n const upload = useCallback(\n async (files: File[]): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n\n // Validate file sizes\n for (const file of files) {\n if (file.size > MAX_FILE_SIZE) {\n const msg = `File \"${file.name}\" exceeds the maximum size of 5 GB.`;\n setError(msg);\n throw new Error(msg);\n }\n }\n\n setIsUploading(true);\n setError(null);\n setProgress({ current: 0, total: files.length, fileName: files[0]?.name ?? '', percent: 0 });\n\n try {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file, file.name);\n }\n\n // Derive the upload URL from the configured Athena backend URL.\n // If backendUrl points at a nested Athena endpoint, trim it back to the API base first.\n const baseUrl = backendUrl.replace(/\\/api\\/assistant-ui\\/?$/, '');\n const uploadUrl = `${baseUrl}/api/upload/`;\n\n // Read the current token at call time so rotated tokens are picked up.\n const currentToken = configRef.current.token;\n const headers: Record<string, string> = {};\n if (currentToken) {\n headers['Authorization'] = `Bearer ${currentToken}`;\n } else if (apiKey) {\n headers['X-API-KEY'] = apiKey;\n }\n\n const xhr = new XMLHttpRequest();\n xhrRef.current = xhr;\n\n const result = await new Promise<{ success: UploadedAsset[]; errors: Array<{ file: { filename: string }; error: string }> }>((resolve, reject) => {\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n const percent = e.loaded / e.total;\n // Estimate which file we're on based on progress\n const fileIndex = Math.min(\n Math.floor(percent * files.length),\n files.length - 1,\n );\n setProgress({\n current: fileIndex + 1,\n total: files.length,\n fileName: files[fileIndex]?.name ?? '',\n percent,\n });\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const data = JSON.parse(xhr.responseText);\n const fileIndexes: unknown = data.success_file_indexes;\n const assets: UploadedAsset[] = (data.success ?? []).map((a: Record<string, unknown>, at: number) => {\n const fileIndex = Array.isArray(fileIndexes) ? fileIndexes[at] : undefined;\n return {\n id: a.id as string,\n title: (a.title ?? a.file_name) as string,\n fileName: a.file_name as string,\n fileSize: a.file_size as number,\n mediaType: a.media_type as string,\n ...(typeof fileIndex === 'number' && { fileIndex }),\n };\n });\n resolve({ success: assets, errors: data.errors ?? [] });\n } catch {\n reject(new Error('Failed to parse upload response'));\n }\n } else if (xhr.status === 401 || xhr.status === 403) {\n reject(new Error('Authentication failed. Check your API key or token.'));\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => reject(new Error('Network error during upload')));\n xhr.addEventListener('abort', () => reject(new Error('Upload was cancelled')));\n\n xhr.open('POST', uploadUrl);\n for (const [key, value] of Object.entries(headers)) {\n xhr.setRequestHeader(key, value);\n }\n xhr.withCredentials = !currentToken && !apiKey;\n xhr.send(formData);\n });\n\n if (result.errors.length > 0) {\n const errMsg = result.errors.map((e) => `${e.file.filename}: ${e.error}`).join('; ');\n if (result.success.length === 0) {\n setError(errMsg);\n throw new Error(errMsg);\n }\n // Partial success — set error but still return successful uploads\n setError(errMsg);\n }\n\n return result.success;\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Upload failed';\n setError(msg);\n throw err;\n } finally {\n xhrRef.current = null;\n setIsUploading(false);\n setProgress(null);\n }\n },\n [backendUrl, apiKey],\n );\n\n return { upload, isUploading, progress, error, clearError };\n}\n"],"names":["useAthenaConfig","useRef","useState","useEffect","useCallback","_a"],"mappings":"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"}
@@ -4,6 +4,18 @@ export interface UploadedAsset {
4
4
  fileName: string;
5
5
  fileSize: number;
6
6
  mediaType: string;
7
+ /**
8
+ * The position, in the batch `upload` was given, of the file this asset was
9
+ * uploaded from (the upload's `success_file_indexes`; absent from a server
10
+ * that does not send them).
11
+ */
12
+ fileIndex?: number;
13
+ /**
14
+ * A local `blob:` URL of the picture this attachment was uploaded from, for
15
+ * the composer's thumbnail and full-screen viewer. Set by the composer's
16
+ * intake for image files, and revoked when the draft lets the attachment go.
17
+ */
18
+ previewUrl?: string;
7
19
  }
8
20
  export interface UploadProgress {
9
21
  current: number;
@@ -68,13 +68,18 @@ function useFileUpload() {
68
68
  if (xhr.status >= 200 && xhr.status < 300) {
69
69
  try {
70
70
  const data = JSON.parse(xhr.responseText);
71
- const assets = (data.success ?? []).map((a) => ({
72
- id: a.id,
73
- title: a.title ?? a.file_name,
74
- fileName: a.file_name,
75
- fileSize: a.file_size,
76
- mediaType: a.media_type
77
- }));
71
+ const fileIndexes = data.success_file_indexes;
72
+ const assets = (data.success ?? []).map((a, at) => {
73
+ const fileIndex = Array.isArray(fileIndexes) ? fileIndexes[at] : void 0;
74
+ return {
75
+ id: a.id,
76
+ title: a.title ?? a.file_name,
77
+ fileName: a.file_name,
78
+ fileSize: a.file_size,
79
+ mediaType: a.media_type,
80
+ ...typeof fileIndex === "number" && { fileIndex }
81
+ };
82
+ });
78
83
  resolve({ success: assets, errors: data.errors ?? [] });
79
84
  } catch {
80
85
  reject(new Error("Failed to parse upload response"));
@@ -1 +1 @@
1
- {"version":3,"file":"useFileUpload.js","sources":["../../src/composer/useFileUpload.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAthenaConfig } from '../provider/AthenaContext';\n\nexport interface UploadedAsset {\n id: string;\n title: string;\n fileName: string;\n fileSize: number;\n mediaType: string;\n}\n\nexport interface UploadProgress {\n current: number;\n total: number;\n fileName: string;\n /** 0–1 normalized progress for the current file */\n percent: number;\n}\n\nexport interface UseFileUploadReturn {\n /** Upload one or more files to Athena. Returns the created asset(s). */\n upload: (files: File[]) => Promise<UploadedAsset[]>;\n /** Whether an upload is currently in progress. */\n isUploading: boolean;\n /** Upload progress info (null when idle). */\n progress: UploadProgress | null;\n /** Last upload error (null when no error). */\n error: string | null;\n /** Clear the error state. */\n clearError: () => void;\n}\n\nconst MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB\n\n/**\n * Hook for uploading files to the Athena platform via the Athena upload endpoint.\n * Files become Athena assets (documents, spreadsheets, PDFs, images, etc.).\n *\n * Usage:\n * const { upload, isUploading, progress, error } = useFileUpload();\n * const assets = await upload(fileList);\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const config = useAthenaConfig();\n // Keep config in a ref so upload() always reads the latest token at call\n // time. AthenaConfig's token is a getter that returns the current value\n // from PropelAuth, and reading via the ref avoids capturing stale\n // destructured values in the useCallback closure.\n const configRef = useRef(config);\n configRef.current = config;\n const { backendUrl, apiKey } = config;\n const [isUploading, setIsUploading] = useState(false);\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n const [error, setError] = useState<string | null>(null);\n const xhrRef = useRef<XMLHttpRequest | null>(null);\n\n // Abort any in-flight upload when the component unmounts\n useEffect(() => {\n return () => {\n xhrRef.current?.abort();\n };\n }, []);\n\n const clearError = useCallback(() => setError(null), []);\n\n const upload = useCallback(\n async (files: File[]): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n\n // Validate file sizes\n for (const file of files) {\n if (file.size > MAX_FILE_SIZE) {\n const msg = `File \"${file.name}\" exceeds the maximum size of 5 GB.`;\n setError(msg);\n throw new Error(msg);\n }\n }\n\n setIsUploading(true);\n setError(null);\n setProgress({ current: 0, total: files.length, fileName: files[0]?.name ?? '', percent: 0 });\n\n try {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file, file.name);\n }\n\n // Derive the upload URL from the configured Athena backend URL.\n // If backendUrl points at a nested Athena endpoint, trim it back to the API base first.\n const baseUrl = backendUrl.replace(/\\/api\\/assistant-ui\\/?$/, '');\n const uploadUrl = `${baseUrl}/api/upload/`;\n\n // Read the current token at call time so rotated tokens are picked up.\n const currentToken = configRef.current.token;\n const headers: Record<string, string> = {};\n if (currentToken) {\n headers['Authorization'] = `Bearer ${currentToken}`;\n } else if (apiKey) {\n headers['X-API-KEY'] = apiKey;\n }\n\n const xhr = new XMLHttpRequest();\n xhrRef.current = xhr;\n\n const result = await new Promise<{ success: UploadedAsset[]; errors: Array<{ file: { filename: string }; error: string }> }>((resolve, reject) => {\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n const percent = e.loaded / e.total;\n // Estimate which file we're on based on progress\n const fileIndex = Math.min(\n Math.floor(percent * files.length),\n files.length - 1,\n );\n setProgress({\n current: fileIndex + 1,\n total: files.length,\n fileName: files[fileIndex]?.name ?? '',\n percent,\n });\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const data = JSON.parse(xhr.responseText);\n const assets: UploadedAsset[] = (data.success ?? []).map((a: Record<string, unknown>) => ({\n id: a.id as string,\n title: (a.title ?? a.file_name) as string,\n fileName: a.file_name as string,\n fileSize: a.file_size as number,\n mediaType: a.media_type as string,\n }));\n resolve({ success: assets, errors: data.errors ?? [] });\n } catch {\n reject(new Error('Failed to parse upload response'));\n }\n } else if (xhr.status === 401 || xhr.status === 403) {\n reject(new Error('Authentication failed. Check your API key or token.'));\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => reject(new Error('Network error during upload')));\n xhr.addEventListener('abort', () => reject(new Error('Upload was cancelled')));\n\n xhr.open('POST', uploadUrl);\n for (const [key, value] of Object.entries(headers)) {\n xhr.setRequestHeader(key, value);\n }\n xhr.withCredentials = !currentToken && !apiKey;\n xhr.send(formData);\n });\n\n if (result.errors.length > 0) {\n const errMsg = result.errors.map((e) => `${e.file.filename}: ${e.error}`).join('; ');\n if (result.success.length === 0) {\n setError(errMsg);\n throw new Error(errMsg);\n }\n // Partial success — set error but still return successful uploads\n setError(errMsg);\n }\n\n return result.success;\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Upload failed';\n setError(msg);\n throw err;\n } finally {\n xhrRef.current = null;\n setIsUploading(false);\n setProgress(null);\n }\n },\n [backendUrl, apiKey],\n );\n\n return { upload, isUploading, progress, error, clearError };\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"useFileUpload.js","sources":["../../src/composer/useFileUpload.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useAthenaConfig } from '../provider/AthenaContext';\n\nexport interface UploadedAsset {\n id: string;\n title: string;\n fileName: string;\n fileSize: number;\n mediaType: string;\n /**\n * The position, in the batch `upload` was given, of the file this asset was\n * uploaded from (the upload's `success_file_indexes`; absent from a server\n * that does not send them).\n */\n fileIndex?: number;\n /**\n * A local `blob:` URL of the picture this attachment was uploaded from, for\n * the composer's thumbnail and full-screen viewer. Set by the composer's\n * intake for image files, and revoked when the draft lets the attachment go.\n */\n previewUrl?: string;\n}\n\nexport interface UploadProgress {\n current: number;\n total: number;\n fileName: string;\n /** 0–1 normalized progress for the current file */\n percent: number;\n}\n\nexport interface UseFileUploadReturn {\n /** Upload one or more files to Athena. Returns the created asset(s). */\n upload: (files: File[]) => Promise<UploadedAsset[]>;\n /** Whether an upload is currently in progress. */\n isUploading: boolean;\n /** Upload progress info (null when idle). */\n progress: UploadProgress | null;\n /** Last upload error (null when no error). */\n error: string | null;\n /** Clear the error state. */\n clearError: () => void;\n}\n\nconst MAX_FILE_SIZE = 5 * 1024 * 1024 * 1024; // 5 GB\n\n/**\n * Hook for uploading files to the Athena platform via the Athena upload endpoint.\n * Files become Athena assets (documents, spreadsheets, PDFs, images, etc.).\n *\n * Usage:\n * const { upload, isUploading, progress, error } = useFileUpload();\n * const assets = await upload(fileList);\n */\nexport function useFileUpload(): UseFileUploadReturn {\n const config = useAthenaConfig();\n // Keep config in a ref so upload() always reads the latest token at call\n // time. AthenaConfig's token is a getter that returns the current value\n // from PropelAuth, and reading via the ref avoids capturing stale\n // destructured values in the useCallback closure.\n const configRef = useRef(config);\n configRef.current = config;\n const { backendUrl, apiKey } = config;\n const [isUploading, setIsUploading] = useState(false);\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n const [error, setError] = useState<string | null>(null);\n const xhrRef = useRef<XMLHttpRequest | null>(null);\n\n // Abort any in-flight upload when the component unmounts\n useEffect(() => {\n return () => {\n xhrRef.current?.abort();\n };\n }, []);\n\n const clearError = useCallback(() => setError(null), []);\n\n const upload = useCallback(\n async (files: File[]): Promise<UploadedAsset[]> => {\n if (files.length === 0) return [];\n\n // Validate file sizes\n for (const file of files) {\n if (file.size > MAX_FILE_SIZE) {\n const msg = `File \"${file.name}\" exceeds the maximum size of 5 GB.`;\n setError(msg);\n throw new Error(msg);\n }\n }\n\n setIsUploading(true);\n setError(null);\n setProgress({ current: 0, total: files.length, fileName: files[0]?.name ?? '', percent: 0 });\n\n try {\n const formData = new FormData();\n for (const file of files) {\n formData.append('files', file, file.name);\n }\n\n // Derive the upload URL from the configured Athena backend URL.\n // If backendUrl points at a nested Athena endpoint, trim it back to the API base first.\n const baseUrl = backendUrl.replace(/\\/api\\/assistant-ui\\/?$/, '');\n const uploadUrl = `${baseUrl}/api/upload/`;\n\n // Read the current token at call time so rotated tokens are picked up.\n const currentToken = configRef.current.token;\n const headers: Record<string, string> = {};\n if (currentToken) {\n headers['Authorization'] = `Bearer ${currentToken}`;\n } else if (apiKey) {\n headers['X-API-KEY'] = apiKey;\n }\n\n const xhr = new XMLHttpRequest();\n xhrRef.current = xhr;\n\n const result = await new Promise<{ success: UploadedAsset[]; errors: Array<{ file: { filename: string }; error: string }> }>((resolve, reject) => {\n xhr.upload.addEventListener('progress', (e) => {\n if (e.lengthComputable) {\n const percent = e.loaded / e.total;\n // Estimate which file we're on based on progress\n const fileIndex = Math.min(\n Math.floor(percent * files.length),\n files.length - 1,\n );\n setProgress({\n current: fileIndex + 1,\n total: files.length,\n fileName: files[fileIndex]?.name ?? '',\n percent,\n });\n }\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const data = JSON.parse(xhr.responseText);\n const fileIndexes: unknown = data.success_file_indexes;\n const assets: UploadedAsset[] = (data.success ?? []).map((a: Record<string, unknown>, at: number) => {\n const fileIndex = Array.isArray(fileIndexes) ? fileIndexes[at] : undefined;\n return {\n id: a.id as string,\n title: (a.title ?? a.file_name) as string,\n fileName: a.file_name as string,\n fileSize: a.file_size as number,\n mediaType: a.media_type as string,\n ...(typeof fileIndex === 'number' && { fileIndex }),\n };\n });\n resolve({ success: assets, errors: data.errors ?? [] });\n } catch {\n reject(new Error('Failed to parse upload response'));\n }\n } else if (xhr.status === 401 || xhr.status === 403) {\n reject(new Error('Authentication failed. Check your API key or token.'));\n } else {\n reject(new Error(`Upload failed with status ${xhr.status}`));\n }\n });\n\n xhr.addEventListener('error', () => reject(new Error('Network error during upload')));\n xhr.addEventListener('abort', () => reject(new Error('Upload was cancelled')));\n\n xhr.open('POST', uploadUrl);\n for (const [key, value] of Object.entries(headers)) {\n xhr.setRequestHeader(key, value);\n }\n xhr.withCredentials = !currentToken && !apiKey;\n xhr.send(formData);\n });\n\n if (result.errors.length > 0) {\n const errMsg = result.errors.map((e) => `${e.file.filename}: ${e.error}`).join('; ');\n if (result.success.length === 0) {\n setError(errMsg);\n throw new Error(errMsg);\n }\n // Partial success — set error but still return successful uploads\n setError(errMsg);\n }\n\n return result.success;\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Upload failed';\n setError(msg);\n throw err;\n } finally {\n xhrRef.current = null;\n setIsUploading(false);\n setProgress(null);\n }\n },\n [backendUrl, apiKey],\n );\n\n return { upload, isUploading, progress, error, clearError };\n}\n"],"names":["_a"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react$1 = require("react");
3
+ const require$$0 = require("react");
4
4
  const react = require("@assistant-ui/react");
5
5
  function useReadComposerDraft() {
6
6
  const aui = react.useAui();
7
- return react$1.useCallback(() => {
7
+ return require$$0.useCallback(() => {
8
8
  try {
9
9
  return aui.composer.getState().text ?? "";
10
10
  } catch {
@@ -1 +1 @@
1
- {"version":3,"file":"useReadComposerDraft.cjs","sources":["../../src/composer/useReadComposerDraft.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useAui } from '@assistant-ui/react';\n\n/**\n * Reads the composer's draft (its text) when called, for a host that hands the chat elsewhere and\n * carries what was not sent yet along (a launcher window's \"open in the app\"). An empty string\n * before the composer exists.\n */\nexport function useReadComposerDraft(): () => string {\n const aui = useAui();\n return useCallback(() => {\n try {\n return aui.composer.getState().text ?? '';\n } catch {\n return '';\n }\n }, [aui]);\n}\n"],"names":["useAui","useCallback"],"mappings":";;;;AAQO,SAAS,uBAAqC;AACnD,QAAM,MAAMA,MAAAA,OAAA;AACZ,SAAOC,QAAAA,YAAY,MAAM;AACvB,QAAI;AACF,aAAO,IAAI,SAAS,SAAA,EAAW,QAAQ;AAAA,IACzC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AACV;;"}
1
+ {"version":3,"file":"useReadComposerDraft.cjs","sources":["../../src/composer/useReadComposerDraft.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useAui } from '@assistant-ui/react';\n\n/**\n * Reads the composer's draft (its text) when called, for a host that hands the chat elsewhere and\n * carries what was not sent yet along (a launcher window's \"open in the app\"). An empty string\n * before the composer exists.\n */\nexport function useReadComposerDraft(): () => string {\n const aui = useAui();\n return useCallback(() => {\n try {\n return aui.composer.getState().text ?? '';\n } catch {\n return '';\n }\n }, [aui]);\n}\n"],"names":["useAui","useCallback"],"mappings":";;;;AAQO,SAAS,uBAAqC;AACnD,QAAM,MAAMA,MAAAA,OAAA;AACZ,SAAOC,WAAAA,YAAY,MAAM;AACvB,QAAI;AACF,aAAO,IAAI,SAAS,SAAA,EAAW,QAAQ;AAAA,IACzC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AACV;;"}
@@ -1,17 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react$1 = require("react");
3
+ const require$$0 = require("react");
4
4
  const react = require("@assistant-ui/react");
5
5
  const threadIdContext = require("../threads/thread-id-context.cjs");
6
6
  const composerHandoff = require("./composer-handoff.cjs");
7
7
  function useSendMessage() {
8
8
  const aui = react.useAui();
9
9
  const store = composerHandoff.useComposerHandoffStore();
10
- const threadId = react$1.useContext(threadIdContext.AthenaStatewireThreadIdContext);
10
+ const threadId = require$$0.useContext(threadIdContext.AthenaStatewireThreadIdContext);
11
11
  const ready = composerHandoff.useComposerReady();
12
- const readyRef = react$1.useRef(ready);
12
+ const readyRef = require$$0.useRef(ready);
13
13
  readyRef.current = ready;
14
- return react$1.useCallback(
14
+ return require$$0.useCallback(
15
15
  async (text, options) => {
16
16
  if (!text.trim()) return;
17
17
  const write = {
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessage.cjs","sources":["../../src/composer/useSendMessage.ts"],"sourcesContent":["import { useCallback, useContext, useRef } from 'react';\nimport { useAui } from '@assistant-ui/react';\nimport { AthenaStatewireThreadIdContext } from '../threads/thread-id-context';\nimport {\n applyComposerWrite,\n queueComposerWrite,\n useComposerHandoffStore,\n useComposerReady,\n type ComposerWrite,\n} from './composer-handoff';\n\nexport interface SendMessageOptions {\n /**\n * Replace the current composer text before sending.\n * Defaults to `true`.\n */\n replace?: boolean;\n}\n\n/**\n * Hook to programmatically send a user message from anywhere inside AthenaProvider.\n *\n * This is intended for custom workflow buttons, sidebar shortcuts, or other UI\n * that lives outside the AthenaChat thread tree. Unlike `aui.thread().append()`,\n * this uses the provider-scoped composer runtime and does not depend on\n * ThreadPrimitive context.\n *\n * Safe to call at any time: a send made before the chat is ready (the thread\n * list still resolving the active thread, the thread's history still\n * loading, or a sign-in provider above still resolving who is signed in)\n * waits in the provider, in order with any other early sends, and goes out\n * once the composer is ready. The returned promise settles when\n * that send has been dispatched, and rejects with an `AthenaSdkError`\n * (`composer_write_dropped`) if it can no longer land — the user switched\n * threads, the identity changed, or the provider unmounted first.\n *\n * Usage:\n * const sendMessage = useSendMessage();\n * await sendMessage(\"Run the quarterly workflow\");\n * await sendMessage(\"Add this follow-up\", { replace: false });\n */\nexport function useSendMessage() {\n const aui = useAui();\n const store = useComposerHandoffStore();\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const ready = useComposerReady();\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n return useCallback(\n async (text: string, options?: SendMessageOptions) => {\n if (!text.trim()) return;\n\n const write: ComposerWrite = {\n text,\n replace: options?.replace ?? true,\n send: true,\n focus: false,\n threadId,\n };\n if (store && !readyRef.current) {\n await new Promise<void>((resolve, reject) => {\n write.resolve = (outcome) => {\n Promise.resolve(outcome).then(() => resolve(), reject);\n };\n write.reject = reject;\n queueComposerWrite({ store, write });\n });\n return;\n }\n await applyComposerWrite({ target: aui, store, write });\n },\n [aui, store, threadId],\n );\n}\n"],"names":["useAui","useComposerHandoffStore","useContext","AthenaStatewireThreadIdContext","useComposerReady","useRef","useCallback","queueComposerWrite","applyComposerWrite"],"mappings":";;;;;;AAyCO,SAAS,iBAAiB;AAC/B,QAAM,MAAMA,MAAAA,OAAA;AACZ,QAAM,QAAQC,gBAAAA,wBAAA;AACd,QAAM,WAAWC,QAAAA,WAAWC,8CAA8B;AAC1D,QAAM,QAAQC,gBAAAA,iBAAA;AACd,QAAM,WAAWC,QAAAA,OAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,SAAOC,QAAAA;AAAAA,IACL,OAAO,MAAc,YAAiC;AACpD,UAAI,CAAC,KAAK,OAAQ;AAElB,YAAM,QAAuB;AAAA,QAC3B;AAAA,QACA,UAAS,mCAAS,YAAW;AAAA,QAC7B,MAAM;AAAA,QACN,OAAO;AAAA,QACP;AAAA,MAAA;AAEF,UAAI,SAAS,CAAC,SAAS,SAAS;AAC9B,cAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,gBAAM,UAAU,CAAC,YAAY;AAC3B,oBAAQ,QAAQ,OAAO,EAAE,KAAK,MAAM,QAAA,GAAW,MAAM;AAAA,UACvD;AACA,gBAAM,SAAS;AACfC,6CAAmB,EAAE,OAAO,OAAO;AAAA,QACrC,CAAC;AACD;AAAA,MACF;AACA,YAAMC,gBAAAA,mBAAmB,EAAE,QAAQ,KAAK,OAAO,OAAO;AAAA,IACxD;AAAA,IACA,CAAC,KAAK,OAAO,QAAQ;AAAA,EAAA;AAEzB;;"}
1
+ {"version":3,"file":"useSendMessage.cjs","sources":["../../src/composer/useSendMessage.ts"],"sourcesContent":["import { useCallback, useContext, useRef } from 'react';\nimport { useAui } from '@assistant-ui/react';\nimport { AthenaStatewireThreadIdContext } from '../threads/thread-id-context';\nimport {\n applyComposerWrite,\n queueComposerWrite,\n useComposerHandoffStore,\n useComposerReady,\n type ComposerWrite,\n} from './composer-handoff';\n\nexport interface SendMessageOptions {\n /**\n * Replace the current composer text before sending.\n * Defaults to `true`.\n */\n replace?: boolean;\n}\n\n/**\n * Hook to programmatically send a user message from anywhere inside AthenaProvider.\n *\n * This is intended for custom workflow buttons, sidebar shortcuts, or other UI\n * that lives outside the AthenaChat thread tree. Unlike `aui.thread().append()`,\n * this uses the provider-scoped composer runtime and does not depend on\n * ThreadPrimitive context.\n *\n * Safe to call at any time: a send made before the chat is ready (the thread\n * list still resolving the active thread, the thread's history still\n * loading, or a sign-in provider above still resolving who is signed in)\n * waits in the provider, in order with any other early sends, and goes out\n * once the composer is ready. The returned promise settles when\n * that send has been dispatched, and rejects with an `AthenaSdkError`\n * (`composer_write_dropped`) if it can no longer land — the user switched\n * threads, the identity changed, or the provider unmounted first.\n *\n * Usage:\n * const sendMessage = useSendMessage();\n * await sendMessage(\"Run the quarterly workflow\");\n * await sendMessage(\"Add this follow-up\", { replace: false });\n */\nexport function useSendMessage() {\n const aui = useAui();\n const store = useComposerHandoffStore();\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const ready = useComposerReady();\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n return useCallback(\n async (text: string, options?: SendMessageOptions) => {\n if (!text.trim()) return;\n\n const write: ComposerWrite = {\n text,\n replace: options?.replace ?? true,\n send: true,\n focus: false,\n threadId,\n };\n if (store && !readyRef.current) {\n await new Promise<void>((resolve, reject) => {\n write.resolve = (outcome) => {\n Promise.resolve(outcome).then(() => resolve(), reject);\n };\n write.reject = reject;\n queueComposerWrite({ store, write });\n });\n return;\n }\n await applyComposerWrite({ target: aui, store, write });\n },\n [aui, store, threadId],\n );\n}\n"],"names":["useAui","useComposerHandoffStore","useContext","AthenaStatewireThreadIdContext","useComposerReady","useRef","useCallback","queueComposerWrite","applyComposerWrite"],"mappings":";;;;;;AAyCO,SAAS,iBAAiB;AAC/B,QAAM,MAAMA,MAAAA,OAAA;AACZ,QAAM,QAAQC,gBAAAA,wBAAA;AACd,QAAM,WAAWC,WAAAA,WAAWC,8CAA8B;AAC1D,QAAM,QAAQC,gBAAAA,iBAAA;AACd,QAAM,WAAWC,WAAAA,OAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,SAAOC,WAAAA;AAAAA,IACL,OAAO,MAAc,YAAiC;AACpD,UAAI,CAAC,KAAK,OAAQ;AAElB,YAAM,QAAuB;AAAA,QAC3B;AAAA,QACA,UAAS,mCAAS,YAAW;AAAA,QAC7B,MAAM;AAAA,QACN,OAAO;AAAA,QACP;AAAA,MAAA;AAEF,UAAI,SAAS,CAAC,SAAS,SAAS;AAC9B,cAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,gBAAM,UAAU,CAAC,YAAY;AAC3B,oBAAQ,QAAQ,OAAO,EAAE,KAAK,MAAM,QAAA,GAAW,MAAM;AAAA,UACvD;AACA,gBAAM,SAAS;AACfC,6CAAmB,EAAE,OAAO,OAAO;AAAA,QACrC,CAAC;AACD;AAAA,MACF;AACA,YAAMC,gBAAAA,mBAAmB,EAAE,QAAQ,KAAK,OAAO,OAAO;AAAA,IACxD;AAAA,IACA,CAAC,KAAK,OAAO,QAAQ;AAAA,EAAA;AAEzB;;"}
@@ -1,15 +1,15 @@
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 athenaDiagnostics = require("./athena-diagnostics.cjs");
5
5
  function useAthenaDiagnostics() {
6
- const snapshot = react.useSyncExternalStore(
6
+ const snapshot = require$$0.useSyncExternalStore(
7
7
  athenaDiagnostics.athenaDiagnostics.subscribeSnapshot.bind(athenaDiagnostics.athenaDiagnostics),
8
8
  athenaDiagnostics.athenaDiagnostics.snapshot.bind(athenaDiagnostics.athenaDiagnostics),
9
9
  athenaDiagnostics.athenaDiagnostics.snapshot.bind(athenaDiagnostics.athenaDiagnostics)
10
10
  );
11
- const clear = react.useCallback(() => athenaDiagnostics.athenaDiagnostics.clear(), []);
12
- const exportJson = react.useCallback(() => athenaDiagnostics.athenaDiagnostics.export(), []);
11
+ const clear = require$$0.useCallback(() => athenaDiagnostics.athenaDiagnostics.clear(), []);
12
+ const exportJson = require$$0.useCallback(() => athenaDiagnostics.athenaDiagnostics.export(), []);
13
13
  return { ...snapshot, clear, export: exportJson };
14
14
  }
15
15
  exports.useAthenaDiagnostics = useAthenaDiagnostics;
@@ -1 +1 @@
1
- {"version":3,"file":"useAthenaDiagnostics.cjs","sources":["../../src/diagnostics/useAthenaDiagnostics.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport { athenaDiagnostics, type AthenaDiagnosticsSnapshot } from './athena-diagnostics';\n\n/**\n * Read the SDK diagnostics buffer reactively — events, gauges (connection\n * status, transport, auth mode), and the latest span timings (time to auth,\n * time to thread list, time to statewire snapshot, time to first token).\n *\n * Renders on every emitted event; mount it in a debug panel, not in the chat\n * transcript.\n */\nexport function useAthenaDiagnostics(): AthenaDiagnosticsSnapshot & {\n clear: () => void;\n export: () => string;\n} {\n const snapshot = useSyncExternalStore(\n athenaDiagnostics.subscribeSnapshot.bind(athenaDiagnostics),\n athenaDiagnostics.snapshot.bind(athenaDiagnostics),\n athenaDiagnostics.snapshot.bind(athenaDiagnostics),\n );\n const clear = useCallback(() => athenaDiagnostics.clear(), []);\n const exportJson = useCallback(() => athenaDiagnostics.export(), []);\n return { ...snapshot, clear, export: exportJson };\n}\n"],"names":["useSyncExternalStore","athenaDiagnostics","useCallback"],"mappings":";;;;AAWO,SAAS,uBAGd;AACA,QAAM,WAAWA,MAAAA;AAAAA,IACfC,oCAAkB,kBAAkB,KAAKA,mCAAiB;AAAA,IAC1DA,oCAAkB,SAAS,KAAKA,mCAAiB;AAAA,IACjDA,oCAAkB,SAAS,KAAKA,kBAAAA,iBAAiB;AAAA,EAAA;AAEnD,QAAM,QAAQC,MAAAA,YAAY,MAAMD,kBAAAA,kBAAkB,MAAA,GAAS,CAAA,CAAE;AAC7D,QAAM,aAAaC,MAAAA,YAAY,MAAMD,kBAAAA,kBAAkB,OAAA,GAAU,CAAA,CAAE;AACnE,SAAO,EAAE,GAAG,UAAU,OAAO,QAAQ,WAAA;AACvC;;"}
1
+ {"version":3,"file":"useAthenaDiagnostics.cjs","sources":["../../src/diagnostics/useAthenaDiagnostics.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport { athenaDiagnostics, type AthenaDiagnosticsSnapshot } from './athena-diagnostics';\n\n/**\n * Read the SDK diagnostics buffer reactively — events, gauges (connection\n * status, transport, auth mode), and the latest span timings (time to auth,\n * time to thread list, time to statewire snapshot, time to first token).\n *\n * Renders on every emitted event; mount it in a debug panel, not in the chat\n * transcript.\n */\nexport function useAthenaDiagnostics(): AthenaDiagnosticsSnapshot & {\n clear: () => void;\n export: () => string;\n} {\n const snapshot = useSyncExternalStore(\n athenaDiagnostics.subscribeSnapshot.bind(athenaDiagnostics),\n athenaDiagnostics.snapshot.bind(athenaDiagnostics),\n athenaDiagnostics.snapshot.bind(athenaDiagnostics),\n );\n const clear = useCallback(() => athenaDiagnostics.clear(), []);\n const exportJson = useCallback(() => athenaDiagnostics.export(), []);\n return { ...snapshot, clear, export: exportJson };\n}\n"],"names":["useSyncExternalStore","athenaDiagnostics","useCallback"],"mappings":";;;;AAWO,SAAS,uBAGd;AACA,QAAM,WAAWA,WAAAA;AAAAA,IACfC,oCAAkB,kBAAkB,KAAKA,mCAAiB;AAAA,IAC1DA,oCAAkB,SAAS,KAAKA,mCAAiB;AAAA,IACjDA,oCAAkB,SAAS,KAAKA,kBAAAA,iBAAiB;AAAA,EAAA;AAEnD,QAAM,QAAQC,WAAAA,YAAY,MAAMD,kBAAAA,kBAAkB,MAAA,GAAS,CAAA,CAAE;AAC7D,QAAM,aAAaC,WAAAA,YAAY,MAAMD,kBAAAA,kBAAkB,OAAA,GAAU,CAAA,CAAE;AACnE,SAAO,EAAE,GAAG,UAAU,OAAO,QAAQ,WAAA;AACvC;;"}
@@ -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
  function emptyAudioLevelHistory(size) {
5
5
  return new Array(Math.max(0, size)).fill(null);
6
6
  }
@@ -20,8 +20,8 @@ function displayLevelFromSamples(samples, gain = 4) {
20
20
  return Math.min(1, rms * gain);
21
21
  }
22
22
  function useAudioLevelHistory(stream, { size, intervalMs = 50 }) {
23
- const [history, setHistory] = react.useState(() => emptyAudioLevelHistory(size));
24
- react.useEffect(() => {
23
+ const [history, setHistory] = require$$0.useState(() => emptyAudioLevelHistory(size));
24
+ require$$0.useEffect(() => {
25
25
  setHistory(emptyAudioLevelHistory(size));
26
26
  if (!stream || typeof window === "undefined") return;
27
27
  const AudioContextCtor = window.AudioContext ?? window.webkitAudioContext;