@athenaintel/react 0.43.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (746) hide show
  1. package/README.md +258 -8
  2. package/dist/agent-runtime/src/answer-label.cjs +137 -0
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
  4. package/dist/agent-runtime/src/answer-label.d.ts +104 -0
  5. package/dist/agent-runtime/src/answer-label.js +137 -0
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -0
  7. package/dist/agent-runtime/src/answer-rows.cjs +180 -0
  8. package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
  9. package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
  10. package/dist/agent-runtime/src/answer-rows.js +180 -0
  11. package/dist/agent-runtime/src/answer-rows.js.map +1 -0
  12. package/dist/agent-runtime/src/call-recap.cjs +319 -0
  13. package/dist/agent-runtime/src/call-recap.cjs.map +1 -0
  14. package/dist/agent-runtime/src/call-recap.d.ts +142 -0
  15. package/dist/agent-runtime/src/call-recap.js +319 -0
  16. package/dist/agent-runtime/src/call-recap.js.map +1 -0
  17. package/dist/agent-runtime/src/chat-outbox-store.cjs +1 -0
  18. package/dist/agent-runtime/src/chat-outbox-store.cjs.map +1 -1
  19. package/dist/agent-runtime/src/chat-outbox-store.d.ts +7 -0
  20. package/dist/agent-runtime/src/chat-outbox-store.js +1 -0
  21. package/dist/agent-runtime/src/chat-outbox-store.js.map +1 -1
  22. package/dist/agent-runtime/src/chat-outbox.cjs +46 -5
  23. package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -1
  24. package/dist/agent-runtime/src/chat-outbox.d.ts +29 -0
  25. package/dist/agent-runtime/src/chat-outbox.js +46 -5
  26. package/dist/agent-runtime/src/chat-outbox.js.map +1 -1
  27. package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
  28. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  29. package/dist/agent-runtime/src/conversation-index.cjs +8 -8
  30. package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
  31. package/dist/agent-runtime/src/conversation-index.d.ts +7 -0
  32. package/dist/agent-runtime/src/conversation-index.js.map +1 -1
  33. package/dist/agent-runtime/src/conversation-list.cjs +2 -1
  34. package/dist/agent-runtime/src/conversation-list.cjs.map +1 -1
  35. package/dist/agent-runtime/src/conversation-list.d.ts +19 -3
  36. package/dist/agent-runtime/src/conversation-list.js +2 -1
  37. package/dist/agent-runtime/src/conversation-list.js.map +1 -1
  38. package/dist/agent-runtime/src/decision-checks.cjs +207 -0
  39. package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
  40. package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
  41. package/dist/agent-runtime/src/decision-checks.js +207 -0
  42. package/dist/agent-runtime/src/decision-checks.js.map +1 -0
  43. package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
  44. package/dist/agent-runtime/src/errors.cjs +18 -0
  45. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  46. package/dist/agent-runtime/src/errors.d.ts +7 -0
  47. package/dist/agent-runtime/src/errors.js +18 -0
  48. package/dist/agent-runtime/src/errors.js.map +1 -1
  49. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
  50. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  51. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
  52. package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
  53. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  54. package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
  55. package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
  56. package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
  57. package/dist/agent-runtime/src/handoff-arrival.js +60 -0
  58. package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
  59. package/dist/agent-runtime/src/index.d.ts +16 -9
  60. package/dist/agent-runtime/src/interrupts.cjs +71 -19
  61. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  62. package/dist/agent-runtime/src/interrupts.d.ts +40 -3
  63. package/dist/agent-runtime/src/interrupts.js +56 -4
  64. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  65. package/dist/agent-runtime/src/lane-history.cjs +8 -8
  66. package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
  67. package/dist/agent-runtime/src/messages.cjs +43 -8
  68. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  69. package/dist/agent-runtime/src/messages.d.ts +25 -3
  70. package/dist/agent-runtime/src/messages.js +43 -8
  71. package/dist/agent-runtime/src/messages.js.map +1 -1
  72. package/dist/agent-runtime/src/model-context.cjs +3 -2
  73. package/dist/agent-runtime/src/model-context.cjs.map +1 -1
  74. package/dist/agent-runtime/src/model-context.d.ts +6 -1
  75. package/dist/agent-runtime/src/model-context.js +3 -2
  76. package/dist/agent-runtime/src/model-context.js.map +1 -1
  77. package/dist/agent-runtime/src/offline-status.cjs +36 -0
  78. package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
  79. package/dist/agent-runtime/src/offline-status.d.ts +118 -3
  80. package/dist/agent-runtime/src/offline-status.js +36 -0
  81. package/dist/agent-runtime/src/offline-status.js.map +1 -0
  82. package/dist/agent-runtime/src/queue.cjs +0 -9
  83. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  84. package/dist/agent-runtime/src/queue.js +0 -9
  85. package/dist/agent-runtime/src/queue.js.map +1 -1
  86. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
  87. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  88. package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
  89. package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
  90. package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
  91. package/dist/agent-runtime/src/runtime-catalog.js +42 -0
  92. package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
  93. package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
  94. package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
  95. package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
  96. package/dist/agent-runtime/src/runtime.d.ts +41 -0
  97. package/dist/agent-runtime/src/send-recovery.cjs +37 -3
  98. package/dist/agent-runtime/src/send-recovery.cjs.map +1 -1
  99. package/dist/agent-runtime/src/send-recovery.d.ts +19 -0
  100. package/dist/agent-runtime/src/send-recovery.js +37 -3
  101. package/dist/agent-runtime/src/send-recovery.js.map +1 -1
  102. package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
  103. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  104. package/dist/agent-runtime/src/subagents.cjs +32 -2
  105. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  106. package/dist/agent-runtime/src/subagents.d.ts +9 -0
  107. package/dist/agent-runtime/src/subagents.js +30 -0
  108. package/dist/agent-runtime/src/subagents.js.map +1 -1
  109. package/dist/agent-runtime/src/thread-driver.cjs +67 -0
  110. package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
  111. package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
  112. package/dist/agent-runtime/src/thread-driver.js +67 -0
  113. package/dist/agent-runtime/src/thread-driver.js.map +1 -0
  114. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
  115. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +868 -0
  116. package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
  117. package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
  118. package/dist/agent-runtime/src/thread-status.cjs +3 -3
  119. package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
  120. package/dist/agent-runtime/src/tool-metadata.cjs +210 -25
  121. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  122. package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
  123. package/dist/agent-runtime/src/tool-metadata.js +210 -25
  124. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  125. package/dist/agent-runtime/src/tool-names.cjs +2 -0
  126. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  127. package/dist/agent-runtime/src/tool-names.d.ts +2 -0
  128. package/dist/agent-runtime/src/tool-names.js +2 -0
  129. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  130. package/dist/agent-runtime/src/types.d.ts +10 -2
  131. package/dist/agent-runtime/src/use-conversation-list.cjs +14 -13
  132. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  133. package/dist/agent-runtime/src/use-conversation-list.d.ts +6 -0
  134. package/dist/agent-runtime/src/use-conversation-list.js +3 -2
  135. package/dist/agent-runtime/src/use-conversation-list.js.map +1 -1
  136. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +45 -20
  137. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  138. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +10 -3
  139. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +27 -2
  140. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  141. package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
  142. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  143. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
  144. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  145. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +40 -22
  146. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  147. package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +17 -0
  148. package/dist/agent-runtime/src/use-deep-agent-runtime.js +24 -6
  149. package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
  150. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
  151. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  152. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +588 -130
  153. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  154. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +162 -10
  155. package/dist/agent-runtime/src/use-deep-agent-voice.js +529 -71
  156. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  157. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
  158. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  159. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
  160. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
  161. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +34 -26
  162. package/dist/agent-runtime/src/voice-earcon.cjs +139 -0
  163. package/dist/agent-runtime/src/voice-earcon.cjs.map +1 -0
  164. package/dist/agent-runtime/src/voice-earcon.d.ts +38 -0
  165. package/dist/agent-runtime/src/voice-earcon.js +139 -0
  166. package/dist/agent-runtime/src/voice-earcon.js.map +1 -0
  167. package/dist/agent-runtime/src/voice-media.cjs +117 -0
  168. package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
  169. package/dist/agent-runtime/src/voice-media.d.ts +63 -0
  170. package/dist/agent-runtime/src/voice-media.js +117 -0
  171. package/dist/agent-runtime/src/voice-media.js.map +1 -0
  172. package/dist/agent-runtime/src/voice-presentation.cjs +2 -0
  173. package/dist/agent-runtime/src/voice-presentation.cjs.map +1 -1
  174. package/dist/agent-runtime/src/voice-presentation.js +2 -0
  175. package/dist/agent-runtime/src/voice-presentation.js.map +1 -1
  176. package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
  177. package/dist/assets/AssetPanel.cjs +11 -11
  178. package/dist/assets/AssetPanel.cjs.map +1 -1
  179. package/dist/assets/AthenaAssetEmbed.cjs +11 -9
  180. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  181. package/dist/assets/AthenaAssetEmbed.d.ts +18 -5
  182. package/dist/assets/AthenaAssetEmbed.js +4 -2
  183. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  184. package/dist/assets/AthenaLayout.cjs +16 -16
  185. package/dist/assets/AthenaLayout.cjs.map +1 -1
  186. package/dist/assets/use-asset-content.cjs +4 -4
  187. package/dist/assets/use-asset-content.cjs.map +1 -1
  188. package/dist/assets/use-asset-embed.cjs +14 -7
  189. package/dist/assets/use-asset-embed.cjs.map +1 -1
  190. package/dist/assets/use-asset-embed.d.ts +23 -6
  191. package/dist/assets/use-asset-embed.js +10 -3
  192. package/dist/assets/use-asset-embed.js.map +1 -1
  193. package/dist/auth/AthenaAuthContext.cjs +3 -3
  194. package/dist/auth/AthenaAuthContext.cjs.map +1 -1
  195. package/dist/auth/AthenaAuthProvider.cjs +8 -8
  196. package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
  197. package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
  198. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  199. package/dist/auth/AthenaSSOProvider.cjs +14 -14
  200. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  201. package/dist/auth/credential-source.cjs +26 -13
  202. package/dist/auth/credential-source.cjs.map +1 -1
  203. package/dist/auth/credential-source.d.ts +8 -0
  204. package/dist/auth/credential-source.js +26 -13
  205. package/dist/auth/credential-source.js.map +1 -1
  206. package/dist/catalog/agent-model-options.cjs +25 -17
  207. package/dist/catalog/agent-model-options.cjs.map +1 -1
  208. package/dist/catalog/agent-model-options.d.ts +38 -5
  209. package/dist/catalog/agent-model-options.js +25 -17
  210. package/dist/catalog/agent-model-options.js.map +1 -1
  211. package/dist/catalog/channel-refusal.cjs +36 -0
  212. package/dist/catalog/channel-refusal.cjs.map +1 -0
  213. package/dist/catalog/channel-refusal.d.ts +29 -0
  214. package/dist/catalog/channel-refusal.js +36 -0
  215. package/dist/catalog/channel-refusal.js.map +1 -0
  216. package/dist/catalog/chat-pickers.cjs +60 -24
  217. package/dist/catalog/chat-pickers.cjs.map +1 -1
  218. package/dist/catalog/chat-pickers.d.ts +12 -2
  219. package/dist/catalog/chat-pickers.js +56 -20
  220. package/dist/catalog/chat-pickers.js.map +1 -1
  221. package/dist/catalog/runtime-catalog.cjs +89 -23
  222. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  223. package/dist/catalog/runtime-catalog.d.ts +8 -2
  224. package/dist/catalog/runtime-catalog.js +83 -17
  225. package/dist/catalog/runtime-catalog.js.map +1 -1
  226. package/dist/catalog/use-athena-chat-mode.cjs +12 -12
  227. package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
  228. package/dist/chat/AthenaChat.cjs +155 -67
  229. package/dist/chat/AthenaChat.cjs.map +1 -1
  230. package/dist/chat/AthenaChat.d.ts +42 -2
  231. package/dist/chat/AthenaChat.js +106 -18
  232. package/dist/chat/AthenaChat.js.map +1 -1
  233. package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
  234. package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
  235. package/dist/chat/DrivingOnChip.cjs +23 -0
  236. package/dist/chat/DrivingOnChip.cjs.map +1 -0
  237. package/dist/chat/DrivingOnChip.d.ts +17 -0
  238. package/dist/chat/DrivingOnChip.js +23 -0
  239. package/dist/chat/DrivingOnChip.js.map +1 -0
  240. package/dist/chat/StatewireApprovalCard.cjs +166 -37
  241. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  242. package/dist/chat/StatewireApprovalCard.d.ts +91 -2
  243. package/dist/chat/StatewireApprovalCard.js +156 -27
  244. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  245. package/dist/chat/StatewireClientToolBridge.cjs +2 -2
  246. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  247. package/dist/chat/StatewireQueuedMessages.cjs +81 -69
  248. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  249. package/dist/chat/StatewireQueuedMessages.d.ts +25 -13
  250. package/dist/chat/StatewireQueuedMessages.js +73 -61
  251. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  252. package/dist/chat/WaitingOnYouBanner.cjs +9 -5
  253. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
  254. package/dist/chat/WaitingOnYouBanner.js +7 -3
  255. package/dist/chat/WaitingOnYouBanner.js.map +1 -1
  256. package/dist/chat/athena-chat-welcome.cjs +2 -2
  257. package/dist/chat/athena-chat-welcome.cjs.map +1 -1
  258. package/dist/chat/athena-citation-links.cjs +5 -5
  259. package/dist/chat/athena-citation-links.cjs.map +1 -1
  260. package/dist/chat/athena-composer-controls.cjs +26 -16
  261. package/dist/chat/athena-composer-controls.cjs.map +1 -1
  262. package/dist/chat/athena-composer-controls.d.ts +6 -0
  263. package/dist/chat/athena-composer-controls.js +26 -16
  264. package/dist/chat/athena-composer-controls.js.map +1 -1
  265. package/dist/chat/athena-turn-end-status.cjs +42 -0
  266. package/dist/chat/athena-turn-end-status.cjs.map +1 -0
  267. package/dist/chat/athena-turn-end-status.d.ts +24 -0
  268. package/dist/chat/athena-turn-end-status.js +42 -0
  269. package/dist/chat/athena-turn-end-status.js.map +1 -0
  270. package/dist/chat/browser-decision-check.cjs +131 -0
  271. package/dist/chat/browser-decision-check.cjs.map +1 -0
  272. package/dist/chat/browser-decision-check.d.ts +61 -0
  273. package/dist/chat/browser-decision-check.js +131 -0
  274. package/dist/chat/browser-decision-check.js.map +1 -0
  275. package/dist/chat/chat-outbox-rows.cjs +3 -3
  276. package/dist/chat/chat-outbox-rows.cjs.map +1 -1
  277. package/dist/chat/chat-voice-controls.cjs +96 -29
  278. package/dist/chat/chat-voice-controls.cjs.map +1 -1
  279. package/dist/chat/chat-voice-controls.d.ts +42 -3
  280. package/dist/chat/chat-voice-controls.js +92 -25
  281. package/dist/chat/chat-voice-controls.js.map +1 -1
  282. package/dist/chat/composer-keyboard-hint.cjs +5 -5
  283. package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
  284. package/dist/chat/device-operation.cjs +29 -0
  285. package/dist/chat/device-operation.cjs.map +1 -0
  286. package/dist/chat/device-operation.d.ts +34 -0
  287. package/dist/chat/device-operation.js +29 -0
  288. package/dist/chat/device-operation.js.map +1 -0
  289. package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
  290. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  291. package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
  292. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
  293. package/dist/chat/super-grouping/SuperGroupingCard.cjs +52 -36
  294. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  295. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
  296. package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
  297. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  298. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
  299. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  300. package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
  301. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  302. package/dist/chat/super-grouping/ToolTimeline.cjs +73 -40
  303. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  304. package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
  305. package/dist/chat/super-grouping/ToolTimeline.js +69 -36
  306. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  307. package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
  308. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  309. package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
  310. package/dist/chat/super-grouping/activity-timeline.js +47 -12
  311. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  312. package/dist/chat/super-grouping/grouping-function.cjs +4 -0
  313. package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
  314. package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
  315. package/dist/chat/super-grouping/grouping-function.js +5 -1
  316. package/dist/chat/super-grouping/grouping-function.js.map +1 -1
  317. package/dist/chat/super-grouping/index.cjs +6 -0
  318. package/dist/chat/super-grouping/index.cjs.map +1 -1
  319. package/dist/chat/super-grouping/index.d.ts +5 -2
  320. package/dist/chat/super-grouping/index.js +7 -1
  321. package/dist/chat/super-grouping/index.js.map +1 -1
  322. package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
  323. package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
  324. package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
  325. package/dist/chat/super-grouping/tool-part-placement.js +17 -0
  326. package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
  327. package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
  328. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
  329. package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
  330. package/dist/chat/thread-scroll-to-bottom.js +2 -2
  331. package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
  332. package/dist/chat/tooltip-icon-button.cjs +2 -2
  333. package/dist/chat/tooltip-icon-button.cjs.map +1 -1
  334. package/dist/chat/use-athena-voice-live.cjs +11 -0
  335. package/dist/chat/use-athena-voice-live.cjs.map +1 -0
  336. package/dist/chat/use-athena-voice-live.d.ts +11 -0
  337. package/dist/chat/use-athena-voice-live.js +11 -0
  338. package/dist/chat/use-athena-voice-live.js.map +1 -0
  339. package/dist/chat/use-statewire-approval-request.cjs +56 -24
  340. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  341. package/dist/chat/use-statewire-approval-request.d.ts +33 -4
  342. package/dist/chat/use-statewire-approval-request.js +41 -9
  343. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  344. package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
  345. package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
  346. package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
  347. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  348. package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
  349. package/dist/chat-ui/composer/tiptap-composer.js +85 -54
  350. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  351. package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
  352. package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
  353. package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
  354. package/dist/chat-ui/header/conversation-history-panel.js +38 -12
  355. package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
  356. package/dist/chat-ui/index.cjs +21 -0
  357. package/dist/chat-ui/index.cjs.map +1 -1
  358. package/dist/chat-ui/index.d.ts +8 -1
  359. package/dist/chat-ui/index.js +21 -0
  360. package/dist/chat-ui/index.js.map +1 -1
  361. package/dist/chat-ui/mentions/mention-chip.cjs +4 -4
  362. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  363. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
  364. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  365. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
  366. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  367. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
  368. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
  369. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
  370. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  371. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
  372. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
  373. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  374. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
  375. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
  376. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
  377. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
  378. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
  379. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  380. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
  381. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
  382. package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
  383. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
  384. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
  385. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
  386. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  387. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
  388. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
  389. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  390. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
  391. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  392. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
  393. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
  394. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  395. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
  396. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
  397. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
  398. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
  399. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
  400. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
  401. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  402. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
  403. package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
  404. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  405. package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
  406. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
  407. package/dist/chat-ui/mentions/use-mention-asset.cjs +3 -3
  408. package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
  409. package/dist/chat-ui/messages/answer-label.cjs +42 -0
  410. package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
  411. package/dist/chat-ui/messages/answer-label.d.ts +33 -0
  412. package/dist/chat-ui/messages/answer-label.js +42 -0
  413. package/dist/chat-ui/messages/answer-label.js.map +1 -0
  414. package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
  415. package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
  416. package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
  417. package/dist/chat-ui/messages/arrival-animation.js +13 -0
  418. package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
  419. package/dist/chat-ui/messages/continue-pill.cjs +5 -5
  420. package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
  421. package/dist/chat-ui/messages/from-the-call-card.cjs +124 -0
  422. package/dist/chat-ui/messages/from-the-call-card.cjs.map +1 -0
  423. package/dist/chat-ui/messages/from-the-call-card.d.ts +17 -0
  424. package/dist/chat-ui/messages/from-the-call-card.js +124 -0
  425. package/dist/chat-ui/messages/from-the-call-card.js.map +1 -0
  426. package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
  427. package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
  428. package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
  429. package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
  430. package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
  431. package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
  432. package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
  433. package/dist/chat-ui/messages/message-components.cjs +8 -4
  434. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  435. package/dist/chat-ui/messages/message-components.js +5 -1
  436. package/dist/chat-ui/messages/message-components.js.map +1 -1
  437. package/dist/chat-ui/messages/message-images.cjs +66 -0
  438. package/dist/chat-ui/messages/message-images.cjs.map +1 -0
  439. package/dist/chat-ui/messages/message-images.d.ts +16 -0
  440. package/dist/chat-ui/messages/message-images.js +66 -0
  441. package/dist/chat-ui/messages/message-images.js.map +1 -0
  442. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
  443. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  444. package/dist/chat-ui/messages/wake-marker.cjs +3 -3
  445. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
  446. package/dist/chat-ui/rich-text/chat-link.cjs +3 -2
  447. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
  448. package/dist/chat-ui/rich-text/chat-link.d.ts +4 -0
  449. package/dist/chat-ui/rich-text/chat-link.js +4 -3
  450. package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
  451. package/dist/chat-ui/rich-text/chat-message-body.cjs +9 -8
  452. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  453. package/dist/chat-ui/rich-text/chat-message-body.d.ts +12 -0
  454. package/dist/chat-ui/rich-text/chat-message-body.js +2 -1
  455. package/dist/chat-ui/rich-text/chat-message-body.js.map +1 -1
  456. package/dist/chat-ui/rich-text/chat-node-views.cjs +6 -6
  457. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  458. package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
  459. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
  460. package/dist/chat-ui/statewire.cjs +3 -0
  461. package/dist/chat-ui/statewire.cjs.map +1 -1
  462. package/dist/chat-ui/statewire.d.ts +2 -1
  463. package/dist/chat-ui/statewire.js +3 -0
  464. package/dist/chat-ui/statewire.js.map +1 -1
  465. package/dist/chat-ui/thread/chat-thread-shell.cjs +45 -14
  466. package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
  467. package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
  468. package/dist/chat-ui/thread/chat-thread-shell.js +37 -6
  469. package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
  470. package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
  471. package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
  472. package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
  473. package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
  474. package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
  475. package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
  476. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  477. package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
  478. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  479. package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
  480. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
  481. package/dist/collab/client.cjs +52 -3
  482. package/dist/collab/client.cjs.map +1 -1
  483. package/dist/collab/client.d.ts +27 -0
  484. package/dist/collab/client.js +52 -3
  485. package/dist/collab/client.js.map +1 -1
  486. package/dist/collab/document-status.cjs +150 -0
  487. package/dist/collab/document-status.cjs.map +1 -0
  488. package/dist/collab/document-status.d.ts +68 -0
  489. package/dist/collab/document-status.js +150 -0
  490. package/dist/collab/document-status.js.map +1 -0
  491. package/dist/collab/index.cjs +7 -0
  492. package/dist/collab/index.cjs.map +1 -1
  493. package/dist/collab/index.d.ts +6 -1
  494. package/dist/collab/index.js +7 -0
  495. package/dist/collab/index.js.map +1 -1
  496. package/dist/collab/presence-react.cjs +11 -11
  497. package/dist/collab/presence-react.cjs.map +1 -1
  498. package/dist/collab/react.cjs +6 -6
  499. package/dist/collab/react.cjs.map +1 -1
  500. package/dist/composer/AttachmentContext.cjs +24 -11
  501. package/dist/composer/AttachmentContext.cjs.map +1 -1
  502. package/dist/composer/AttachmentContext.js +18 -5
  503. package/dist/composer/AttachmentContext.js.map +1 -1
  504. package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
  505. package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
  506. package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
  507. package/dist/composer/ComposerAttachmentPreview.js +79 -24
  508. package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
  509. package/dist/composer/ComposerDropZone.cjs +7 -7
  510. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  511. package/dist/composer/FileUploadButton.cjs +37 -22
  512. package/dist/composer/FileUploadButton.cjs.map +1 -1
  513. package/dist/composer/FileUploadButton.d.ts +6 -0
  514. package/dist/composer/FileUploadButton.js +34 -19
  515. package/dist/composer/FileUploadButton.js.map +1 -1
  516. package/dist/composer/QuoteContext.cjs +8 -8
  517. package/dist/composer/QuoteContext.cjs.map +1 -1
  518. package/dist/composer/composer-handoff.cjs +4 -4
  519. package/dist/composer/composer-handoff.cjs.map +1 -1
  520. package/dist/composer/index.d.ts +1 -1
  521. package/dist/composer/useAppendToComposer.cjs +4 -4
  522. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  523. package/dist/composer/useAttachFiles.cjs +23 -6
  524. package/dist/composer/useAttachFiles.cjs.map +1 -1
  525. package/dist/composer/useAttachFiles.d.ts +15 -7
  526. package/dist/composer/useAttachFiles.js +22 -5
  527. package/dist/composer/useAttachFiles.js.map +1 -1
  528. package/dist/composer/useComposerAttachment.cjs +4 -4
  529. package/dist/composer/useComposerAttachment.cjs.map +1 -1
  530. package/dist/composer/useFileUpload.cjs +21 -16
  531. package/dist/composer/useFileUpload.cjs.map +1 -1
  532. package/dist/composer/useFileUpload.d.ts +12 -0
  533. package/dist/composer/useFileUpload.js +12 -7
  534. package/dist/composer/useFileUpload.js.map +1 -1
  535. package/dist/composer/useReadComposerDraft.cjs +27 -8
  536. package/dist/composer/useReadComposerDraft.cjs.map +1 -1
  537. package/dist/composer/useReadComposerDraft.d.ts +23 -1
  538. package/dist/composer/useReadComposerDraft.js +27 -8
  539. package/dist/composer/useReadComposerDraft.js.map +1 -1
  540. package/dist/composer/useSendMessage.cjs +4 -4
  541. package/dist/composer/useSendMessage.cjs.map +1 -1
  542. package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
  543. package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
  544. package/dist/dictation/audio-level-history.cjs +3 -3
  545. package/dist/dictation/audio-level-history.cjs.map +1 -1
  546. package/dist/dictation/dictation-controls.cjs +24 -20
  547. package/dist/dictation/dictation-controls.cjs.map +1 -1
  548. package/dist/dictation/dictation-controls.d.ts +6 -1
  549. package/dist/dictation/dictation-controls.js +24 -20
  550. package/dist/dictation/dictation-controls.js.map +1 -1
  551. package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
  552. package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
  553. package/dist/dictation/use-dictation.cjs +22 -22
  554. package/dist/dictation/use-dictation.cjs.map +1 -1
  555. package/dist/index.cjs +29 -2
  556. package/dist/index.cjs.map +1 -1
  557. package/dist/index.d.ts +18 -4
  558. package/dist/index.js +30 -3
  559. package/dist/index.js.map +1 -1
  560. package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
  561. package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
  562. package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
  563. package/dist/keryx-http/src/receive-only-socket.js +40 -0
  564. package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
  565. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs +190 -0
  566. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs.map +1 -0
  567. package/dist/keryx-http/src/unconfirmed-update-attributions.d.ts +132 -0
  568. package/dist/keryx-http/src/unconfirmed-update-attributions.js +190 -0
  569. package/dist/keryx-http/src/unconfirmed-update-attributions.js.map +1 -0
  570. package/dist/keryx-http/src/update-attributions.cjs +141 -0
  571. package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
  572. package/dist/keryx-http/src/update-attributions.d.ts +107 -0
  573. package/dist/keryx-http/src/update-attributions.js +141 -0
  574. package/dist/keryx-http/src/update-attributions.js.map +1 -0
  575. package/dist/lib/owner-document.cjs +6 -6
  576. package/dist/lib/owner-document.cjs.map +1 -1
  577. package/dist/lib/use-athena-rest-query.cjs +4 -4
  578. package/dist/lib/use-athena-rest-query.cjs.map +1 -1
  579. package/dist/lib/use-document-active.cjs +4 -4
  580. package/dist/lib/use-document-active.cjs.map +1 -1
  581. package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
  582. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
  583. package/dist/offline/offline-history.cjs +7 -7
  584. package/dist/offline/offline-history.cjs.map +1 -1
  585. package/dist/provider/AthenaContext.cjs +3 -3
  586. package/dist/provider/AthenaContext.cjs.map +1 -1
  587. package/dist/provider/AthenaProvider.cjs +120 -79
  588. package/dist/provider/AthenaProvider.cjs.map +1 -1
  589. package/dist/provider/AthenaProvider.d.ts +11 -1
  590. package/dist/provider/AthenaProvider.js +44 -3
  591. package/dist/provider/AthenaProvider.js.map +1 -1
  592. package/dist/provider/PostHogProvider.cjs +2 -2
  593. package/dist/provider/PostHogProvider.cjs.map +1 -1
  594. package/dist/provider/agent-selection-context.cjs +2 -2
  595. package/dist/provider/agent-selection-context.cjs.map +1 -1
  596. package/dist/provider/chat-mode-context.cjs +2 -2
  597. package/dist/provider/chat-mode-context.cjs.map +1 -1
  598. package/dist/provider/session-persistence-context.cjs +10 -0
  599. package/dist/provider/session-persistence-context.cjs.map +1 -0
  600. package/dist/provider/session-persistence-context.d.ts +15 -0
  601. package/dist/provider/session-persistence-context.js +10 -0
  602. package/dist/provider/session-persistence-context.js.map +1 -0
  603. package/dist/provider/statewire-history-context.cjs +4 -4
  604. package/dist/provider/statewire-history-context.cjs.map +1 -1
  605. package/dist/provider/statewire-lifecycle-context.cjs +3 -3
  606. package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
  607. package/dist/provider/statewire-window-context.cjs +3 -3
  608. package/dist/provider/statewire-window-context.cjs.map +1 -1
  609. package/dist/provider/theme-style-context.cjs +3 -3
  610. package/dist/provider/theme-style-context.cjs.map +1 -1
  611. package/dist/react/package.json.cjs +1 -1
  612. package/dist/react/package.json.js +1 -1
  613. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
  614. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  615. package/dist/runtime/auth-refusal-restart.cjs +7 -7
  616. package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
  617. package/dist/runtime/auth.cjs +13 -13
  618. package/dist/runtime/auth.cjs.map +1 -1
  619. package/dist/runtime/statewire-lifecycle.cjs +1 -0
  620. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  621. package/dist/runtime/statewire-lifecycle.d.ts +3 -1
  622. package/dist/runtime/statewire-lifecycle.js +2 -1
  623. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  624. package/dist/runtime/statewire-server-lane-context.cjs +2 -2
  625. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
  626. package/dist/runtime/statewire-session-lane.cjs +4 -4
  627. package/dist/runtime/statewire-session-lane.cjs.map +1 -1
  628. package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
  629. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  630. package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
  631. package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
  632. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  633. package/dist/styles.css +1 -1
  634. package/dist/threads/Inbox.cjs +8 -8
  635. package/dist/threads/Inbox.cjs.map +1 -1
  636. package/dist/threads/SessionList.cjs +9 -9
  637. package/dist/threads/SessionList.cjs.map +1 -1
  638. package/dist/threads/SessionsPage.cjs +11 -11
  639. package/dist/threads/SessionsPage.cjs.map +1 -1
  640. package/dist/threads/api.cjs.map +1 -1
  641. package/dist/threads/api.d.ts +15 -0
  642. package/dist/threads/api.js.map +1 -1
  643. package/dist/threads/conversation-list-fetcher.cjs +13 -5
  644. package/dist/threads/conversation-list-fetcher.cjs.map +1 -1
  645. package/dist/threads/conversation-list-fetcher.d.ts +4 -1
  646. package/dist/threads/conversation-list-fetcher.js +13 -5
  647. package/dist/threads/conversation-list-fetcher.js.map +1 -1
  648. package/dist/threads/index-triggered-refresh.cjs +10 -10
  649. package/dist/threads/index-triggered-refresh.cjs.map +1 -1
  650. package/dist/threads/mark-viewed-thread-read.cjs +12 -12
  651. package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
  652. package/dist/threads/offline-session-list.cjs +3 -3
  653. package/dist/threads/offline-session-list.cjs.map +1 -1
  654. package/dist/threads/session-list-tab-share.cjs +5 -5
  655. package/dist/threads/session-list-tab-share.cjs.map +1 -1
  656. package/dist/threads/statewire-thread-list.cjs +79 -57
  657. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  658. package/dist/threads/statewire-thread-list.d.ts +20 -8
  659. package/dist/threads/statewire-thread-list.js +28 -6
  660. package/dist/threads/statewire-thread-list.js.map +1 -1
  661. package/dist/threads/thread-id-context.cjs +5 -5
  662. package/dist/threads/thread-id-context.cjs.map +1 -1
  663. package/dist/threads/use-athena-session-attention.cjs +2 -2
  664. package/dist/threads/use-athena-session-attention.cjs.map +1 -1
  665. package/dist/threads/use-athena-sessions.cjs +37 -15
  666. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  667. package/dist/threads/use-athena-sessions.d.ts +10 -5
  668. package/dist/threads/use-athena-sessions.js +28 -6
  669. package/dist/threads/use-athena-sessions.js.map +1 -1
  670. package/dist/threads/use-athena-thread-model.cjs +3 -3
  671. package/dist/threads/use-athena-thread-model.cjs.map +1 -1
  672. package/dist/threads/use-rest-conversation-history.cjs +3 -3
  673. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  674. package/dist/threads/use-rest-conversation-history.d.ts +1 -0
  675. package/dist/threads/use-statewire-conversation-history.cjs +8 -8
  676. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  677. package/dist/threads/use-thread-archive.cjs +9 -9
  678. package/dist/threads/use-thread-archive.cjs.map +1 -1
  679. package/dist/threads/use-thread-favorite.cjs +2 -2
  680. package/dist/threads/use-thread-favorite.cjs.map +1 -1
  681. package/dist/threads/use-thread-field-override.cjs +20 -20
  682. package/dist/threads/use-thread-field-override.cjs.map +1 -1
  683. package/dist/threads/use-thread-read-state.cjs +4 -4
  684. package/dist/threads/use-thread-read-state.cjs.map +1 -1
  685. package/dist/threads/use-thread-rename.cjs +2 -2
  686. package/dist/threads/use-thread-rename.cjs.map +1 -1
  687. package/dist/threads/useAthenaThreadManager.cjs +2 -2
  688. package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
  689. package/dist/tools/NestedPtcMessages.cjs +6 -6
  690. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  691. package/dist/tools/append-document-tool-ui.cjs +7 -7
  692. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  693. package/dist/tools/file-tool-uis.cjs +2 -2
  694. package/dist/tools/file-tool-uis.cjs.map +1 -1
  695. package/dist/tools/misc-tool-uis.cjs +2 -2
  696. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  697. package/dist/tools/primitives.cjs +6 -6
  698. package/dist/tools/primitives.cjs.map +1 -1
  699. package/dist/tools/read-asset-tool-ui.cjs +6 -6
  700. package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
  701. package/dist/tools/subagent-task-tool-ui.cjs +21 -21
  702. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  703. package/dist/tools/test-recording-tool-uis.cjs +16 -16
  704. package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
  705. package/dist/tools/todo-plan-store.cjs +4 -4
  706. package/dist/tools/todo-plan-store.cjs.map +1 -1
  707. package/dist/tools/tool-appearance.cjs +3 -3
  708. package/dist/tools/tool-appearance.cjs.map +1 -1
  709. package/dist/tools/tool-fallback.cjs +14 -14
  710. package/dist/tools/tool-fallback.cjs.map +1 -1
  711. package/dist/tools/tool-uis.cjs +74 -74
  712. package/dist/tools/tool-uis.cjs.map +1 -1
  713. package/dist/tools/use-elapsed-seconds.cjs +3 -3
  714. package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
  715. package/dist/tools/write-todos-tool-ui.cjs +9 -9
  716. package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
  717. package/dist/ui/image-viewer.cjs +382 -0
  718. package/dist/ui/image-viewer.cjs.map +1 -0
  719. package/dist/ui/image-viewer.d.ts +50 -0
  720. package/dist/ui/image-viewer.js +382 -0
  721. package/dist/ui/image-viewer.js.map +1 -0
  722. package/dist/voice/chat.cjs +6 -0
  723. package/dist/voice/chat.cjs.map +1 -1
  724. package/dist/voice/chat.d.ts +1 -1
  725. package/dist/voice/chat.js +8 -2
  726. package/dist/voice/livekit-join.cjs +52 -101
  727. package/dist/voice/livekit-join.cjs.map +1 -1
  728. package/dist/voice/livekit-join.d.ts +1 -6
  729. package/dist/voice/livekit-join.js +52 -101
  730. package/dist/voice/livekit-join.js.map +1 -1
  731. package/dist/voice/livekit.cjs.map +1 -1
  732. package/dist/voice/livekit.d.ts +11 -1
  733. package/dist/voice/livekit.js.map +1 -1
  734. package/dist/voice/use-athena-voice-session.cjs +34 -34
  735. package/dist/voice/use-athena-voice-session.cjs.map +1 -1
  736. package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
  737. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
  738. package/dist/workbench/SessionWorkbench.cjs +22 -22
  739. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  740. package/dist/workbench/session-workbench-context.cjs +3 -3
  741. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  742. package/dist/workbench/session-workbench-panes.cjs +8 -8
  743. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  744. package/dist/workbench/workbench-layout-context.cjs +3 -3
  745. package/dist/workbench/workbench-layout-context.cjs.map +1 -1
  746. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-task-tool-ui.cjs","sources":["../../src/tools/subagent-task-tool-ui.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The subagent card: one `task` call the deep agent delegated, shown the way\n * Olympus shows a subagent lane.\n *\n * - On the card: where the lane is (queued, running, done, failed, stopped),\n * how many tool calls it made (the wire's cut marker counts a lane whose\n * card carries only its newest steps), how long it has run, and while it\n * runs, its newest step; a finished lane's report, or why it failed, under\n * it, clamped.\n * - Behind its disclosure: the lane's steps, live while it runs, ending on\n * what the lane ended on, whole (a failure, or a report no step carries),\n * so a lane with no steps still opens to its full result. The lane is\n * assistant-ui's native nested thread: the `task` part's `messages`, which\n * the SDK runtime's opt-in conversion fills\n * (`createSubagentTranscriptConversionCache`), rendered read-only under\n * `ReadonlyThreadProvider` with the chat's own tool UIs. A cut lane (a\n * running card always; a finished one when the provider declares the\n * lane-cut contract, `subagentLaneHistory`) says how many of its steps it\n * shows, and \"Load earlier steps\" reads the rest with `history/lane`\n * (`useDeepAgentLaneHistory`), a read under the thread's own attach.\n *\n * A read-only nested thread has no statewire thread behind it: a `task` call\n * inside a subagent's own steps renders as a static row, and the steps are\n * their own error boundary, so a tool UI that throws there never takes the\n * chat down with it.\n */\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n ReadonlyThreadProvider,\n type ThreadMessage,\n ThreadPrimitive,\n type ToolCallMessagePartComponent,\n type ToolCallMessagePartProps,\n type ToolCallMessagePartStatus,\n useAuiState,\n} from \"@assistant-ui/react\";\nimport type { LangChainMessage } from \"@assistant-ui/react-langgraph\";\nimport {\n createSubagentLaneConversion,\n deepAgentRowKey,\n hasStatewireThreadExtras,\n salientToolCallDetail,\n type SubagentDiscoverySnapshot,\n type SubagentStatus,\n subagentAwaitingApproval,\n subagentToolCallAwaitingApproval,\n taskSubagentsOfTurn,\n useDeepAgentLaneHistory,\n withLaneReport,\n} from \"@athenaintel/agent-runtime\";\nimport { QueryClientProvider } from \"@tanstack/react-query\";\nimport {\n AlertCircleIcon,\n BotIcon,\n CheckIcon,\n ChevronDownIcon,\n CircleDashedIcon,\n LoaderIcon,\n ShieldAlertIcon,\n XCircleIcon,\n} from \"lucide-react\";\nimport {\n Component,\n createContext,\n type ErrorInfo,\n type FC,\n memo,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { useApprovalWaitInScope } from \"../chat/use-statewire-approval-request\";\nimport { MESSAGE_CREATED_AT_KEY } from \"../chat/message-time\";\nimport { formatWorkDuration, readInstantMs } from \"../chat/super-grouping/turn-timing\";\nimport { athenaDiagnostics } from \"../diagnostics/athena-diagnostics\";\nimport { useAthenaQueryClient } from \"../lib/use-athena-rest-query\";\nimport { cn } from \"../lib/utils\";\nimport { CollapsibleTrigger } from \"../ui/collapsible\";\nimport { useNestedPtcComponents } from \"./NestedPtcMessages\";\nimport { StepText } from \"./step-text\";\nimport { useToolAppearance } from \"./tool-appearance\";\nimport { ToolFallback, ToolFallbackContent, ToolFallbackRoot } from \"./tool-fallback\";\nimport { humanizeToolName, summarizeToolCall, type ToolCallSummary } from \"./tool-summary\";\n\nconst NO_LANE_STEPS: readonly LangChainMessage[] = [];\nconst NO_MESSAGES: readonly ThreadMessage[] = [];\n\n// ─── What the card says ──────────────────────────────────────────────\n// Pure: where a lane is, how long it ran, the step it took last, and the\n// note over a cut lane's steps, tested without rendering the card.\n\n/**\n * Where a lane is, as the card shows it: the lane's own status, except that a\n * lane parked on a person's approval is `approval` (its own dispatch, or a call\n * it made, is a gated call nobody has answered), any other call the run waits\n * on an answer for is `waiting`, and one the run stopped before it settled is\n * `stopped`.\n */\nexport type SubagentLanePhase =\n | \"queued\"\n | \"approval\"\n | \"waiting\"\n | \"running\"\n | \"complete\"\n | \"error\"\n | \"stopped\";\n\nexport const SUBAGENT_LANE_PHASE_LABELS: Record<SubagentLanePhase, string> = {\n queued: \"Queued\",\n approval: \"Waiting for approval\",\n waiting: \"Waiting for you\",\n running: \"Running\",\n complete: \"Done\",\n error: \"Failed\",\n stopped: \"Stopped\",\n};\n\n/** The lane's phase from its status, the status assistant-ui gives its part, and the run's approval. */\nexport function subagentLanePhase({\n status,\n partStatus,\n awaitingApproval = false,\n}: {\n status: SubagentStatus;\n partStatus: ToolCallMessagePartStatus | undefined;\n /** The lane waits on a person's approval (agent-runtime's `subagentAwaitingApproval`). */\n awaitingApproval?: boolean;\n}): SubagentLanePhase {\n if (status === \"complete\" || status === \"error\") return status;\n if (awaitingApproval) return \"approval\";\n if (partStatus?.type === \"requires-action\") return \"waiting\";\n if (partStatus?.type === \"incomplete\") {\n return partStatus.reason === \"cancelled\" ? \"stopped\" : \"error\";\n }\n return status;\n}\n\n/** The phases a lane never leaves. */\nexport function isSettledSubagentLanePhase(phase: SubagentLanePhase): boolean {\n return phase === \"complete\" || phase === \"error\" || phase === \"stopped\";\n}\n\n/**\n * What a settled lane ended on, whole: its report, or why it failed. A lane\n * that the run's own failure ended has no result of its own, so the `task`\n * part's status says why (as the generic card shows a failed call). Empty\n * while the lane runs.\n */\nexport function subagentLaneResult({\n output,\n phase,\n partStatus,\n}: {\n /** The lane's own result text (`SubagentDiscoverySnapshot.output`). */\n output: string | undefined;\n phase: SubagentLanePhase;\n partStatus: ToolCallMessagePartStatus | undefined;\n}): string {\n if (!isSettledSubagentLanePhase(phase)) return \"\";\n const own = output?.trim() ?? \"\";\n if (own !== \"\" || phase !== \"error\" || partStatus?.type !== \"incomplete\") return own;\n const { error } = partStatus;\n if (error === undefined || error === null) return \"\";\n return (typeof error === \"string\" ? error : JSON.stringify(error)).trim();\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/**\n * How long a finished lane ran, measured by the server: the `task` result's\n * `_started_at` and `_created_at`, which the deep agent's tool-call timing\n * stamps on every tool result and mirrors onto its artifact (the one field of\n * a tool message the converter hands the tool-call part). `null` when either\n * stamp is missing.\n */\nexport function finishedLaneDurationMs(artifact: unknown): number | null {\n const stamps = record(artifact);\n const startedAt = readInstantMs(stamps?._started_at);\n const finishedAt = readInstantMs(stamps?.[MESSAGE_CREATED_AT_KEY]);\n return startedAt !== null && finishedAt !== null && finishedAt >= startedAt\n ? finishedAt - startedAt\n : null;\n}\n\nconst ASSISTANT_TYPES: ReadonlySet<unknown> = new Set([\"ai\", \"AIMessageChunk\"]);\n\n/**\n * When the agent delegated the call `toolCallId`: the server stamp\n * (`_created_at`) of the assistant message that made it, among the raw\n * messages bound to the turn. A running lane's card carries no stamp of its\n * own, so its clock counts from here, the way the turn header counts from the\n * turn's own stamps. `null` without one.\n */\nexport function laneDelegatedAtMs({\n sources,\n toolCallId,\n}: {\n sources: readonly unknown[];\n toolCallId: string;\n}): number | null {\n for (const source of sources) {\n const message = record(source);\n if (!message || !ASSISTANT_TYPES.has(message.type)) continue;\n const calls = message.tool_calls;\n if (!Array.isArray(calls) || !calls.some((call) => record(call)?.id === toolCallId)) continue;\n const kwargs = record(message.additional_kwargs);\n const metadata = record(kwargs?.metadata);\n return (\n readInstantMs(metadata?.[MESSAGE_CREATED_AT_KEY]) ??\n readInstantMs(kwargs?.[MESSAGE_CREATED_AT_KEY]) ??\n readInstantMs(message[MESSAGE_CREATED_AT_KEY])\n );\n }\n return null;\n}\n\n/**\n * The lane's newest tool step as its summary line (\"Read `routes.ts`\",\n * \"Running `npm test`\"), from the lane's converted steps: the last tool call\n * of its newest assistant turn, worded for whether it has answered. `null`\n * before the lane's first tool call.\n */\nexport function latestLaneStep(messages: readonly ThreadMessage[]): ToolCallSummary | null {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role !== \"assistant\") continue;\n for (let partIndex = message.content.length - 1; partIndex >= 0; partIndex -= 1) {\n const part = message.content[partIndex];\n if (part?.type !== \"tool-call\") continue;\n const answered = part.result !== undefined && part.isPreliminary !== true;\n return summarizeToolCall({\n toolName: part.toolName,\n args: part.args,\n result: answered ? part.result : undefined,\n status: answered ? (part.isError === true ? \"error\" : \"complete\") : \"running\",\n });\n }\n }\n return null;\n}\n\n/**\n * The subagent's type as the card names it: the `task` call's `subagent_type`\n * in words, with the default `general-purpose` agent as \"Subagent\".\n */\nexport function subagentTypeLabel(name: string): string {\n const trimmed = name.trim();\n if (trimmed === \"\" || trimmed === \"subagent\" || trimmed === \"general-purpose\") return \"Subagent\";\n return humanizeToolName(trimmed);\n}\n\n/** \"1 tool call\", \"12 tool calls\". */\nexport function toolCallCountLabel(count: number): string {\n return `${count} tool call${count === 1 ? \"\" : \"s\"}`;\n}\n\n/** \"1 step\", \"12 steps\". */\nfunction stepsLabel(count: number): string {\n return `${count} step${count === 1 ? \"\" : \"s\"}`;\n}\n\n/** What the steps panel says about the steps it shows of a cut lane. */\nexport function laneStepsNote({\n shown,\n total,\n arrivesLater,\n}: {\n /** Steps the panel shows. */\n shown: number;\n /** Steps the lane stores (its cut marker), when the card carries fewer. */\n total: number | undefined;\n /**\n * A running lane on a host that pages no running lane: its card brings the\n * rest once the subagent finishes.\n */\n arrivesLater: boolean;\n}): string | null {\n if (total === undefined || total <= shown) return null;\n const leftOff = total - shown;\n return arrivesLater\n ? `Showing the latest steps. ${leftOff} earlier ${leftOff === 1 ? \"step arrives\" : \"steps arrive\"} when this subagent finishes.`\n : `Showing the latest ${shown} of ${stepsLabel(total)}.`;\n}\n\n/**\n * Whether this card renders inside a read-only nested thread (a subagent's own\n * steps, under `ReadonlyThreadProvider`), whose thread has no statewire\n * extras. Never throws: rendered outside any thread, it is not nested.\n */\nfunction useInReadOnlyThread(): boolean {\n return useAuiState((s) => {\n const thread = s.optional?.thread;\n return thread !== undefined && !hasStatewireThreadExtras(thread.extras);\n });\n}\n\n/** A lane for a call agent-runtime read no lane for: what its arguments say, queued. */\nfunction laneFromArgs(toolCallId: string, args: unknown): SubagentDiscoverySnapshot {\n const record = typeof args === \"object\" && args !== null ? (args as Record<string, unknown>) : {};\n return {\n id: toolCallId,\n name: typeof record.subagent_type === \"string\" ? record.subagent_type : \"subagent\",\n description: typeof record.description === \"string\" ? record.description : \"\",\n status: \"queued\",\n toolCallCount: 0,\n messages: NO_MESSAGES,\n messageCount: 0,\n currentText: \"\",\n };\n}\n\n// ─── Status glyph ────────────────────────────────────────────────────\n\nfunction LaneStatusGlyph({ phase }: { phase: SubagentLanePhase }) {\n const glyph =\n phase === \"running\" ? (\n <LoaderIcon className=\"size-3.5 animate-spin text-muted-foreground motion-reduce:animate-none\" />\n ) : phase === \"complete\" ? (\n <CheckIcon className=\"size-3.5 text-emerald-600\" />\n ) : phase === \"error\" ? (\n <AlertCircleIcon className=\"size-3.5 text-destructive\" />\n ) : phase === \"stopped\" ? (\n <XCircleIcon className=\"size-3.5 text-muted-foreground\" />\n ) : phase === \"waiting\" || phase === \"approval\" ? (\n <ShieldAlertIcon className=\"size-3.5 text-amber-600\" />\n ) : (\n <CircleDashedIcon className=\"size-3.5 text-muted-foreground motion-safe:animate-pulse\" />\n );\n return (\n <span\n data-slot=\"subagent-status\"\n data-phase={phase}\n aria-hidden=\"true\"\n className=\"mt-0.5 flex size-4 shrink-0 items-center justify-center\"\n >\n {glyph}\n </span>\n );\n}\n\n// ─── Clock ───────────────────────────────────────────────────────────\n\n/**\n * How long a running lane has run: since `startMs` (the server's stamp on the\n * delegating message), else since this card saw it running; `null` while it\n * does not run. Ticks once a second off the wall clock.\n */\nfunction useRunningElapsedMs(running: boolean, startMs: number | null): number | null {\n const [clock, setClock] = useState<{ seenAt: number; now: number } | null>(null);\n useEffect(() => {\n if (!running) {\n setClock(null);\n return undefined;\n }\n const seenAt = Date.now();\n setClock({ seenAt, now: seenAt });\n const timer = setInterval(() => setClock({ seenAt, now: Date.now() }), 1000);\n return () => clearInterval(timer);\n }, [running]);\n if (!running || clock === null) return null;\n return Math.max(0, clock.now - (startMs ?? clock.seenAt));\n}\n\n// ─── The lane's steps ────────────────────────────────────────────────\n\ntype NestedPartsComponents = ReturnType<typeof useNestedPtcComponents>;\n\nconst LaneStepComponentsContext = createContext<NestedPartsComponents | null>(null);\n\nconst EmptyStepPart: FC = () => null;\n\n/**\n * One row of the lane: an assistant turn's parts, through the chat's own\n * renderers (`NestedPtcComponentsProvider`, which `AthenaChat` mounts). The\n * subagent's brief (its user message) is the card's own description, so it is\n * not repeated.\n */\nconst LaneStep: FC = () => {\n const role = useAuiState((s) => s.message.role);\n const components = useContext(LaneStepComponentsContext);\n if (role !== \"assistant\") return null;\n return <MessagePrimitive.Parts components={{ Empty: EmptyStepPart, ...components }} />;\n};\n\nconst LANE_ROW_COMPONENTS = { Message: LaneStep };\n\nconst ROW_KEY_SEPARATOR = \"\\u0000\";\n\n/**\n * The nested thread's rows, each under its row key (`deepAgentRowKey`): the\n * lane's turn keeps its row while the card's cut drops its oldest steps and\n * when earlier pages land, so what the person opened in it stays open.\n */\nfunction LaneRows() {\n const joinedKeys = useAuiState((s) =>\n s.thread.messages.map((message) => deepAgentRowKey(message)).join(ROW_KEY_SEPARATOR),\n );\n const rowKeys = useMemo(\n () => (joinedKeys === \"\" ? [] : joinedKeys.split(ROW_KEY_SEPARATOR)),\n [joinedKeys],\n );\n return (\n <>\n {rowKeys.map((key, index) => (\n <ThreadPrimitive.MessageByIndex key={key} index={index} components={LANE_ROW_COMPONENTS} />\n ))}\n </>\n );\n}\n\ninterface LaneStepsBoundaryProps {\n name: string;\n children: ReactNode;\n}\n\n/**\n * The steps' own boundary: they render the chat's tool UIs (a host's own\n * among them) in a nested thread no statewire thread backs, and a card that\n * throws there must not take the chat down. Reported like a chat render\n * crash, with the lane named.\n */\nclass LaneStepsBoundary extends Component<LaneStepsBoundaryProps, { failed: boolean }> {\n constructor(props: LaneStepsBoundaryProps) {\n super(props);\n this.state = { failed: false };\n }\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n athenaDiagnostics.error(\n \"sdk.error\",\n error,\n {\n code: \"chat_render_crash\",\n message: \"A subagent's steps could not be shown\",\n hint: \"Inspect component_stack: a tool UI that reads the live thread fails inside a subagent's read-only steps.\",\n },\n {\n surface: \"subagent-lane\",\n subagent: this.props.name,\n component_stack: errorInfo.componentStack?.slice(0, 2000) ?? null,\n },\n );\n }\n\n render(): ReactNode {\n if (this.state.failed) {\n return (\n <p role=\"alert\" className=\"px-1 text-xs text-muted-foreground\">\n These steps couldn't be shown. The conversation is not affected.\n </p>\n );\n }\n return this.props.children;\n }\n}\n\n/** The host's `QueryClient` when one is in context, else one of the panel's own (`useAthenaQueryClient`). */\nfunction LaneQueryScope({ children }: { children: ReactNode }) {\n const queryClient = useAthenaQueryClient();\n return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;\n}\n\ninterface LaneStepsProps {\n lane: SubagentDiscoverySnapshot;\n phase: SubagentLanePhase;\n /** What the lane ended on, whole (`subagentLaneResult`); empty while it runs. */\n result: string;\n /** The `task` part's own nested thread, shown if the panel cannot convert the lane itself. */\n partMessages: readonly ThreadMessage[] | undefined;\n}\n\n/**\n * The open card's steps: the lane the card carries, and the earlier steps the\n * person asks for. The panel converts the lane itself, with one conversion\n * memory while it is open (`createSubagentLaneConversion`), so the lane's turn\n * keeps its row key as the cut slides and pages land. It ends on what the lane\n * ended on, whole and selectable: the card clamps it.\n */\nfunction LaneSteps({ lane, phase, result, partMessages }: LaneStepsProps) {\n // The lane's card is its running placeholder, whether it streams or waits on an approval.\n const running = lane.status === \"running\" && (phase === \"running\" || phase === \"approval\");\n const source = lane.source;\n const history = useDeepAgentLaneHistory({\n messageId: source?.messageId,\n lane: source?.lane,\n carried: source?.transcript ?? NO_LANE_STEPS,\n total: source?.truncated?.messages,\n finished: source?.truncated?.finished === true,\n });\n const [convertLane] = useState(() => createSubagentLaneConversion());\n // A `task` lane that finished ends on its report, the card's content, even\n // when its stored transcript does not (`withLaneReport`), as in Olympus's drawer.\n const report =\n lane.status === \"complete\" && source?.messageId !== undefined ? lane.output : undefined;\n const messages =\n (source === undefined\n ? undefined\n : convertLane(withLaneReport(history.steps, report), running)) ??\n partMessages ??\n NO_MESSAGES;\n const components = useNestedPtcComponents(ToolFallback);\n const shown = history.steps.length;\n // A running card on a host that pages no running lane carries the rest once it finishes.\n const arrivesLater = running && source?.messageId !== undefined && !history.available;\n const note = laneStepsNote({ shown, total: history.total, arrivesLater });\n const emptyText =\n phase === \"running\"\n ? \"Starting…\"\n : phase === \"queued\" || phase === \"waiting\" || phase === \"approval\"\n ? \"Not started yet.\"\n : \"No steps were recorded for this subagent.\";\n // Why a lane failed is never one of its steps; a report is the closing\n // step of a lane with steps to close (`withLaneReport`).\n const failed = phase === \"error\";\n const closing = failed || messages.length === 0 ? result : \"\";\n\n return (\n <div data-slot=\"subagent-steps\" className=\"flex min-w-0 flex-col gap-2 px-2.5\">\n {lane.description ? (\n <p\n data-slot=\"subagent-brief\"\n className=\"whitespace-pre-wrap break-words text-xs leading-relaxed text-muted-foreground\"\n >\n {lane.description}\n </p>\n ) : null}\n {note ? (\n <div\n data-slot=\"subagent-steps-note\"\n className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground\"\n >\n <span>{note}</span>\n {history.hasEarlier && !arrivesLater ? (\n <button\n type=\"button\"\n onClick={history.loadEarlier}\n disabled={history.loading}\n className=\"rounded font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:no-underline disabled:opacity-60\"\n >\n {history.loading ? \"Loading earlier steps…\" : \"Load earlier steps\"}\n </button>\n ) : null}\n </div>\n ) : null}\n {messages.length > 0 ? (\n <LaneStepsBoundary name={lane.name}>\n <LaneStepComponentsContext.Provider value={components}>\n <ReadonlyThreadProvider messages={messages}>\n <div data-slot=\"subagent-step-rows\" className=\"flex min-w-0 flex-col gap-1\">\n <LaneRows />\n </div>\n </ReadonlyThreadProvider>\n </LaneStepComponentsContext.Provider>\n </LaneStepsBoundary>\n ) : (\n <p className=\"text-xs text-muted-foreground\">{emptyText}</p>\n )}\n {closing ? (\n <div data-slot=\"subagent-result\" className=\"flex min-w-0 flex-col gap-0.5\">\n <p\n className={cn(\n \"text-xs font-medium\",\n failed ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {failed ? \"Error\" : \"Report\"}\n </p>\n <p\n data-slot=\"subagent-result-text\"\n className={cn(\n \"max-h-72 overflow-auto whitespace-pre-wrap break-words text-xs leading-relaxed\",\n failed ? \"text-destructive/80\" : \"text-foreground/80\",\n )}\n >\n {closing}\n </p>\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── The card ────────────────────────────────────────────────────────\n\n/** The card's second line: where the lane is, its tool calls, how long it ran. */\nfunction laneMeta({\n phase,\n toolCallCount,\n elapsedMs,\n}: {\n phase: SubagentLanePhase;\n toolCallCount: number;\n elapsedMs: number | null;\n}): string {\n const parts: string[] = [SUBAGENT_LANE_PHASE_LABELS[phase]];\n if (toolCallCount > 0 || isSettledSubagentLanePhase(phase)) {\n parts.push(toolCallCountLabel(toolCallCount));\n }\n if (elapsedMs !== null && (phase !== \"running\" || elapsedMs >= 1000)) {\n parts.push(formatWorkDuration(elapsedMs));\n }\n return parts.join(\" · \");\n}\n\nfunction SubagentTaskCard({ toolCallId, args, status, artifact, messages }: ToolCallMessagePartProps) {\n const appearance = useToolAppearance();\n const isThread = appearance === \"thread\";\n const readLane = useAuiState((s) => taskSubagentsOfTurn(s.message).get(toolCallId));\n const lane = useMemo(\n () => readLane ?? laneFromArgs(toolCallId, args),\n [readLane, toolCallId, args],\n );\n // A lane holding a gated call the run's approval names waits on a person:\n // no live activity, no clock, just what it waits on. Read-only (the approval\n // card answers).\n const { toolCallIds: waitingToolCallIds } = useApprovalWaitInScope();\n const awaitingApproval = subagentAwaitingApproval({ lane, toolCallIds: waitingToolCallIds });\n const gatedCall = awaitingApproval\n ? subagentToolCallAwaitingApproval({ lane, toolCallIds: waitingToolCallIds })\n : undefined;\n const phase = subagentLanePhase({ status: lane.status, partStatus: status, awaitingApproval });\n const running = phase === \"running\";\n // Only a running lane's clock reads it, so a settled card scans nothing.\n const delegatedAt = useAuiState((s) =>\n running\n ? laneDelegatedAtMs({ sources: getExternalStoreMessages<unknown>(s.message), toolCallId })\n : null,\n );\n const runningElapsed = useRunningElapsedMs(running, delegatedAt);\n const elapsedMs = running\n ? runningElapsed\n : isSettledSubagentLanePhase(phase)\n ? finishedLaneDurationMs(artifact)\n : null;\n const step = useMemo(() => (running ? latestLaneStep(lane.messages) : null), [running, lane.messages]);\n const hasSteps = lane.messageCount > 0 || (lane.omittedMessageCount ?? 0) > 0;\n const typeLabel = subagentTypeLabel(lane.name);\n const title = lane.description.trim() || typeLabel;\n const meta = laneMeta({ phase, toolCallCount: lane.toolCallCount, elapsedMs });\n const liveText = step ? null : lane.currentText.trim();\n const report = subagentLaneResult({ output: lane.output, phase, partStatus: status });\n\n const header = (\n <>\n <LaneStatusGlyph phase={phase} />\n <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"flex min-w-0 items-baseline gap-1.5\">\n <span\n data-slot=\"subagent-title\"\n title={lane.description || undefined}\n className=\"min-w-0 truncate font-medium text-foreground\"\n >\n {title}\n </span>\n {title !== typeLabel ? (\n <span\n data-slot=\"subagent-type\"\n className=\"shrink-0 rounded-full bg-muted px-1.5 py-px text-[10px] font-medium text-muted-foreground\"\n >\n {typeLabel}\n </span>\n ) : null}\n </span>\n <span\n data-slot=\"subagent-meta\"\n className={cn(\n \"text-xs tabular-nums text-muted-foreground\",\n phase === \"error\" && \"text-destructive\",\n )}\n >\n {meta}\n </span>\n {phase === \"approval\" ? (\n <span\n data-slot=\"subagent-approval\"\n className=\"flex min-w-0 items-baseline gap-1 text-xs text-muted-foreground\"\n >\n <span className=\"shrink-0 text-amber-700\">\n {gatedCall ? \"Needs approval to run\" : \"Needs approval to start\"}\n </span>\n {gatedCall ? (\n <>\n <code className=\"shrink-0 rounded bg-foreground/[0.06] px-1 py-px font-mono text-[11px] text-foreground/85\">\n {gatedCall.name}\n </code>\n <span className=\"min-w-0 truncate\">{salientToolCallDetail(gatedCall)}</span>\n </>\n ) : null}\n </span>\n ) : running ? (\n <span data-slot=\"subagent-activity\" className=\"min-w-0 truncate text-xs text-muted-foreground\">\n {step ? (\n <span title={step.detail}>\n <StepText text={step.label} code={step.code} />\n </span>\n ) : (\n liveText || \"Starting…\"\n )}\n </span>\n ) : null}\n </span>\n </>\n );\n\n return (\n <ToolFallbackRoot\n data-testid=\"subagent-task-card\"\n data-phase={phase}\n role=\"group\"\n aria-label={`Subagent: ${title}`}\n className={cn(isThread && phase === \"error\" && \"border-destructive/30 bg-destructive/5\")}\n >\n {/* A report or a failure is behind the disclosure whole, steps or none. */}\n {hasSteps || running || report ? (\n <CollapsibleTrigger\n data-slot=\"subagent-trigger\"\n className={cn(\n \"group/trigger flex w-full min-w-0 items-start gap-2 text-left text-[13px] leading-snug transition-colors hover:bg-muted/40\",\n isThread ? \"rounded-lg px-2.5 py-1.5\" : \"px-3\",\n )}\n >\n {header}\n <ChevronDownIcon\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 size-3.5 shrink-0 text-muted-foreground/60\",\n \"transition-transform duration-(--animation-duration) ease-out\",\n \"group-data-[state=closed]/trigger:-rotate-90\",\n )}\n />\n </CollapsibleTrigger>\n ) : (\n <div\n data-slot=\"subagent-trigger\"\n className={cn(\n \"flex w-full min-w-0 items-start gap-2 text-[13px] leading-snug\",\n isThread ? \"px-2.5 py-1.5\" : \"px-3\",\n )}\n >\n {header}\n </div>\n )}\n {report ? (\n <p\n data-slot=\"subagent-report\"\n // Margins, not padding: a clamped block clips at its padding edge,\n // so bottom padding would show the top of the next line.\n className={cn(\n \"mb-1.5 line-clamp-3 whitespace-pre-line break-words text-xs leading-relaxed\",\n isThread ? \"mr-2.5 ml-8\" : \"mx-3 mt-1.5 ml-9\",\n phase === \"error\" ? \"text-destructive\" : \"text-foreground/80\",\n )}\n >\n {report}\n </p>\n ) : null}\n <ToolFallbackContent>\n <LaneQueryScope>\n <LaneSteps lane={lane} phase={phase} result={report} partMessages={messages} />\n </LaneQueryScope>\n </ToolFallbackContent>\n </ToolFallbackRoot>\n );\n}\n\n/**\n * A delegation inside a subagent's own steps: one static row. It is not the\n * run's lane to show; its steps live in the subagent's own transcript.\n */\nfunction SubagentDelegationRow({ args, result, isError, status }: ToolCallMessagePartProps) {\n const settled = result !== undefined && status?.type !== \"running\";\n const summary = summarizeToolCall({\n toolName: \"task\",\n args: typeof args === \"object\" && args !== null ? (args as Record<string, unknown>) : undefined,\n status: !settled ? \"running\" : isError === true ? \"error\" : \"complete\",\n });\n return (\n <div\n data-testid=\"subagent-delegation\"\n className=\"my-1 flex min-w-0 items-center gap-2 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-[13px]\"\n >\n <BotIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span title={summary.detail} className=\"min-w-0 truncate text-foreground\">\n {summary.label}\n </span>\n </div>\n );\n}\n\nconst SubagentTaskToolUIImpl: ToolCallMessagePartComponent = (props) =>\n useInReadOnlyThread() ? <SubagentDelegationRow {...props} /> : <SubagentTaskCard {...props} />;\n\n/**\n * The `task` tool UI (`TOOL_UI_REGISTRY.task`): the subagent card, or inside\n * a subagent's own steps, a static delegation row.\n */\nexport const SubagentTaskToolUI = memo(\n SubagentTaskToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nSubagentTaskToolUI.displayName = \"SubagentTaskToolUI\";\n"],"names":["readInstantMs","MESSAGE_CREATED_AT_KEY","messages","summarizeToolCall","humanizeToolName","useAuiState","hasStatewireThreadExtras","record","LoaderIcon","jsx","CheckIcon","AlertCircleIcon","XCircleIcon","ShieldAlertIcon","CircleDashedIcon","useState","useEffect","createContext","useContext","MessagePrimitive","deepAgentRowKey","useMemo","Fragment","ThreadPrimitive","Component","athenaDiagnostics","useAthenaQueryClient","QueryClientProvider","useDeepAgentLaneHistory","createSubagentLaneConversion","withLaneReport","useNestedPtcComponents","ToolFallback","jsxs","ReadonlyThreadProvider","cn","formatWorkDuration","useToolAppearance","taskSubagentsOfTurn","useApprovalWaitInScope","subagentAwaitingApproval","subagentToolCallAwaitingApproval","getExternalStoreMessages","salientToolCallDetail","StepText","ToolFallbackRoot","CollapsibleTrigger","ChevronDownIcon","ToolFallbackContent","BotIcon","memo"],"mappings":"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"}
1
+ {"version":3,"file":"subagent-task-tool-ui.cjs","sources":["../../src/tools/subagent-task-tool-ui.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The subagent card: one `task` call the deep agent delegated, shown the way\n * Olympus shows a subagent lane.\n *\n * - On the card: where the lane is (queued, running, done, failed, stopped),\n * how many tool calls it made (the wire's cut marker counts a lane whose\n * card carries only its newest steps), how long it has run, and while it\n * runs, its newest step; a finished lane's report, or why it failed, under\n * it, clamped.\n * - Behind its disclosure: the lane's steps, live while it runs, ending on\n * what the lane ended on, whole (a failure, or a report no step carries),\n * so a lane with no steps still opens to its full result. The lane is\n * assistant-ui's native nested thread: the `task` part's `messages`, which\n * the SDK runtime's opt-in conversion fills\n * (`createSubagentTranscriptConversionCache`), rendered read-only under\n * `ReadonlyThreadProvider` with the chat's own tool UIs. A cut lane (a\n * running card always; a finished one when the provider declares the\n * lane-cut contract, `subagentLaneHistory`) says how many of its steps it\n * shows, and \"Load earlier steps\" reads the rest with `history/lane`\n * (`useDeepAgentLaneHistory`), a read under the thread's own attach.\n *\n * A read-only nested thread has no statewire thread behind it: a `task` call\n * inside a subagent's own steps renders as a static row, and the steps are\n * their own error boundary, so a tool UI that throws there never takes the\n * chat down with it.\n */\nimport {\n getExternalStoreMessages,\n MessagePrimitive,\n ReadonlyThreadProvider,\n type ThreadMessage,\n ThreadPrimitive,\n type ToolCallMessagePartComponent,\n type ToolCallMessagePartProps,\n type ToolCallMessagePartStatus,\n useAuiState,\n} from \"@assistant-ui/react\";\nimport type { LangChainMessage } from \"@assistant-ui/react-langgraph\";\nimport {\n createSubagentLaneConversion,\n deepAgentRowKey,\n hasStatewireThreadExtras,\n salientToolCallDetail,\n type SubagentDiscoverySnapshot,\n type SubagentStatus,\n subagentAwaitingApproval,\n subagentToolCallAwaitingApproval,\n taskSubagentsOfTurn,\n useDeepAgentLaneHistory,\n withLaneReport,\n} from \"@athenaintel/agent-runtime\";\nimport { QueryClientProvider } from \"@tanstack/react-query\";\nimport {\n AlertCircleIcon,\n BotIcon,\n CheckIcon,\n ChevronDownIcon,\n CircleDashedIcon,\n LoaderIcon,\n ShieldAlertIcon,\n XCircleIcon,\n} from \"lucide-react\";\nimport {\n Component,\n createContext,\n type ErrorInfo,\n type FC,\n memo,\n type ReactNode,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport { useApprovalWaitInScope } from \"../chat/use-statewire-approval-request\";\nimport { MESSAGE_CREATED_AT_KEY } from \"../chat/message-time\";\nimport { formatWorkDuration, readInstantMs } from \"../chat/super-grouping/turn-timing\";\nimport { athenaDiagnostics } from \"../diagnostics/athena-diagnostics\";\nimport { useAthenaQueryClient } from \"../lib/use-athena-rest-query\";\nimport { cn } from \"../lib/utils\";\nimport { CollapsibleTrigger } from \"../ui/collapsible\";\nimport { useNestedPtcComponents } from \"./NestedPtcMessages\";\nimport { StepText } from \"./step-text\";\nimport { useToolAppearance } from \"./tool-appearance\";\nimport { ToolFallback, ToolFallbackContent, ToolFallbackRoot } from \"./tool-fallback\";\nimport { humanizeToolName, summarizeToolCall, type ToolCallSummary } from \"./tool-summary\";\n\nconst NO_LANE_STEPS: readonly LangChainMessage[] = [];\nconst NO_MESSAGES: readonly ThreadMessage[] = [];\n\n// ─── What the card says ──────────────────────────────────────────────\n// Pure: where a lane is, how long it ran, the step it took last, and the\n// note over a cut lane's steps, tested without rendering the card.\n\n/**\n * Where a lane is, as the card shows it: the lane's own status, except that a\n * lane parked on a person's approval is `approval` (its own dispatch, or a call\n * it made, is a gated call nobody has answered), any other call the run waits\n * on an answer for is `waiting`, and one the run stopped before it settled is\n * `stopped`.\n */\nexport type SubagentLanePhase =\n | \"queued\"\n | \"approval\"\n | \"waiting\"\n | \"running\"\n | \"complete\"\n | \"error\"\n | \"stopped\";\n\nexport const SUBAGENT_LANE_PHASE_LABELS: Record<SubagentLanePhase, string> = {\n queued: \"Queued\",\n approval: \"Waiting for approval\",\n waiting: \"Waiting for you\",\n running: \"Running\",\n complete: \"Done\",\n error: \"Failed\",\n stopped: \"Stopped\",\n};\n\n/** The lane's phase from its status, the status assistant-ui gives its part, and the run's approval. */\nexport function subagentLanePhase({\n status,\n partStatus,\n awaitingApproval = false,\n}: {\n status: SubagentStatus;\n partStatus: ToolCallMessagePartStatus | undefined;\n /** The lane waits on a person's approval (agent-runtime's `subagentAwaitingApproval`). */\n awaitingApproval?: boolean;\n}): SubagentLanePhase {\n if (status === \"complete\" || status === \"error\") return status;\n if (awaitingApproval) return \"approval\";\n if (partStatus?.type === \"requires-action\") return \"waiting\";\n if (partStatus?.type === \"incomplete\") {\n return partStatus.reason === \"cancelled\" ? \"stopped\" : \"error\";\n }\n return status;\n}\n\n/** The phases a lane never leaves. */\nexport function isSettledSubagentLanePhase(phase: SubagentLanePhase): boolean {\n return phase === \"complete\" || phase === \"error\" || phase === \"stopped\";\n}\n\n/**\n * What a settled lane ended on, whole: its report, or why it failed. A lane\n * that the run's own failure ended has no result of its own, so the `task`\n * part's status says why (as the generic card shows a failed call). Empty\n * while the lane runs.\n */\nexport function subagentLaneResult({\n output,\n phase,\n partStatus,\n}: {\n /** The lane's own result text (`SubagentDiscoverySnapshot.output`). */\n output: string | undefined;\n phase: SubagentLanePhase;\n partStatus: ToolCallMessagePartStatus | undefined;\n}): string {\n if (!isSettledSubagentLanePhase(phase)) return \"\";\n const own = output?.trim() ?? \"\";\n if (own !== \"\" || phase !== \"error\" || partStatus?.type !== \"incomplete\") return own;\n const { error } = partStatus;\n if (error === undefined || error === null) return \"\";\n return (typeof error === \"string\" ? error : JSON.stringify(error)).trim();\n}\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/**\n * How long a finished lane ran, measured by the server: the `task` result's\n * `_started_at` and `_created_at`, which the deep agent's tool-call timing\n * stamps on every tool result and mirrors onto its artifact (the one field of\n * a tool message the converter hands the tool-call part). `null` when either\n * stamp is missing.\n */\nexport function finishedLaneDurationMs(artifact: unknown): number | null {\n const stamps = record(artifact);\n const startedAt = readInstantMs(stamps?._started_at);\n const finishedAt = readInstantMs(stamps?.[MESSAGE_CREATED_AT_KEY]);\n return startedAt !== null && finishedAt !== null && finishedAt >= startedAt\n ? finishedAt - startedAt\n : null;\n}\n\nconst ASSISTANT_TYPES: ReadonlySet<unknown> = new Set([\"ai\", \"AIMessageChunk\"]);\n\n/**\n * When the agent delegated the call `toolCallId`: the server stamp\n * (`_created_at`) of the assistant message that made it, among the raw\n * messages bound to the turn. A running lane's card carries no stamp of its\n * own, so its clock counts from here, the way the turn header counts from the\n * turn's own stamps. `null` without one.\n */\nexport function laneDelegatedAtMs({\n sources,\n toolCallId,\n}: {\n sources: readonly unknown[];\n toolCallId: string;\n}): number | null {\n for (const source of sources) {\n const message = record(source);\n if (!message || !ASSISTANT_TYPES.has(message.type)) continue;\n const calls = message.tool_calls;\n if (!Array.isArray(calls) || !calls.some((call) => record(call)?.id === toolCallId)) continue;\n const kwargs = record(message.additional_kwargs);\n const metadata = record(kwargs?.metadata);\n return (\n readInstantMs(metadata?.[MESSAGE_CREATED_AT_KEY]) ??\n readInstantMs(kwargs?.[MESSAGE_CREATED_AT_KEY]) ??\n readInstantMs(message[MESSAGE_CREATED_AT_KEY])\n );\n }\n return null;\n}\n\n/**\n * The lane's newest tool step as its summary line (\"Read `routes.ts`\",\n * \"Running `npm test`\"), from the lane's converted steps: the last tool call\n * of its newest assistant turn, worded for whether it has answered. `null`\n * before the lane's first tool call.\n */\nexport function latestLaneStep(messages: readonly ThreadMessage[]): ToolCallSummary | null {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role !== \"assistant\") continue;\n for (let partIndex = message.content.length - 1; partIndex >= 0; partIndex -= 1) {\n const part = message.content[partIndex];\n if (part?.type !== \"tool-call\") continue;\n const answered = part.result !== undefined && part.isPreliminary !== true;\n return summarizeToolCall({\n toolName: part.toolName,\n args: part.args,\n result: answered ? part.result : undefined,\n status: answered ? (part.isError === true ? \"error\" : \"complete\") : \"running\",\n });\n }\n }\n return null;\n}\n\n/**\n * The subagent's type as the card names it: the `task` call's `subagent_type`\n * in words, with the default `general-purpose` agent as \"Subagent\".\n */\nexport function subagentTypeLabel(name: string): string {\n const trimmed = name.trim();\n if (trimmed === \"\" || trimmed === \"subagent\" || trimmed === \"general-purpose\") return \"Subagent\";\n return humanizeToolName(trimmed);\n}\n\n/** \"1 tool call\", \"12 tool calls\". */\nexport function toolCallCountLabel(count: number): string {\n return `${count} tool call${count === 1 ? \"\" : \"s\"}`;\n}\n\n/** \"1 step\", \"12 steps\". */\nfunction stepsLabel(count: number): string {\n return `${count} step${count === 1 ? \"\" : \"s\"}`;\n}\n\n/** What the steps panel says about the steps it shows of a cut lane. */\nexport function laneStepsNote({\n shown,\n total,\n arrivesLater,\n}: {\n /** Steps the panel shows. */\n shown: number;\n /** Steps the lane stores (its cut marker), when the card carries fewer. */\n total: number | undefined;\n /**\n * A running lane on a host that pages no running lane: its card brings the\n * rest once the subagent finishes.\n */\n arrivesLater: boolean;\n}): string | null {\n if (total === undefined || total <= shown) return null;\n const leftOff = total - shown;\n return arrivesLater\n ? `Showing the latest steps. ${leftOff} earlier ${leftOff === 1 ? \"step arrives\" : \"steps arrive\"} when this subagent finishes.`\n : `Showing the latest ${shown} of ${stepsLabel(total)}.`;\n}\n\n/**\n * Whether this card renders inside a read-only nested thread (a subagent's own\n * steps, under `ReadonlyThreadProvider`), whose thread has no statewire\n * extras. Never throws: rendered outside any thread, it is not nested.\n */\nfunction useInReadOnlyThread(): boolean {\n return useAuiState((s) => {\n const thread = s.optional?.thread;\n return thread !== undefined && !hasStatewireThreadExtras(thread.extras);\n });\n}\n\n/** A lane for a call agent-runtime read no lane for: what its arguments say, queued. */\nfunction laneFromArgs(toolCallId: string, args: unknown): SubagentDiscoverySnapshot {\n const record = typeof args === \"object\" && args !== null ? (args as Record<string, unknown>) : {};\n return {\n id: toolCallId,\n name: typeof record.subagent_type === \"string\" ? record.subagent_type : \"subagent\",\n description: typeof record.description === \"string\" ? record.description : \"\",\n status: \"queued\",\n toolCallCount: 0,\n messages: NO_MESSAGES,\n messageCount: 0,\n currentText: \"\",\n };\n}\n\n// ─── Status glyph ────────────────────────────────────────────────────\n\nfunction LaneStatusGlyph({ phase }: { phase: SubagentLanePhase }) {\n const glyph =\n phase === \"running\" ? (\n <LoaderIcon className=\"size-3.5 animate-spin text-muted-foreground motion-reduce:animate-none\" />\n ) : phase === \"complete\" ? (\n <CheckIcon className=\"size-3.5 text-emerald-600\" />\n ) : phase === \"error\" ? (\n <AlertCircleIcon className=\"size-3.5 text-destructive\" />\n ) : phase === \"stopped\" ? (\n <XCircleIcon className=\"size-3.5 text-muted-foreground\" />\n ) : phase === \"waiting\" || phase === \"approval\" ? (\n <ShieldAlertIcon className=\"size-3.5 text-amber-600\" />\n ) : (\n <CircleDashedIcon className=\"size-3.5 text-muted-foreground motion-safe:animate-pulse\" />\n );\n return (\n <span\n data-slot=\"subagent-status\"\n data-phase={phase}\n aria-hidden=\"true\"\n className=\"mt-0.5 flex size-4 shrink-0 items-center justify-center\"\n >\n {glyph}\n </span>\n );\n}\n\n// ─── Clock ───────────────────────────────────────────────────────────\n\n/**\n * How long a running lane has run: since `startMs` (the server's stamp on the\n * delegating message), else since this card saw it running; `null` while it\n * does not run. Ticks once a second off the wall clock.\n */\nfunction useRunningElapsedMs(running: boolean, startMs: number | null): number | null {\n const [clock, setClock] = useState<{ seenAt: number; now: number } | null>(null);\n useEffect(() => {\n if (!running) {\n setClock(null);\n return undefined;\n }\n const seenAt = Date.now();\n setClock({ seenAt, now: seenAt });\n const timer = setInterval(() => setClock({ seenAt, now: Date.now() }), 1000);\n return () => clearInterval(timer);\n }, [running]);\n if (!running || clock === null) return null;\n return Math.max(0, clock.now - (startMs ?? clock.seenAt));\n}\n\n// ─── The lane's steps ────────────────────────────────────────────────\n\ntype NestedPartsComponents = ReturnType<typeof useNestedPtcComponents>;\n\nconst LaneStepComponentsContext = createContext<NestedPartsComponents | null>(null);\n\nconst EmptyStepPart: FC = () => null;\n\n/**\n * One row of the lane: an assistant turn's parts, through the chat's own\n * renderers (`NestedPtcComponentsProvider`, which `AthenaChat` mounts). The\n * subagent's brief (its user message) is the card's own description, so it is\n * not repeated.\n */\nconst LaneStep: FC = () => {\n const role = useAuiState((s) => s.message.role);\n const components = useContext(LaneStepComponentsContext);\n if (role !== \"assistant\") return null;\n return <MessagePrimitive.Parts components={{ Empty: EmptyStepPart, ...components }} />;\n};\n\nconst LANE_ROW_COMPONENTS = { Message: LaneStep };\n\nconst ROW_KEY_SEPARATOR = \"\\u0000\";\n\n/**\n * The nested thread's rows, each under its row key (`deepAgentRowKey`): the\n * lane's turn keeps its row while the card's cut drops its oldest steps and\n * when earlier pages land, so what the person opened in it stays open.\n */\nfunction LaneRows() {\n const joinedKeys = useAuiState((s) =>\n s.thread.messages.map((message) => deepAgentRowKey(message)).join(ROW_KEY_SEPARATOR),\n );\n const rowKeys = useMemo(\n () => (joinedKeys === \"\" ? [] : joinedKeys.split(ROW_KEY_SEPARATOR)),\n [joinedKeys],\n );\n return (\n <>\n {rowKeys.map((key, index) => (\n <ThreadPrimitive.MessageByIndex key={key} index={index} components={LANE_ROW_COMPONENTS} />\n ))}\n </>\n );\n}\n\ninterface LaneStepsBoundaryProps {\n name: string;\n children: ReactNode;\n}\n\n/**\n * The steps' own boundary: they render the chat's tool UIs (a host's own\n * among them) in a nested thread no statewire thread backs, and a card that\n * throws there must not take the chat down. Reported like a chat render\n * crash, with the lane named.\n */\nclass LaneStepsBoundary extends Component<LaneStepsBoundaryProps, { failed: boolean }> {\n constructor(props: LaneStepsBoundaryProps) {\n super(props);\n this.state = { failed: false };\n }\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n athenaDiagnostics.error(\n \"sdk.error\",\n error,\n {\n code: \"chat_render_crash\",\n message: \"A subagent's steps could not be shown\",\n hint: \"Inspect component_stack: a tool UI that reads the live thread fails inside a subagent's read-only steps.\",\n },\n {\n surface: \"subagent-lane\",\n subagent: this.props.name,\n component_stack: errorInfo.componentStack?.slice(0, 2000) ?? null,\n },\n );\n }\n\n render(): ReactNode {\n if (this.state.failed) {\n return (\n <p role=\"alert\" className=\"px-1 text-xs text-muted-foreground\">\n These steps couldn't be shown. The conversation is not affected.\n </p>\n );\n }\n return this.props.children;\n }\n}\n\n/** The host's `QueryClient` when one is in context, else one of the panel's own (`useAthenaQueryClient`). */\nfunction LaneQueryScope({ children }: { children: ReactNode }) {\n const queryClient = useAthenaQueryClient();\n return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;\n}\n\ninterface LaneStepsProps {\n lane: SubagentDiscoverySnapshot;\n phase: SubagentLanePhase;\n /** What the lane ended on, whole (`subagentLaneResult`); empty while it runs. */\n result: string;\n /** The `task` part's own nested thread, shown if the panel cannot convert the lane itself. */\n partMessages: readonly ThreadMessage[] | undefined;\n}\n\n/**\n * The open card's steps: the lane the card carries, and the earlier steps the\n * person asks for. The panel converts the lane itself, with one conversion\n * memory while it is open (`createSubagentLaneConversion`), so the lane's turn\n * keeps its row key as the cut slides and pages land. It ends on what the lane\n * ended on, whole and selectable: the card clamps it.\n */\nfunction LaneSteps({ lane, phase, result, partMessages }: LaneStepsProps) {\n // The lane's card is its running placeholder, whether it streams or waits on an approval.\n const running = lane.status === \"running\" && (phase === \"running\" || phase === \"approval\");\n const source = lane.source;\n const history = useDeepAgentLaneHistory({\n messageId: source?.messageId,\n lane: source?.lane,\n carried: source?.transcript ?? NO_LANE_STEPS,\n total: source?.truncated?.messages,\n finished: source?.truncated?.finished === true,\n });\n const [convertLane] = useState(() => createSubagentLaneConversion());\n // A `task` lane that finished ends on its report, the card's content, even\n // when its stored transcript does not (`withLaneReport`), as in Olympus's drawer.\n const report =\n lane.status === \"complete\" && source?.messageId !== undefined ? lane.output : undefined;\n const messages =\n (source === undefined\n ? undefined\n : convertLane(withLaneReport(history.steps, report), running)) ??\n partMessages ??\n NO_MESSAGES;\n const components = useNestedPtcComponents(ToolFallback);\n const shown = history.steps.length;\n // A running card on a host that pages no running lane carries the rest once it finishes.\n const arrivesLater = running && source?.messageId !== undefined && !history.available;\n const note = laneStepsNote({ shown, total: history.total, arrivesLater });\n const emptyText =\n phase === \"running\"\n ? \"Starting…\"\n : phase === \"queued\" || phase === \"waiting\" || phase === \"approval\"\n ? \"Not started yet.\"\n : \"No steps were recorded for this subagent.\";\n // Why a lane failed is never one of its steps; a report is the closing\n // step of a lane with steps to close (`withLaneReport`).\n const failed = phase === \"error\";\n const closing = failed || messages.length === 0 ? result : \"\";\n\n return (\n <div data-slot=\"subagent-steps\" className=\"flex min-w-0 flex-col gap-2 px-2.5\">\n {lane.description ? (\n <p\n data-slot=\"subagent-brief\"\n className=\"whitespace-pre-wrap break-words text-xs leading-relaxed text-muted-foreground\"\n >\n {lane.description}\n </p>\n ) : null}\n {note ? (\n <div\n data-slot=\"subagent-steps-note\"\n className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground\"\n >\n <span>{note}</span>\n {history.hasEarlier && !arrivesLater ? (\n <button\n type=\"button\"\n onClick={history.loadEarlier}\n disabled={history.loading}\n className=\"rounded font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default disabled:no-underline disabled:opacity-60\"\n >\n {history.loading ? \"Loading earlier steps…\" : \"Load earlier steps\"}\n </button>\n ) : null}\n </div>\n ) : null}\n {messages.length > 0 ? (\n <LaneStepsBoundary name={lane.name}>\n <LaneStepComponentsContext.Provider value={components}>\n <ReadonlyThreadProvider messages={messages}>\n <div data-slot=\"subagent-step-rows\" className=\"flex min-w-0 flex-col gap-1\">\n <LaneRows />\n </div>\n </ReadonlyThreadProvider>\n </LaneStepComponentsContext.Provider>\n </LaneStepsBoundary>\n ) : (\n <p className=\"text-xs text-muted-foreground\">{emptyText}</p>\n )}\n {closing ? (\n <div data-slot=\"subagent-result\" className=\"flex min-w-0 flex-col gap-0.5\">\n <p\n className={cn(\n \"text-xs font-medium\",\n failed ? \"text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {failed ? \"Error\" : \"Report\"}\n </p>\n <p\n data-slot=\"subagent-result-text\"\n className={cn(\n \"max-h-72 overflow-auto whitespace-pre-wrap break-words text-xs leading-relaxed\",\n failed ? \"text-destructive/80\" : \"text-foreground/80\",\n )}\n >\n {closing}\n </p>\n </div>\n ) : null}\n </div>\n );\n}\n\n// ─── The card ────────────────────────────────────────────────────────\n\n/** The card's second line: where the lane is, its tool calls, how long it ran. */\nfunction laneMeta({\n phase,\n toolCallCount,\n elapsedMs,\n}: {\n phase: SubagentLanePhase;\n toolCallCount: number;\n elapsedMs: number | null;\n}): string {\n const parts: string[] = [SUBAGENT_LANE_PHASE_LABELS[phase]];\n if (toolCallCount > 0 || isSettledSubagentLanePhase(phase)) {\n parts.push(toolCallCountLabel(toolCallCount));\n }\n if (elapsedMs !== null && (phase !== \"running\" || elapsedMs >= 1000)) {\n parts.push(formatWorkDuration(elapsedMs));\n }\n return parts.join(\" · \");\n}\n\nfunction SubagentTaskCard({ toolCallId, args, status, artifact, messages }: ToolCallMessagePartProps) {\n const appearance = useToolAppearance();\n const isThread = appearance === \"thread\";\n const readLane = useAuiState((s) => taskSubagentsOfTurn(s.message).get(toolCallId));\n const lane = useMemo(\n () => readLane ?? laneFromArgs(toolCallId, args),\n [readLane, toolCallId, args],\n );\n // A lane holding a gated call the run's approval names waits on a person:\n // no live activity, no clock, just what it waits on. Read-only (the approval\n // card answers).\n const { toolCallIds: waitingToolCallIds } = useApprovalWaitInScope();\n const awaitingApproval = subagentAwaitingApproval({ lane, toolCallIds: waitingToolCallIds });\n const gatedCall = awaitingApproval\n ? subagentToolCallAwaitingApproval({ lane, toolCallIds: waitingToolCallIds })\n : undefined;\n const phase = subagentLanePhase({ status: lane.status, partStatus: status, awaitingApproval });\n const running = phase === \"running\";\n // Only a running lane's clock reads it, so a settled card scans nothing.\n const delegatedAt = useAuiState((s) =>\n running\n ? laneDelegatedAtMs({ sources: getExternalStoreMessages<unknown>(s.message), toolCallId })\n : null,\n );\n const runningElapsed = useRunningElapsedMs(running, delegatedAt);\n const elapsedMs = running\n ? runningElapsed\n : isSettledSubagentLanePhase(phase)\n ? finishedLaneDurationMs(artifact)\n : null;\n const step = useMemo(() => (running ? latestLaneStep(lane.messages) : null), [running, lane.messages]);\n const hasSteps = lane.messageCount > 0 || (lane.omittedMessageCount ?? 0) > 0;\n const typeLabel = subagentTypeLabel(lane.name);\n const title = lane.description.trim() || typeLabel;\n const meta = laneMeta({ phase, toolCallCount: lane.toolCallCount, elapsedMs });\n const liveText = step ? null : lane.currentText.trim();\n const report = subagentLaneResult({ output: lane.output, phase, partStatus: status });\n\n const header = (\n <>\n <LaneStatusGlyph phase={phase} />\n <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"flex min-w-0 items-baseline gap-1.5\">\n <span\n data-slot=\"subagent-title\"\n title={lane.description || undefined}\n className=\"min-w-0 truncate font-medium text-foreground\"\n >\n {title}\n </span>\n {title !== typeLabel ? (\n <span\n data-slot=\"subagent-type\"\n className=\"shrink-0 rounded-full bg-muted px-1.5 py-px text-[10px] font-medium text-muted-foreground\"\n >\n {typeLabel}\n </span>\n ) : null}\n </span>\n <span\n data-slot=\"subagent-meta\"\n className={cn(\n \"text-xs tabular-nums text-muted-foreground\",\n phase === \"error\" && \"text-destructive\",\n )}\n >\n {meta}\n </span>\n {phase === \"approval\" ? (\n <span\n data-slot=\"subagent-approval\"\n className=\"flex min-w-0 items-baseline gap-1 text-xs text-muted-foreground\"\n >\n <span className=\"shrink-0 text-amber-700\">\n {gatedCall ? \"Needs approval to run\" : \"Needs approval to start\"}\n </span>\n {gatedCall ? (\n <>\n <code className=\"shrink-0 rounded bg-foreground/[0.06] px-1 py-px font-mono text-[11px] text-foreground/85\">\n {gatedCall.name}\n </code>\n <span className=\"min-w-0 truncate\">{salientToolCallDetail(gatedCall)}</span>\n </>\n ) : null}\n </span>\n ) : running ? (\n <span data-slot=\"subagent-activity\" className=\"min-w-0 truncate text-xs text-muted-foreground\">\n {step ? (\n <span title={step.detail}>\n <StepText text={step.label} code={step.code} />\n </span>\n ) : (\n liveText || \"Starting…\"\n )}\n </span>\n ) : null}\n </span>\n </>\n );\n\n return (\n <ToolFallbackRoot\n data-testid=\"subagent-task-card\"\n data-phase={phase}\n role=\"group\"\n aria-label={`Subagent: ${title}`}\n className={cn(isThread && phase === \"error\" && \"border-destructive/30 bg-destructive/5\")}\n >\n {/* A report or a failure is behind the disclosure whole, steps or none. */}\n {hasSteps || running || report ? (\n <CollapsibleTrigger\n data-slot=\"subagent-trigger\"\n className={cn(\n \"group/trigger flex w-full min-w-0 items-start gap-2 text-left text-[13px] leading-snug transition-colors hover:bg-muted/40\",\n isThread ? \"rounded-lg px-2.5 py-1.5\" : \"px-3\",\n )}\n >\n {header}\n <ChevronDownIcon\n aria-hidden=\"true\"\n className={cn(\n \"mt-0.5 size-3.5 shrink-0 text-muted-foreground/60\",\n \"transition-transform duration-(--animation-duration) ease-out\",\n \"group-data-[state=closed]/trigger:-rotate-90\",\n )}\n />\n </CollapsibleTrigger>\n ) : (\n <div\n data-slot=\"subagent-trigger\"\n className={cn(\n \"flex w-full min-w-0 items-start gap-2 text-[13px] leading-snug\",\n isThread ? \"px-2.5 py-1.5\" : \"px-3\",\n )}\n >\n {header}\n </div>\n )}\n {report ? (\n <p\n data-slot=\"subagent-report\"\n // Margins, not padding: a clamped block clips at its padding edge,\n // so bottom padding would show the top of the next line.\n className={cn(\n \"mb-1.5 line-clamp-3 whitespace-pre-line break-words text-xs leading-relaxed\",\n isThread ? \"mr-2.5 ml-8\" : \"mx-3 mt-1.5 ml-9\",\n phase === \"error\" ? \"text-destructive\" : \"text-foreground/80\",\n )}\n >\n {report}\n </p>\n ) : null}\n <ToolFallbackContent>\n <LaneQueryScope>\n <LaneSteps lane={lane} phase={phase} result={report} partMessages={messages} />\n </LaneQueryScope>\n </ToolFallbackContent>\n </ToolFallbackRoot>\n );\n}\n\n/**\n * A delegation inside a subagent's own steps: one static row. It is not the\n * run's lane to show; its steps live in the subagent's own transcript.\n */\nfunction SubagentDelegationRow({ args, result, isError, status }: ToolCallMessagePartProps) {\n const settled = result !== undefined && status?.type !== \"running\";\n const summary = summarizeToolCall({\n toolName: \"task\",\n args: typeof args === \"object\" && args !== null ? (args as Record<string, unknown>) : undefined,\n status: !settled ? \"running\" : isError === true ? \"error\" : \"complete\",\n });\n return (\n <div\n data-testid=\"subagent-delegation\"\n className=\"my-1 flex min-w-0 items-center gap-2 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-[13px]\"\n >\n <BotIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0 text-muted-foreground\" />\n <span title={summary.detail} className=\"min-w-0 truncate text-foreground\">\n {summary.label}\n </span>\n </div>\n );\n}\n\nconst SubagentTaskToolUIImpl: ToolCallMessagePartComponent = (props) =>\n useInReadOnlyThread() ? <SubagentDelegationRow {...props} /> : <SubagentTaskCard {...props} />;\n\n/**\n * The `task` tool UI (`TOOL_UI_REGISTRY.task`): the subagent card, or inside\n * a subagent's own steps, a static delegation row.\n */\nexport const SubagentTaskToolUI = memo(\n SubagentTaskToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nSubagentTaskToolUI.displayName = \"SubagentTaskToolUI\";\n"],"names":["readInstantMs","MESSAGE_CREATED_AT_KEY","messages","summarizeToolCall","humanizeToolName","useAuiState","hasStatewireThreadExtras","record","LoaderIcon","jsx","CheckIcon","AlertCircleIcon","XCircleIcon","ShieldAlertIcon","CircleDashedIcon","useState","useEffect","createContext","useContext","MessagePrimitive","deepAgentRowKey","useMemo","Fragment","ThreadPrimitive","Component","athenaDiagnostics","useAthenaQueryClient","QueryClientProvider","useDeepAgentLaneHistory","createSubagentLaneConversion","withLaneReport","useNestedPtcComponents","ToolFallback","jsxs","ReadonlyThreadProvider","cn","formatWorkDuration","useToolAppearance","taskSubagentsOfTurn","useApprovalWaitInScope","subagentAwaitingApproval","subagentToolCallAwaitingApproval","getExternalStoreMessages","salientToolCallDetail","StepText","ToolFallbackRoot","CollapsibleTrigger","ChevronDownIcon","ToolFallbackContent","BotIcon","memo"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const lucideReact = require("lucide-react");
5
- const react = require("react");
5
+ const require$$0 = require("react");
6
6
  const useAssetContent = require("../assets/use-asset-content.cjs");
7
7
  const AthenaContext = require("../provider/AthenaContext.cjs");
8
8
  const primitives = require("./primitives.cjs");
@@ -41,14 +41,14 @@ function TestRecordingPlayer({
41
41
  const content = useAssetContent.useAthenaAssetContent({ assetId, enabled: playback.requested });
42
42
  const src = useAssetContent.useObjectUrl(playback.requested ? content.data : void 0);
43
43
  const { refetch } = content;
44
- const retry = react.useCallback(() => {
44
+ const retry = require$$0.useCallback(() => {
45
45
  void refetch();
46
46
  }, [refetch]);
47
- const videoRef = react.useRef(null);
48
- const pendingSeekRef = react.useRef(null);
47
+ const videoRef = require$$0.useRef(null);
48
+ const pendingSeekRef = require$$0.useRef(null);
49
49
  const seekTime = (_a = playback.seek) == null ? void 0 : _a.time;
50
50
  const seekNonce = ((_b = playback.seek) == null ? void 0 : _b.nonce) ?? 0;
51
- react.useEffect(() => {
51
+ require$$0.useEffect(() => {
52
52
  var _a2;
53
53
  const video = videoRef.current;
54
54
  if (!video || !src) return;
@@ -59,7 +59,7 @@ function TestRecordingPlayer({
59
59
  (_a2 = video.play()) == null ? void 0 : _a2.catch(() => {
60
60
  });
61
61
  }, [src, seekNonce]);
62
- const handleLoadedMetadata = react.useCallback((event) => {
62
+ const handleLoadedMetadata = require$$0.useCallback((event) => {
63
63
  const pending = pendingSeekRef.current;
64
64
  pendingSeekRef.current = null;
65
65
  if (pending !== null) event.currentTarget.currentTime = pending;
@@ -233,11 +233,11 @@ function TestRow({ test, onSeek }) {
233
233
  ] });
234
234
  }
235
235
  function TestRecordingReportCard({ report, className }) {
236
- const [playback, setPlayback] = react.useState(IDLE_PLAYBACK);
237
- const play = react.useCallback(() => {
236
+ const [playback, setPlayback] = require$$0.useState(IDLE_PLAYBACK);
237
+ const play = require$$0.useCallback(() => {
238
238
  setPlayback((previous) => ({ ...previous, requested: true }));
239
239
  }, []);
240
- const seek = react.useCallback((time) => {
240
+ const seek = require$$0.useCallback((time) => {
241
241
  setPlayback((previous) => {
242
242
  var _a;
243
243
  return {
@@ -246,7 +246,7 @@ function TestRecordingReportCard({ report, className }) {
246
246
  };
247
247
  });
248
248
  }, []);
249
- const athenaConfig = react.useContext(AthenaContext.AthenaContext);
249
+ const athenaConfig = require$$0.useContext(AthenaContext.AthenaContext);
250
250
  const playableAssetId = athenaConfig ? report.assetId : null;
251
251
  const onSeek = playableAssetId ? seek : null;
252
252
  const hasFailures = report.failed > 0;
@@ -340,7 +340,7 @@ const TestRecordingStopToolUIImpl = ({
340
340
  }) => {
341
341
  const typedArgs = argsRecord(args);
342
342
  const titleArg = argString(typedArgs, "title");
343
- const parsed = react.useMemo(
343
+ const parsed = require$$0.useMemo(
344
344
  () => testRecordingReport.parseTestRecordingStopResult(result, { fallbackTitle: titleArg }),
345
345
  [result, titleArg]
346
346
  );
@@ -363,7 +363,7 @@ const TestRecordingStopToolUIImpl = ({
363
363
  }
364
364
  );
365
365
  };
366
- const TestRecordingStopToolUI = react.memo(
366
+ const TestRecordingStopToolUI = require$$0.memo(
367
367
  TestRecordingStopToolUIImpl
368
368
  );
369
369
  TestRecordingStopToolUI.displayName = "TestRecordingStopToolUI";
@@ -401,7 +401,7 @@ function TestRecordingRow({
401
401
  );
402
402
  }
403
403
  const TestRecordingStartToolUIImpl = ({ args, result, status }) => {
404
- const start = react.useMemo(
404
+ const start = require$$0.useMemo(
405
405
  () => testRecordingReport.describeTestRecordingStart({ args: argsRecord(args), result }),
406
406
  [args, result]
407
407
  );
@@ -424,7 +424,7 @@ const TestRecordingStartToolUIImpl = ({ args, result, status }) => {
424
424
  }
425
425
  );
426
426
  };
427
- const TestRecordingStartToolUI = react.memo(
427
+ const TestRecordingStartToolUI = require$$0.memo(
428
428
  TestRecordingStartToolUIImpl
429
429
  );
430
430
  TestRecordingStartToolUI.displayName = "TestRecordingStartToolUI";
@@ -461,7 +461,7 @@ const UNKNOWN_MARK_ROW = {
461
461
  labelClassName: "text-muted-foreground"
462
462
  };
463
463
  const TestRecordingMarkToolUIImpl = ({ args, result, status }) => {
464
- const mark = react.useMemo(
464
+ const mark = require$$0.useMemo(
465
465
  () => testRecordingReport.describeTestRecordingMark({ args: argsRecord(args), result }),
466
466
  [args, result]
467
467
  );
@@ -487,7 +487,7 @@ const TestRecordingMarkToolUIImpl = ({ args, result, status }) => {
487
487
  }
488
488
  );
489
489
  };
490
- const TestRecordingMarkToolUI = react.memo(
490
+ const TestRecordingMarkToolUI = require$$0.memo(
491
491
  TestRecordingMarkToolUIImpl
492
492
  );
493
493
  TestRecordingMarkToolUI.displayName = "TestRecordingMarkToolUI";
@@ -1 +1 @@
1
- {"version":3,"file":"test-recording-tool-uis.cjs","sources":["../../src/tools/test-recording-tool-uis.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The UI Testing toolkit's cards: an agent records itself checking a UI\n * change on its computer and hands back an annotated video.\n *\n * - `test_recording_stop` — the report: the recording's title, \"N passed · M\n * failed\", each test with its ✓ / ✗ assertions (what the agent saw), the\n * summary, and the video, with every test's start as a chapter that plays\n * from there. It stays in the conversation instead of folding into the\n * turn's steps (`isSdkInlineTool`).\n * - `test_recording_start` / `test_recording_mark` — one compact row each.\n *\n * The video is an Athena asset the signed-in user owns. It is read with the\n * user's own credential through `useAthenaAssetContent` (a permission-checked\n * read of the stored file) and played from a page-local object URL, only when\n * the person presses play or picks a chapter; no shareable link is minted.\n */\nimport type { ToolCallMessagePartComponent } from \"@assistant-ui/react\";\nimport {\n AlertCircleIcon,\n CheckIcon,\n CircleDashedIcon,\n CircleDotIcon,\n ClapperboardIcon,\n ExternalLinkIcon,\n FlaskConicalIcon,\n LoaderIcon,\n PlayIcon,\n StickyNoteIcon,\n XIcon,\n} from \"lucide-react\";\nimport {\n type ElementType,\n memo,\n type SyntheticEvent,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAthenaAssetContent, useObjectUrl } from \"../assets/use-asset-content\";\nimport { cn } from \"../lib/utils\";\nimport { AthenaContext } from \"../provider/AthenaContext\";\nimport { ToolCard, type ToolStatus } from \"./primitives\";\nimport {\n describeTestRecordingMark,\n describeTestRecordingStart,\n formatRecordingClock,\n parseTestRecordingStopResult,\n type TestRecordingAssertion,\n type TestRecordingMarkKind,\n type TestRecordingOutcome,\n type TestRecordingReport,\n type TestRecordingTest,\n} from \"./test-recording-report\";\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction argsRecord(args: unknown): Record<string, unknown> | undefined {\n return typeof args === \"object\" && args !== null && !Array.isArray(args)\n ? (args as Record<string, unknown>)\n : undefined;\n}\n\nfunction argString(args: Record<string, unknown> | undefined, key: string): string | undefined {\n const value = args?.[key];\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : undefined;\n}\n\n/** The message an `incomplete` tool status carries, or `null` for any other status. */\nfunction incompleteMessage(\n status: { type: string; reason?: string; error?: unknown } | undefined,\n fallback: string,\n): string | null {\n if (status?.type !== \"incomplete\") return null;\n if (status.reason === \"cancelled\") return \"Cancelled\";\n if (typeof status.error === \"string\" && status.error.trim() !== \"\") return status.error;\n return fallback;\n}\n\n// ─── Playback ────────────────────────────────────────────────────────\n\ninterface PlaybackRequest {\n /** The person asked to play: the video is read from then on. */\n requested: boolean;\n /** The last chapter picked; `nonce` makes picking the same chapter twice seek twice. */\n seek: { time: number; nonce: number } | null;\n}\n\nconst IDLE_PLAYBACK: PlaybackRequest = { requested: false, seek: null };\n\n/** `HTMLMediaElement.HAVE_METADATA`: below it a seek waits for the video's metadata. */\nconst HAVE_METADATA = 1;\n\nfunction playbackErrorMessage(error: Error): string {\n const status = (error as { status?: unknown }).status;\n if (status === 401 || status === 403) return \"You don't have access to this recording.\";\n if (status === 404) return \"The recording's video was not found.\";\n return \"The recording could not be loaded.\";\n}\n\nfunction TestRecordingPlayer({\n assetId,\n title,\n durationS,\n url,\n playback,\n onPlay,\n}: {\n assetId: string;\n title: string;\n durationS: number | null;\n url: string | null;\n playback: PlaybackRequest;\n onPlay: () => void;\n}) {\n const content = useAthenaAssetContent({ assetId, enabled: playback.requested });\n // Bytes a query already holds still wait for the person to press play.\n const src = useObjectUrl(playback.requested ? content.data : undefined);\n const { refetch } = content;\n const retry = useCallback(() => {\n void refetch();\n }, [refetch]);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const pendingSeekRef = useRef<number | null>(null);\n const seekTime = playback.seek?.time;\n const seekNonce = playback.seek?.nonce ?? 0;\n\n // Play once the bytes are here, and again from each chapter picked (the\n // nonce is the pick's change signal; picking one chapter twice seeks twice).\n // A seek before the metadata loads sets the start position and is applied\n // again once it has (`onLoadedMetadata`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n const video = videoRef.current;\n if (!video || !src) return;\n if (seekTime !== undefined) {\n video.currentTime = seekTime;\n pendingSeekRef.current = video.readyState < HAVE_METADATA ? seekTime : null;\n }\n video.play()?.catch(() => {\n // Autoplay refused (no recent user gesture): the controls stay to press play.\n });\n }, [src, seekNonce]);\n\n const handleLoadedMetadata = useCallback((event: SyntheticEvent<HTMLVideoElement>) => {\n const pending = pendingSeekRef.current;\n pendingSeekRef.current = null;\n if (pending !== null) event.currentTarget.currentTime = pending;\n }, []);\n\n if (src) {\n return (\n <video\n ref={videoRef}\n data-testid=\"test-recording-video\"\n src={src}\n controls\n playsInline\n preload=\"auto\"\n aria-label={`Recording: ${title}`}\n onLoadedMetadata={handleLoadedMetadata}\n className=\"block max-h-[480px] w-full bg-black\"\n />\n );\n }\n\n if (content.isError && !content.isFetching) {\n return (\n <div\n role=\"alert\"\n data-testid=\"test-recording-video-error\"\n className=\"flex aspect-video w-full flex-col items-center justify-center gap-2 bg-muted/40 px-6 text-center\"\n >\n <AlertCircleIcon className=\"size-5 text-destructive\" aria-hidden />\n <p className=\"text-[12.5px] text-foreground\">{playbackErrorMessage(content.error)}</p>\n <div className=\"flex items-center gap-3\">\n {/* An explicit retry, refusals included: access may have changed since. */}\n <button\n type=\"button\"\n onClick={retry}\n className=\"rounded-md border border-border bg-background px-2.5 py-1 text-[12px] font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Try again\n </button>\n {url ? (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-[12px] font-medium text-primary hover:underline\"\n >\n Watch in Athena\n </a>\n ) : null}\n </div>\n </div>\n );\n }\n\n if (playback.requested) {\n return (\n <output\n data-testid=\"test-recording-video-loading\"\n className=\"flex aspect-video w-full items-center justify-center gap-2 bg-zinc-950 text-[12px] text-white/80\"\n >\n <LoaderIcon className=\"size-4 animate-spin\" aria-hidden />\n Loading recording…\n </output>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onPlay}\n aria-label={`Play recording: ${title}`}\n className=\"group relative flex aspect-video w-full items-center justify-center bg-zinc-950 text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset\"\n >\n <span className=\"flex size-12 items-center justify-center rounded-full bg-white/15 transition-colors group-hover:bg-white/25\">\n <PlayIcon className=\"ml-0.5 size-5 fill-current\" aria-hidden />\n </span>\n {durationS !== null ? (\n <span className=\"absolute right-3 bottom-2 text-[11px] tabular-nums text-white/80\">\n {formatRecordingClock(durationS)}\n </span>\n ) : null}\n </button>\n );\n}\n\n/** A time that plays the recording from there: a test's chapter or an assertion's moment. */\nfunction ChapterButton({\n time,\n label,\n onSeek,\n}: {\n time: number;\n label: string;\n onSeek: (time: number) => void;\n}) {\n const clock = formatRecordingClock(time);\n return (\n <button\n type=\"button\"\n data-testid=\"test-recording-chapter\"\n onClick={() => onSeek(time)}\n aria-label={`Play from ${clock}: ${label}`}\n className=\"shrink-0 rounded px-1.5 py-0.5 font-mono text-[11px] tabular-nums text-primary transition-colors hover:bg-primary/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {clock}\n </button>\n );\n}\n\n// ─── Report card ─────────────────────────────────────────────────────\n\nconst OUTCOME_LABEL: Record<TestRecordingOutcome, string> = {\n passed: \"Passed\",\n failed: \"Failed\",\n untested: \"Not checked\",\n};\n\nfunction OutcomeIcon({ result }: { result: TestRecordingOutcome }) {\n if (result === \"passed\") {\n return (\n <span className=\"mt-px flex size-4 shrink-0 items-center justify-center rounded-full bg-emerald-500 text-white\">\n <CheckIcon className=\"size-2.5\" strokeWidth={3.5} aria-hidden />\n </span>\n );\n }\n if (result === \"failed\") {\n return (\n <span className=\"mt-px flex size-4 shrink-0 items-center justify-center rounded-full bg-destructive text-white\">\n <XIcon className=\"size-2.5\" strokeWidth={3.5} aria-hidden />\n </span>\n );\n }\n return <CircleDashedIcon className=\"mt-px size-4 shrink-0 text-muted-foreground\" aria-hidden />;\n}\n\nfunction AssertionRow({\n assertion,\n onSeek,\n}: {\n assertion: TestRecordingAssertion;\n onSeek: ((time: number) => void) | null;\n}) {\n const failed = assertion.result === \"failed\";\n const text = assertion.text || (failed ? \"Failed\" : \"Passed\");\n return (\n <li\n data-testid=\"test-recording-assertion\"\n data-result={assertion.result}\n className={cn(\n \"flex items-start gap-1.5 rounded-md px-1.5 py-0.5 text-[12px] leading-snug\",\n failed ? \"bg-destructive/10 text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {failed ? (\n <XIcon className=\"mt-0.5 size-3 shrink-0\" strokeWidth={3} aria-hidden />\n ) : (\n <CheckIcon className=\"mt-0.5 size-3 shrink-0 text-emerald-600\" strokeWidth={3} aria-hidden />\n )}\n <span className=\"min-w-0 flex-1 break-words\">\n <span className=\"sr-only\">{failed ? \"Failed: \" : \"Passed: \"}</span>\n {text}\n </span>\n {onSeek && assertion.editedTimeS !== null ? (\n <ChapterButton time={assertion.editedTimeS} label={text} onSeek={onSeek} />\n ) : null}\n </li>\n );\n}\n\nfunction TestRow({ test, onSeek }: { test: TestRecordingTest; onSeek: ((time: number) => void) | null }) {\n return (\n <li data-testid=\"test-recording-test\" data-result={test.result} className=\"px-4 py-2.5\">\n <div className=\"flex items-start gap-2\">\n <OutcomeIcon result={test.result} />\n <span\n className={cn(\n \"min-w-0 flex-1 break-words text-[12.5px] font-medium leading-snug\",\n test.result === \"failed\" && \"text-destructive\",\n test.result === \"passed\" && \"text-foreground\",\n test.result === \"untested\" && \"text-muted-foreground\",\n )}\n >\n <span className=\"sr-only\">{`${OUTCOME_LABEL[test.result]}: `}</span>\n {test.name}\n </span>\n {test.result === \"untested\" ? (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n Not checked\n </span>\n ) : null}\n {onSeek && test.startTimeS !== null ? (\n <ChapterButton time={test.startTimeS} label={test.name} onSeek={onSeek} />\n ) : null}\n </div>\n {test.assertions.length > 0 ? (\n <ul className=\"mt-1 flex flex-col gap-0.5 pl-6\">\n {test.assertions.map((assertion, index) => (\n <AssertionRow\n // Assertions are an ordered log with no id of their own, never reordered.\n key={index}\n assertion={assertion}\n onSeek={onSeek}\n />\n ))}\n </ul>\n ) : null}\n </li>\n );\n}\n\nexport interface TestRecordingReportCardProps {\n report: TestRecordingReport;\n className?: string;\n}\n\n/**\n * A saved test recording: the title and counts, the video (read with the\n * signed-in user's credential when the person presses play), each test with\n * its assertions and chapter times, the summary, and a link to the asset in\n * Athena.\n */\nexport function TestRecordingReportCard({ report, className }: TestRecordingReportCardProps) {\n const [playback, setPlayback] = useState<PlaybackRequest>(IDLE_PLAYBACK);\n const play = useCallback(() => {\n setPlayback((previous) => ({ ...previous, requested: true }));\n }, []);\n const seek = useCallback((time: number) => {\n setPlayback((previous) => ({\n requested: true,\n seek: { time, nonce: (previous.seek?.nonce ?? 0) + 1 },\n }));\n }, []);\n // The video is read with the provider's credentials; a host that renders\n // the card outside `<AthenaProvider>` gets the report and the link only.\n const athenaConfig = useContext(AthenaContext);\n const playableAssetId = athenaConfig ? report.assetId : null;\n const onSeek = playableAssetId ? seek : null;\n const hasFailures = report.failed > 0;\n\n return (\n <section\n data-testid=\"test-recording-report\"\n data-has-failures={hasFailures ? \"true\" : \"false\"}\n aria-label={`Test recording: ${report.title}`}\n className={cn(\n \"my-3 w-full overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm\",\n className,\n )}\n >\n <header className=\"flex items-start gap-3 px-4 py-3\">\n <span\n className={cn(\n \"flex size-8 shrink-0 items-center justify-center rounded-lg\",\n hasFailures ? \"bg-destructive/10 text-destructive\" : \"bg-emerald-50 text-emerald-600\",\n )}\n >\n <ClapperboardIcon className=\"size-4\" aria-hidden />\n </span>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"break-words text-[13px] font-medium leading-snug text-foreground\">\n {report.title}\n </h3>\n <p data-testid=\"test-recording-counts\" className=\"text-[12px] tabular-nums text-muted-foreground\">\n <span className={cn(report.passed > 0 && \"text-emerald-700\")}>{report.passed} passed</span>\n {\" · \"}\n <span className={cn(hasFailures && \"font-medium text-destructive\")}>{report.failed} failed</span>\n {report.untested > 0 ? ` · ${report.untested} untested` : null}\n </p>\n </div>\n <span className=\"shrink-0 rounded-md bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n UI test\n </span>\n </header>\n\n {playableAssetId ? (\n <div className=\"border-t border-border/40\">\n <TestRecordingPlayer\n assetId={playableAssetId}\n title={report.title}\n durationS={report.editedDurationS}\n url={report.url}\n playback={playback}\n onPlay={play}\n />\n </div>\n ) : null}\n\n {report.tests.length > 0 ? (\n <ol aria-label=\"Tests\" className=\"flex flex-col divide-y divide-border/40 border-t border-border/40\">\n {report.tests.map((test, index) => (\n // Tests are an ordered log, never reordered; two may share a name.\n <TestRow key={index} test={test} onSeek={onSeek} />\n ))}\n </ol>\n ) : (\n <p className=\"border-t border-border/40 px-4 py-2.5 text-[12px] text-muted-foreground\">\n No tests were marked in this recording.\n </p>\n )}\n\n {report.summary ? (\n <div className=\"border-t border-border/40 px-4 py-2.5\">\n <p className=\"text-[11px] font-medium text-muted-foreground\">Summary</p>\n <p\n data-testid=\"test-recording-summary\"\n className=\"mt-0.5 whitespace-pre-wrap break-words text-[12.5px] leading-relaxed text-foreground\"\n >\n {report.summary}\n </p>\n </div>\n ) : null}\n\n {report.url ? (\n <div className=\"flex justify-end border-t border-border/40 px-4 py-2\">\n <a\n href={report.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1.5 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground\"\n >\n <ExternalLinkIcon className=\"size-3\" aria-hidden />\n Watch in Athena\n </a>\n </div>\n ) : null}\n </section>\n );\n}\n\n// ─── test_recording_stop ─────────────────────────────────────────────\n\nconst TestRecordingStopToolUIImpl: ToolCallMessagePartComponent = ({\n toolName,\n args,\n result,\n status,\n}) => {\n const typedArgs = argsRecord(args);\n const titleArg = argString(typedArgs, \"title\");\n const parsed = useMemo(\n () => parseTestRecordingStopResult(result, { fallbackTitle: titleArg }),\n [result, titleArg],\n );\n\n if (parsed.kind === \"saved\") return <TestRecordingReportCard report={parsed.report} />;\n\n const isRunning = status?.type === \"running\";\n const error =\n incompleteMessage(status, \"The test recording could not be saved.\") ??\n (parsed.kind === \"error\" ? parsed.message : null);\n const cardStatus: ToolStatus = error ? \"incomplete\" : isRunning ? \"running\" : \"complete\";\n return (\n <ToolCard\n icon={ClapperboardIcon}\n status={cardStatus}\n title={\n error ? \"Couldn't save the test recording\" : isRunning ? \"Saving test recording…\" : \"Test recording\"\n }\n subtitle={titleArg}\n toolName={toolName}\n error={error}\n args={typedArgs}\n result={result}\n >\n {cardStatus === \"complete\" ? (\n <p className=\"border-t border-border/40 px-4 py-2.5 text-[12px] text-muted-foreground\">\n The recording's report could not be read.\n </p>\n ) : null}\n </ToolCard>\n );\n};\n\nexport const TestRecordingStopToolUI = memo(\n TestRecordingStopToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingStopToolUI.displayName = \"TestRecordingStopToolUI\";\n\n// ─── Compact rows: test_recording_start / test_recording_mark ────────\n\nfunction TestRecordingRow({\n testId,\n kind,\n icon: Icon,\n iconClassName,\n label,\n labelClassName,\n text,\n time,\n error,\n}: {\n testId: string;\n kind?: string;\n icon: ElementType;\n iconClassName?: string;\n label: string;\n labelClassName?: string;\n text?: string;\n time?: string | null;\n error?: string | null;\n}) {\n return (\n <div\n data-testid={testId}\n data-kind={kind}\n data-failed={error ? \"true\" : \"false\"}\n className={cn(\n \"my-1 flex items-start gap-2 rounded-lg px-2 py-1 text-[12.5px] leading-snug\",\n error && \"bg-destructive/5\",\n )}\n >\n <Icon className={cn(\"mt-0.5 size-3.5 shrink-0\", iconClassName)} aria-hidden />\n <div className=\"min-w-0 flex-1\">\n <span className={cn(\"mr-1.5 font-medium\", labelClassName)}>{label}</span>\n {text ? <span className=\"break-words text-foreground\">{text}</span> : null}\n {error ? <p className=\"mt-0.5 break-words text-[12px] text-destructive\">{error}</p> : null}\n </div>\n {time ? (\n <span className=\"shrink-0 font-mono text-[11px] tabular-nums text-muted-foreground\">{time}</span>\n ) : null}\n </div>\n );\n}\n\nconst TestRecordingStartToolUIImpl: ToolCallMessagePartComponent = ({ args, result, status }) => {\n const start = useMemo(\n () => describeTestRecordingStart({ args: argsRecord(args), result }),\n [args, result],\n );\n const error = incompleteMessage(status, \"The recording could not start.\") ?? start.error;\n const isRunning = !error && status?.type === \"running\";\n return (\n <TestRecordingRow\n testId=\"test-recording-start\"\n icon={error ? AlertCircleIcon : isRunning ? LoaderIcon : CircleDotIcon}\n iconClassName={cn(\n error && \"text-destructive\",\n isRunning && \"animate-spin text-muted-foreground\",\n !error && !isRunning && \"text-red-500\",\n )}\n label={error ? \"Couldn't start recording\" : isRunning ? \"Starting recording\" : \"Recording started\"}\n labelClassName={error ? \"text-destructive\" : \"text-muted-foreground\"}\n text={start.title}\n error={error}\n />\n );\n};\n\nexport const TestRecordingStartToolUI = memo(\n TestRecordingStartToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingStartToolUI.displayName = \"TestRecordingStartToolUI\";\n\nconst MARK_ROW: Record<\n TestRecordingMarkKind,\n { label: string; icon: ElementType; iconClassName: string; labelClassName: string }\n> = {\n test: {\n label: \"Test\",\n icon: FlaskConicalIcon,\n iconClassName: \"text-primary\",\n labelClassName: \"text-primary\",\n },\n pass: {\n label: \"Pass\",\n icon: CheckIcon,\n iconClassName: \"text-emerald-600\",\n labelClassName: \"text-emerald-700\",\n },\n fail: {\n label: \"Fail\",\n icon: XIcon,\n iconClassName: \"text-destructive\",\n labelClassName: \"text-destructive\",\n },\n note: {\n label: \"Note\",\n icon: StickyNoteIcon,\n iconClassName: \"text-muted-foreground\",\n labelClassName: \"text-muted-foreground\",\n },\n};\n\n/** A mark whose kind has not streamed in yet (or is one this SDK does not know). */\nconst UNKNOWN_MARK_ROW = {\n label: \"Mark\",\n icon: StickyNoteIcon,\n iconClassName: \"text-muted-foreground\",\n labelClassName: \"text-muted-foreground\",\n} as const;\n\nconst TestRecordingMarkToolUIImpl: ToolCallMessagePartComponent = ({ args, result, status }) => {\n const mark = useMemo(\n () => describeTestRecordingMark({ args: argsRecord(args), result }),\n [args, result],\n );\n const error = incompleteMessage(status, \"The mark was not recorded.\") ?? mark.error;\n const isRunning = !error && status?.type === \"running\";\n const row = mark.kind ? MARK_ROW[mark.kind] : UNKNOWN_MARK_ROW;\n return (\n <TestRecordingRow\n testId=\"test-recording-mark\"\n kind={mark.kind ?? undefined}\n icon={error ? AlertCircleIcon : isRunning ? LoaderIcon : row.icon}\n iconClassName={cn(\n error && \"text-destructive\",\n isRunning && \"animate-spin text-muted-foreground\",\n !error && !isRunning && row.iconClassName,\n )}\n label={error ? `Couldn't mark ${row.label.toLowerCase()}` : row.label}\n labelClassName={error ? \"text-destructive\" : row.labelClassName}\n text={mark.text}\n time={mark.elapsedS !== null ? formatRecordingClock(mark.elapsedS) : null}\n error={error}\n />\n );\n};\n\nexport const TestRecordingMarkToolUI = memo(\n TestRecordingMarkToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingMarkToolUI.displayName = \"TestRecordingMarkToolUI\";\n"],"names":["useAthenaAssetContent","useObjectUrl","useCallback","useRef","useEffect","_a","jsx","jsxs","AlertCircleIcon","LoaderIcon","PlayIcon","formatRecordingClock","CheckIcon","XIcon","CircleDashedIcon","cn","useState","useContext","AthenaContext","ClapperboardIcon","ExternalLinkIcon","useMemo","parseTestRecordingStopResult","ToolCard","memo","describeTestRecordingStart","CircleDotIcon","FlaskConicalIcon","StickyNoteIcon","describeTestRecordingMark"],"mappings":"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"}
1
+ {"version":3,"file":"test-recording-tool-uis.cjs","sources":["../../src/tools/test-recording-tool-uis.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * The UI Testing toolkit's cards: an agent records itself checking a UI\n * change on its computer and hands back an annotated video.\n *\n * - `test_recording_stop` — the report: the recording's title, \"N passed · M\n * failed\", each test with its ✓ / ✗ assertions (what the agent saw), the\n * summary, and the video, with every test's start as a chapter that plays\n * from there. It stays in the conversation instead of folding into the\n * turn's steps (`isSdkInlineTool`).\n * - `test_recording_start` / `test_recording_mark` — one compact row each.\n *\n * The video is an Athena asset the signed-in user owns. It is read with the\n * user's own credential through `useAthenaAssetContent` (a permission-checked\n * read of the stored file) and played from a page-local object URL, only when\n * the person presses play or picks a chapter; no shareable link is minted.\n */\nimport type { ToolCallMessagePartComponent } from \"@assistant-ui/react\";\nimport {\n AlertCircleIcon,\n CheckIcon,\n CircleDashedIcon,\n CircleDotIcon,\n ClapperboardIcon,\n ExternalLinkIcon,\n FlaskConicalIcon,\n LoaderIcon,\n PlayIcon,\n StickyNoteIcon,\n XIcon,\n} from \"lucide-react\";\nimport {\n type ElementType,\n memo,\n type SyntheticEvent,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useAthenaAssetContent, useObjectUrl } from \"../assets/use-asset-content\";\nimport { cn } from \"../lib/utils\";\nimport { AthenaContext } from \"../provider/AthenaContext\";\nimport { ToolCard, type ToolStatus } from \"./primitives\";\nimport {\n describeTestRecordingMark,\n describeTestRecordingStart,\n formatRecordingClock,\n parseTestRecordingStopResult,\n type TestRecordingAssertion,\n type TestRecordingMarkKind,\n type TestRecordingOutcome,\n type TestRecordingReport,\n type TestRecordingTest,\n} from \"./test-recording-report\";\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction argsRecord(args: unknown): Record<string, unknown> | undefined {\n return typeof args === \"object\" && args !== null && !Array.isArray(args)\n ? (args as Record<string, unknown>)\n : undefined;\n}\n\nfunction argString(args: Record<string, unknown> | undefined, key: string): string | undefined {\n const value = args?.[key];\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : undefined;\n}\n\n/** The message an `incomplete` tool status carries, or `null` for any other status. */\nfunction incompleteMessage(\n status: { type: string; reason?: string; error?: unknown } | undefined,\n fallback: string,\n): string | null {\n if (status?.type !== \"incomplete\") return null;\n if (status.reason === \"cancelled\") return \"Cancelled\";\n if (typeof status.error === \"string\" && status.error.trim() !== \"\") return status.error;\n return fallback;\n}\n\n// ─── Playback ────────────────────────────────────────────────────────\n\ninterface PlaybackRequest {\n /** The person asked to play: the video is read from then on. */\n requested: boolean;\n /** The last chapter picked; `nonce` makes picking the same chapter twice seek twice. */\n seek: { time: number; nonce: number } | null;\n}\n\nconst IDLE_PLAYBACK: PlaybackRequest = { requested: false, seek: null };\n\n/** `HTMLMediaElement.HAVE_METADATA`: below it a seek waits for the video's metadata. */\nconst HAVE_METADATA = 1;\n\nfunction playbackErrorMessage(error: Error): string {\n const status = (error as { status?: unknown }).status;\n if (status === 401 || status === 403) return \"You don't have access to this recording.\";\n if (status === 404) return \"The recording's video was not found.\";\n return \"The recording could not be loaded.\";\n}\n\nfunction TestRecordingPlayer({\n assetId,\n title,\n durationS,\n url,\n playback,\n onPlay,\n}: {\n assetId: string;\n title: string;\n durationS: number | null;\n url: string | null;\n playback: PlaybackRequest;\n onPlay: () => void;\n}) {\n const content = useAthenaAssetContent({ assetId, enabled: playback.requested });\n // Bytes a query already holds still wait for the person to press play.\n const src = useObjectUrl(playback.requested ? content.data : undefined);\n const { refetch } = content;\n const retry = useCallback(() => {\n void refetch();\n }, [refetch]);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n const pendingSeekRef = useRef<number | null>(null);\n const seekTime = playback.seek?.time;\n const seekNonce = playback.seek?.nonce ?? 0;\n\n // Play once the bytes are here, and again from each chapter picked (the\n // nonce is the pick's change signal; picking one chapter twice seeks twice).\n // A seek before the metadata loads sets the start position and is applied\n // again once it has (`onLoadedMetadata`).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => {\n const video = videoRef.current;\n if (!video || !src) return;\n if (seekTime !== undefined) {\n video.currentTime = seekTime;\n pendingSeekRef.current = video.readyState < HAVE_METADATA ? seekTime : null;\n }\n video.play()?.catch(() => {\n // Autoplay refused (no recent user gesture): the controls stay to press play.\n });\n }, [src, seekNonce]);\n\n const handleLoadedMetadata = useCallback((event: SyntheticEvent<HTMLVideoElement>) => {\n const pending = pendingSeekRef.current;\n pendingSeekRef.current = null;\n if (pending !== null) event.currentTarget.currentTime = pending;\n }, []);\n\n if (src) {\n return (\n <video\n ref={videoRef}\n data-testid=\"test-recording-video\"\n src={src}\n controls\n playsInline\n preload=\"auto\"\n aria-label={`Recording: ${title}`}\n onLoadedMetadata={handleLoadedMetadata}\n className=\"block max-h-[480px] w-full bg-black\"\n />\n );\n }\n\n if (content.isError && !content.isFetching) {\n return (\n <div\n role=\"alert\"\n data-testid=\"test-recording-video-error\"\n className=\"flex aspect-video w-full flex-col items-center justify-center gap-2 bg-muted/40 px-6 text-center\"\n >\n <AlertCircleIcon className=\"size-5 text-destructive\" aria-hidden />\n <p className=\"text-[12.5px] text-foreground\">{playbackErrorMessage(content.error)}</p>\n <div className=\"flex items-center gap-3\">\n {/* An explicit retry, refusals included: access may have changed since. */}\n <button\n type=\"button\"\n onClick={retry}\n className=\"rounded-md border border-border bg-background px-2.5 py-1 text-[12px] font-medium text-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n Try again\n </button>\n {url ? (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-[12px] font-medium text-primary hover:underline\"\n >\n Watch in Athena\n </a>\n ) : null}\n </div>\n </div>\n );\n }\n\n if (playback.requested) {\n return (\n <output\n data-testid=\"test-recording-video-loading\"\n className=\"flex aspect-video w-full items-center justify-center gap-2 bg-zinc-950 text-[12px] text-white/80\"\n >\n <LoaderIcon className=\"size-4 animate-spin\" aria-hidden />\n Loading recording…\n </output>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={onPlay}\n aria-label={`Play recording: ${title}`}\n className=\"group relative flex aspect-video w-full items-center justify-center bg-zinc-950 text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset\"\n >\n <span className=\"flex size-12 items-center justify-center rounded-full bg-white/15 transition-colors group-hover:bg-white/25\">\n <PlayIcon className=\"ml-0.5 size-5 fill-current\" aria-hidden />\n </span>\n {durationS !== null ? (\n <span className=\"absolute right-3 bottom-2 text-[11px] tabular-nums text-white/80\">\n {formatRecordingClock(durationS)}\n </span>\n ) : null}\n </button>\n );\n}\n\n/** A time that plays the recording from there: a test's chapter or an assertion's moment. */\nfunction ChapterButton({\n time,\n label,\n onSeek,\n}: {\n time: number;\n label: string;\n onSeek: (time: number) => void;\n}) {\n const clock = formatRecordingClock(time);\n return (\n <button\n type=\"button\"\n data-testid=\"test-recording-chapter\"\n onClick={() => onSeek(time)}\n aria-label={`Play from ${clock}: ${label}`}\n className=\"shrink-0 rounded px-1.5 py-0.5 font-mono text-[11px] tabular-nums text-primary transition-colors hover:bg-primary/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {clock}\n </button>\n );\n}\n\n// ─── Report card ─────────────────────────────────────────────────────\n\nconst OUTCOME_LABEL: Record<TestRecordingOutcome, string> = {\n passed: \"Passed\",\n failed: \"Failed\",\n untested: \"Not checked\",\n};\n\nfunction OutcomeIcon({ result }: { result: TestRecordingOutcome }) {\n if (result === \"passed\") {\n return (\n <span className=\"mt-px flex size-4 shrink-0 items-center justify-center rounded-full bg-emerald-500 text-white\">\n <CheckIcon className=\"size-2.5\" strokeWidth={3.5} aria-hidden />\n </span>\n );\n }\n if (result === \"failed\") {\n return (\n <span className=\"mt-px flex size-4 shrink-0 items-center justify-center rounded-full bg-destructive text-white\">\n <XIcon className=\"size-2.5\" strokeWidth={3.5} aria-hidden />\n </span>\n );\n }\n return <CircleDashedIcon className=\"mt-px size-4 shrink-0 text-muted-foreground\" aria-hidden />;\n}\n\nfunction AssertionRow({\n assertion,\n onSeek,\n}: {\n assertion: TestRecordingAssertion;\n onSeek: ((time: number) => void) | null;\n}) {\n const failed = assertion.result === \"failed\";\n const text = assertion.text || (failed ? \"Failed\" : \"Passed\");\n return (\n <li\n data-testid=\"test-recording-assertion\"\n data-result={assertion.result}\n className={cn(\n \"flex items-start gap-1.5 rounded-md px-1.5 py-0.5 text-[12px] leading-snug\",\n failed ? \"bg-destructive/10 text-destructive\" : \"text-muted-foreground\",\n )}\n >\n {failed ? (\n <XIcon className=\"mt-0.5 size-3 shrink-0\" strokeWidth={3} aria-hidden />\n ) : (\n <CheckIcon className=\"mt-0.5 size-3 shrink-0 text-emerald-600\" strokeWidth={3} aria-hidden />\n )}\n <span className=\"min-w-0 flex-1 break-words\">\n <span className=\"sr-only\">{failed ? \"Failed: \" : \"Passed: \"}</span>\n {text}\n </span>\n {onSeek && assertion.editedTimeS !== null ? (\n <ChapterButton time={assertion.editedTimeS} label={text} onSeek={onSeek} />\n ) : null}\n </li>\n );\n}\n\nfunction TestRow({ test, onSeek }: { test: TestRecordingTest; onSeek: ((time: number) => void) | null }) {\n return (\n <li data-testid=\"test-recording-test\" data-result={test.result} className=\"px-4 py-2.5\">\n <div className=\"flex items-start gap-2\">\n <OutcomeIcon result={test.result} />\n <span\n className={cn(\n \"min-w-0 flex-1 break-words text-[12.5px] font-medium leading-snug\",\n test.result === \"failed\" && \"text-destructive\",\n test.result === \"passed\" && \"text-foreground\",\n test.result === \"untested\" && \"text-muted-foreground\",\n )}\n >\n <span className=\"sr-only\">{`${OUTCOME_LABEL[test.result]}: `}</span>\n {test.name}\n </span>\n {test.result === \"untested\" ? (\n <span className=\"shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n Not checked\n </span>\n ) : null}\n {onSeek && test.startTimeS !== null ? (\n <ChapterButton time={test.startTimeS} label={test.name} onSeek={onSeek} />\n ) : null}\n </div>\n {test.assertions.length > 0 ? (\n <ul className=\"mt-1 flex flex-col gap-0.5 pl-6\">\n {test.assertions.map((assertion, index) => (\n <AssertionRow\n // Assertions are an ordered log with no id of their own, never reordered.\n key={index}\n assertion={assertion}\n onSeek={onSeek}\n />\n ))}\n </ul>\n ) : null}\n </li>\n );\n}\n\nexport interface TestRecordingReportCardProps {\n report: TestRecordingReport;\n className?: string;\n}\n\n/**\n * A saved test recording: the title and counts, the video (read with the\n * signed-in user's credential when the person presses play), each test with\n * its assertions and chapter times, the summary, and a link to the asset in\n * Athena.\n */\nexport function TestRecordingReportCard({ report, className }: TestRecordingReportCardProps) {\n const [playback, setPlayback] = useState<PlaybackRequest>(IDLE_PLAYBACK);\n const play = useCallback(() => {\n setPlayback((previous) => ({ ...previous, requested: true }));\n }, []);\n const seek = useCallback((time: number) => {\n setPlayback((previous) => ({\n requested: true,\n seek: { time, nonce: (previous.seek?.nonce ?? 0) + 1 },\n }));\n }, []);\n // The video is read with the provider's credentials; a host that renders\n // the card outside `<AthenaProvider>` gets the report and the link only.\n const athenaConfig = useContext(AthenaContext);\n const playableAssetId = athenaConfig ? report.assetId : null;\n const onSeek = playableAssetId ? seek : null;\n const hasFailures = report.failed > 0;\n\n return (\n <section\n data-testid=\"test-recording-report\"\n data-has-failures={hasFailures ? \"true\" : \"false\"}\n aria-label={`Test recording: ${report.title}`}\n className={cn(\n \"my-3 w-full overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm\",\n className,\n )}\n >\n <header className=\"flex items-start gap-3 px-4 py-3\">\n <span\n className={cn(\n \"flex size-8 shrink-0 items-center justify-center rounded-lg\",\n hasFailures ? \"bg-destructive/10 text-destructive\" : \"bg-emerald-50 text-emerald-600\",\n )}\n >\n <ClapperboardIcon className=\"size-4\" aria-hidden />\n </span>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"break-words text-[13px] font-medium leading-snug text-foreground\">\n {report.title}\n </h3>\n <p data-testid=\"test-recording-counts\" className=\"text-[12px] tabular-nums text-muted-foreground\">\n <span className={cn(report.passed > 0 && \"text-emerald-700\")}>{report.passed} passed</span>\n {\" · \"}\n <span className={cn(hasFailures && \"font-medium text-destructive\")}>{report.failed} failed</span>\n {report.untested > 0 ? ` · ${report.untested} untested` : null}\n </p>\n </div>\n <span className=\"shrink-0 rounded-md bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n UI test\n </span>\n </header>\n\n {playableAssetId ? (\n <div className=\"border-t border-border/40\">\n <TestRecordingPlayer\n assetId={playableAssetId}\n title={report.title}\n durationS={report.editedDurationS}\n url={report.url}\n playback={playback}\n onPlay={play}\n />\n </div>\n ) : null}\n\n {report.tests.length > 0 ? (\n <ol aria-label=\"Tests\" className=\"flex flex-col divide-y divide-border/40 border-t border-border/40\">\n {report.tests.map((test, index) => (\n // Tests are an ordered log, never reordered; two may share a name.\n <TestRow key={index} test={test} onSeek={onSeek} />\n ))}\n </ol>\n ) : (\n <p className=\"border-t border-border/40 px-4 py-2.5 text-[12px] text-muted-foreground\">\n No tests were marked in this recording.\n </p>\n )}\n\n {report.summary ? (\n <div className=\"border-t border-border/40 px-4 py-2.5\">\n <p className=\"text-[11px] font-medium text-muted-foreground\">Summary</p>\n <p\n data-testid=\"test-recording-summary\"\n className=\"mt-0.5 whitespace-pre-wrap break-words text-[12.5px] leading-relaxed text-foreground\"\n >\n {report.summary}\n </p>\n </div>\n ) : null}\n\n {report.url ? (\n <div className=\"flex justify-end border-t border-border/40 px-4 py-2\">\n <a\n href={report.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1.5 rounded-md px-2 py-1 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground\"\n >\n <ExternalLinkIcon className=\"size-3\" aria-hidden />\n Watch in Athena\n </a>\n </div>\n ) : null}\n </section>\n );\n}\n\n// ─── test_recording_stop ─────────────────────────────────────────────\n\nconst TestRecordingStopToolUIImpl: ToolCallMessagePartComponent = ({\n toolName,\n args,\n result,\n status,\n}) => {\n const typedArgs = argsRecord(args);\n const titleArg = argString(typedArgs, \"title\");\n const parsed = useMemo(\n () => parseTestRecordingStopResult(result, { fallbackTitle: titleArg }),\n [result, titleArg],\n );\n\n if (parsed.kind === \"saved\") return <TestRecordingReportCard report={parsed.report} />;\n\n const isRunning = status?.type === \"running\";\n const error =\n incompleteMessage(status, \"The test recording could not be saved.\") ??\n (parsed.kind === \"error\" ? parsed.message : null);\n const cardStatus: ToolStatus = error ? \"incomplete\" : isRunning ? \"running\" : \"complete\";\n return (\n <ToolCard\n icon={ClapperboardIcon}\n status={cardStatus}\n title={\n error ? \"Couldn't save the test recording\" : isRunning ? \"Saving test recording…\" : \"Test recording\"\n }\n subtitle={titleArg}\n toolName={toolName}\n error={error}\n args={typedArgs}\n result={result}\n >\n {cardStatus === \"complete\" ? (\n <p className=\"border-t border-border/40 px-4 py-2.5 text-[12px] text-muted-foreground\">\n The recording's report could not be read.\n </p>\n ) : null}\n </ToolCard>\n );\n};\n\nexport const TestRecordingStopToolUI = memo(\n TestRecordingStopToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingStopToolUI.displayName = \"TestRecordingStopToolUI\";\n\n// ─── Compact rows: test_recording_start / test_recording_mark ────────\n\nfunction TestRecordingRow({\n testId,\n kind,\n icon: Icon,\n iconClassName,\n label,\n labelClassName,\n text,\n time,\n error,\n}: {\n testId: string;\n kind?: string;\n icon: ElementType;\n iconClassName?: string;\n label: string;\n labelClassName?: string;\n text?: string;\n time?: string | null;\n error?: string | null;\n}) {\n return (\n <div\n data-testid={testId}\n data-kind={kind}\n data-failed={error ? \"true\" : \"false\"}\n className={cn(\n \"my-1 flex items-start gap-2 rounded-lg px-2 py-1 text-[12.5px] leading-snug\",\n error && \"bg-destructive/5\",\n )}\n >\n <Icon className={cn(\"mt-0.5 size-3.5 shrink-0\", iconClassName)} aria-hidden />\n <div className=\"min-w-0 flex-1\">\n <span className={cn(\"mr-1.5 font-medium\", labelClassName)}>{label}</span>\n {text ? <span className=\"break-words text-foreground\">{text}</span> : null}\n {error ? <p className=\"mt-0.5 break-words text-[12px] text-destructive\">{error}</p> : null}\n </div>\n {time ? (\n <span className=\"shrink-0 font-mono text-[11px] tabular-nums text-muted-foreground\">{time}</span>\n ) : null}\n </div>\n );\n}\n\nconst TestRecordingStartToolUIImpl: ToolCallMessagePartComponent = ({ args, result, status }) => {\n const start = useMemo(\n () => describeTestRecordingStart({ args: argsRecord(args), result }),\n [args, result],\n );\n const error = incompleteMessage(status, \"The recording could not start.\") ?? start.error;\n const isRunning = !error && status?.type === \"running\";\n return (\n <TestRecordingRow\n testId=\"test-recording-start\"\n icon={error ? AlertCircleIcon : isRunning ? LoaderIcon : CircleDotIcon}\n iconClassName={cn(\n error && \"text-destructive\",\n isRunning && \"animate-spin text-muted-foreground\",\n !error && !isRunning && \"text-red-500\",\n )}\n label={error ? \"Couldn't start recording\" : isRunning ? \"Starting recording\" : \"Recording started\"}\n labelClassName={error ? \"text-destructive\" : \"text-muted-foreground\"}\n text={start.title}\n error={error}\n />\n );\n};\n\nexport const TestRecordingStartToolUI = memo(\n TestRecordingStartToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingStartToolUI.displayName = \"TestRecordingStartToolUI\";\n\nconst MARK_ROW: Record<\n TestRecordingMarkKind,\n { label: string; icon: ElementType; iconClassName: string; labelClassName: string }\n> = {\n test: {\n label: \"Test\",\n icon: FlaskConicalIcon,\n iconClassName: \"text-primary\",\n labelClassName: \"text-primary\",\n },\n pass: {\n label: \"Pass\",\n icon: CheckIcon,\n iconClassName: \"text-emerald-600\",\n labelClassName: \"text-emerald-700\",\n },\n fail: {\n label: \"Fail\",\n icon: XIcon,\n iconClassName: \"text-destructive\",\n labelClassName: \"text-destructive\",\n },\n note: {\n label: \"Note\",\n icon: StickyNoteIcon,\n iconClassName: \"text-muted-foreground\",\n labelClassName: \"text-muted-foreground\",\n },\n};\n\n/** A mark whose kind has not streamed in yet (or is one this SDK does not know). */\nconst UNKNOWN_MARK_ROW = {\n label: \"Mark\",\n icon: StickyNoteIcon,\n iconClassName: \"text-muted-foreground\",\n labelClassName: \"text-muted-foreground\",\n} as const;\n\nconst TestRecordingMarkToolUIImpl: ToolCallMessagePartComponent = ({ args, result, status }) => {\n const mark = useMemo(\n () => describeTestRecordingMark({ args: argsRecord(args), result }),\n [args, result],\n );\n const error = incompleteMessage(status, \"The mark was not recorded.\") ?? mark.error;\n const isRunning = !error && status?.type === \"running\";\n const row = mark.kind ? MARK_ROW[mark.kind] : UNKNOWN_MARK_ROW;\n return (\n <TestRecordingRow\n testId=\"test-recording-mark\"\n kind={mark.kind ?? undefined}\n icon={error ? AlertCircleIcon : isRunning ? LoaderIcon : row.icon}\n iconClassName={cn(\n error && \"text-destructive\",\n isRunning && \"animate-spin text-muted-foreground\",\n !error && !isRunning && row.iconClassName,\n )}\n label={error ? `Couldn't mark ${row.label.toLowerCase()}` : row.label}\n labelClassName={error ? \"text-destructive\" : row.labelClassName}\n text={mark.text}\n time={mark.elapsedS !== null ? formatRecordingClock(mark.elapsedS) : null}\n error={error}\n />\n );\n};\n\nexport const TestRecordingMarkToolUI = memo(\n TestRecordingMarkToolUIImpl,\n) as unknown as ToolCallMessagePartComponent;\nTestRecordingMarkToolUI.displayName = \"TestRecordingMarkToolUI\";\n"],"names":["useAthenaAssetContent","useObjectUrl","useCallback","useRef","useEffect","_a","jsx","jsxs","AlertCircleIcon","LoaderIcon","PlayIcon","formatRecordingClock","CheckIcon","XIcon","CircleDashedIcon","cn","useState","useContext","AthenaContext","ClapperboardIcon","ExternalLinkIcon","useMemo","parseTestRecordingStopResult","ToolCard","memo","describeTestRecordingStart","CircleDotIcon","FlaskConicalIcon","StickyNoteIcon","describeTestRecordingMark"],"mappings":";;;;;;;;;;AA6DA,SAAS,WAAW,MAAoD;AACtE,SAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI,IAClE,OACD;AACN;AAEA,SAAS,UAAU,MAA2C,KAAiC;AAC7F,QAAM,QAAQ,6BAAO;AACrB,SAAO,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,KAAA,IAAS;AAC3E;AAGA,SAAS,kBACP,QACA,UACe;AACf,OAAI,iCAAQ,UAAS,aAAc,QAAO;AAC1C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,WAAW,GAAI,QAAO,OAAO;AAClF,SAAO;AACT;AAWA,MAAM,gBAAiC,EAAE,WAAW,OAAO,MAAM,KAAA;AAGjE,MAAM,gBAAgB;AAEtB,SAAS,qBAAqB,OAAsB;AAClD,QAAM,SAAU,MAA+B;AAC/C,MAAI,WAAW,OAAO,WAAW,IAAK,QAAO;AAC7C,MAAI,WAAW,IAAK,QAAO;AAC3B,SAAO;AACT;AAEA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;;AACD,QAAM,UAAUA,gBAAAA,sBAAsB,EAAE,SAAS,SAAS,SAAS,WAAW;AAE9E,QAAM,MAAMC,gBAAAA,aAAa,SAAS,YAAY,QAAQ,OAAO,MAAS;AACtE,QAAM,EAAE,YAAY;AACpB,QAAM,QAAQC,WAAAA,YAAY,MAAM;AAC9B,SAAK,QAAA;AAAA,EACP,GAAG,CAAC,OAAO,CAAC;AACZ,QAAM,WAAWC,WAAAA,OAAgC,IAAI;AACrD,QAAM,iBAAiBA,WAAAA,OAAsB,IAAI;AACjD,QAAM,YAAW,cAAS,SAAT,mBAAe;AAChC,QAAM,cAAY,cAAS,SAAT,mBAAe,UAAS;AAO1CC,aAAAA,UAAU,MAAM;;AACd,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,SAAS,CAAC,IAAK;AACpB,QAAI,aAAa,QAAW;AAC1B,YAAM,cAAc;AACpB,qBAAe,UAAU,MAAM,aAAa,gBAAgB,WAAW;AAAA,IACzE;AACA,KAAAC,MAAA,MAAM,WAAN,gBAAAA,IAAc,MAAM,MAAM;AAAA,IAE1B;AAAA,EACF,GAAG,CAAC,KAAK,SAAS,CAAC;AAEnB,QAAM,uBAAuBH,uBAAY,CAAC,UAA4C;AACpF,UAAM,UAAU,eAAe;AAC/B,mBAAe,UAAU;AACzB,QAAI,YAAY,KAAM,OAAM,cAAc,cAAc;AAAA,EAC1D,GAAG,CAAA,CAAE;AAEL,MAAI,KAAK;AACP,WACEI,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,eAAY;AAAA,QACZ;AAAA,QACA,UAAQ;AAAA,QACR,aAAW;AAAA,QACX,SAAQ;AAAA,QACR,cAAY,cAAc,KAAK;AAAA,QAC/B,kBAAkB;AAAA,QAClB,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EAGhB;AAEA,MAAI,QAAQ,WAAW,CAAC,QAAQ,YAAY;AAC1C,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAU;AAAA,QAEV,UAAA;AAAA,UAAAD,2BAAAA,IAACE,YAAAA,iBAAA,EAAgB,WAAU,2BAA0B,eAAW,MAAC;AAAA,yCAChE,KAAA,EAAE,WAAU,iCAAiC,UAAA,qBAAqB,QAAQ,KAAK,GAAE;AAAA,UAClFD,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BAEb,UAAA;AAAA,YAAAD,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS;AAAA,gBACT,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGA,MACCA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAM;AAAA,gBACN,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA,IAGC;AAAA,UAAA,EAAA,CACN;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAEA,MAAI,SAAS,WAAW;AACtB,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,eAAY;AAAA,QACZ,WAAU;AAAA,QAEV,UAAA;AAAA,UAAAD,2BAAAA,IAACG,YAAAA,YAAA,EAAW,WAAU,uBAAsB,eAAW,MAAC;AAAA,UAAE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIhE;AAEA,SACEF,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,cAAY,mBAAmB,KAAK;AAAA,MACpC,WAAU;AAAA,MAEV,UAAA;AAAA,QAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAU,+GACd,UAAAA,2BAAAA,IAACI,wBAAS,WAAU,8BAA6B,eAAW,KAAA,CAAC,EAAA,CAC/D;AAAA,QACC,cAAc,OACbJ,+BAAC,QAAA,EAAK,WAAU,oEACb,UAAAK,oBAAAA,qBAAqB,SAAS,EAAA,CACjC,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAGA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,QAAQA,oBAAAA,qBAAqB,IAAI;AACvC,SACEL,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,eAAY;AAAA,MACZ,SAAS,MAAM,OAAO,IAAI;AAAA,MAC1B,cAAY,aAAa,KAAK,KAAK,KAAK;AAAA,MACxC,WAAU;AAAA,MAET,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAIA,MAAM,gBAAsD;AAAA,EAC1D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AACZ;AAEA,SAAS,YAAY,EAAE,UAA4C;AACjE,MAAI,WAAW,UAAU;AACvB,WACEA,2BAAAA,IAAC,QAAA,EAAK,WAAU,iGACd,UAAAA,+BAACM,YAAAA,WAAA,EAAU,WAAU,YAAW,aAAa,KAAK,eAAW,KAAA,CAAC,GAChE;AAAA,EAEJ;AACA,MAAI,WAAW,UAAU;AACvB,WACEN,2BAAAA,IAAC,QAAA,EAAK,WAAU,iGACd,UAAAA,+BAACO,YAAAA,OAAA,EAAM,WAAU,YAAW,aAAa,KAAK,eAAW,KAAA,CAAC,GAC5D;AAAA,EAEJ;AACA,SAAOP,2BAAAA,IAACQ,YAAAA,kBAAA,EAAiB,WAAU,+CAA8C,eAAW,MAAC;AAC/F;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AACF,GAGG;AACD,QAAM,SAAS,UAAU,WAAW;AACpC,QAAM,OAAO,UAAU,SAAS,SAAS,WAAW;AACpD,SACEP,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,eAAa,UAAU;AAAA,MACvB,WAAWQ,OAAAA;AAAAA,QACT;AAAA,QACA,SAAS,uCAAuC;AAAA,MAAA;AAAA,MAGjD,UAAA;AAAA,QAAA,wCACEF,YAAAA,OAAA,EAAM,WAAU,0BAAyB,aAAa,GAAG,eAAW,KAAA,CAAC,IAEtEP,+BAACM,YAAAA,aAAU,WAAU,2CAA0C,aAAa,GAAG,eAAW,MAAC;AAAA,QAE7FL,2BAAAA,KAAC,QAAA,EAAK,WAAU,8BACd,UAAA;AAAA,UAAAD,+BAAC,QAAA,EAAK,WAAU,WAAW,UAAA,SAAS,aAAa,YAAW;AAAA,UAC3D;AAAA,QAAA,GACH;AAAA,QACC,UAAU,UAAU,gBAAgB,OACnCA,2BAAAA,IAAC,eAAA,EAAc,MAAM,UAAU,aAAa,OAAO,MAAM,OAAA,CAAgB,IACvE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,SAAS,QAAQ,EAAE,MAAM,UAAgF;AACvG,SACEC,gCAAC,QAAG,eAAY,uBAAsB,eAAa,KAAK,QAAQ,WAAU,eACxE,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,0BACb,UAAA;AAAA,MAAAD,2BAAAA,IAAC,aAAA,EAAY,QAAQ,KAAK,OAAA,CAAQ;AAAA,MAClCC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWQ,OAAAA;AAAAA,YACT;AAAA,YACA,KAAK,WAAW,YAAY;AAAA,YAC5B,KAAK,WAAW,YAAY;AAAA,YAC5B,KAAK,WAAW,cAAc;AAAA,UAAA;AAAA,UAGhC,UAAA;AAAA,YAAAT,2BAAAA,IAAC,QAAA,EAAK,WAAU,WAAW,UAAA,GAAG,cAAc,KAAK,MAAM,CAAC,KAAA,CAAK;AAAA,YAC5D,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAEP,KAAK,WAAW,aACfA,2BAAAA,IAAC,UAAK,WAAU,8FAA6F,yBAE7G,IACE;AAAA,MACH,UAAU,KAAK,eAAe,OAC7BA,2BAAAA,IAAC,eAAA,EAAc,MAAM,KAAK,YAAY,OAAO,KAAK,MAAM,QAAgB,IACtE;AAAA,IAAA,GACN;AAAA,IACC,KAAK,WAAW,SAAS,IACxBA,2BAAAA,IAAC,MAAA,EAAG,WAAU,mCACX,UAAA,KAAK,WAAW,IAAI,CAAC,WAAW,UAC/BA,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QAGC;AAAA,QACA;AAAA,MAAA;AAAA,MAFK;AAAA,IAAA,CAIR,GACH,IACE;AAAA,EAAA,GACN;AAEJ;AAaO,SAAS,wBAAwB,EAAE,QAAQ,aAA2C;AAC3F,QAAM,CAAC,UAAU,WAAW,IAAIU,WAAAA,SAA0B,aAAa;AACvE,QAAM,OAAOd,WAAAA,YAAY,MAAM;AAC7B,gBAAY,CAAC,cAAc,EAAE,GAAG,UAAU,WAAW,OAAO;AAAA,EAC9D,GAAG,CAAA,CAAE;AACL,QAAM,OAAOA,uBAAY,CAAC,SAAiB;AACzC,gBAAY,CAAC,aAAA;;AAAc;AAAA,QACzB,WAAW;AAAA,QACX,MAAM,EAAE,MAAM,UAAQ,cAAS,SAAT,mBAAe,UAAS,KAAK,EAAA;AAAA,MAAE;AAAA,KACrD;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAM,eAAee,WAAAA,WAAWC,2BAAa;AAC7C,QAAM,kBAAkB,eAAe,OAAO,UAAU;AACxD,QAAM,SAAS,kBAAkB,OAAO;AACxC,QAAM,cAAc,OAAO,SAAS;AAEpC,SACEX,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,qBAAmB,cAAc,SAAS;AAAA,MAC1C,cAAY,mBAAmB,OAAO,KAAK;AAAA,MAC3C,WAAWQ,OAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAAR,2BAAAA,KAAC,UAAA,EAAO,WAAU,oCAChB,UAAA;AAAA,UAAAD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWS,OAAAA;AAAAA,gBACT;AAAA,gBACA,cAAc,uCAAuC;AAAA,cAAA;AAAA,cAGvD,UAAAT,2BAAAA,IAACa,8BAAA,EAAiB,WAAU,UAAS,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAEnDZ,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAAD,2BAAAA,IAAC,MAAA,EAAG,WAAU,oEACX,UAAA,OAAO,OACV;AAAA,YACAC,2BAAAA,KAAC,KAAA,EAAE,eAAY,yBAAwB,WAAU,kDAC/C,UAAA;AAAA,cAAAA,gCAAC,UAAK,WAAWQ,OAAAA,GAAG,OAAO,SAAS,KAAK,kBAAkB,GAAI,UAAA;AAAA,gBAAA,OAAO;AAAA,gBAAO;AAAA,cAAA,GAAO;AAAA,cACnF;AAAA,8CACA,QAAA,EAAK,WAAWA,OAAAA,GAAG,eAAe,8BAA8B,GAAI,UAAA;AAAA,gBAAA,OAAO;AAAA,gBAAO;AAAA,cAAA,GAAO;AAAA,cACzF,OAAO,WAAW,IAAI,MAAM,OAAO,QAAQ,cAAc;AAAA,YAAA,EAAA,CAC5D;AAAA,UAAA,GACF;AAAA,UACAT,2BAAAA,IAAC,QAAA,EAAK,WAAU,+FAA8F,UAAA,UAAA,CAE9G;AAAA,QAAA,GACF;AAAA,QAEC,kBACCA,2BAAAA,IAAC,OAAA,EAAI,WAAU,6BACb,UAAAA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS;AAAA,YACT,OAAO,OAAO;AAAA,YACd,WAAW,OAAO;AAAA,YAClB,KAAK,OAAO;AAAA,YACZ;AAAA,YACA,QAAQ;AAAA,UAAA;AAAA,QAAA,GAEZ,IACE;AAAA,QAEH,OAAO,MAAM,SAAS,mCACpB,MAAA,EAAG,cAAW,SAAQ,WAAU,qEAC9B,UAAA,OAAO,MAAM,IAAI,CAAC,MAAM;AAAA;AAAA,UAEvBA,2BAAAA,IAAC,SAAA,EAAoB,MAAY,OAAA,GAAnB,KAAmC;AAAA,SAClD,GACH,IAEAA,2BAAAA,IAAC,KAAA,EAAE,WAAU,2EAA0E,UAAA,2CAEvF;AAAA,QAGD,OAAO,UACNC,gCAAC,OAAA,EAAI,WAAU,yCACb,UAAA;AAAA,UAAAD,2BAAAA,IAAC,KAAA,EAAE,WAAU,iDAAgD,UAAA,WAAO;AAAA,UACpEA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAU;AAAA,cAET,UAAA,OAAO;AAAA,YAAA;AAAA,UAAA;AAAA,QACV,EAAA,CACF,IACE;AAAA,QAEH,OAAO,MACNA,+BAAC,OAAA,EAAI,WAAU,wDACb,UAAAC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAM,OAAO;AAAA,YACb,QAAO;AAAA,YACP,KAAI;AAAA,YACJ,WAAU;AAAA,YAEV,UAAA;AAAA,cAAAD,2BAAAA,IAACc,YAAAA,kBAAA,EAAiB,WAAU,UAAS,eAAW,MAAC;AAAA,cAAE;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAGvD,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAIA,MAAM,8BAA4D,CAAC;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,YAAY,WAAW,IAAI;AACjC,QAAM,WAAW,UAAU,WAAW,OAAO;AAC7C,QAAM,SAASC,WAAAA;AAAAA,IACb,MAAMC,oBAAAA,6BAA6B,QAAQ,EAAE,eAAe,UAAU;AAAA,IACtE,CAAC,QAAQ,QAAQ;AAAA,EAAA;AAGnB,MAAI,OAAO,SAAS,QAAS,uCAAQ,yBAAA,EAAwB,QAAQ,OAAO,QAAQ;AAEpF,QAAM,aAAY,iCAAQ,UAAS;AACnC,QAAM,QACJ,kBAAkB,QAAQ,wCAAwC,MACjE,OAAO,SAAS,UAAU,OAAO,UAAU;AAC9C,QAAM,aAAyB,QAAQ,eAAe,YAAY,YAAY;AAC9E,SACEhB,2BAAAA;AAAAA,IAACiB,WAAAA;AAAAA,IAAA;AAAA,MACC,MAAMJ,YAAAA;AAAAA,MACN,QAAQ;AAAA,MACR,OACE,QAAQ,qCAAqC,YAAY,2BAA2B;AAAA,MAEtF,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MAEC,yBAAe,aACdb,2BAAAA,IAAC,OAAE,WAAU,2EAA0E,uDAEvF,IACE;AAAA,IAAA;AAAA,EAAA;AAGV;AAEO,MAAM,0BAA0BkB,WAAAA;AAAAA,EACrC;AACF;AACA,wBAAwB,cAAc;AAItC,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUG;AACD,SACEjB,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAa;AAAA,MACb,aAAW;AAAA,MACX,eAAa,QAAQ,SAAS;AAAA,MAC9B,WAAWQ,OAAAA;AAAAA,QACT;AAAA,QACA,SAAS;AAAA,MAAA;AAAA,MAGX,UAAA;AAAA,QAAAT,+BAAC,QAAK,WAAWS,OAAAA,GAAG,4BAA4B,aAAa,GAAG,eAAW,MAAC;AAAA,QAC5ER,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAAD,+BAAC,UAAK,WAAWS,OAAAA,GAAG,sBAAsB,cAAc,GAAI,UAAA,OAAM;AAAA,UACjE,OAAOT,2BAAAA,IAAC,QAAA,EAAK,WAAU,+BAA+B,gBAAK,IAAU;AAAA,UACrE,QAAQA,2BAAAA,IAAC,KAAA,EAAE,WAAU,mDAAmD,iBAAM,IAAO;AAAA,QAAA,GACxF;AAAA,QACC,OACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,qEAAqE,gBAAK,IACxF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;AAEA,MAAM,+BAA6D,CAAC,EAAE,MAAM,QAAQ,aAAa;AAC/F,QAAM,QAAQe,WAAAA;AAAAA,IACZ,MAAMI,oBAAAA,2BAA2B,EAAE,MAAM,WAAW,IAAI,GAAG,QAAQ;AAAA,IACnE,CAAC,MAAM,MAAM;AAAA,EAAA;AAEf,QAAM,QAAQ,kBAAkB,QAAQ,gCAAgC,KAAK,MAAM;AACnF,QAAM,YAAY,CAAC,UAAS,iCAAQ,UAAS;AAC7C,SACEnB,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,QAAO;AAAA,MACP,MAAM,QAAQE,YAAAA,kBAAkB,YAAYC,YAAAA,aAAaiB,YAAAA;AAAAA,MACzD,eAAeX,OAAAA;AAAAA,QACb,SAAS;AAAA,QACT,aAAa;AAAA,QACb,CAAC,SAAS,CAAC,aAAa;AAAA,MAAA;AAAA,MAE1B,OAAO,QAAQ,6BAA6B,YAAY,uBAAuB;AAAA,MAC/E,gBAAgB,QAAQ,qBAAqB;AAAA,MAC7C,MAAM,MAAM;AAAA,MACZ;AAAA,IAAA;AAAA,EAAA;AAGN;AAEO,MAAM,2BAA2BS,WAAAA;AAAAA,EACtC;AACF;AACA,yBAAyB,cAAc;AAEvC,MAAM,WAGF;AAAA,EACF,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,MAAMG,YAAAA;AAAAA,IACN,eAAe;AAAA,IACf,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,MAAMf,YAAAA;AAAAA,IACN,eAAe;AAAA,IACf,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,MAAMC,YAAAA;AAAAA,IACN,eAAe;AAAA,IACf,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,MAAMe,YAAAA;AAAAA,IACN,eAAe;AAAA,IACf,gBAAgB;AAAA,EAAA;AAEpB;AAGA,MAAM,mBAAmB;AAAA,EACvB,OAAO;AAAA,EACP,MAAMA,YAAAA;AAAAA,EACN,eAAe;AAAA,EACf,gBAAgB;AAClB;AAEA,MAAM,8BAA4D,CAAC,EAAE,MAAM,QAAQ,aAAa;AAC9F,QAAM,OAAOP,WAAAA;AAAAA,IACX,MAAMQ,oBAAAA,0BAA0B,EAAE,MAAM,WAAW,IAAI,GAAG,QAAQ;AAAA,IAClE,CAAC,MAAM,MAAM;AAAA,EAAA;AAEf,QAAM,QAAQ,kBAAkB,QAAQ,4BAA4B,KAAK,KAAK;AAC9E,QAAM,YAAY,CAAC,UAAS,iCAAQ,UAAS;AAC7C,QAAM,MAAM,KAAK,OAAO,SAAS,KAAK,IAAI,IAAI;AAC9C,SACEvB,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,QAAO;AAAA,MACP,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,QAAQE,YAAAA,kBAAkB,YAAYC,YAAAA,aAAa,IAAI;AAAA,MAC7D,eAAeM,OAAAA;AAAAA,QACb,SAAS;AAAA,QACT,aAAa;AAAA,QACb,CAAC,SAAS,CAAC,aAAa,IAAI;AAAA,MAAA;AAAA,MAE9B,OAAO,QAAQ,iBAAiB,IAAI,MAAM,YAAA,CAAa,KAAK,IAAI;AAAA,MAChE,gBAAgB,QAAQ,qBAAqB,IAAI;AAAA,MACjD,MAAM,KAAK;AAAA,MACX,MAAM,KAAK,aAAa,OAAOJ,oBAAAA,qBAAqB,KAAK,QAAQ,IAAI;AAAA,MACrE;AAAA,IAAA;AAAA,EAAA;AAGN;AAEO,MAAM,0BAA0Ba,WAAAA;AAAAA,EACrC;AACF;AACA,wBAAwB,cAAc;;;;;"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
3
+ const require$$0 = require("react");
4
4
  const threadIdContext = require("../threads/thread-id-context.cjs");
5
5
  const DEFAULT_SCOPE = "default";
6
6
  let nextSeq = 1;
@@ -64,16 +64,16 @@ function subscribe(listener) {
64
64
  }
65
65
  const getVersion = () => version;
66
66
  function usePlanScope() {
67
- return react.useContext(threadIdContext.AthenaThreadIdContext) ?? DEFAULT_SCOPE;
67
+ return require$$0.useContext(threadIdContext.AthenaThreadIdContext) ?? DEFAULT_SCOPE;
68
68
  }
69
69
  function useIsLatestPlanCard(scope, seq) {
70
- react.useSyncExternalStore(subscribe, getVersion, getVersion);
70
+ require$$0.useSyncExternalStore(subscribe, getVersion, getVersion);
71
71
  const latest = latestPlanSeq(scope);
72
72
  return latest === null || latest === seq;
73
73
  }
74
74
  function useLatestTodoPlan() {
75
75
  const scope = usePlanScope();
76
- react.useSyncExternalStore(subscribe, getVersion, getVersion);
76
+ require$$0.useSyncExternalStore(subscribe, getVersion, getVersion);
77
77
  const entry = latestPlanEntry(scope);
78
78
  return entry ? { plan: entry.plan, isWriting: entry.isWriting } : null;
79
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"todo-plan-store.cjs","sources":["../../src/tools/todo-plan-store.ts"],"sourcesContent":["/**\n * Live registry of mounted `write_todos` cards — the newest one wins.\n *\n * A run updates its plan by calling `write_todos` repeatedly, and every call\n * renders its own card, so a conversation stacks \"Plan in progress / Plan\n * complete\" cards that all describe the same plan. The registry tracks the\n * mounted cards in mount order (the thread renders messages top-down, so the\n * newest call mounts last); {@link WriteTodosToolUI} renders the full card\n * only for the newest instance and nothing for superseded ones.\n *\n * Scoped by thread id (from `AthenaThreadIdContext`): a page hosting several\n * chats ranks each conversation's cards separately, so one chat's plan never\n * suppresses another's. Two views of the SAME thread share a scope, which is\n * the correct behavior — they show the same plan.\n *\n * Instance-scoped sequence numbers, not callId-scoped: reopening a thread\n * mounts fresh instances with fresh sequence numbers, so \"newest\" always\n * resolves within what is currently on screen.\n *\n * Hosts that want a pinned plan strip instead of the inline card should\n * register {@link HiddenWriteTodosToolUI} (which feeds this registry and\n * renders nothing) and read {@link useLatestTodoPlan}.\n */\nimport { useContext, useSyncExternalStore } from \"react\";\nimport { AthenaThreadIdContext } from \"../threads/thread-id-context\";\nimport type { TodoPlan } from \"./write-todos-tool-ui\";\n\ninterface PlanEntry {\n seq: number;\n plan: TodoPlan;\n isWriting: boolean;\n}\n\nconst DEFAULT_SCOPE = \"default\";\n\nlet nextSeq = 1;\nconst scopes = new Map<string, Map<number, PlanEntry>>();\nconst listeners = new Set<() => void>();\nlet version = 0;\n\nfunction emit(): void {\n version++;\n for (const listener of listeners) listener();\n}\n\nfunction scopeEntries(scope: string): Map<number, PlanEntry> {\n let entries = scopes.get(scope);\n if (!entries) {\n entries = new Map();\n scopes.set(scope, entries);\n }\n return entries;\n}\n\n/** Allocate a mount-ordered sequence number (pure counter — safe to discard). */\nexport function allocatePlanSeq(): number {\n return nextSeq++;\n}\n\nexport function registerPlanCard(\n scope: string,\n seq: number,\n plan: TodoPlan,\n isWriting: boolean,\n): void {\n scopeEntries(scope).set(seq, { seq, plan, isWriting });\n emit();\n}\n\nexport function updatePlanCard(\n scope: string,\n seq: number,\n plan: TodoPlan,\n isWriting: boolean,\n): void {\n const entry = scopes.get(scope)?.get(seq);\n if (!entry) return;\n entry.plan = plan;\n entry.isWriting = isWriting;\n emit();\n}\n\nexport function unregisterPlanCard(scope: string, seq: number): void {\n const entries = scopes.get(scope);\n if (!entries) return;\n if (entries.delete(seq)) {\n if (entries.size === 0) scopes.delete(scope);\n emit();\n }\n}\n\nexport function latestPlanSeq(scope: string): number | null {\n const entries = scopes.get(scope);\n if (!entries) return null;\n let latest: number | null = null;\n for (const seq of entries.keys()) {\n if (latest === null || seq > latest) latest = seq;\n }\n return latest;\n}\n\nfunction latestPlanEntry(scope: string): PlanEntry | null {\n const seq = latestPlanSeq(scope);\n return seq === null ? null : (scopes.get(scope)?.get(seq) ?? null);\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nconst getVersion = () => version;\n\n/** The plan scope for the calling component's chat (its thread id). */\nexport function usePlanScope(): string {\n return useContext(AthenaThreadIdContext) ?? DEFAULT_SCOPE;\n}\n\n/**\n * Whether the card with this sequence number is the newest mounted plan card\n * in its scope. On the server (and before client effects have registered any\n * card) every card reports latest, so static renders still show the plan.\n */\nexport function useIsLatestPlanCard(scope: string, seq: number): boolean {\n const currentVersion = useSyncExternalStore(subscribe, getVersion, getVersion);\n void currentVersion; // subscription tick — the value itself is not meaningful\n const latest = latestPlanSeq(scope);\n return latest === null || latest === seq;\n}\n\nexport interface LatestTodoPlan {\n plan: TodoPlan;\n /** True while the newest plan card's tool call is still streaming. */\n isWriting: boolean;\n}\n\n/**\n * The newest mounted plan for the calling chat, for hosts building their own\n * pinned plan UI. Pair with `toolUIs={{ write_todos: HiddenWriteTodosToolUI }}`\n * — that component keeps feeding this registry while rendering nothing inline\n * (a bare `() => null` override would starve it).\n */\nexport function useLatestTodoPlan(): LatestTodoPlan | null {\n const scope = usePlanScope();\n const currentVersion = useSyncExternalStore(subscribe, getVersion, getVersion);\n void currentVersion;\n const entry = latestPlanEntry(scope);\n return entry ? { plan: entry.plan, isWriting: entry.isWriting } : null;\n}\n\n/** Test-only: reset module state between cases. */\nexport function resetTodoPlanStoreForTests(): void {\n nextSeq = 1;\n scopes.clear();\n version = 0;\n}\n"],"names":["useContext","AthenaThreadIdContext","useSyncExternalStore"],"mappings":";;;;AAiCA,MAAM,gBAAgB;AAEtB,IAAI,UAAU;AACd,MAAM,6BAAa,IAAA;AACnB,MAAM,gCAAgB,IAAA;AACtB,IAAI,UAAU;AAEd,SAAS,OAAa;AACpB;AACA,aAAW,YAAY,UAAW,UAAA;AACpC;AAEA,SAAS,aAAa,OAAuC;AAC3D,MAAI,UAAU,OAAO,IAAI,KAAK;AAC9B,MAAI,CAAC,SAAS;AACZ,kCAAc,IAAA;AACd,WAAO,IAAI,OAAO,OAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAGO,SAAS,kBAA0B;AACxC,SAAO;AACT;AAEO,SAAS,iBACd,OACA,KACA,MACA,WACM;AACN,eAAa,KAAK,EAAE,IAAI,KAAK,EAAE,KAAK,MAAM,WAAW;AACrD,OAAA;AACF;AAEO,SAAS,eACd,OACA,KACA,MACA,WACM;;AACN,QAAM,SAAQ,YAAO,IAAI,KAAK,MAAhB,mBAAmB,IAAI;AACrC,MAAI,CAAC,MAAO;AACZ,QAAM,OAAO;AACb,QAAM,YAAY;AAClB,OAAA;AACF;AAEO,SAAS,mBAAmB,OAAe,KAAmB;AACnE,QAAM,UAAU,OAAO,IAAI,KAAK;AAChC,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,OAAO,GAAG,GAAG;AACvB,QAAI,QAAQ,SAAS,EAAG,QAAO,OAAO,KAAK;AAC3C,SAAA;AAAA,EACF;AACF;AAEO,SAAS,cAAc,OAA8B;AAC1D,QAAM,UAAU,OAAO,IAAI,KAAK;AAChC,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,SAAwB;AAC5B,aAAW,OAAO,QAAQ,QAAQ;AAChC,QAAI,WAAW,QAAQ,MAAM,OAAQ,UAAS;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAiC;;AACxD,QAAM,MAAM,cAAc,KAAK;AAC/B,SAAO,QAAQ,OAAO,SAAQ,YAAO,IAAI,KAAK,MAAhB,mBAAmB,IAAI,SAAQ;AAC/D;AAEA,SAAS,UAAU,UAAkC;AACnD,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AAAA,EAC3B;AACF;AAEA,MAAM,aAAa,MAAM;AAGlB,SAAS,eAAuB;AACrC,SAAOA,MAAAA,WAAWC,gBAAAA,qBAAqB,KAAK;AAC9C;AAOO,SAAS,oBAAoB,OAAe,KAAsB;AAChDC,6BAAqB,WAAW,YAAY,UAAU;AAE7E,QAAM,SAAS,cAAc,KAAK;AAClC,SAAO,WAAW,QAAQ,WAAW;AACvC;AAcO,SAAS,oBAA2C;AACzD,QAAM,QAAQ,aAAA;AACSA,6BAAqB,WAAW,YAAY,UAAU;AAE7E,QAAM,QAAQ,gBAAgB,KAAK;AACnC,SAAO,QAAQ,EAAE,MAAM,MAAM,MAAM,WAAW,MAAM,cAAc;AACpE;;;;;;;;;"}
1
+ {"version":3,"file":"todo-plan-store.cjs","sources":["../../src/tools/todo-plan-store.ts"],"sourcesContent":["/**\n * Live registry of mounted `write_todos` cards — the newest one wins.\n *\n * A run updates its plan by calling `write_todos` repeatedly, and every call\n * renders its own card, so a conversation stacks \"Plan in progress / Plan\n * complete\" cards that all describe the same plan. The registry tracks the\n * mounted cards in mount order (the thread renders messages top-down, so the\n * newest call mounts last); {@link WriteTodosToolUI} renders the full card\n * only for the newest instance and nothing for superseded ones.\n *\n * Scoped by thread id (from `AthenaThreadIdContext`): a page hosting several\n * chats ranks each conversation's cards separately, so one chat's plan never\n * suppresses another's. Two views of the SAME thread share a scope, which is\n * the correct behavior — they show the same plan.\n *\n * Instance-scoped sequence numbers, not callId-scoped: reopening a thread\n * mounts fresh instances with fresh sequence numbers, so \"newest\" always\n * resolves within what is currently on screen.\n *\n * Hosts that want a pinned plan strip instead of the inline card should\n * register {@link HiddenWriteTodosToolUI} (which feeds this registry and\n * renders nothing) and read {@link useLatestTodoPlan}.\n */\nimport { useContext, useSyncExternalStore } from \"react\";\nimport { AthenaThreadIdContext } from \"../threads/thread-id-context\";\nimport type { TodoPlan } from \"./write-todos-tool-ui\";\n\ninterface PlanEntry {\n seq: number;\n plan: TodoPlan;\n isWriting: boolean;\n}\n\nconst DEFAULT_SCOPE = \"default\";\n\nlet nextSeq = 1;\nconst scopes = new Map<string, Map<number, PlanEntry>>();\nconst listeners = new Set<() => void>();\nlet version = 0;\n\nfunction emit(): void {\n version++;\n for (const listener of listeners) listener();\n}\n\nfunction scopeEntries(scope: string): Map<number, PlanEntry> {\n let entries = scopes.get(scope);\n if (!entries) {\n entries = new Map();\n scopes.set(scope, entries);\n }\n return entries;\n}\n\n/** Allocate a mount-ordered sequence number (pure counter — safe to discard). */\nexport function allocatePlanSeq(): number {\n return nextSeq++;\n}\n\nexport function registerPlanCard(\n scope: string,\n seq: number,\n plan: TodoPlan,\n isWriting: boolean,\n): void {\n scopeEntries(scope).set(seq, { seq, plan, isWriting });\n emit();\n}\n\nexport function updatePlanCard(\n scope: string,\n seq: number,\n plan: TodoPlan,\n isWriting: boolean,\n): void {\n const entry = scopes.get(scope)?.get(seq);\n if (!entry) return;\n entry.plan = plan;\n entry.isWriting = isWriting;\n emit();\n}\n\nexport function unregisterPlanCard(scope: string, seq: number): void {\n const entries = scopes.get(scope);\n if (!entries) return;\n if (entries.delete(seq)) {\n if (entries.size === 0) scopes.delete(scope);\n emit();\n }\n}\n\nexport function latestPlanSeq(scope: string): number | null {\n const entries = scopes.get(scope);\n if (!entries) return null;\n let latest: number | null = null;\n for (const seq of entries.keys()) {\n if (latest === null || seq > latest) latest = seq;\n }\n return latest;\n}\n\nfunction latestPlanEntry(scope: string): PlanEntry | null {\n const seq = latestPlanSeq(scope);\n return seq === null ? null : (scopes.get(scope)?.get(seq) ?? null);\n}\n\nfunction subscribe(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nconst getVersion = () => version;\n\n/** The plan scope for the calling component's chat (its thread id). */\nexport function usePlanScope(): string {\n return useContext(AthenaThreadIdContext) ?? DEFAULT_SCOPE;\n}\n\n/**\n * Whether the card with this sequence number is the newest mounted plan card\n * in its scope. On the server (and before client effects have registered any\n * card) every card reports latest, so static renders still show the plan.\n */\nexport function useIsLatestPlanCard(scope: string, seq: number): boolean {\n const currentVersion = useSyncExternalStore(subscribe, getVersion, getVersion);\n void currentVersion; // subscription tick — the value itself is not meaningful\n const latest = latestPlanSeq(scope);\n return latest === null || latest === seq;\n}\n\nexport interface LatestTodoPlan {\n plan: TodoPlan;\n /** True while the newest plan card's tool call is still streaming. */\n isWriting: boolean;\n}\n\n/**\n * The newest mounted plan for the calling chat, for hosts building their own\n * pinned plan UI. Pair with `toolUIs={{ write_todos: HiddenWriteTodosToolUI }}`\n * — that component keeps feeding this registry while rendering nothing inline\n * (a bare `() => null` override would starve it).\n */\nexport function useLatestTodoPlan(): LatestTodoPlan | null {\n const scope = usePlanScope();\n const currentVersion = useSyncExternalStore(subscribe, getVersion, getVersion);\n void currentVersion;\n const entry = latestPlanEntry(scope);\n return entry ? { plan: entry.plan, isWriting: entry.isWriting } : null;\n}\n\n/** Test-only: reset module state between cases. */\nexport function resetTodoPlanStoreForTests(): void {\n nextSeq = 1;\n scopes.clear();\n version = 0;\n}\n"],"names":["useContext","AthenaThreadIdContext","useSyncExternalStore"],"mappings":";;;;AAiCA,MAAM,gBAAgB;AAEtB,IAAI,UAAU;AACd,MAAM,6BAAa,IAAA;AACnB,MAAM,gCAAgB,IAAA;AACtB,IAAI,UAAU;AAEd,SAAS,OAAa;AACpB;AACA,aAAW,YAAY,UAAW,UAAA;AACpC;AAEA,SAAS,aAAa,OAAuC;AAC3D,MAAI,UAAU,OAAO,IAAI,KAAK;AAC9B,MAAI,CAAC,SAAS;AACZ,kCAAc,IAAA;AACd,WAAO,IAAI,OAAO,OAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAGO,SAAS,kBAA0B;AACxC,SAAO;AACT;AAEO,SAAS,iBACd,OACA,KACA,MACA,WACM;AACN,eAAa,KAAK,EAAE,IAAI,KAAK,EAAE,KAAK,MAAM,WAAW;AACrD,OAAA;AACF;AAEO,SAAS,eACd,OACA,KACA,MACA,WACM;;AACN,QAAM,SAAQ,YAAO,IAAI,KAAK,MAAhB,mBAAmB,IAAI;AACrC,MAAI,CAAC,MAAO;AACZ,QAAM,OAAO;AACb,QAAM,YAAY;AAClB,OAAA;AACF;AAEO,SAAS,mBAAmB,OAAe,KAAmB;AACnE,QAAM,UAAU,OAAO,IAAI,KAAK;AAChC,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,OAAO,GAAG,GAAG;AACvB,QAAI,QAAQ,SAAS,EAAG,QAAO,OAAO,KAAK;AAC3C,SAAA;AAAA,EACF;AACF;AAEO,SAAS,cAAc,OAA8B;AAC1D,QAAM,UAAU,OAAO,IAAI,KAAK;AAChC,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,SAAwB;AAC5B,aAAW,OAAO,QAAQ,QAAQ;AAChC,QAAI,WAAW,QAAQ,MAAM,OAAQ,UAAS;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAiC;;AACxD,QAAM,MAAM,cAAc,KAAK;AAC/B,SAAO,QAAQ,OAAO,SAAQ,YAAO,IAAI,KAAK,MAAhB,mBAAmB,IAAI,SAAQ;AAC/D;AAEA,SAAS,UAAU,UAAkC;AACnD,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AAAA,EAC3B;AACF;AAEA,MAAM,aAAa,MAAM;AAGlB,SAAS,eAAuB;AACrC,SAAOA,WAAAA,WAAWC,gBAAAA,qBAAqB,KAAK;AAC9C;AAOO,SAAS,oBAAoB,OAAe,KAAsB;AAChDC,kCAAqB,WAAW,YAAY,UAAU;AAE7E,QAAM,SAAS,cAAc,KAAK;AAClC,SAAO,WAAW,QAAQ,WAAW;AACvC;AAcO,SAAS,oBAA2C;AACzD,QAAM,QAAQ,aAAA;AACSA,kCAAqB,WAAW,YAAY,UAAU;AAE7E,QAAM,QAAQ,gBAAgB,KAAK;AACnC,SAAO,QAAQ,EAAE,MAAM,MAAM,MAAM,WAAW,MAAM,cAAc;AACpE;;;;;;;;;"}
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
4
- const ToolAppearanceContext = react.createContext(null);
3
+ const require$$0 = require("react");
4
+ const ToolAppearanceContext = require$$0.createContext(null);
5
5
  function useToolAppearance(explicit) {
6
- const fromContext = react.useContext(ToolAppearanceContext);
6
+ const fromContext = require$$0.useContext(ToolAppearanceContext);
7
7
  return explicit ?? (fromContext == null ? void 0 : fromContext.appearance) ?? "card";
8
8
  }
9
9
  exports.ToolAppearanceContext = ToolAppearanceContext;