@athenaintel/react 0.43.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (661) hide show
  1. package/README.md +215 -3
  2. package/dist/agent-runtime/src/answer-label.cjs +137 -0
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
  4. package/dist/agent-runtime/src/answer-label.d.ts +104 -0
  5. package/dist/agent-runtime/src/answer-label.js +137 -0
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -0
  7. package/dist/agent-runtime/src/answer-rows.cjs +180 -0
  8. package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
  9. package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
  10. package/dist/agent-runtime/src/answer-rows.js +180 -0
  11. package/dist/agent-runtime/src/answer-rows.js.map +1 -0
  12. package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
  13. package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
  14. package/dist/agent-runtime/src/conversation-index.cjs +8 -8
  15. package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
  16. package/dist/agent-runtime/src/decision-checks.cjs +207 -0
  17. package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
  18. package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
  19. package/dist/agent-runtime/src/decision-checks.js +207 -0
  20. package/dist/agent-runtime/src/decision-checks.js.map +1 -0
  21. package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
  22. package/dist/agent-runtime/src/errors.cjs +18 -0
  23. package/dist/agent-runtime/src/errors.cjs.map +1 -1
  24. package/dist/agent-runtime/src/errors.d.ts +7 -0
  25. package/dist/agent-runtime/src/errors.js +18 -0
  26. package/dist/agent-runtime/src/errors.js.map +1 -1
  27. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
  28. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  29. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
  30. package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
  31. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  32. package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
  33. package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
  34. package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
  35. package/dist/agent-runtime/src/handoff-arrival.js +60 -0
  36. package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
  37. package/dist/agent-runtime/src/index.d.ts +14 -8
  38. package/dist/agent-runtime/src/interrupts.cjs +43 -18
  39. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  40. package/dist/agent-runtime/src/interrupts.d.ts +19 -2
  41. package/dist/agent-runtime/src/interrupts.js +28 -3
  42. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  43. package/dist/agent-runtime/src/lane-history.cjs +8 -8
  44. package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
  45. package/dist/agent-runtime/src/messages.cjs +43 -8
  46. package/dist/agent-runtime/src/messages.cjs.map +1 -1
  47. package/dist/agent-runtime/src/messages.d.ts +25 -3
  48. package/dist/agent-runtime/src/messages.js +43 -8
  49. package/dist/agent-runtime/src/messages.js.map +1 -1
  50. package/dist/agent-runtime/src/offline-status.cjs +36 -0
  51. package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
  52. package/dist/agent-runtime/src/offline-status.d.ts +118 -3
  53. package/dist/agent-runtime/src/offline-status.js +36 -0
  54. package/dist/agent-runtime/src/offline-status.js.map +1 -0
  55. package/dist/agent-runtime/src/queue.cjs +0 -9
  56. package/dist/agent-runtime/src/queue.cjs.map +1 -1
  57. package/dist/agent-runtime/src/queue.js +0 -9
  58. package/dist/agent-runtime/src/queue.js.map +1 -1
  59. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
  60. package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  61. package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
  62. package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
  63. package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
  64. package/dist/agent-runtime/src/runtime-catalog.js +42 -0
  65. package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
  66. package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
  67. package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
  68. package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
  69. package/dist/agent-runtime/src/runtime.d.ts +40 -0
  70. package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
  71. package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  72. package/dist/agent-runtime/src/subagents.cjs +32 -2
  73. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  74. package/dist/agent-runtime/src/subagents.d.ts +9 -0
  75. package/dist/agent-runtime/src/subagents.js +30 -0
  76. package/dist/agent-runtime/src/subagents.js.map +1 -1
  77. package/dist/agent-runtime/src/thread-driver.cjs +67 -0
  78. package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
  79. package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
  80. package/dist/agent-runtime/src/thread-driver.js +67 -0
  81. package/dist/agent-runtime/src/thread-driver.js.map +1 -0
  82. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
  83. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
  84. package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
  85. package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
  86. package/dist/agent-runtime/src/thread-status.cjs +3 -3
  87. package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
  88. package/dist/agent-runtime/src/tool-metadata.cjs +210 -25
  89. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  90. package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
  91. package/dist/agent-runtime/src/tool-metadata.js +210 -25
  92. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  93. package/dist/agent-runtime/src/tool-names.cjs +2 -0
  94. package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
  95. package/dist/agent-runtime/src/tool-names.d.ts +2 -0
  96. package/dist/agent-runtime/src/tool-names.js +2 -0
  97. package/dist/agent-runtime/src/tool-names.js.map +1 -1
  98. package/dist/agent-runtime/src/types.d.ts +10 -2
  99. package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
  100. package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
  101. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
  102. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
  103. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +2 -1
  104. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
  105. package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
  106. package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
  107. package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
  108. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
  109. package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  110. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
  111. package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
  112. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
  113. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  114. package/dist/agent-runtime/src/use-deep-agent-voice.cjs +547 -124
  115. package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
  116. package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +129 -10
  117. package/dist/agent-runtime/src/use-deep-agent-voice.js +487 -64
  118. package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
  119. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
  120. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  121. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
  122. package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
  123. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
  124. package/dist/agent-runtime/src/voice-media.cjs +117 -0
  125. package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
  126. package/dist/agent-runtime/src/voice-media.d.ts +49 -0
  127. package/dist/agent-runtime/src/voice-media.js +117 -0
  128. package/dist/agent-runtime/src/voice-media.js.map +1 -0
  129. package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
  130. package/dist/assets/AssetPanel.cjs +11 -11
  131. package/dist/assets/AssetPanel.cjs.map +1 -1
  132. package/dist/assets/AthenaAssetEmbed.cjs +11 -9
  133. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  134. package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
  135. package/dist/assets/AthenaAssetEmbed.js +4 -2
  136. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  137. package/dist/assets/AthenaLayout.cjs +16 -16
  138. package/dist/assets/AthenaLayout.cjs.map +1 -1
  139. package/dist/assets/use-asset-content.cjs +4 -4
  140. package/dist/assets/use-asset-content.cjs.map +1 -1
  141. package/dist/assets/use-asset-embed.cjs +14 -7
  142. package/dist/assets/use-asset-embed.cjs.map +1 -1
  143. package/dist/assets/use-asset-embed.d.ts +11 -1
  144. package/dist/assets/use-asset-embed.js +10 -3
  145. package/dist/assets/use-asset-embed.js.map +1 -1
  146. package/dist/auth/AthenaAuthContext.cjs +3 -3
  147. package/dist/auth/AthenaAuthContext.cjs.map +1 -1
  148. package/dist/auth/AthenaAuthProvider.cjs +8 -8
  149. package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
  150. package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
  151. package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
  152. package/dist/auth/AthenaSSOProvider.cjs +14 -14
  153. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  154. package/dist/auth/credential-source.cjs +26 -13
  155. package/dist/auth/credential-source.cjs.map +1 -1
  156. package/dist/auth/credential-source.d.ts +8 -0
  157. package/dist/auth/credential-source.js +26 -13
  158. package/dist/auth/credential-source.js.map +1 -1
  159. package/dist/catalog/agent-model-options.cjs +25 -17
  160. package/dist/catalog/agent-model-options.cjs.map +1 -1
  161. package/dist/catalog/agent-model-options.d.ts +38 -5
  162. package/dist/catalog/agent-model-options.js +25 -17
  163. package/dist/catalog/agent-model-options.js.map +1 -1
  164. package/dist/catalog/channel-refusal.cjs +36 -0
  165. package/dist/catalog/channel-refusal.cjs.map +1 -0
  166. package/dist/catalog/channel-refusal.d.ts +29 -0
  167. package/dist/catalog/channel-refusal.js +36 -0
  168. package/dist/catalog/channel-refusal.js.map +1 -0
  169. package/dist/catalog/chat-pickers.cjs +60 -24
  170. package/dist/catalog/chat-pickers.cjs.map +1 -1
  171. package/dist/catalog/chat-pickers.d.ts +12 -2
  172. package/dist/catalog/chat-pickers.js +56 -20
  173. package/dist/catalog/chat-pickers.js.map +1 -1
  174. package/dist/catalog/runtime-catalog.cjs +89 -23
  175. package/dist/catalog/runtime-catalog.cjs.map +1 -1
  176. package/dist/catalog/runtime-catalog.d.ts +8 -2
  177. package/dist/catalog/runtime-catalog.js +83 -17
  178. package/dist/catalog/runtime-catalog.js.map +1 -1
  179. package/dist/catalog/use-athena-chat-mode.cjs +12 -12
  180. package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
  181. package/dist/chat/AthenaChat.cjs +155 -67
  182. package/dist/chat/AthenaChat.cjs.map +1 -1
  183. package/dist/chat/AthenaChat.d.ts +42 -2
  184. package/dist/chat/AthenaChat.js +106 -18
  185. package/dist/chat/AthenaChat.js.map +1 -1
  186. package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
  187. package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
  188. package/dist/chat/DrivingOnChip.cjs +23 -0
  189. package/dist/chat/DrivingOnChip.cjs.map +1 -0
  190. package/dist/chat/DrivingOnChip.d.ts +17 -0
  191. package/dist/chat/DrivingOnChip.js +23 -0
  192. package/dist/chat/DrivingOnChip.js.map +1 -0
  193. package/dist/chat/StatewireApprovalCard.cjs +125 -31
  194. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  195. package/dist/chat/StatewireApprovalCard.d.ts +73 -1
  196. package/dist/chat/StatewireApprovalCard.js +115 -21
  197. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  198. package/dist/chat/StatewireClientToolBridge.cjs +2 -2
  199. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  200. package/dist/chat/StatewireQueuedMessages.cjs +25 -63
  201. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  202. package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
  203. package/dist/chat/StatewireQueuedMessages.js +16 -54
  204. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  205. package/dist/chat/WaitingOnYouBanner.cjs +3 -3
  206. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
  207. package/dist/chat/athena-chat-welcome.cjs +2 -2
  208. package/dist/chat/athena-chat-welcome.cjs.map +1 -1
  209. package/dist/chat/athena-citation-links.cjs +5 -5
  210. package/dist/chat/athena-citation-links.cjs.map +1 -1
  211. package/dist/chat/athena-composer-controls.cjs +26 -16
  212. package/dist/chat/athena-composer-controls.cjs.map +1 -1
  213. package/dist/chat/athena-composer-controls.d.ts +6 -0
  214. package/dist/chat/athena-composer-controls.js +26 -16
  215. package/dist/chat/athena-composer-controls.js.map +1 -1
  216. package/dist/chat/athena-turn-end-status.cjs +42 -0
  217. package/dist/chat/athena-turn-end-status.cjs.map +1 -0
  218. package/dist/chat/athena-turn-end-status.d.ts +24 -0
  219. package/dist/chat/athena-turn-end-status.js +42 -0
  220. package/dist/chat/athena-turn-end-status.js.map +1 -0
  221. package/dist/chat/browser-decision-check.cjs +131 -0
  222. package/dist/chat/browser-decision-check.cjs.map +1 -0
  223. package/dist/chat/browser-decision-check.d.ts +61 -0
  224. package/dist/chat/browser-decision-check.js +131 -0
  225. package/dist/chat/browser-decision-check.js.map +1 -0
  226. package/dist/chat/chat-outbox-rows.cjs +3 -3
  227. package/dist/chat/chat-outbox-rows.cjs.map +1 -1
  228. package/dist/chat/chat-voice-controls.cjs +93 -28
  229. package/dist/chat/chat-voice-controls.cjs.map +1 -1
  230. package/dist/chat/chat-voice-controls.d.ts +36 -2
  231. package/dist/chat/chat-voice-controls.js +89 -24
  232. package/dist/chat/chat-voice-controls.js.map +1 -1
  233. package/dist/chat/composer-keyboard-hint.cjs +5 -5
  234. package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
  235. package/dist/chat/device-operation.cjs +29 -0
  236. package/dist/chat/device-operation.cjs.map +1 -0
  237. package/dist/chat/device-operation.d.ts +34 -0
  238. package/dist/chat/device-operation.js +29 -0
  239. package/dist/chat/device-operation.js.map +1 -0
  240. package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
  241. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  242. package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
  243. package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
  244. package/dist/chat/super-grouping/SuperGroupingCard.cjs +52 -36
  245. package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
  246. package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
  247. package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
  248. package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
  249. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
  250. package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
  251. package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
  252. package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
  253. package/dist/chat/super-grouping/ToolTimeline.cjs +73 -40
  254. package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
  255. package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
  256. package/dist/chat/super-grouping/ToolTimeline.js +69 -36
  257. package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
  258. package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
  259. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  260. package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
  261. package/dist/chat/super-grouping/activity-timeline.js +47 -12
  262. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  263. package/dist/chat/super-grouping/grouping-function.cjs +4 -0
  264. package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
  265. package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
  266. package/dist/chat/super-grouping/grouping-function.js +5 -1
  267. package/dist/chat/super-grouping/grouping-function.js.map +1 -1
  268. package/dist/chat/super-grouping/index.cjs +6 -0
  269. package/dist/chat/super-grouping/index.cjs.map +1 -1
  270. package/dist/chat/super-grouping/index.d.ts +5 -2
  271. package/dist/chat/super-grouping/index.js +7 -1
  272. package/dist/chat/super-grouping/index.js.map +1 -1
  273. package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
  274. package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
  275. package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
  276. package/dist/chat/super-grouping/tool-part-placement.js +17 -0
  277. package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
  278. package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
  279. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
  280. package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
  281. package/dist/chat/thread-scroll-to-bottom.js +2 -2
  282. package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
  283. package/dist/chat/tooltip-icon-button.cjs +2 -2
  284. package/dist/chat/tooltip-icon-button.cjs.map +1 -1
  285. package/dist/chat/use-athena-voice-live.cjs +11 -0
  286. package/dist/chat/use-athena-voice-live.cjs.map +1 -0
  287. package/dist/chat/use-athena-voice-live.d.ts +11 -0
  288. package/dist/chat/use-athena-voice-live.js +11 -0
  289. package/dist/chat/use-athena-voice-live.js.map +1 -0
  290. package/dist/chat/use-statewire-approval-request.cjs +56 -24
  291. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  292. package/dist/chat/use-statewire-approval-request.d.ts +33 -4
  293. package/dist/chat/use-statewire-approval-request.js +41 -9
  294. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  295. package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
  296. package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
  297. package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
  298. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  299. package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
  300. package/dist/chat-ui/composer/tiptap-composer.js +85 -54
  301. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  302. package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
  303. package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
  304. package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
  305. package/dist/chat-ui/header/conversation-history-panel.js +38 -12
  306. package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
  307. package/dist/chat-ui/index.cjs +18 -0
  308. package/dist/chat-ui/index.cjs.map +1 -1
  309. package/dist/chat-ui/index.d.ts +7 -1
  310. package/dist/chat-ui/index.js +18 -0
  311. package/dist/chat-ui/index.js.map +1 -1
  312. package/dist/chat-ui/mentions/mention-chip.cjs +4 -4
  313. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  314. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
  315. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
  316. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
  317. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
  318. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
  319. package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
  320. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
  321. package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
  322. package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
  323. package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
  324. package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
  325. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
  326. package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
  327. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
  328. package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
  329. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
  330. package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
  331. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
  332. package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
  333. package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
  334. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
  335. package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
  336. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
  337. package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
  338. package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
  339. package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
  340. package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
  341. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
  342. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
  343. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
  344. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
  345. package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
  346. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
  347. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
  348. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
  349. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
  350. package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
  351. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
  352. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  353. package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
  354. package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
  355. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  356. package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
  357. package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
  358. package/dist/chat-ui/mentions/use-mention-asset.cjs +3 -3
  359. package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
  360. package/dist/chat-ui/messages/answer-label.cjs +42 -0
  361. package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
  362. package/dist/chat-ui/messages/answer-label.d.ts +33 -0
  363. package/dist/chat-ui/messages/answer-label.js +42 -0
  364. package/dist/chat-ui/messages/answer-label.js.map +1 -0
  365. package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
  366. package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
  367. package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
  368. package/dist/chat-ui/messages/arrival-animation.js +13 -0
  369. package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
  370. package/dist/chat-ui/messages/continue-pill.cjs +5 -5
  371. package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
  372. package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
  373. package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
  374. package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
  375. package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
  376. package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
  377. package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
  378. package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
  379. package/dist/chat-ui/messages/message-components.cjs +8 -4
  380. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  381. package/dist/chat-ui/messages/message-components.js +5 -1
  382. package/dist/chat-ui/messages/message-components.js.map +1 -1
  383. package/dist/chat-ui/messages/message-images.cjs +66 -0
  384. package/dist/chat-ui/messages/message-images.cjs.map +1 -0
  385. package/dist/chat-ui/messages/message-images.d.ts +16 -0
  386. package/dist/chat-ui/messages/message-images.js +66 -0
  387. package/dist/chat-ui/messages/message-images.js.map +1 -0
  388. package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
  389. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  390. package/dist/chat-ui/messages/wake-marker.cjs +3 -3
  391. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
  392. package/dist/chat-ui/rich-text/chat-link.cjs +2 -2
  393. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
  394. package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
  395. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  396. package/dist/chat-ui/rich-text/chat-node-views.cjs +6 -6
  397. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  398. package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
  399. package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
  400. package/dist/chat-ui/statewire.cjs +3 -0
  401. package/dist/chat-ui/statewire.cjs.map +1 -1
  402. package/dist/chat-ui/statewire.d.ts +2 -1
  403. package/dist/chat-ui/statewire.js +3 -0
  404. package/dist/chat-ui/statewire.js.map +1 -1
  405. package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
  406. package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
  407. package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
  408. package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
  409. package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
  410. package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
  411. package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
  412. package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
  413. package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
  414. package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
  415. package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
  416. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  417. package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
  418. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  419. package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
  420. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
  421. package/dist/collab/client.cjs +40 -3
  422. package/dist/collab/client.cjs.map +1 -1
  423. package/dist/collab/client.d.ts +25 -0
  424. package/dist/collab/client.js +40 -3
  425. package/dist/collab/client.js.map +1 -1
  426. package/dist/collab/document-status.cjs +150 -0
  427. package/dist/collab/document-status.cjs.map +1 -0
  428. package/dist/collab/document-status.d.ts +68 -0
  429. package/dist/collab/document-status.js +150 -0
  430. package/dist/collab/document-status.js.map +1 -0
  431. package/dist/collab/index.cjs +7 -0
  432. package/dist/collab/index.cjs.map +1 -1
  433. package/dist/collab/index.d.ts +6 -1
  434. package/dist/collab/index.js +7 -0
  435. package/dist/collab/index.js.map +1 -1
  436. package/dist/collab/presence-react.cjs +11 -11
  437. package/dist/collab/presence-react.cjs.map +1 -1
  438. package/dist/collab/react.cjs +6 -6
  439. package/dist/collab/react.cjs.map +1 -1
  440. package/dist/composer/AttachmentContext.cjs +24 -11
  441. package/dist/composer/AttachmentContext.cjs.map +1 -1
  442. package/dist/composer/AttachmentContext.js +18 -5
  443. package/dist/composer/AttachmentContext.js.map +1 -1
  444. package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
  445. package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
  446. package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
  447. package/dist/composer/ComposerAttachmentPreview.js +79 -24
  448. package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
  449. package/dist/composer/ComposerDropZone.cjs +7 -7
  450. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  451. package/dist/composer/FileUploadButton.cjs +37 -22
  452. package/dist/composer/FileUploadButton.cjs.map +1 -1
  453. package/dist/composer/FileUploadButton.d.ts +6 -0
  454. package/dist/composer/FileUploadButton.js +34 -19
  455. package/dist/composer/FileUploadButton.js.map +1 -1
  456. package/dist/composer/QuoteContext.cjs +8 -8
  457. package/dist/composer/QuoteContext.cjs.map +1 -1
  458. package/dist/composer/composer-handoff.cjs +4 -4
  459. package/dist/composer/composer-handoff.cjs.map +1 -1
  460. package/dist/composer/useAppendToComposer.cjs +4 -4
  461. package/dist/composer/useAppendToComposer.cjs.map +1 -1
  462. package/dist/composer/useAttachFiles.cjs +23 -6
  463. package/dist/composer/useAttachFiles.cjs.map +1 -1
  464. package/dist/composer/useAttachFiles.d.ts +15 -7
  465. package/dist/composer/useAttachFiles.js +22 -5
  466. package/dist/composer/useAttachFiles.js.map +1 -1
  467. package/dist/composer/useComposerAttachment.cjs +4 -4
  468. package/dist/composer/useComposerAttachment.cjs.map +1 -1
  469. package/dist/composer/useFileUpload.cjs +21 -16
  470. package/dist/composer/useFileUpload.cjs.map +1 -1
  471. package/dist/composer/useFileUpload.d.ts +12 -0
  472. package/dist/composer/useFileUpload.js +12 -7
  473. package/dist/composer/useFileUpload.js.map +1 -1
  474. package/dist/composer/useReadComposerDraft.cjs +2 -2
  475. package/dist/composer/useReadComposerDraft.cjs.map +1 -1
  476. package/dist/composer/useSendMessage.cjs +4 -4
  477. package/dist/composer/useSendMessage.cjs.map +1 -1
  478. package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
  479. package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
  480. package/dist/dictation/audio-level-history.cjs +3 -3
  481. package/dist/dictation/audio-level-history.cjs.map +1 -1
  482. package/dist/dictation/dictation-controls.cjs +24 -20
  483. package/dist/dictation/dictation-controls.cjs.map +1 -1
  484. package/dist/dictation/dictation-controls.d.ts +6 -1
  485. package/dist/dictation/dictation-controls.js +24 -20
  486. package/dist/dictation/dictation-controls.js.map +1 -1
  487. package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
  488. package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
  489. package/dist/dictation/use-dictation.cjs +22 -22
  490. package/dist/dictation/use-dictation.cjs.map +1 -1
  491. package/dist/index.cjs +26 -2
  492. package/dist/index.cjs.map +1 -1
  493. package/dist/index.d.ts +15 -3
  494. package/dist/index.js +26 -2
  495. package/dist/index.js.map +1 -1
  496. package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
  497. package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
  498. package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
  499. package/dist/keryx-http/src/receive-only-socket.js +40 -0
  500. package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
  501. package/dist/keryx-http/src/update-attributions.cjs +111 -0
  502. package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
  503. package/dist/keryx-http/src/update-attributions.d.ts +75 -0
  504. package/dist/keryx-http/src/update-attributions.js +111 -0
  505. package/dist/keryx-http/src/update-attributions.js.map +1 -0
  506. package/dist/lib/owner-document.cjs +6 -6
  507. package/dist/lib/owner-document.cjs.map +1 -1
  508. package/dist/lib/use-athena-rest-query.cjs +4 -4
  509. package/dist/lib/use-athena-rest-query.cjs.map +1 -1
  510. package/dist/lib/use-document-active.cjs +4 -4
  511. package/dist/lib/use-document-active.cjs.map +1 -1
  512. package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
  513. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
  514. package/dist/offline/offline-history.cjs +7 -7
  515. package/dist/offline/offline-history.cjs.map +1 -1
  516. package/dist/provider/AthenaContext.cjs +3 -3
  517. package/dist/provider/AthenaContext.cjs.map +1 -1
  518. package/dist/provider/AthenaProvider.cjs +116 -79
  519. package/dist/provider/AthenaProvider.cjs.map +1 -1
  520. package/dist/provider/AthenaProvider.js +40 -3
  521. package/dist/provider/AthenaProvider.js.map +1 -1
  522. package/dist/provider/PostHogProvider.cjs +2 -2
  523. package/dist/provider/PostHogProvider.cjs.map +1 -1
  524. package/dist/provider/agent-selection-context.cjs +2 -2
  525. package/dist/provider/agent-selection-context.cjs.map +1 -1
  526. package/dist/provider/chat-mode-context.cjs +2 -2
  527. package/dist/provider/chat-mode-context.cjs.map +1 -1
  528. package/dist/provider/session-persistence-context.cjs +10 -0
  529. package/dist/provider/session-persistence-context.cjs.map +1 -0
  530. package/dist/provider/session-persistence-context.d.ts +15 -0
  531. package/dist/provider/session-persistence-context.js +10 -0
  532. package/dist/provider/session-persistence-context.js.map +1 -0
  533. package/dist/provider/statewire-history-context.cjs +4 -4
  534. package/dist/provider/statewire-history-context.cjs.map +1 -1
  535. package/dist/provider/statewire-lifecycle-context.cjs +3 -3
  536. package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
  537. package/dist/provider/statewire-window-context.cjs +3 -3
  538. package/dist/provider/statewire-window-context.cjs.map +1 -1
  539. package/dist/provider/theme-style-context.cjs +3 -3
  540. package/dist/provider/theme-style-context.cjs.map +1 -1
  541. package/dist/react/package.json.cjs +1 -1
  542. package/dist/react/package.json.js +1 -1
  543. package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
  544. package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
  545. package/dist/runtime/auth-refusal-restart.cjs +7 -7
  546. package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
  547. package/dist/runtime/auth.cjs +13 -13
  548. package/dist/runtime/auth.cjs.map +1 -1
  549. package/dist/runtime/statewire-lifecycle.cjs +1 -0
  550. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  551. package/dist/runtime/statewire-lifecycle.d.ts +3 -1
  552. package/dist/runtime/statewire-lifecycle.js +2 -1
  553. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  554. package/dist/runtime/statewire-server-lane-context.cjs +2 -2
  555. package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
  556. package/dist/runtime/statewire-session-lane.cjs +4 -4
  557. package/dist/runtime/statewire-session-lane.cjs.map +1 -1
  558. package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
  559. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  560. package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
  561. package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
  562. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  563. package/dist/styles.css +1 -1
  564. package/dist/threads/Inbox.cjs +8 -8
  565. package/dist/threads/Inbox.cjs.map +1 -1
  566. package/dist/threads/SessionList.cjs +9 -9
  567. package/dist/threads/SessionList.cjs.map +1 -1
  568. package/dist/threads/SessionsPage.cjs +11 -11
  569. package/dist/threads/SessionsPage.cjs.map +1 -1
  570. package/dist/threads/index-triggered-refresh.cjs +10 -10
  571. package/dist/threads/index-triggered-refresh.cjs.map +1 -1
  572. package/dist/threads/mark-viewed-thread-read.cjs +12 -12
  573. package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
  574. package/dist/threads/offline-session-list.cjs +3 -3
  575. package/dist/threads/offline-session-list.cjs.map +1 -1
  576. package/dist/threads/session-list-tab-share.cjs +5 -5
  577. package/dist/threads/session-list-tab-share.cjs.map +1 -1
  578. package/dist/threads/statewire-thread-list.cjs +51 -51
  579. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  580. package/dist/threads/thread-id-context.cjs +5 -5
  581. package/dist/threads/thread-id-context.cjs.map +1 -1
  582. package/dist/threads/use-athena-session-attention.cjs +2 -2
  583. package/dist/threads/use-athena-session-attention.cjs.map +1 -1
  584. package/dist/threads/use-athena-sessions.cjs +10 -10
  585. package/dist/threads/use-athena-sessions.cjs.map +1 -1
  586. package/dist/threads/use-athena-thread-model.cjs +3 -3
  587. package/dist/threads/use-athena-thread-model.cjs.map +1 -1
  588. package/dist/threads/use-rest-conversation-history.cjs +3 -3
  589. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  590. package/dist/threads/use-statewire-conversation-history.cjs +8 -8
  591. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  592. package/dist/threads/use-thread-archive.cjs +9 -9
  593. package/dist/threads/use-thread-archive.cjs.map +1 -1
  594. package/dist/threads/use-thread-favorite.cjs +2 -2
  595. package/dist/threads/use-thread-favorite.cjs.map +1 -1
  596. package/dist/threads/use-thread-field-override.cjs +20 -20
  597. package/dist/threads/use-thread-field-override.cjs.map +1 -1
  598. package/dist/threads/use-thread-read-state.cjs +4 -4
  599. package/dist/threads/use-thread-read-state.cjs.map +1 -1
  600. package/dist/threads/use-thread-rename.cjs +2 -2
  601. package/dist/threads/use-thread-rename.cjs.map +1 -1
  602. package/dist/threads/useAthenaThreadManager.cjs +2 -2
  603. package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
  604. package/dist/tools/NestedPtcMessages.cjs +6 -6
  605. package/dist/tools/NestedPtcMessages.cjs.map +1 -1
  606. package/dist/tools/append-document-tool-ui.cjs +7 -7
  607. package/dist/tools/append-document-tool-ui.cjs.map +1 -1
  608. package/dist/tools/file-tool-uis.cjs +2 -2
  609. package/dist/tools/file-tool-uis.cjs.map +1 -1
  610. package/dist/tools/misc-tool-uis.cjs +2 -2
  611. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  612. package/dist/tools/primitives.cjs +6 -6
  613. package/dist/tools/primitives.cjs.map +1 -1
  614. package/dist/tools/read-asset-tool-ui.cjs +6 -6
  615. package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
  616. package/dist/tools/subagent-task-tool-ui.cjs +21 -21
  617. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  618. package/dist/tools/test-recording-tool-uis.cjs +16 -16
  619. package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
  620. package/dist/tools/todo-plan-store.cjs +4 -4
  621. package/dist/tools/todo-plan-store.cjs.map +1 -1
  622. package/dist/tools/tool-appearance.cjs +3 -3
  623. package/dist/tools/tool-appearance.cjs.map +1 -1
  624. package/dist/tools/tool-fallback.cjs +14 -14
  625. package/dist/tools/tool-fallback.cjs.map +1 -1
  626. package/dist/tools/tool-uis.cjs +74 -74
  627. package/dist/tools/tool-uis.cjs.map +1 -1
  628. package/dist/tools/use-elapsed-seconds.cjs +3 -3
  629. package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
  630. package/dist/tools/write-todos-tool-ui.cjs +9 -9
  631. package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
  632. package/dist/ui/image-viewer.cjs +382 -0
  633. package/dist/ui/image-viewer.cjs.map +1 -0
  634. package/dist/ui/image-viewer.d.ts +50 -0
  635. package/dist/ui/image-viewer.js +382 -0
  636. package/dist/ui/image-viewer.js.map +1 -0
  637. package/dist/voice/chat.cjs +6 -0
  638. package/dist/voice/chat.cjs.map +1 -1
  639. package/dist/voice/chat.d.ts +1 -1
  640. package/dist/voice/chat.js +8 -2
  641. package/dist/voice/livekit-join.cjs +52 -101
  642. package/dist/voice/livekit-join.cjs.map +1 -1
  643. package/dist/voice/livekit-join.d.ts +1 -6
  644. package/dist/voice/livekit-join.js +52 -101
  645. package/dist/voice/livekit-join.js.map +1 -1
  646. package/dist/voice/livekit.cjs.map +1 -1
  647. package/dist/voice/livekit.d.ts +11 -1
  648. package/dist/voice/livekit.js.map +1 -1
  649. package/dist/voice/use-athena-voice-session.cjs +34 -34
  650. package/dist/voice/use-athena-voice-session.cjs.map +1 -1
  651. package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
  652. package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
  653. package/dist/workbench/SessionWorkbench.cjs +22 -22
  654. package/dist/workbench/SessionWorkbench.cjs.map +1 -1
  655. package/dist/workbench/session-workbench-context.cjs +3 -3
  656. package/dist/workbench/session-workbench-context.cjs.map +1 -1
  657. package/dist/workbench/session-workbench-panes.cjs +8 -8
  658. package/dist/workbench/session-workbench-panes.cjs.map +1 -1
  659. package/dist/workbench/workbench-layout-context.cjs +3 -3
  660. package/dist/workbench/workbench-layout-context.cjs.map +1 -1
  661. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"activity-timeline.cjs","sources":["../../../src/chat/super-grouping/activity-timeline.ts"],"sourcesContent":["/**\n * The assistant turn's activity timeline — the one derivation of \"what did\n * this turn do, and how did each step end\" behind the collapsed view\n * (previously called the conversational view) on every surface: the SDK's\n * `AthenaChat`, Olympus's Spaces chat, and the Chrome extension. Pure\n * functions over assistant-ui message parts; `SuperGroupingCard` renders them.\n *\n * Step states come from the shared classifier (`classifyToolResult`) plus the\n * approval outcomes a part carries (`approval`, `interrupt`, a rejection\n * result), so a call that reads as failed, paused, or rejected on one surface\n * cannot read as a green check on another. Copy comes from the shared tool\n * summary registry (`summarizeToolCall`), itself built on the display\n * registry.\n */\nimport type {\n MessageStatus,\n ThreadAssistantMessagePart,\n ToolCallMessagePartStatus,\n} from '@assistant-ui/react';\nimport {\n classifyToolResult,\n isRunningToolPlaceholderArtifact,\n isSpokenTurnTextPart,\n readRejectedToolResult,\n type ToolStatusLabelState,\n} from '@athenaintel/agent-runtime';\nimport { summarizeToolCall, type ToolCallSummary } from '../../tools/tool-summary';\nimport type { GroupablePart, GroupingFunction } from './grouping-function';\n\nexport type ActivityToolState = ToolStatusLabelState;\n\nexport type ActivityItem =\n | {\n kind: 'reasoning';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n text: string;\n state: 'running' | 'complete';\n }\n | {\n kind: 'tool';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n toolName: string;\n args?: ToolCallPart['args'];\n /** The tool's real result; absent while it runs or holds only the streaming placeholder. */\n result?: unknown;\n state: ActivityToolState;\n };\n\n/** The turn as a whole: still working, parked on the person, ended in error, or done. */\nexport type ActivityPhase = 'running' | 'waiting' | 'complete' | 'error';\n\ntype ToolCallPart = Extract<ThreadAssistantMessagePart, { type: 'tool-call' }>;\n\nexport interface ActivityTimelineOptions {\n /**\n * Tools whose unresolved call means the turn is waiting on the person even\n * without an interrupt or approval on the part (the Chrome extension's\n * device plan approval, which the tool UI itself collects).\n */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id, as the host reads them off\n * its pending approval: a gated call, or (in Olympus) a `task` call whose\n * subagent waits on an approval. Any of them still without its real result\n * reads as waiting.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /**\n * Tools whose result is an application payload relayed verbatim (the Chrome\n * extension's page JavaScript), so a `success: false` flag counts only with\n * an error detail — see `classifyToolResult`'s `passThroughPayload`.\n */\n passThroughTools?: ReadonlySet<string>;\n}\n\nconst NO_TOOLS: ReadonlySet<string> = new Set();\nconst NO_TOOL_CALLS: ReadonlySet<string> = new Set();\n\n/**\n * Whether a tool-call part still holds the backend's running-tool placeholder\n * result rather than the tool's real output. Long-running tools (task\n * subagents, studio and Python execution, deep research) append a ToolMessage\n * the moment they start so their card can fill in live; its marker reaches the\n * part's artifact (`isRunningToolPlaceholderArtifact`). The real ToolMessage\n * that replaces it has no such marker, so a defined `result` alone does not\n * mean the tool is done.\n */\nexport function isStreamingToolPlaceholder(part: Pick<ToolCallPart, 'artifact'>): boolean {\n return isRunningToolPlaceholderArtifact(part.artifact);\n}\n\n/** The tool's real result: undefined while it has none or only the streaming placeholder. */\nfunction finalResult(part: ToolCallPart): unknown {\n return isStreamingToolPlaceholder(part) ? undefined : part.result;\n}\n\nfunction toolCallStatus(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n): ToolCallMessagePartStatus | undefined {\n if (finalResult(part) !== undefined) return { type: 'complete' };\n if (messageStatus?.type === 'incomplete') {\n return {\n type: 'incomplete',\n reason: messageStatus.reason === 'tool-calls' ? 'other' : messageStatus.reason,\n error: messageStatus.error,\n };\n }\n if (messageStatus?.type === 'complete') {\n // The placeholder is the backend's word that the call is still in flight.\n // A turn reads `complete` whenever nothing streams (a run parked on an\n // approval inside a subagent, the gap before a drained run resumes), and\n // assistant-ui counts the placeholder as the call's result when it settles\n // that status, so the turn's status cannot finish the call.\n return isStreamingToolPlaceholder(part) ? { type: 'running' } : { type: 'complete' };\n }\n if (messageStatus?.type === 'requires-action') {\n return { type: 'requires-action', reason: messageStatus.reason };\n }\n if (messageStatus?.type === 'running') return { type: 'running' };\n return undefined;\n}\n\n/** How one tool call ended (or is going), reading the approval fields before the result. */\nexport function getActivityToolState(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n {\n waitingTools = NO_TOOLS,\n waitingToolCallIds = NO_TOOL_CALLS,\n passThroughTools = NO_TOOLS,\n }: ActivityTimelineOptions = {},\n): ActivityToolState {\n if (part.approval?.approved === false || readRejectedToolResult(part.result) !== null) {\n return 'rejected';\n }\n if (part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired') {\n return 'cancelled';\n }\n const result = finalResult(part);\n const unresolved = result === undefined;\n const messageIsActive =\n messageStatus === undefined ||\n messageStatus.type === 'running' ||\n messageStatus.type === 'requires-action';\n if (\n unresolved &&\n (part.interrupt?.type === 'human' ||\n (part.approval !== undefined &&\n part.approval.approved === undefined &&\n part.approval.resolution === undefined) ||\n waitingToolCallIds.has(part.toolCallId) ||\n (waitingTools.has(part.toolName) && messageIsActive))\n ) {\n return 'waiting';\n }\n\n const classification = classifyToolResult({\n status: toolCallStatus(part, messageStatus),\n result,\n isError: part.isError,\n passThroughPayload: passThroughTools.has(part.toolName),\n });\n if (classification.state === 'requires-action') return 'waiting';\n return classification.state;\n}\n\n/**\n * The compact reasoning/tool timeline in the order the parts streamed.\n *\n * A reasoning part is still streaming only while it is the final part of a\n * running message — once any later part appears, the thought has settled.\n * Settled reasoning parts with no text are dropped so the list never shows an\n * empty thinking row.\n */\nexport function buildActivityTimeline(\n content: readonly ThreadAssistantMessagePart[] | undefined,\n messageStatus: MessageStatus | undefined,\n options: ActivityTimelineOptions = {},\n): ActivityItem[] {\n if (!content?.length) return [];\n\n const lastPartIndex = content.length - 1;\n const timeline: ActivityItem[] = [];\n for (let index = 0; index < content.length; index += 1) {\n const part = content[index];\n if (part.type === 'tool-call') {\n const result = finalResult(part);\n timeline.push({\n kind: 'tool',\n id: part.toolCallId,\n partIndex: index,\n args: part.args,\n ...(result !== undefined ? { result } : {}),\n toolName: part.toolName,\n state: getActivityToolState(part, messageStatus, options),\n });\n continue;\n }\n if (part.type !== 'reasoning') continue;\n\n const text = typeof part.text === 'string' ? part.text : '';\n const stillStreaming = messageStatus?.type === 'running' && index === lastPartIndex;\n if (!stillStreaming && text.trim() === '') continue;\n timeline.push({\n kind: 'reasoning',\n id: `reasoning-${index}`,\n partIndex: index,\n text,\n state: stillStreaming ? 'running' : 'complete',\n });\n }\n return timeline;\n}\n\n/** Number of tool calls in the timeline. */\nexport function countActivityTools(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => (item.kind === 'tool' ? count + 1 : count), 0);\n}\n\n/**\n * The turn's phase. Waiting on the person wins over everything — a\n * `requires-action` status, a waiting tool, or a host's own `waitingForInput`\n * assertion (no in-repo host passes one) — then the message's own status. A\n * complete turn with a step still running is running: only a step holding the\n * backend's running placeholder reads so once nothing streams (a run parked on\n * an approval inside a subagent, the gap before a drained run resumes).\n */\nexport function resolveActivityPhase(\n status: MessageStatus | undefined,\n timeline: readonly ActivityItem[],\n { waitingForInput = false }: { waitingForInput?: boolean } = {},\n): ActivityPhase {\n if (\n waitingForInput ||\n status?.type === 'requires-action' ||\n timeline.some((item) => item.kind === 'tool' && item.state === 'waiting')\n ) {\n return 'waiting';\n }\n if (status?.type === 'running') return 'running';\n if (status?.type === 'incomplete') return 'error';\n if (\n status?.type === 'complete' &&\n timeline.some((item) => item.kind === 'tool' && item.state === 'running')\n ) {\n return 'running';\n }\n return 'complete';\n}\n\n/**\n * A settled thought's row: the heading a reasoning summary opens with\n * (\"**Checking the workstation**\" → \"Checking the workstation\"), else the\n * generic wording. The thought itself stays in the run's details.\n */\nexport function getReasoningLabel(text: string, state: 'running' | 'complete'): string {\n if (state === 'running') return 'Thinking';\n const heading = /^\\s*\\*\\*([^*\\n]{3,80}?)\\*\\*/.exec(text)?.[1]?.trim();\n return heading ? heading.replace(/[.:]+$/, '') : 'Thought through the next step';\n}\n\n/**\n * The status-row copy for one step: the call's own summary from the shared\n * summary registry (`summarizeToolCall`: \"Ran git status\", \"Read config.ts\").\n * `resolveToolDisplayName` lets a host with a richer tool catalog name tools\n * neither registry has an entry for; `assetTitles` names the machine or\n * document a call targeted by id when an earlier result in the turn did.\n */\nexport function getActivityItemLabel(\n item: ActivityItem,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): string {\n if (item.kind === 'reasoning') return getReasoningLabel(item.text, item.state);\n return summarizeActivityTool(item, resolveToolDisplayName, assetTitles).label;\n}\n\n/** The summary of one tool step (see {@link getActivityItemLabel}). */\nexport function summarizeActivityTool(\n item: Extract<ActivityItem, { kind: 'tool' }>,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): ToolCallSummary {\n return summarizeToolCall({\n toolName: item.toolName,\n args: item.args,\n result: item.result,\n status: item.state,\n ...(assetTitles ? { assetTitles } : {}),\n ...(resolveToolDisplayName ? { displayName: resolveToolDisplayName(item.toolName) } : {}),\n });\n}\n\n/**\n * The collapsed-card summary of a finished turn. \"Completed with issues\" means\n * the turn ended on a problem: a call the person refused, or a failed call\n * that no later call completed after. A failed command the agent then got past\n * (a search that found nothing, a retry that worked) is ordinary work, so a\n * long turn that recovered from it reads as the tools it used.\n */\nexport function getActivitySummary(timeline: readonly ActivityItem[]): string {\n const toolCount = countActivityTools(timeline);\n const tools = timeline.filter((item) => item.kind === 'tool');\n const lastFailure = tools.findLastIndex((item) => item.state === 'error');\n const endedOnFailure =\n lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === 'complete');\n const hasIssue = endedOnFailure || tools.some((item) => item.state === 'rejected');\n if (hasIssue) return 'Completed with issues';\n if (timeline.some((item) => item.kind === 'tool' && item.state === 'cancelled')) {\n return 'Action cancelled';\n }\n if (timeline.some((item) => item.kind === 'tool' && item.state === 'paused')) {\n return 'Paused during tool use';\n }\n if (toolCount > 0) return `Used ${toolCount} ${toolCount === 1 ? 'tool' : 'tools'}`;\n return 'Reasoning complete';\n}\n\n/** The part shape the final-text read needs; any message role's parts satisfy it. */\nexport type FinalTextPart = { readonly type: string; readonly text?: string };\n\n/**\n * Whether a text part shows below the card instead of in the details panel:\n * it comes after the final tool call, or it holds a spoken voice turn's words\n * (a live turn heard during a delegated run lands between the run's tool\n * calls, see `isSpokenTurnTextPart`; it is the conversation, not narration).\n */\nfunction isAnswerTextPart(\n part: { readonly type: string } | undefined,\n index: number,\n lastToolIndex: number,\n): boolean {\n return part?.type === 'text' && (index > lastToolIndex || isSpokenTurnTextPart(part));\n}\n\n/**\n * The visible answer of a grouped turn: the text after the final tool call\n * (all of it when the turn never called a tool), plus the words of every\n * spoken voice turn in the message, in order. Other intermediate text (before\n * or between tool calls) stays available in the details panel.\n */\nexport function getFinalText(content: readonly FinalTextPart[] | undefined): string | null {\n const parts = getFinalTextParts(content);\n return parts.length > 0 ? parts.map((part) => part.text).join('\\n\\n') : null;\n}\n\n/** One text part of the visible answer, with its index in the message content. */\nexport interface FinalTextSegment {\n index: number;\n text: string;\n}\n\n/**\n * The parts `getFinalText` joins, each kept separate with its content index.\n * A spoken turn and the run's own reply can stream at the same time, so the\n * earlier part may grow while a later one exists: rendered as one joined\n * string, that text changes in the middle rather than at its end, and the\n * streaming reveal restarts from an empty bubble on every word.\n */\nexport function getFinalTextParts(content: readonly FinalTextPart[] | undefined): FinalTextSegment[] {\n if (!content?.length) return [];\n\n const lastToolIndex = content.findLastIndex((part) => part?.type === 'tool-call');\n const parts: FinalTextSegment[] = [];\n content.forEach((part, index) => {\n if (part.text && isAnswerTextPart(part, index, lastToolIndex)) parts.push({ index, text: part.text });\n });\n return parts;\n}\n\n/**\n * Keep the answer out of the details panel: it renders below the card\n * (`SuperGroupingFinalText`), so the details grouping drops every text part\n * `getFinalText` shows and any group that becomes empty.\n */\nexport function excludeFinalTextFromGroups(grouping: GroupingFunction): GroupingFunction {\n return (parts) => {\n const lastToolIndex = parts.findLastIndex((part) => part?.type === 'tool-call');\n return grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => !isAnswerTextPart(parts[index], index, lastToolIndex)),\n }))\n .filter((group) => group.indices.length > 0);\n };\n}\n\n/**\n * Drop the parts `exclude` matches from every group, and any group left\n * empty: `SuperGroupingCard` renders inline tool calls outside the details,\n * so they must not render a second time inside it.\n */\nexport function excludePartsFromGroups(\n grouping: GroupingFunction,\n exclude: (part: GroupablePart) => boolean,\n): GroupingFunction {\n return (parts) =>\n grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => {\n const part = parts[index];\n return part === undefined || !exclude(part);\n }),\n }))\n .filter((group) => group.indices.length > 0);\n}\n"],"names":["isRunningToolPlaceholderArtifact","readRejectedToolResult","classifyToolResult","summarizeToolCall","isSpokenTurnTextPart"],"mappings":"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"}
1
+ {"version":3,"file":"activity-timeline.cjs","sources":["../../../src/chat/super-grouping/activity-timeline.ts"],"sourcesContent":["/**\n * The assistant turn's activity timeline — the one derivation of \"what did\n * this turn do, and how did each step end\" behind the collapsed view\n * (previously called the conversational view) on every surface: the SDK's\n * `AthenaChat`, Olympus's Spaces chat, and the Chrome extension. Pure\n * functions over assistant-ui message parts; `SuperGroupingCard` renders them.\n *\n * Step states come from the shared classifier (`classifyToolResult`) plus the\n * approval outcomes a part carries (`approval`, `interrupt`, a rejection\n * result), so a call that reads as failed, paused, or rejected on one surface\n * cannot read as a green check on another. Copy comes from the shared tool\n * summary registry (`summarizeToolCall`), itself built on the display\n * registry.\n */\nimport type {\n MessageStatus,\n ThreadAssistantMessagePart,\n ToolCallMessagePartStatus,\n} from '@assistant-ui/react';\nimport {\n classifyToolResult,\n countInEvalDispatches,\n EVAL_TOOL_NAME,\n isRunningToolPlaceholderArtifact,\n isSpokenTurnTextPart,\n readRejectedToolResult,\n TASK_TOOL_NAME,\n type ToolStatusLabelState,\n} from '@athenaintel/agent-runtime';\nimport { summarizeToolCall, type ToolCallSummary } from '../../tools/tool-summary';\nimport type { GroupablePart, GroupingFunction } from './grouping-function';\n\nexport type ActivityToolState = ToolStatusLabelState;\n\nexport type ActivityItem =\n | {\n kind: 'reasoning';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n text: string;\n state: 'running' | 'complete';\n }\n | {\n kind: 'tool';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n toolName: string;\n args?: ToolCallPart['args'];\n /** The tool's real result; absent while it runs or holds only the streaming placeholder. */\n result?: unknown;\n state: ActivityToolState;\n /**\n * Subagents the call delegated to: for a `task` call one, or none when it\n * was refused, withdrawn or expired at its approval and never ran; for an\n * `eval` call its in-interpreter `task()` dispatches\n * (`countInEvalDispatches`), absent when it made none.\n */\n delegations?: number;\n };\n\n/** The turn as a whole: still working, parked on the person, ended in error, or done. */\nexport type ActivityPhase = 'running' | 'waiting' | 'complete' | 'error';\n\ntype ToolCallPart = Extract<ThreadAssistantMessagePart, { type: 'tool-call' }>;\n\nexport interface ActivityTimelineOptions {\n /**\n * Tools whose unresolved call means the turn is waiting on the person even\n * without an interrupt or approval on the part (the Chrome extension's\n * device plan approval, which the tool UI itself collects).\n */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id, as the host reads them off\n * its pending approval: a gated call, or (in Olympus) a `task` call whose\n * subagent waits on an approval. Any of them still without its real result\n * reads as waiting.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /**\n * Tools whose result is an application payload relayed verbatim (the Chrome\n * extension's page JavaScript), so a `success: false` flag counts only with\n * an error detail — see `classifyToolResult`'s `passThroughPayload`.\n */\n passThroughTools?: ReadonlySet<string>;\n}\n\nconst NO_TOOLS: ReadonlySet<string> = new Set();\nconst NO_TOOL_CALLS: ReadonlySet<string> = new Set();\n\n/**\n * Whether a tool-call part still holds the backend's running-tool placeholder\n * result rather than the tool's real output. Long-running tools (task\n * subagents, studio and Python execution, deep research) append a ToolMessage\n * the moment they start so their card can fill in live; its marker reaches the\n * part's artifact (`isRunningToolPlaceholderArtifact`). The real ToolMessage\n * that replaces it has no such marker, so a defined `result` alone does not\n * mean the tool is done.\n */\nexport function isStreamingToolPlaceholder(part: Pick<ToolCallPart, 'artifact'>): boolean {\n return isRunningToolPlaceholderArtifact(part.artifact);\n}\n\n/** The tool's real result: undefined while it has none or only the streaming placeholder. */\nfunction finalResult(part: ToolCallPart): unknown {\n return isStreamingToolPlaceholder(part) ? undefined : part.result;\n}\n\nfunction toolCallStatus(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n): ToolCallMessagePartStatus | undefined {\n if (finalResult(part) !== undefined) return { type: 'complete' };\n if (messageStatus?.type === 'incomplete') {\n return {\n type: 'incomplete',\n reason: messageStatus.reason === 'tool-calls' ? 'other' : messageStatus.reason,\n error: messageStatus.error,\n };\n }\n if (messageStatus?.type === 'complete') {\n // The placeholder is the backend's word that the call is still in flight.\n // A turn reads `complete` whenever nothing streams (a run parked on an\n // approval inside a subagent, the gap before a drained run resumes), and\n // assistant-ui counts the placeholder as the call's result when it settles\n // that status, so the turn's status cannot finish the call.\n return isStreamingToolPlaceholder(part) ? { type: 'running' } : { type: 'complete' };\n }\n if (messageStatus?.type === 'requires-action') {\n return { type: 'requires-action', reason: messageStatus.reason };\n }\n if (messageStatus?.type === 'running') return { type: 'running' };\n return undefined;\n}\n\n/** How one tool call ended (or is going), reading the approval fields before the result. */\nexport function getActivityToolState(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n {\n waitingTools = NO_TOOLS,\n waitingToolCallIds = NO_TOOL_CALLS,\n passThroughTools = NO_TOOLS,\n }: ActivityTimelineOptions = {},\n): ActivityToolState {\n if (part.approval?.approved === false || readRejectedToolResult(part.result) !== null) {\n return 'rejected';\n }\n if (part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired') {\n return 'cancelled';\n }\n const result = finalResult(part);\n const unresolved = result === undefined;\n const messageIsActive =\n messageStatus === undefined ||\n messageStatus.type === 'running' ||\n messageStatus.type === 'requires-action';\n if (\n unresolved &&\n (part.interrupt?.type === 'human' ||\n (part.approval !== undefined &&\n part.approval.approved === undefined &&\n part.approval.resolution === undefined) ||\n waitingToolCallIds.has(part.toolCallId) ||\n (waitingTools.has(part.toolName) && messageIsActive))\n ) {\n return 'waiting';\n }\n\n const classification = classifyToolResult({\n status: toolCallStatus(part, messageStatus),\n result,\n isError: part.isError,\n passThroughPayload: passThroughTools.has(part.toolName),\n });\n if (classification.state === 'requires-action') return 'waiting';\n return classification.state;\n}\n\n/**\n * The compact reasoning/tool timeline in the order the parts streamed.\n *\n * A reasoning part is still streaming only while it is the final part of a\n * running message — once any later part appears, the thought has settled.\n * Settled reasoning parts with no text are dropped so the list never shows an\n * empty thinking row.\n */\nexport function buildActivityTimeline(\n content: readonly ThreadAssistantMessagePart[] | undefined,\n messageStatus: MessageStatus | undefined,\n options: ActivityTimelineOptions = {},\n): ActivityItem[] {\n if (!content?.length) return [];\n\n const lastPartIndex = content.length - 1;\n const timeline: ActivityItem[] = [];\n for (let index = 0; index < content.length; index += 1) {\n const part = content[index];\n if (part.type === 'tool-call') {\n const result = finalResult(part);\n const state = getActivityToolState(part, messageStatus, options);\n const delegations = toolCallDelegations({ part, state });\n timeline.push({\n kind: 'tool',\n id: part.toolCallId,\n partIndex: index,\n args: part.args,\n ...(result !== undefined ? { result } : {}),\n toolName: part.toolName,\n state,\n ...(delegations !== null ? { delegations } : {}),\n });\n continue;\n }\n if (part.type !== 'reasoning') continue;\n\n const text = typeof part.text === 'string' ? part.text : '';\n const stillStreaming = messageStatus?.type === 'running' && index === lastPartIndex;\n if (!stillStreaming && text.trim() === '') continue;\n timeline.push({\n kind: 'reasoning',\n id: `reasoning-${index}`,\n partIndex: index,\n text,\n state: stillStreaming ? 'running' : 'complete',\n });\n }\n return timeline;\n}\n\n/**\n * Subagents one tool call delegated to (see `ActivityItem.delegations`), or\n * `null` for a call that delegates by nature of neither: a `task` call one,\n * unless the person refused it or its approval was withdrawn or expired (it\n * never ran); an `eval` call its in-interpreter dispatches, when it made any.\n */\nfunction toolCallDelegations({\n part,\n state,\n}: {\n part: ToolCallPart;\n state: ActivityToolState;\n}): number | null {\n if (part.toolName === TASK_TOOL_NAME) {\n const withdrawn =\n part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired';\n return state === 'rejected' || withdrawn ? 0 : 1;\n }\n if (part.toolName === EVAL_TOOL_NAME) {\n const dispatches = countInEvalDispatches(part.artifact);\n return dispatches > 0 ? dispatches : null;\n }\n return null;\n}\n\n/** Number of tool calls in the timeline. */\nexport function countActivityTools(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => (item.kind === 'tool' ? count + 1 : count), 0);\n}\n\n/**\n * Subagents the turn delegated to: its `task` calls that ran, plus the\n * `task()` dispatches its `eval` calls made from inside the interpreter. A\n * `task` step built without its count (a host's own timeline) counts unless it\n * reads refused or cancelled.\n */\nexport function countActivityDelegations(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => {\n if (item.kind !== 'tool') return count;\n if (item.delegations !== undefined) return count + item.delegations;\n const ranTask =\n item.toolName === TASK_TOOL_NAME && item.state !== 'rejected' && item.state !== 'cancelled';\n return ranTask ? count + 1 : count;\n }, 0);\n}\n\n/**\n * The turn's phase. Waiting on the person wins over everything — a\n * `requires-action` status, a waiting tool, or a host's own `waitingForInput`\n * assertion (no in-repo host passes one) — then the message's own status. A\n * complete turn with a step still running is running: only a step holding the\n * backend's running placeholder reads so once nothing streams (a run parked on\n * an approval inside a subagent, the gap before a drained run resumes).\n */\nexport function resolveActivityPhase(\n status: MessageStatus | undefined,\n timeline: readonly ActivityItem[],\n { waitingForInput = false }: { waitingForInput?: boolean } = {},\n): ActivityPhase {\n if (\n waitingForInput ||\n status?.type === 'requires-action' ||\n timeline.some((item) => item.kind === 'tool' && item.state === 'waiting')\n ) {\n return 'waiting';\n }\n if (status?.type === 'running') return 'running';\n if (status?.type === 'incomplete') return 'error';\n if (\n status?.type === 'complete' &&\n timeline.some((item) => item.kind === 'tool' && item.state === 'running')\n ) {\n return 'running';\n }\n return 'complete';\n}\n\n/**\n * A settled thought's row: the heading a reasoning summary opens with\n * (\"**Checking the workstation**\" → \"Checking the workstation\"), else the\n * generic wording. The thought itself stays in the run's details.\n */\nexport function getReasoningLabel(text: string, state: 'running' | 'complete'): string {\n if (state === 'running') return 'Thinking';\n const heading = /^\\s*\\*\\*([^*\\n]{3,80}?)\\*\\*/.exec(text)?.[1]?.trim();\n return heading ? heading.replace(/[.:]+$/, '') : 'Thought through the next step';\n}\n\n/**\n * The status-row copy for one step: the call's own summary from the shared\n * summary registry (`summarizeToolCall`: \"Ran git status\", \"Read config.ts\").\n * `resolveToolDisplayName` lets a host with a richer tool catalog name tools\n * neither registry has an entry for; `assetTitles` names the machine or\n * document a call targeted by id when an earlier result in the turn did.\n */\nexport function getActivityItemLabel(\n item: ActivityItem,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): string {\n if (item.kind === 'reasoning') return getReasoningLabel(item.text, item.state);\n return summarizeActivityTool(item, resolveToolDisplayName, assetTitles).label;\n}\n\n/** The summary of one tool step (see {@link getActivityItemLabel}). */\nexport function summarizeActivityTool(\n item: Extract<ActivityItem, { kind: 'tool' }>,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): ToolCallSummary {\n return summarizeToolCall({\n toolName: item.toolName,\n args: item.args,\n result: item.result,\n status: item.state,\n ...(assetTitles ? { assetTitles } : {}),\n ...(resolveToolDisplayName ? { displayName: resolveToolDisplayName(item.toolName) } : {}),\n });\n}\n\n/**\n * The collapsed-card summary of a finished turn. \"Completed with issues\" means\n * the turn ended on a problem: a call the person refused, or a failed call\n * that no later call completed after. A failed command the agent then got past\n * (a search that found nothing, a retry that worked) is ordinary work, so a\n * long turn that recovered from it reads as the tools it used.\n *\n * A turn that delegated work leads with it — \"Delegated to 10 agents · used 6\n * tools\" — counting its `task` calls and the `task()` dispatches its `eval`\n * calls made from inside the interpreter (`countActivityDelegations`). A\n * `task` call is the delegation itself, so the tools it is followed by are the\n * turn's other calls; an outcome above replaces them (\"Delegated to 3 agents ·\n * completed with issues\").\n */\nexport function getActivitySummary(timeline: readonly ActivityItem[]): string {\n const tools = timeline.filter((item): item is ToolActivityItem => item.kind === 'tool');\n const outcome = activityOutcome(tools);\n const delegations = countActivityDelegations(timeline);\n if (delegations > 0) {\n const lead = `Delegated to ${delegations} ${delegations === 1 ? 'agent' : 'agents'}`;\n const otherTools = tools.filter((item) => item.toolName !== TASK_TOOL_NAME).length;\n const rest = outcome\n ? `${outcome.charAt(0).toLowerCase()}${outcome.slice(1)}`\n : otherTools > 0\n ? `used ${otherTools} ${otherTools === 1 ? 'tool' : 'tools'}`\n : null;\n return rest ? `${lead} · ${rest}` : lead;\n }\n if (outcome) return outcome;\n if (tools.length > 0) return `Used ${tools.length} ${tools.length === 1 ? 'tool' : 'tools'}`;\n return 'Reasoning complete';\n}\n\ntype ToolActivityItem = Extract<ActivityItem, { kind: 'tool' }>;\n\n/** How a finished turn's tool calls ended, when that is not simply the tools it used. */\nfunction activityOutcome(tools: readonly ToolActivityItem[]): string | null {\n const lastFailure = tools.findLastIndex((item) => item.state === 'error');\n const endedOnFailure =\n lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === 'complete');\n if (endedOnFailure || tools.some((item) => item.state === 'rejected')) return 'Completed with issues';\n if (tools.some((item) => item.state === 'cancelled')) return 'Action cancelled';\n if (tools.some((item) => item.state === 'paused')) return 'Paused during tool use';\n return null;\n}\n\n/** The part shape the final-text read needs; any message role's parts satisfy it. */\nexport type FinalTextPart = { readonly type: string; readonly text?: string };\n\n/**\n * Whether a text part shows below the card instead of in the details panel:\n * it comes after the final tool call, or it holds a spoken voice turn's words\n * (a live turn heard during a delegated run lands between the run's tool\n * calls, see `isSpokenTurnTextPart`; it is the conversation, not narration).\n */\nfunction isAnswerTextPart(\n part: { readonly type: string } | undefined,\n index: number,\n lastToolIndex: number,\n): boolean {\n return part?.type === 'text' && (index > lastToolIndex || isSpokenTurnTextPart(part));\n}\n\n/**\n * The visible answer of a grouped turn: the text after the final tool call\n * (all of it when the turn never called a tool), plus the words of every\n * spoken voice turn in the message, in order. Other intermediate text (before\n * or between tool calls) stays available in the details panel.\n */\nexport function getFinalText(content: readonly FinalTextPart[] | undefined): string | null {\n const parts = getFinalTextParts(content);\n return parts.length > 0 ? parts.map((part) => part.text).join('\\n\\n') : null;\n}\n\n/** One text part of the visible answer, with its index in the message content. */\nexport interface FinalTextSegment {\n index: number;\n text: string;\n}\n\n/**\n * The parts `getFinalText` joins, each kept separate with its content index.\n * A spoken turn and the run's own reply can stream at the same time, so the\n * earlier part may grow while a later one exists: rendered as one joined\n * string, that text changes in the middle rather than at its end, and the\n * streaming reveal restarts from an empty bubble on every word.\n */\nexport function getFinalTextParts(content: readonly FinalTextPart[] | undefined): FinalTextSegment[] {\n if (!content?.length) return [];\n\n const lastToolIndex = content.findLastIndex((part) => part?.type === 'tool-call');\n const parts: FinalTextSegment[] = [];\n content.forEach((part, index) => {\n if (part.text && isAnswerTextPart(part, index, lastToolIndex)) parts.push({ index, text: part.text });\n });\n return parts;\n}\n\n/**\n * Keep the answer out of the details panel: it renders below the card\n * (`SuperGroupingFinalText`), so the details grouping drops every text part\n * `getFinalText` shows and any group that becomes empty.\n */\nexport function excludeFinalTextFromGroups(grouping: GroupingFunction): GroupingFunction {\n return (parts) => {\n const lastToolIndex = parts.findLastIndex((part) => part?.type === 'tool-call');\n return grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => !isAnswerTextPart(parts[index], index, lastToolIndex)),\n }))\n .filter((group) => group.indices.length > 0);\n };\n}\n\n/**\n * Drop the parts `exclude` matches from every group, and any group left\n * empty: `SuperGroupingCard` renders inline tool calls outside the details,\n * so they must not render a second time inside it.\n */\nexport function excludePartsFromGroups(\n grouping: GroupingFunction,\n exclude: (part: GroupablePart) => boolean,\n): GroupingFunction {\n return (parts) =>\n grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => {\n const part = parts[index];\n return part === undefined || !exclude(part);\n }),\n }))\n .filter((group) => group.indices.length > 0);\n}\n"],"names":["isRunningToolPlaceholderArtifact","readRejectedToolResult","classifyToolResult","TASK_TOOL_NAME","EVAL_TOOL_NAME","countInEvalDispatches","summarizeToolCall","isSpokenTurnTextPart"],"mappings":"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"}
@@ -34,6 +34,13 @@ export type ActivityItem = {
34
34
  /** The tool's real result; absent while it runs or holds only the streaming placeholder. */
35
35
  result?: unknown;
36
36
  state: ActivityToolState;
37
+ /**
38
+ * Subagents the call delegated to: for a `task` call one, or none when it
39
+ * was refused, withdrawn or expired at its approval and never ran; for an
40
+ * `eval` call its in-interpreter `task()` dispatches
41
+ * (`countInEvalDispatches`), absent when it made none.
42
+ */
43
+ delegations?: number;
37
44
  };
38
45
  /** The turn as a whole: still working, parked on the person, ended in error, or done. */
39
46
  export type ActivityPhase = 'running' | 'waiting' | 'complete' | 'error';
@@ -84,6 +91,13 @@ export declare function getActivityToolState(part: ToolCallPart, messageStatus:
84
91
  export declare function buildActivityTimeline(content: readonly ThreadAssistantMessagePart[] | undefined, messageStatus: MessageStatus | undefined, options?: ActivityTimelineOptions): ActivityItem[];
85
92
  /** Number of tool calls in the timeline. */
86
93
  export declare function countActivityTools(timeline: readonly ActivityItem[]): number;
94
+ /**
95
+ * Subagents the turn delegated to: its `task` calls that ran, plus the
96
+ * `task()` dispatches its `eval` calls made from inside the interpreter. A
97
+ * `task` step built without its count (a host's own timeline) counts unless it
98
+ * reads refused or cancelled.
99
+ */
100
+ export declare function countActivityDelegations(timeline: readonly ActivityItem[]): number;
87
101
  /**
88
102
  * The turn's phase. Waiting on the person wins over everything — a
89
103
  * `requires-action` status, a waiting tool, or a host's own `waitingForInput`
@@ -119,6 +133,13 @@ export declare function summarizeActivityTool(item: Extract<ActivityItem, {
119
133
  * that no later call completed after. A failed command the agent then got past
120
134
  * (a search that found nothing, a retry that worked) is ordinary work, so a
121
135
  * long turn that recovered from it reads as the tools it used.
136
+ *
137
+ * A turn that delegated work leads with it — "Delegated to 10 agents · used 6
138
+ * tools" — counting its `task` calls and the `task()` dispatches its `eval`
139
+ * calls made from inside the interpreter (`countActivityDelegations`). A
140
+ * `task` call is the delegation itself, so the tools it is followed by are the
141
+ * turn's other calls; an outcome above replaces them ("Delegated to 3 agents ·
142
+ * completed with issues").
122
143
  */
123
144
  export declare function getActivitySummary(timeline: readonly ActivityItem[]): string;
124
145
  /** The part shape the final-text read needs; any message role's parts satisfy it. */
@@ -1,6 +1,8 @@
1
1
  import { summarizeToolCall } from "../../tools/tool-summary.js";
2
+ import { TASK_TOOL_NAME, EVAL_TOOL_NAME } from "../../agent-runtime/src/tool-names.js";
2
3
  import { readRejectedToolResult, classifyToolResult } from "../../agent-runtime/src/tool-result.js";
3
4
  import { isRunningToolPlaceholderArtifact } from "../../agent-runtime/src/running-tool-placeholder.js";
5
+ import { countInEvalDispatches } from "../../agent-runtime/src/subagents.js";
4
6
  import { isSpokenTurnTextPart } from "../../agent-runtime/src/voice-presentation.js";
5
7
  const NO_TOOLS = /* @__PURE__ */ new Set();
6
8
  const NO_TOOL_CALLS = /* @__PURE__ */ new Set();
@@ -63,6 +65,8 @@ function buildActivityTimeline(content, messageStatus, options = {}) {
63
65
  const part = content[index];
64
66
  if (part.type === "tool-call") {
65
67
  const result = finalResult(part);
68
+ const state = getActivityToolState(part, messageStatus, options);
69
+ const delegations = toolCallDelegations({ part, state });
66
70
  timeline.push({
67
71
  kind: "tool",
68
72
  id: part.toolCallId,
@@ -70,7 +74,8 @@ function buildActivityTimeline(content, messageStatus, options = {}) {
70
74
  args: part.args,
71
75
  ...result !== void 0 ? { result } : {},
72
76
  toolName: part.toolName,
73
- state: getActivityToolState(part, messageStatus, options)
77
+ state,
78
+ ...delegations !== null ? { delegations } : {}
74
79
  });
75
80
  continue;
76
81
  }
@@ -88,9 +93,32 @@ function buildActivityTimeline(content, messageStatus, options = {}) {
88
93
  }
89
94
  return timeline;
90
95
  }
96
+ function toolCallDelegations({
97
+ part,
98
+ state
99
+ }) {
100
+ var _a, _b;
101
+ if (part.toolName === TASK_TOOL_NAME) {
102
+ const withdrawn = ((_a = part.approval) == null ? void 0 : _a.resolution) === "cancelled" || ((_b = part.approval) == null ? void 0 : _b.resolution) === "expired";
103
+ return state === "rejected" || withdrawn ? 0 : 1;
104
+ }
105
+ if (part.toolName === EVAL_TOOL_NAME) {
106
+ const dispatches = countInEvalDispatches(part.artifact);
107
+ return dispatches > 0 ? dispatches : null;
108
+ }
109
+ return null;
110
+ }
91
111
  function countActivityTools(timeline) {
92
112
  return timeline.reduce((count, item) => item.kind === "tool" ? count + 1 : count, 0);
93
113
  }
114
+ function countActivityDelegations(timeline) {
115
+ return timeline.reduce((count, item) => {
116
+ if (item.kind !== "tool") return count;
117
+ if (item.delegations !== void 0) return count + item.delegations;
118
+ const ranTask = item.toolName === TASK_TOOL_NAME && item.state !== "rejected" && item.state !== "cancelled";
119
+ return ranTask ? count + 1 : count;
120
+ }, 0);
121
+ }
94
122
  function resolveActivityPhase(status, timeline, { waitingForInput = false } = {}) {
95
123
  if (waitingForInput || (status == null ? void 0 : status.type) === "requires-action" || timeline.some((item) => item.kind === "tool" && item.state === "waiting")) {
96
124
  return "waiting";
@@ -123,21 +151,27 @@ function summarizeActivityTool(item, resolveToolDisplayName, assetTitles) {
123
151
  });
124
152
  }
125
153
  function getActivitySummary(timeline) {
126
- const toolCount = countActivityTools(timeline);
127
154
  const tools = timeline.filter((item) => item.kind === "tool");
128
- const lastFailure = tools.findLastIndex((item) => item.state === "error");
129
- const endedOnFailure = lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === "complete");
130
- const hasIssue = endedOnFailure || tools.some((item) => item.state === "rejected");
131
- if (hasIssue) return "Completed with issues";
132
- if (timeline.some((item) => item.kind === "tool" && item.state === "cancelled")) {
133
- return "Action cancelled";
134
- }
135
- if (timeline.some((item) => item.kind === "tool" && item.state === "paused")) {
136
- return "Paused during tool use";
155
+ const outcome = activityOutcome(tools);
156
+ const delegations = countActivityDelegations(timeline);
157
+ if (delegations > 0) {
158
+ const lead = `Delegated to ${delegations} ${delegations === 1 ? "agent" : "agents"}`;
159
+ const otherTools = tools.filter((item) => item.toolName !== TASK_TOOL_NAME).length;
160
+ const rest = outcome ? `${outcome.charAt(0).toLowerCase()}${outcome.slice(1)}` : otherTools > 0 ? `used ${otherTools} ${otherTools === 1 ? "tool" : "tools"}` : null;
161
+ return rest ? `${lead} · ${rest}` : lead;
137
162
  }
138
- if (toolCount > 0) return `Used ${toolCount} ${toolCount === 1 ? "tool" : "tools"}`;
163
+ if (outcome) return outcome;
164
+ if (tools.length > 0) return `Used ${tools.length} ${tools.length === 1 ? "tool" : "tools"}`;
139
165
  return "Reasoning complete";
140
166
  }
167
+ function activityOutcome(tools) {
168
+ const lastFailure = tools.findLastIndex((item) => item.state === "error");
169
+ const endedOnFailure = lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === "complete");
170
+ if (endedOnFailure || tools.some((item) => item.state === "rejected")) return "Completed with issues";
171
+ if (tools.some((item) => item.state === "cancelled")) return "Action cancelled";
172
+ if (tools.some((item) => item.state === "paused")) return "Paused during tool use";
173
+ return null;
174
+ }
141
175
  function isAnswerTextPart(part, index, lastToolIndex) {
142
176
  return (part == null ? void 0 : part.type) === "text" && (index > lastToolIndex || isSpokenTurnTextPart(part));
143
177
  }
@@ -174,6 +208,7 @@ function excludePartsFromGroups(grouping, exclude) {
174
208
  }
175
209
  export {
176
210
  buildActivityTimeline,
211
+ countActivityDelegations,
177
212
  countActivityTools,
178
213
  excludeFinalTextFromGroups,
179
214
  excludePartsFromGroups,
@@ -1 +1 @@
1
- {"version":3,"file":"activity-timeline.js","sources":["../../../src/chat/super-grouping/activity-timeline.ts"],"sourcesContent":["/**\n * The assistant turn's activity timeline — the one derivation of \"what did\n * this turn do, and how did each step end\" behind the collapsed view\n * (previously called the conversational view) on every surface: the SDK's\n * `AthenaChat`, Olympus's Spaces chat, and the Chrome extension. Pure\n * functions over assistant-ui message parts; `SuperGroupingCard` renders them.\n *\n * Step states come from the shared classifier (`classifyToolResult`) plus the\n * approval outcomes a part carries (`approval`, `interrupt`, a rejection\n * result), so a call that reads as failed, paused, or rejected on one surface\n * cannot read as a green check on another. Copy comes from the shared tool\n * summary registry (`summarizeToolCall`), itself built on the display\n * registry.\n */\nimport type {\n MessageStatus,\n ThreadAssistantMessagePart,\n ToolCallMessagePartStatus,\n} from '@assistant-ui/react';\nimport {\n classifyToolResult,\n isRunningToolPlaceholderArtifact,\n isSpokenTurnTextPart,\n readRejectedToolResult,\n type ToolStatusLabelState,\n} from '@athenaintel/agent-runtime';\nimport { summarizeToolCall, type ToolCallSummary } from '../../tools/tool-summary';\nimport type { GroupablePart, GroupingFunction } from './grouping-function';\n\nexport type ActivityToolState = ToolStatusLabelState;\n\nexport type ActivityItem =\n | {\n kind: 'reasoning';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n text: string;\n state: 'running' | 'complete';\n }\n | {\n kind: 'tool';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n toolName: string;\n args?: ToolCallPart['args'];\n /** The tool's real result; absent while it runs or holds only the streaming placeholder. */\n result?: unknown;\n state: ActivityToolState;\n };\n\n/** The turn as a whole: still working, parked on the person, ended in error, or done. */\nexport type ActivityPhase = 'running' | 'waiting' | 'complete' | 'error';\n\ntype ToolCallPart = Extract<ThreadAssistantMessagePart, { type: 'tool-call' }>;\n\nexport interface ActivityTimelineOptions {\n /**\n * Tools whose unresolved call means the turn is waiting on the person even\n * without an interrupt or approval on the part (the Chrome extension's\n * device plan approval, which the tool UI itself collects).\n */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id, as the host reads them off\n * its pending approval: a gated call, or (in Olympus) a `task` call whose\n * subagent waits on an approval. Any of them still without its real result\n * reads as waiting.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /**\n * Tools whose result is an application payload relayed verbatim (the Chrome\n * extension's page JavaScript), so a `success: false` flag counts only with\n * an error detail — see `classifyToolResult`'s `passThroughPayload`.\n */\n passThroughTools?: ReadonlySet<string>;\n}\n\nconst NO_TOOLS: ReadonlySet<string> = new Set();\nconst NO_TOOL_CALLS: ReadonlySet<string> = new Set();\n\n/**\n * Whether a tool-call part still holds the backend's running-tool placeholder\n * result rather than the tool's real output. Long-running tools (task\n * subagents, studio and Python execution, deep research) append a ToolMessage\n * the moment they start so their card can fill in live; its marker reaches the\n * part's artifact (`isRunningToolPlaceholderArtifact`). The real ToolMessage\n * that replaces it has no such marker, so a defined `result` alone does not\n * mean the tool is done.\n */\nexport function isStreamingToolPlaceholder(part: Pick<ToolCallPart, 'artifact'>): boolean {\n return isRunningToolPlaceholderArtifact(part.artifact);\n}\n\n/** The tool's real result: undefined while it has none or only the streaming placeholder. */\nfunction finalResult(part: ToolCallPart): unknown {\n return isStreamingToolPlaceholder(part) ? undefined : part.result;\n}\n\nfunction toolCallStatus(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n): ToolCallMessagePartStatus | undefined {\n if (finalResult(part) !== undefined) return { type: 'complete' };\n if (messageStatus?.type === 'incomplete') {\n return {\n type: 'incomplete',\n reason: messageStatus.reason === 'tool-calls' ? 'other' : messageStatus.reason,\n error: messageStatus.error,\n };\n }\n if (messageStatus?.type === 'complete') {\n // The placeholder is the backend's word that the call is still in flight.\n // A turn reads `complete` whenever nothing streams (a run parked on an\n // approval inside a subagent, the gap before a drained run resumes), and\n // assistant-ui counts the placeholder as the call's result when it settles\n // that status, so the turn's status cannot finish the call.\n return isStreamingToolPlaceholder(part) ? { type: 'running' } : { type: 'complete' };\n }\n if (messageStatus?.type === 'requires-action') {\n return { type: 'requires-action', reason: messageStatus.reason };\n }\n if (messageStatus?.type === 'running') return { type: 'running' };\n return undefined;\n}\n\n/** How one tool call ended (or is going), reading the approval fields before the result. */\nexport function getActivityToolState(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n {\n waitingTools = NO_TOOLS,\n waitingToolCallIds = NO_TOOL_CALLS,\n passThroughTools = NO_TOOLS,\n }: ActivityTimelineOptions = {},\n): ActivityToolState {\n if (part.approval?.approved === false || readRejectedToolResult(part.result) !== null) {\n return 'rejected';\n }\n if (part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired') {\n return 'cancelled';\n }\n const result = finalResult(part);\n const unresolved = result === undefined;\n const messageIsActive =\n messageStatus === undefined ||\n messageStatus.type === 'running' ||\n messageStatus.type === 'requires-action';\n if (\n unresolved &&\n (part.interrupt?.type === 'human' ||\n (part.approval !== undefined &&\n part.approval.approved === undefined &&\n part.approval.resolution === undefined) ||\n waitingToolCallIds.has(part.toolCallId) ||\n (waitingTools.has(part.toolName) && messageIsActive))\n ) {\n return 'waiting';\n }\n\n const classification = classifyToolResult({\n status: toolCallStatus(part, messageStatus),\n result,\n isError: part.isError,\n passThroughPayload: passThroughTools.has(part.toolName),\n });\n if (classification.state === 'requires-action') return 'waiting';\n return classification.state;\n}\n\n/**\n * The compact reasoning/tool timeline in the order the parts streamed.\n *\n * A reasoning part is still streaming only while it is the final part of a\n * running message — once any later part appears, the thought has settled.\n * Settled reasoning parts with no text are dropped so the list never shows an\n * empty thinking row.\n */\nexport function buildActivityTimeline(\n content: readonly ThreadAssistantMessagePart[] | undefined,\n messageStatus: MessageStatus | undefined,\n options: ActivityTimelineOptions = {},\n): ActivityItem[] {\n if (!content?.length) return [];\n\n const lastPartIndex = content.length - 1;\n const timeline: ActivityItem[] = [];\n for (let index = 0; index < content.length; index += 1) {\n const part = content[index];\n if (part.type === 'tool-call') {\n const result = finalResult(part);\n timeline.push({\n kind: 'tool',\n id: part.toolCallId,\n partIndex: index,\n args: part.args,\n ...(result !== undefined ? { result } : {}),\n toolName: part.toolName,\n state: getActivityToolState(part, messageStatus, options),\n });\n continue;\n }\n if (part.type !== 'reasoning') continue;\n\n const text = typeof part.text === 'string' ? part.text : '';\n const stillStreaming = messageStatus?.type === 'running' && index === lastPartIndex;\n if (!stillStreaming && text.trim() === '') continue;\n timeline.push({\n kind: 'reasoning',\n id: `reasoning-${index}`,\n partIndex: index,\n text,\n state: stillStreaming ? 'running' : 'complete',\n });\n }\n return timeline;\n}\n\n/** Number of tool calls in the timeline. */\nexport function countActivityTools(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => (item.kind === 'tool' ? count + 1 : count), 0);\n}\n\n/**\n * The turn's phase. Waiting on the person wins over everything — a\n * `requires-action` status, a waiting tool, or a host's own `waitingForInput`\n * assertion (no in-repo host passes one) — then the message's own status. A\n * complete turn with a step still running is running: only a step holding the\n * backend's running placeholder reads so once nothing streams (a run parked on\n * an approval inside a subagent, the gap before a drained run resumes).\n */\nexport function resolveActivityPhase(\n status: MessageStatus | undefined,\n timeline: readonly ActivityItem[],\n { waitingForInput = false }: { waitingForInput?: boolean } = {},\n): ActivityPhase {\n if (\n waitingForInput ||\n status?.type === 'requires-action' ||\n timeline.some((item) => item.kind === 'tool' && item.state === 'waiting')\n ) {\n return 'waiting';\n }\n if (status?.type === 'running') return 'running';\n if (status?.type === 'incomplete') return 'error';\n if (\n status?.type === 'complete' &&\n timeline.some((item) => item.kind === 'tool' && item.state === 'running')\n ) {\n return 'running';\n }\n return 'complete';\n}\n\n/**\n * A settled thought's row: the heading a reasoning summary opens with\n * (\"**Checking the workstation**\" → \"Checking the workstation\"), else the\n * generic wording. The thought itself stays in the run's details.\n */\nexport function getReasoningLabel(text: string, state: 'running' | 'complete'): string {\n if (state === 'running') return 'Thinking';\n const heading = /^\\s*\\*\\*([^*\\n]{3,80}?)\\*\\*/.exec(text)?.[1]?.trim();\n return heading ? heading.replace(/[.:]+$/, '') : 'Thought through the next step';\n}\n\n/**\n * The status-row copy for one step: the call's own summary from the shared\n * summary registry (`summarizeToolCall`: \"Ran git status\", \"Read config.ts\").\n * `resolveToolDisplayName` lets a host with a richer tool catalog name tools\n * neither registry has an entry for; `assetTitles` names the machine or\n * document a call targeted by id when an earlier result in the turn did.\n */\nexport function getActivityItemLabel(\n item: ActivityItem,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): string {\n if (item.kind === 'reasoning') return getReasoningLabel(item.text, item.state);\n return summarizeActivityTool(item, resolveToolDisplayName, assetTitles).label;\n}\n\n/** The summary of one tool step (see {@link getActivityItemLabel}). */\nexport function summarizeActivityTool(\n item: Extract<ActivityItem, { kind: 'tool' }>,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): ToolCallSummary {\n return summarizeToolCall({\n toolName: item.toolName,\n args: item.args,\n result: item.result,\n status: item.state,\n ...(assetTitles ? { assetTitles } : {}),\n ...(resolveToolDisplayName ? { displayName: resolveToolDisplayName(item.toolName) } : {}),\n });\n}\n\n/**\n * The collapsed-card summary of a finished turn. \"Completed with issues\" means\n * the turn ended on a problem: a call the person refused, or a failed call\n * that no later call completed after. A failed command the agent then got past\n * (a search that found nothing, a retry that worked) is ordinary work, so a\n * long turn that recovered from it reads as the tools it used.\n */\nexport function getActivitySummary(timeline: readonly ActivityItem[]): string {\n const toolCount = countActivityTools(timeline);\n const tools = timeline.filter((item) => item.kind === 'tool');\n const lastFailure = tools.findLastIndex((item) => item.state === 'error');\n const endedOnFailure =\n lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === 'complete');\n const hasIssue = endedOnFailure || tools.some((item) => item.state === 'rejected');\n if (hasIssue) return 'Completed with issues';\n if (timeline.some((item) => item.kind === 'tool' && item.state === 'cancelled')) {\n return 'Action cancelled';\n }\n if (timeline.some((item) => item.kind === 'tool' && item.state === 'paused')) {\n return 'Paused during tool use';\n }\n if (toolCount > 0) return `Used ${toolCount} ${toolCount === 1 ? 'tool' : 'tools'}`;\n return 'Reasoning complete';\n}\n\n/** The part shape the final-text read needs; any message role's parts satisfy it. */\nexport type FinalTextPart = { readonly type: string; readonly text?: string };\n\n/**\n * Whether a text part shows below the card instead of in the details panel:\n * it comes after the final tool call, or it holds a spoken voice turn's words\n * (a live turn heard during a delegated run lands between the run's tool\n * calls, see `isSpokenTurnTextPart`; it is the conversation, not narration).\n */\nfunction isAnswerTextPart(\n part: { readonly type: string } | undefined,\n index: number,\n lastToolIndex: number,\n): boolean {\n return part?.type === 'text' && (index > lastToolIndex || isSpokenTurnTextPart(part));\n}\n\n/**\n * The visible answer of a grouped turn: the text after the final tool call\n * (all of it when the turn never called a tool), plus the words of every\n * spoken voice turn in the message, in order. Other intermediate text (before\n * or between tool calls) stays available in the details panel.\n */\nexport function getFinalText(content: readonly FinalTextPart[] | undefined): string | null {\n const parts = getFinalTextParts(content);\n return parts.length > 0 ? parts.map((part) => part.text).join('\\n\\n') : null;\n}\n\n/** One text part of the visible answer, with its index in the message content. */\nexport interface FinalTextSegment {\n index: number;\n text: string;\n}\n\n/**\n * The parts `getFinalText` joins, each kept separate with its content index.\n * A spoken turn and the run's own reply can stream at the same time, so the\n * earlier part may grow while a later one exists: rendered as one joined\n * string, that text changes in the middle rather than at its end, and the\n * streaming reveal restarts from an empty bubble on every word.\n */\nexport function getFinalTextParts(content: readonly FinalTextPart[] | undefined): FinalTextSegment[] {\n if (!content?.length) return [];\n\n const lastToolIndex = content.findLastIndex((part) => part?.type === 'tool-call');\n const parts: FinalTextSegment[] = [];\n content.forEach((part, index) => {\n if (part.text && isAnswerTextPart(part, index, lastToolIndex)) parts.push({ index, text: part.text });\n });\n return parts;\n}\n\n/**\n * Keep the answer out of the details panel: it renders below the card\n * (`SuperGroupingFinalText`), so the details grouping drops every text part\n * `getFinalText` shows and any group that becomes empty.\n */\nexport function excludeFinalTextFromGroups(grouping: GroupingFunction): GroupingFunction {\n return (parts) => {\n const lastToolIndex = parts.findLastIndex((part) => part?.type === 'tool-call');\n return grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => !isAnswerTextPart(parts[index], index, lastToolIndex)),\n }))\n .filter((group) => group.indices.length > 0);\n };\n}\n\n/**\n * Drop the parts `exclude` matches from every group, and any group left\n * empty: `SuperGroupingCard` renders inline tool calls outside the details,\n * so they must not render a second time inside it.\n */\nexport function excludePartsFromGroups(\n grouping: GroupingFunction,\n exclude: (part: GroupablePart) => boolean,\n): GroupingFunction {\n return (parts) =>\n grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => {\n const part = parts[index];\n return part === undefined || !exclude(part);\n }),\n }))\n .filter((group) => group.indices.length > 0);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"activity-timeline.js","sources":["../../../src/chat/super-grouping/activity-timeline.ts"],"sourcesContent":["/**\n * The assistant turn's activity timeline — the one derivation of \"what did\n * this turn do, and how did each step end\" behind the collapsed view\n * (previously called the conversational view) on every surface: the SDK's\n * `AthenaChat`, Olympus's Spaces chat, and the Chrome extension. Pure\n * functions over assistant-ui message parts; `SuperGroupingCard` renders them.\n *\n * Step states come from the shared classifier (`classifyToolResult`) plus the\n * approval outcomes a part carries (`approval`, `interrupt`, a rejection\n * result), so a call that reads as failed, paused, or rejected on one surface\n * cannot read as a green check on another. Copy comes from the shared tool\n * summary registry (`summarizeToolCall`), itself built on the display\n * registry.\n */\nimport type {\n MessageStatus,\n ThreadAssistantMessagePart,\n ToolCallMessagePartStatus,\n} from '@assistant-ui/react';\nimport {\n classifyToolResult,\n countInEvalDispatches,\n EVAL_TOOL_NAME,\n isRunningToolPlaceholderArtifact,\n isSpokenTurnTextPart,\n readRejectedToolResult,\n TASK_TOOL_NAME,\n type ToolStatusLabelState,\n} from '@athenaintel/agent-runtime';\nimport { summarizeToolCall, type ToolCallSummary } from '../../tools/tool-summary';\nimport type { GroupablePart, GroupingFunction } from './grouping-function';\n\nexport type ActivityToolState = ToolStatusLabelState;\n\nexport type ActivityItem =\n | {\n kind: 'reasoning';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n text: string;\n state: 'running' | 'complete';\n }\n | {\n kind: 'tool';\n id?: string;\n /** Position of the part in the message's content. */\n partIndex?: number;\n toolName: string;\n args?: ToolCallPart['args'];\n /** The tool's real result; absent while it runs or holds only the streaming placeholder. */\n result?: unknown;\n state: ActivityToolState;\n /**\n * Subagents the call delegated to: for a `task` call one, or none when it\n * was refused, withdrawn or expired at its approval and never ran; for an\n * `eval` call its in-interpreter `task()` dispatches\n * (`countInEvalDispatches`), absent when it made none.\n */\n delegations?: number;\n };\n\n/** The turn as a whole: still working, parked on the person, ended in error, or done. */\nexport type ActivityPhase = 'running' | 'waiting' | 'complete' | 'error';\n\ntype ToolCallPart = Extract<ThreadAssistantMessagePart, { type: 'tool-call' }>;\n\nexport interface ActivityTimelineOptions {\n /**\n * Tools whose unresolved call means the turn is waiting on the person even\n * without an interrupt or approval on the part (the Chrome extension's\n * device plan approval, which the tool UI itself collects).\n */\n waitingTools?: ReadonlySet<string>;\n /**\n * Calls the run is parked on, by tool-call id, as the host reads them off\n * its pending approval: a gated call, or (in Olympus) a `task` call whose\n * subagent waits on an approval. Any of them still without its real result\n * reads as waiting.\n */\n waitingToolCallIds?: ReadonlySet<string>;\n /**\n * Tools whose result is an application payload relayed verbatim (the Chrome\n * extension's page JavaScript), so a `success: false` flag counts only with\n * an error detail — see `classifyToolResult`'s `passThroughPayload`.\n */\n passThroughTools?: ReadonlySet<string>;\n}\n\nconst NO_TOOLS: ReadonlySet<string> = new Set();\nconst NO_TOOL_CALLS: ReadonlySet<string> = new Set();\n\n/**\n * Whether a tool-call part still holds the backend's running-tool placeholder\n * result rather than the tool's real output. Long-running tools (task\n * subagents, studio and Python execution, deep research) append a ToolMessage\n * the moment they start so their card can fill in live; its marker reaches the\n * part's artifact (`isRunningToolPlaceholderArtifact`). The real ToolMessage\n * that replaces it has no such marker, so a defined `result` alone does not\n * mean the tool is done.\n */\nexport function isStreamingToolPlaceholder(part: Pick<ToolCallPart, 'artifact'>): boolean {\n return isRunningToolPlaceholderArtifact(part.artifact);\n}\n\n/** The tool's real result: undefined while it has none or only the streaming placeholder. */\nfunction finalResult(part: ToolCallPart): unknown {\n return isStreamingToolPlaceholder(part) ? undefined : part.result;\n}\n\nfunction toolCallStatus(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n): ToolCallMessagePartStatus | undefined {\n if (finalResult(part) !== undefined) return { type: 'complete' };\n if (messageStatus?.type === 'incomplete') {\n return {\n type: 'incomplete',\n reason: messageStatus.reason === 'tool-calls' ? 'other' : messageStatus.reason,\n error: messageStatus.error,\n };\n }\n if (messageStatus?.type === 'complete') {\n // The placeholder is the backend's word that the call is still in flight.\n // A turn reads `complete` whenever nothing streams (a run parked on an\n // approval inside a subagent, the gap before a drained run resumes), and\n // assistant-ui counts the placeholder as the call's result when it settles\n // that status, so the turn's status cannot finish the call.\n return isStreamingToolPlaceholder(part) ? { type: 'running' } : { type: 'complete' };\n }\n if (messageStatus?.type === 'requires-action') {\n return { type: 'requires-action', reason: messageStatus.reason };\n }\n if (messageStatus?.type === 'running') return { type: 'running' };\n return undefined;\n}\n\n/** How one tool call ended (or is going), reading the approval fields before the result. */\nexport function getActivityToolState(\n part: ToolCallPart,\n messageStatus: MessageStatus | undefined,\n {\n waitingTools = NO_TOOLS,\n waitingToolCallIds = NO_TOOL_CALLS,\n passThroughTools = NO_TOOLS,\n }: ActivityTimelineOptions = {},\n): ActivityToolState {\n if (part.approval?.approved === false || readRejectedToolResult(part.result) !== null) {\n return 'rejected';\n }\n if (part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired') {\n return 'cancelled';\n }\n const result = finalResult(part);\n const unresolved = result === undefined;\n const messageIsActive =\n messageStatus === undefined ||\n messageStatus.type === 'running' ||\n messageStatus.type === 'requires-action';\n if (\n unresolved &&\n (part.interrupt?.type === 'human' ||\n (part.approval !== undefined &&\n part.approval.approved === undefined &&\n part.approval.resolution === undefined) ||\n waitingToolCallIds.has(part.toolCallId) ||\n (waitingTools.has(part.toolName) && messageIsActive))\n ) {\n return 'waiting';\n }\n\n const classification = classifyToolResult({\n status: toolCallStatus(part, messageStatus),\n result,\n isError: part.isError,\n passThroughPayload: passThroughTools.has(part.toolName),\n });\n if (classification.state === 'requires-action') return 'waiting';\n return classification.state;\n}\n\n/**\n * The compact reasoning/tool timeline in the order the parts streamed.\n *\n * A reasoning part is still streaming only while it is the final part of a\n * running message — once any later part appears, the thought has settled.\n * Settled reasoning parts with no text are dropped so the list never shows an\n * empty thinking row.\n */\nexport function buildActivityTimeline(\n content: readonly ThreadAssistantMessagePart[] | undefined,\n messageStatus: MessageStatus | undefined,\n options: ActivityTimelineOptions = {},\n): ActivityItem[] {\n if (!content?.length) return [];\n\n const lastPartIndex = content.length - 1;\n const timeline: ActivityItem[] = [];\n for (let index = 0; index < content.length; index += 1) {\n const part = content[index];\n if (part.type === 'tool-call') {\n const result = finalResult(part);\n const state = getActivityToolState(part, messageStatus, options);\n const delegations = toolCallDelegations({ part, state });\n timeline.push({\n kind: 'tool',\n id: part.toolCallId,\n partIndex: index,\n args: part.args,\n ...(result !== undefined ? { result } : {}),\n toolName: part.toolName,\n state,\n ...(delegations !== null ? { delegations } : {}),\n });\n continue;\n }\n if (part.type !== 'reasoning') continue;\n\n const text = typeof part.text === 'string' ? part.text : '';\n const stillStreaming = messageStatus?.type === 'running' && index === lastPartIndex;\n if (!stillStreaming && text.trim() === '') continue;\n timeline.push({\n kind: 'reasoning',\n id: `reasoning-${index}`,\n partIndex: index,\n text,\n state: stillStreaming ? 'running' : 'complete',\n });\n }\n return timeline;\n}\n\n/**\n * Subagents one tool call delegated to (see `ActivityItem.delegations`), or\n * `null` for a call that delegates by nature of neither: a `task` call one,\n * unless the person refused it or its approval was withdrawn or expired (it\n * never ran); an `eval` call its in-interpreter dispatches, when it made any.\n */\nfunction toolCallDelegations({\n part,\n state,\n}: {\n part: ToolCallPart;\n state: ActivityToolState;\n}): number | null {\n if (part.toolName === TASK_TOOL_NAME) {\n const withdrawn =\n part.approval?.resolution === 'cancelled' || part.approval?.resolution === 'expired';\n return state === 'rejected' || withdrawn ? 0 : 1;\n }\n if (part.toolName === EVAL_TOOL_NAME) {\n const dispatches = countInEvalDispatches(part.artifact);\n return dispatches > 0 ? dispatches : null;\n }\n return null;\n}\n\n/** Number of tool calls in the timeline. */\nexport function countActivityTools(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => (item.kind === 'tool' ? count + 1 : count), 0);\n}\n\n/**\n * Subagents the turn delegated to: its `task` calls that ran, plus the\n * `task()` dispatches its `eval` calls made from inside the interpreter. A\n * `task` step built without its count (a host's own timeline) counts unless it\n * reads refused or cancelled.\n */\nexport function countActivityDelegations(timeline: readonly ActivityItem[]): number {\n return timeline.reduce((count, item) => {\n if (item.kind !== 'tool') return count;\n if (item.delegations !== undefined) return count + item.delegations;\n const ranTask =\n item.toolName === TASK_TOOL_NAME && item.state !== 'rejected' && item.state !== 'cancelled';\n return ranTask ? count + 1 : count;\n }, 0);\n}\n\n/**\n * The turn's phase. Waiting on the person wins over everything — a\n * `requires-action` status, a waiting tool, or a host's own `waitingForInput`\n * assertion (no in-repo host passes one) — then the message's own status. A\n * complete turn with a step still running is running: only a step holding the\n * backend's running placeholder reads so once nothing streams (a run parked on\n * an approval inside a subagent, the gap before a drained run resumes).\n */\nexport function resolveActivityPhase(\n status: MessageStatus | undefined,\n timeline: readonly ActivityItem[],\n { waitingForInput = false }: { waitingForInput?: boolean } = {},\n): ActivityPhase {\n if (\n waitingForInput ||\n status?.type === 'requires-action' ||\n timeline.some((item) => item.kind === 'tool' && item.state === 'waiting')\n ) {\n return 'waiting';\n }\n if (status?.type === 'running') return 'running';\n if (status?.type === 'incomplete') return 'error';\n if (\n status?.type === 'complete' &&\n timeline.some((item) => item.kind === 'tool' && item.state === 'running')\n ) {\n return 'running';\n }\n return 'complete';\n}\n\n/**\n * A settled thought's row: the heading a reasoning summary opens with\n * (\"**Checking the workstation**\" → \"Checking the workstation\"), else the\n * generic wording. The thought itself stays in the run's details.\n */\nexport function getReasoningLabel(text: string, state: 'running' | 'complete'): string {\n if (state === 'running') return 'Thinking';\n const heading = /^\\s*\\*\\*([^*\\n]{3,80}?)\\*\\*/.exec(text)?.[1]?.trim();\n return heading ? heading.replace(/[.:]+$/, '') : 'Thought through the next step';\n}\n\n/**\n * The status-row copy for one step: the call's own summary from the shared\n * summary registry (`summarizeToolCall`: \"Ran git status\", \"Read config.ts\").\n * `resolveToolDisplayName` lets a host with a richer tool catalog name tools\n * neither registry has an entry for; `assetTitles` names the machine or\n * document a call targeted by id when an earlier result in the turn did.\n */\nexport function getActivityItemLabel(\n item: ActivityItem,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): string {\n if (item.kind === 'reasoning') return getReasoningLabel(item.text, item.state);\n return summarizeActivityTool(item, resolveToolDisplayName, assetTitles).label;\n}\n\n/** The summary of one tool step (see {@link getActivityItemLabel}). */\nexport function summarizeActivityTool(\n item: Extract<ActivityItem, { kind: 'tool' }>,\n resolveToolDisplayName?: (toolName: string) => string | undefined,\n assetTitles?: ReadonlyMap<string, string>,\n): ToolCallSummary {\n return summarizeToolCall({\n toolName: item.toolName,\n args: item.args,\n result: item.result,\n status: item.state,\n ...(assetTitles ? { assetTitles } : {}),\n ...(resolveToolDisplayName ? { displayName: resolveToolDisplayName(item.toolName) } : {}),\n });\n}\n\n/**\n * The collapsed-card summary of a finished turn. \"Completed with issues\" means\n * the turn ended on a problem: a call the person refused, or a failed call\n * that no later call completed after. A failed command the agent then got past\n * (a search that found nothing, a retry that worked) is ordinary work, so a\n * long turn that recovered from it reads as the tools it used.\n *\n * A turn that delegated work leads with it — \"Delegated to 10 agents · used 6\n * tools\" — counting its `task` calls and the `task()` dispatches its `eval`\n * calls made from inside the interpreter (`countActivityDelegations`). A\n * `task` call is the delegation itself, so the tools it is followed by are the\n * turn's other calls; an outcome above replaces them (\"Delegated to 3 agents ·\n * completed with issues\").\n */\nexport function getActivitySummary(timeline: readonly ActivityItem[]): string {\n const tools = timeline.filter((item): item is ToolActivityItem => item.kind === 'tool');\n const outcome = activityOutcome(tools);\n const delegations = countActivityDelegations(timeline);\n if (delegations > 0) {\n const lead = `Delegated to ${delegations} ${delegations === 1 ? 'agent' : 'agents'}`;\n const otherTools = tools.filter((item) => item.toolName !== TASK_TOOL_NAME).length;\n const rest = outcome\n ? `${outcome.charAt(0).toLowerCase()}${outcome.slice(1)}`\n : otherTools > 0\n ? `used ${otherTools} ${otherTools === 1 ? 'tool' : 'tools'}`\n : null;\n return rest ? `${lead} · ${rest}` : lead;\n }\n if (outcome) return outcome;\n if (tools.length > 0) return `Used ${tools.length} ${tools.length === 1 ? 'tool' : 'tools'}`;\n return 'Reasoning complete';\n}\n\ntype ToolActivityItem = Extract<ActivityItem, { kind: 'tool' }>;\n\n/** How a finished turn's tool calls ended, when that is not simply the tools it used. */\nfunction activityOutcome(tools: readonly ToolActivityItem[]): string | null {\n const lastFailure = tools.findLastIndex((item) => item.state === 'error');\n const endedOnFailure =\n lastFailure >= 0 && !tools.slice(lastFailure + 1).some((item) => item.state === 'complete');\n if (endedOnFailure || tools.some((item) => item.state === 'rejected')) return 'Completed with issues';\n if (tools.some((item) => item.state === 'cancelled')) return 'Action cancelled';\n if (tools.some((item) => item.state === 'paused')) return 'Paused during tool use';\n return null;\n}\n\n/** The part shape the final-text read needs; any message role's parts satisfy it. */\nexport type FinalTextPart = { readonly type: string; readonly text?: string };\n\n/**\n * Whether a text part shows below the card instead of in the details panel:\n * it comes after the final tool call, or it holds a spoken voice turn's words\n * (a live turn heard during a delegated run lands between the run's tool\n * calls, see `isSpokenTurnTextPart`; it is the conversation, not narration).\n */\nfunction isAnswerTextPart(\n part: { readonly type: string } | undefined,\n index: number,\n lastToolIndex: number,\n): boolean {\n return part?.type === 'text' && (index > lastToolIndex || isSpokenTurnTextPart(part));\n}\n\n/**\n * The visible answer of a grouped turn: the text after the final tool call\n * (all of it when the turn never called a tool), plus the words of every\n * spoken voice turn in the message, in order. Other intermediate text (before\n * or between tool calls) stays available in the details panel.\n */\nexport function getFinalText(content: readonly FinalTextPart[] | undefined): string | null {\n const parts = getFinalTextParts(content);\n return parts.length > 0 ? parts.map((part) => part.text).join('\\n\\n') : null;\n}\n\n/** One text part of the visible answer, with its index in the message content. */\nexport interface FinalTextSegment {\n index: number;\n text: string;\n}\n\n/**\n * The parts `getFinalText` joins, each kept separate with its content index.\n * A spoken turn and the run's own reply can stream at the same time, so the\n * earlier part may grow while a later one exists: rendered as one joined\n * string, that text changes in the middle rather than at its end, and the\n * streaming reveal restarts from an empty bubble on every word.\n */\nexport function getFinalTextParts(content: readonly FinalTextPart[] | undefined): FinalTextSegment[] {\n if (!content?.length) return [];\n\n const lastToolIndex = content.findLastIndex((part) => part?.type === 'tool-call');\n const parts: FinalTextSegment[] = [];\n content.forEach((part, index) => {\n if (part.text && isAnswerTextPart(part, index, lastToolIndex)) parts.push({ index, text: part.text });\n });\n return parts;\n}\n\n/**\n * Keep the answer out of the details panel: it renders below the card\n * (`SuperGroupingFinalText`), so the details grouping drops every text part\n * `getFinalText` shows and any group that becomes empty.\n */\nexport function excludeFinalTextFromGroups(grouping: GroupingFunction): GroupingFunction {\n return (parts) => {\n const lastToolIndex = parts.findLastIndex((part) => part?.type === 'tool-call');\n return grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => !isAnswerTextPart(parts[index], index, lastToolIndex)),\n }))\n .filter((group) => group.indices.length > 0);\n };\n}\n\n/**\n * Drop the parts `exclude` matches from every group, and any group left\n * empty: `SuperGroupingCard` renders inline tool calls outside the details,\n * so they must not render a second time inside it.\n */\nexport function excludePartsFromGroups(\n grouping: GroupingFunction,\n exclude: (part: GroupablePart) => boolean,\n): GroupingFunction {\n return (parts) =>\n grouping(parts)\n .map((group) => ({\n ...group,\n indices: group.indices.filter((index) => {\n const part = parts[index];\n return part === undefined || !exclude(part);\n }),\n }))\n .filter((group) => group.indices.length > 0);\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function isGroupedToolCallPart(part) {
4
+ return part.type === "tool-call" && typeof part.toolName === "string" && "toolCallId" in part && typeof part.toolCallId === "string";
5
+ }
3
6
  const createToolBasedGroupingFunction = (getToolGroupKey) => (parts) => {
4
7
  const calledToolNames = /* @__PURE__ */ new Set();
5
8
  for (const part of parts) {
@@ -52,4 +55,5 @@ const createToolBasedGroupingFunction = (getToolGroupKey) => (parts) => {
52
55
  return groups;
53
56
  };
54
57
  exports.createToolBasedGroupingFunction = createToolBasedGroupingFunction;
58
+ exports.isGroupedToolCallPart = isGroupedToolCallPart;
55
59
  //# sourceMappingURL=grouping-function.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"grouping-function.cjs","sources":["../../../src/chat/super-grouping/grouping-function.ts"],"sourcesContent":["import type { GetToolGroupKey } from './toolkit-map';\n\n/** The part shape grouping needs; assistant-ui's `ThreadAssistantMessagePart` satisfies it. */\nexport type GroupablePart = {\n type: string;\n toolName?: string;\n};\n\n/** One group `MessagePrimitive.Unstable_PartsGrouped` renders through its `Group` component. */\nexport type MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\n/** The grouping contract `MessagePrimitive.Unstable_PartsGrouped` consumes. */\nexport type GroupingFunction = (parts: readonly GroupablePart[]) => MessagePartGroup[];\n\n/**\n * Groups adjacent parts by their toolkit group key: reasoning parts join the\n * open group, and a text part joins when the tool calls on both sides of it\n * share a key. Every `getToolGroupKey` call sees the open group's key and the\n * set of tools the message called, so a tool shared by several toolkits can\n * resolve to the one actually in play (Olympus attributes shared citation\n * tools to the enabled toolkit that way).\n */\nexport const createToolBasedGroupingFunction =\n (getToolGroupKey: GetToolGroupKey): GroupingFunction =>\n (parts) => {\n const calledToolNames = new Set<string>();\n for (const part of parts) {\n if (part.type === 'tool-call' && part.toolName) calledToolNames.add(part.toolName);\n }\n\n const groups: MessagePartGroup[] = [];\n let currentGroup: MessagePartGroup | null = null;\n\n for (let idx = 0; idx < parts.length; idx++) {\n const part = parts[idx];\n\n // Reasoning parts join the current group (if any).\n if (part?.type === 'reasoning') {\n if (currentGroup) {\n currentGroup.indices.push(idx);\n } else {\n groups.push({ groupKey: undefined, indices: [idx] });\n }\n continue;\n }\n\n let key: string | undefined;\n\n if (part?.type === 'tool-call' && part.toolName) {\n key = getToolGroupKey(part.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n } else if (part?.type === 'text') {\n const prevKey = currentGroup?.groupKey;\n\n let nextKey: string | undefined;\n for (let lookIdx = idx + 1; lookIdx < parts.length; lookIdx++) {\n const lookPart = parts[lookIdx];\n if (lookPart?.type === 'reasoning' || lookPart?.type === 'text') continue;\n if (lookPart?.type === 'tool-call' && lookPart.toolName) {\n nextKey = getToolGroupKey(lookPart.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n }\n break;\n }\n\n if (prevKey && nextKey && prevKey === nextKey) {\n key = prevKey;\n }\n }\n\n if (currentGroup && currentGroup.groupKey === key) {\n currentGroup.indices.push(idx);\n } else {\n if (currentGroup) groups.push(currentGroup);\n currentGroup = { groupKey: key, indices: [idx] };\n }\n }\n if (currentGroup) groups.push(currentGroup);\n return groups;\n };\n"],"names":[],"mappings":";;AAyBO,MAAM,kCACX,CAAC,oBACD,CAAC,UAAU;AACT,QAAM,sCAAsB,IAAA;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAU,iBAAgB,IAAI,KAAK,QAAQ;AAAA,EACnF;AAEA,QAAM,SAA6B,CAAA;AACnC,MAAI,eAAwC;AAE5C,WAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,OAAO;AAC3C,UAAM,OAAO,MAAM,GAAG;AAGtB,SAAI,6BAAM,UAAS,aAAa;AAC9B,UAAI,cAAc;AAChB,qBAAa,QAAQ,KAAK,GAAG;AAAA,MAC/B,OAAO;AACL,eAAO,KAAK,EAAE,UAAU,QAAW,SAAS,CAAC,GAAG,GAAG;AAAA,MACrD;AACA;AAAA,IACF;AAEA,QAAI;AAEJ,SAAI,6BAAM,UAAS,eAAe,KAAK,UAAU;AAC/C,YAAM,gBAAgB,KAAK,UAAU;AAAA,QACnC,mBAAmB,6CAAc;AAAA,QACjC;AAAA,MAAA,CACD;AAAA,IACH,YAAW,6BAAM,UAAS,QAAQ;AAChC,YAAM,UAAU,6CAAc;AAE9B,UAAI;AACJ,eAAS,UAAU,MAAM,GAAG,UAAU,MAAM,QAAQ,WAAW;AAC7D,cAAM,WAAW,MAAM,OAAO;AAC9B,aAAI,qCAAU,UAAS,gBAAe,qCAAU,UAAS,OAAQ;AACjE,aAAI,qCAAU,UAAS,eAAe,SAAS,UAAU;AACvD,oBAAU,gBAAgB,SAAS,UAAU;AAAA,YAC3C,mBAAmB,6CAAc;AAAA,YACjC;AAAA,UAAA,CACD;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,YAAY,SAAS;AAC7C,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,gBAAgB,aAAa,aAAa,KAAK;AACjD,mBAAa,QAAQ,KAAK,GAAG;AAAA,IAC/B,OAAO;AACL,UAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,qBAAe,EAAE,UAAU,KAAK,SAAS,CAAC,GAAG,EAAA;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,SAAO;AACT;;"}
1
+ {"version":3,"file":"grouping-function.cjs","sources":["../../../src/chat/super-grouping/grouping-function.ts"],"sourcesContent":["import type { ToolCallMessagePart } from '@assistant-ui/react';\nimport type { GetToolGroupKey } from './toolkit-map';\n\n/** The part shape grouping needs; assistant-ui's `ThreadAssistantMessagePart` satisfies it. */\nexport type GroupablePart = {\n type: string;\n toolName?: string;\n};\n\n/**\n * Whether a part a grouping function was handed is a tool call. The parts it\n * groups are the message's own, so a tool call carries the whole call (its id,\n * its artifact), which a host's per-call predicate reads (`isInlineTool`).\n */\nexport function isGroupedToolCallPart(part: GroupablePart): part is ToolCallMessagePart {\n return (\n part.type === 'tool-call' &&\n typeof part.toolName === 'string' &&\n 'toolCallId' in part &&\n typeof part.toolCallId === 'string'\n );\n}\n\n/** One group `MessagePrimitive.Unstable_PartsGrouped` renders through its `Group` component. */\nexport type MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\n/** The grouping contract `MessagePrimitive.Unstable_PartsGrouped` consumes. */\nexport type GroupingFunction = (parts: readonly GroupablePart[]) => MessagePartGroup[];\n\n/**\n * Groups adjacent parts by their toolkit group key: reasoning parts join the\n * open group, and a text part joins when the tool calls on both sides of it\n * share a key. Every `getToolGroupKey` call sees the open group's key and the\n * set of tools the message called, so a tool shared by several toolkits can\n * resolve to the one actually in play (Olympus attributes shared citation\n * tools to the enabled toolkit that way).\n */\nexport const createToolBasedGroupingFunction =\n (getToolGroupKey: GetToolGroupKey): GroupingFunction =>\n (parts) => {\n const calledToolNames = new Set<string>();\n for (const part of parts) {\n if (part.type === 'tool-call' && part.toolName) calledToolNames.add(part.toolName);\n }\n\n const groups: MessagePartGroup[] = [];\n let currentGroup: MessagePartGroup | null = null;\n\n for (let idx = 0; idx < parts.length; idx++) {\n const part = parts[idx];\n\n // Reasoning parts join the current group (if any).\n if (part?.type === 'reasoning') {\n if (currentGroup) {\n currentGroup.indices.push(idx);\n } else {\n groups.push({ groupKey: undefined, indices: [idx] });\n }\n continue;\n }\n\n let key: string | undefined;\n\n if (part?.type === 'tool-call' && part.toolName) {\n key = getToolGroupKey(part.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n } else if (part?.type === 'text') {\n const prevKey = currentGroup?.groupKey;\n\n let nextKey: string | undefined;\n for (let lookIdx = idx + 1; lookIdx < parts.length; lookIdx++) {\n const lookPart = parts[lookIdx];\n if (lookPart?.type === 'reasoning' || lookPart?.type === 'text') continue;\n if (lookPart?.type === 'tool-call' && lookPart.toolName) {\n nextKey = getToolGroupKey(lookPart.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n }\n break;\n }\n\n if (prevKey && nextKey && prevKey === nextKey) {\n key = prevKey;\n }\n }\n\n if (currentGroup && currentGroup.groupKey === key) {\n currentGroup.indices.push(idx);\n } else {\n if (currentGroup) groups.push(currentGroup);\n currentGroup = { groupKey: key, indices: [idx] };\n }\n }\n if (currentGroup) groups.push(currentGroup);\n return groups;\n };\n"],"names":[],"mappings":";;AAcO,SAAS,sBAAsB,MAAkD;AACtF,SACE,KAAK,SAAS,eACd,OAAO,KAAK,aAAa,YACzB,gBAAgB,QAChB,OAAO,KAAK,eAAe;AAE/B;AAmBO,MAAM,kCACX,CAAC,oBACD,CAAC,UAAU;AACT,QAAM,sCAAsB,IAAA;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAU,iBAAgB,IAAI,KAAK,QAAQ;AAAA,EACnF;AAEA,QAAM,SAA6B,CAAA;AACnC,MAAI,eAAwC;AAE5C,WAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,OAAO;AAC3C,UAAM,OAAO,MAAM,GAAG;AAGtB,SAAI,6BAAM,UAAS,aAAa;AAC9B,UAAI,cAAc;AAChB,qBAAa,QAAQ,KAAK,GAAG;AAAA,MAC/B,OAAO;AACL,eAAO,KAAK,EAAE,UAAU,QAAW,SAAS,CAAC,GAAG,GAAG;AAAA,MACrD;AACA;AAAA,IACF;AAEA,QAAI;AAEJ,SAAI,6BAAM,UAAS,eAAe,KAAK,UAAU;AAC/C,YAAM,gBAAgB,KAAK,UAAU;AAAA,QACnC,mBAAmB,6CAAc;AAAA,QACjC;AAAA,MAAA,CACD;AAAA,IACH,YAAW,6BAAM,UAAS,QAAQ;AAChC,YAAM,UAAU,6CAAc;AAE9B,UAAI;AACJ,eAAS,UAAU,MAAM,GAAG,UAAU,MAAM,QAAQ,WAAW;AAC7D,cAAM,WAAW,MAAM,OAAO;AAC9B,aAAI,qCAAU,UAAS,gBAAe,qCAAU,UAAS,OAAQ;AACjE,aAAI,qCAAU,UAAS,eAAe,SAAS,UAAU;AACvD,oBAAU,gBAAgB,SAAS,UAAU;AAAA,YAC3C,mBAAmB,6CAAc;AAAA,YACjC;AAAA,UAAA,CACD;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,YAAY,SAAS;AAC7C,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,gBAAgB,aAAa,aAAa,KAAK;AACjD,mBAAa,QAAQ,KAAK,GAAG;AAAA,IAC/B,OAAO;AACL,UAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,qBAAe,EAAE,UAAU,KAAK,SAAS,CAAC,GAAG,EAAA;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,SAAO;AACT;;;"}
@@ -1,9 +1,16 @@
1
+ import type { ToolCallMessagePart } from '@assistant-ui/react';
1
2
  import type { GetToolGroupKey } from './toolkit-map';
2
3
  /** The part shape grouping needs; assistant-ui's `ThreadAssistantMessagePart` satisfies it. */
3
4
  export type GroupablePart = {
4
5
  type: string;
5
6
  toolName?: string;
6
7
  };
8
+ /**
9
+ * Whether a part a grouping function was handed is a tool call. The parts it
10
+ * groups are the message's own, so a tool call carries the whole call (its id,
11
+ * its artifact), which a host's per-call predicate reads (`isInlineTool`).
12
+ */
13
+ export declare function isGroupedToolCallPart(part: GroupablePart): part is ToolCallMessagePart;
7
14
  /** One group `MessagePrimitive.Unstable_PartsGrouped` renders through its `Group` component. */
8
15
  export type MessagePartGroup = {
9
16
  groupKey: string | undefined;
@@ -1,3 +1,6 @@
1
+ function isGroupedToolCallPart(part) {
2
+ return part.type === "tool-call" && typeof part.toolName === "string" && "toolCallId" in part && typeof part.toolCallId === "string";
3
+ }
1
4
  const createToolBasedGroupingFunction = (getToolGroupKey) => (parts) => {
2
5
  const calledToolNames = /* @__PURE__ */ new Set();
3
6
  for (const part of parts) {
@@ -50,6 +53,7 @@ const createToolBasedGroupingFunction = (getToolGroupKey) => (parts) => {
50
53
  return groups;
51
54
  };
52
55
  export {
53
- createToolBasedGroupingFunction
56
+ createToolBasedGroupingFunction,
57
+ isGroupedToolCallPart
54
58
  };
55
59
  //# sourceMappingURL=grouping-function.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grouping-function.js","sources":["../../../src/chat/super-grouping/grouping-function.ts"],"sourcesContent":["import type { GetToolGroupKey } from './toolkit-map';\n\n/** The part shape grouping needs; assistant-ui's `ThreadAssistantMessagePart` satisfies it. */\nexport type GroupablePart = {\n type: string;\n toolName?: string;\n};\n\n/** One group `MessagePrimitive.Unstable_PartsGrouped` renders through its `Group` component. */\nexport type MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\n/** The grouping contract `MessagePrimitive.Unstable_PartsGrouped` consumes. */\nexport type GroupingFunction = (parts: readonly GroupablePart[]) => MessagePartGroup[];\n\n/**\n * Groups adjacent parts by their toolkit group key: reasoning parts join the\n * open group, and a text part joins when the tool calls on both sides of it\n * share a key. Every `getToolGroupKey` call sees the open group's key and the\n * set of tools the message called, so a tool shared by several toolkits can\n * resolve to the one actually in play (Olympus attributes shared citation\n * tools to the enabled toolkit that way).\n */\nexport const createToolBasedGroupingFunction =\n (getToolGroupKey: GetToolGroupKey): GroupingFunction =>\n (parts) => {\n const calledToolNames = new Set<string>();\n for (const part of parts) {\n if (part.type === 'tool-call' && part.toolName) calledToolNames.add(part.toolName);\n }\n\n const groups: MessagePartGroup[] = [];\n let currentGroup: MessagePartGroup | null = null;\n\n for (let idx = 0; idx < parts.length; idx++) {\n const part = parts[idx];\n\n // Reasoning parts join the current group (if any).\n if (part?.type === 'reasoning') {\n if (currentGroup) {\n currentGroup.indices.push(idx);\n } else {\n groups.push({ groupKey: undefined, indices: [idx] });\n }\n continue;\n }\n\n let key: string | undefined;\n\n if (part?.type === 'tool-call' && part.toolName) {\n key = getToolGroupKey(part.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n } else if (part?.type === 'text') {\n const prevKey = currentGroup?.groupKey;\n\n let nextKey: string | undefined;\n for (let lookIdx = idx + 1; lookIdx < parts.length; lookIdx++) {\n const lookPart = parts[lookIdx];\n if (lookPart?.type === 'reasoning' || lookPart?.type === 'text') continue;\n if (lookPart?.type === 'tool-call' && lookPart.toolName) {\n nextKey = getToolGroupKey(lookPart.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n }\n break;\n }\n\n if (prevKey && nextKey && prevKey === nextKey) {\n key = prevKey;\n }\n }\n\n if (currentGroup && currentGroup.groupKey === key) {\n currentGroup.indices.push(idx);\n } else {\n if (currentGroup) groups.push(currentGroup);\n currentGroup = { groupKey: key, indices: [idx] };\n }\n }\n if (currentGroup) groups.push(currentGroup);\n return groups;\n };\n"],"names":[],"mappings":"AAyBO,MAAM,kCACX,CAAC,oBACD,CAAC,UAAU;AACT,QAAM,sCAAsB,IAAA;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAU,iBAAgB,IAAI,KAAK,QAAQ;AAAA,EACnF;AAEA,QAAM,SAA6B,CAAA;AACnC,MAAI,eAAwC;AAE5C,WAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,OAAO;AAC3C,UAAM,OAAO,MAAM,GAAG;AAGtB,SAAI,6BAAM,UAAS,aAAa;AAC9B,UAAI,cAAc;AAChB,qBAAa,QAAQ,KAAK,GAAG;AAAA,MAC/B,OAAO;AACL,eAAO,KAAK,EAAE,UAAU,QAAW,SAAS,CAAC,GAAG,GAAG;AAAA,MACrD;AACA;AAAA,IACF;AAEA,QAAI;AAEJ,SAAI,6BAAM,UAAS,eAAe,KAAK,UAAU;AAC/C,YAAM,gBAAgB,KAAK,UAAU;AAAA,QACnC,mBAAmB,6CAAc;AAAA,QACjC;AAAA,MAAA,CACD;AAAA,IACH,YAAW,6BAAM,UAAS,QAAQ;AAChC,YAAM,UAAU,6CAAc;AAE9B,UAAI;AACJ,eAAS,UAAU,MAAM,GAAG,UAAU,MAAM,QAAQ,WAAW;AAC7D,cAAM,WAAW,MAAM,OAAO;AAC9B,aAAI,qCAAU,UAAS,gBAAe,qCAAU,UAAS,OAAQ;AACjE,aAAI,qCAAU,UAAS,eAAe,SAAS,UAAU;AACvD,oBAAU,gBAAgB,SAAS,UAAU;AAAA,YAC3C,mBAAmB,6CAAc;AAAA,YACjC;AAAA,UAAA,CACD;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,YAAY,SAAS;AAC7C,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,gBAAgB,aAAa,aAAa,KAAK;AACjD,mBAAa,QAAQ,KAAK,GAAG;AAAA,IAC/B,OAAO;AACL,UAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,qBAAe,EAAE,UAAU,KAAK,SAAS,CAAC,GAAG,EAAA;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,SAAO;AACT;"}
1
+ {"version":3,"file":"grouping-function.js","sources":["../../../src/chat/super-grouping/grouping-function.ts"],"sourcesContent":["import type { ToolCallMessagePart } from '@assistant-ui/react';\nimport type { GetToolGroupKey } from './toolkit-map';\n\n/** The part shape grouping needs; assistant-ui's `ThreadAssistantMessagePart` satisfies it. */\nexport type GroupablePart = {\n type: string;\n toolName?: string;\n};\n\n/**\n * Whether a part a grouping function was handed is a tool call. The parts it\n * groups are the message's own, so a tool call carries the whole call (its id,\n * its artifact), which a host's per-call predicate reads (`isInlineTool`).\n */\nexport function isGroupedToolCallPart(part: GroupablePart): part is ToolCallMessagePart {\n return (\n part.type === 'tool-call' &&\n typeof part.toolName === 'string' &&\n 'toolCallId' in part &&\n typeof part.toolCallId === 'string'\n );\n}\n\n/** One group `MessagePrimitive.Unstable_PartsGrouped` renders through its `Group` component. */\nexport type MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\n/** The grouping contract `MessagePrimitive.Unstable_PartsGrouped` consumes. */\nexport type GroupingFunction = (parts: readonly GroupablePart[]) => MessagePartGroup[];\n\n/**\n * Groups adjacent parts by their toolkit group key: reasoning parts join the\n * open group, and a text part joins when the tool calls on both sides of it\n * share a key. Every `getToolGroupKey` call sees the open group's key and the\n * set of tools the message called, so a tool shared by several toolkits can\n * resolve to the one actually in play (Olympus attributes shared citation\n * tools to the enabled toolkit that way).\n */\nexport const createToolBasedGroupingFunction =\n (getToolGroupKey: GetToolGroupKey): GroupingFunction =>\n (parts) => {\n const calledToolNames = new Set<string>();\n for (const part of parts) {\n if (part.type === 'tool-call' && part.toolName) calledToolNames.add(part.toolName);\n }\n\n const groups: MessagePartGroup[] = [];\n let currentGroup: MessagePartGroup | null = null;\n\n for (let idx = 0; idx < parts.length; idx++) {\n const part = parts[idx];\n\n // Reasoning parts join the current group (if any).\n if (part?.type === 'reasoning') {\n if (currentGroup) {\n currentGroup.indices.push(idx);\n } else {\n groups.push({ groupKey: undefined, indices: [idx] });\n }\n continue;\n }\n\n let key: string | undefined;\n\n if (part?.type === 'tool-call' && part.toolName) {\n key = getToolGroupKey(part.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n } else if (part?.type === 'text') {\n const prevKey = currentGroup?.groupKey;\n\n let nextKey: string | undefined;\n for (let lookIdx = idx + 1; lookIdx < parts.length; lookIdx++) {\n const lookPart = parts[lookIdx];\n if (lookPart?.type === 'reasoning' || lookPart?.type === 'text') continue;\n if (lookPart?.type === 'tool-call' && lookPart.toolName) {\n nextKey = getToolGroupKey(lookPart.toolName, {\n preferredGroupKey: currentGroup?.groupKey,\n calledToolNames,\n });\n }\n break;\n }\n\n if (prevKey && nextKey && prevKey === nextKey) {\n key = prevKey;\n }\n }\n\n if (currentGroup && currentGroup.groupKey === key) {\n currentGroup.indices.push(idx);\n } else {\n if (currentGroup) groups.push(currentGroup);\n currentGroup = { groupKey: key, indices: [idx] };\n }\n }\n if (currentGroup) groups.push(currentGroup);\n return groups;\n };\n"],"names":[],"mappings":"AAcO,SAAS,sBAAsB,MAAkD;AACtF,SACE,KAAK,SAAS,eACd,OAAO,KAAK,aAAa,YACzB,gBAAgB,QAChB,OAAO,KAAK,eAAe;AAE/B;AAmBO,MAAM,kCACX,CAAC,oBACD,CAAC,UAAU;AACT,QAAM,sCAAsB,IAAA;AAC5B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,eAAe,KAAK,SAAU,iBAAgB,IAAI,KAAK,QAAQ;AAAA,EACnF;AAEA,QAAM,SAA6B,CAAA;AACnC,MAAI,eAAwC;AAE5C,WAAS,MAAM,GAAG,MAAM,MAAM,QAAQ,OAAO;AAC3C,UAAM,OAAO,MAAM,GAAG;AAGtB,SAAI,6BAAM,UAAS,aAAa;AAC9B,UAAI,cAAc;AAChB,qBAAa,QAAQ,KAAK,GAAG;AAAA,MAC/B,OAAO;AACL,eAAO,KAAK,EAAE,UAAU,QAAW,SAAS,CAAC,GAAG,GAAG;AAAA,MACrD;AACA;AAAA,IACF;AAEA,QAAI;AAEJ,SAAI,6BAAM,UAAS,eAAe,KAAK,UAAU;AAC/C,YAAM,gBAAgB,KAAK,UAAU;AAAA,QACnC,mBAAmB,6CAAc;AAAA,QACjC;AAAA,MAAA,CACD;AAAA,IACH,YAAW,6BAAM,UAAS,QAAQ;AAChC,YAAM,UAAU,6CAAc;AAE9B,UAAI;AACJ,eAAS,UAAU,MAAM,GAAG,UAAU,MAAM,QAAQ,WAAW;AAC7D,cAAM,WAAW,MAAM,OAAO;AAC9B,aAAI,qCAAU,UAAS,gBAAe,qCAAU,UAAS,OAAQ;AACjE,aAAI,qCAAU,UAAS,eAAe,SAAS,UAAU;AACvD,oBAAU,gBAAgB,SAAS,UAAU;AAAA,YAC3C,mBAAmB,6CAAc;AAAA,YACjC;AAAA,UAAA,CACD;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,YAAY,SAAS;AAC7C,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI,gBAAgB,aAAa,aAAa,KAAK;AACjD,mBAAa,QAAQ,KAAK,GAAG;AAAA,IAC/B,OAAO;AACL,UAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,qBAAe,EAAE,UAAU,KAAK,SAAS,CAAC,GAAG,EAAA;AAAA,IAC/C;AAAA,EACF;AACA,MAAI,aAAc,QAAO,KAAK,YAAY;AAC1C,SAAO;AACT;"}
@@ -6,10 +6,13 @@ const GroupedMessageParts = require("./GroupedMessageParts.cjs");
6
6
  const groupingFunction = require("./grouping-function.cjs");
7
7
  const SuperGroupingCard = require("./SuperGroupingCard.cjs");
8
8
  const SuperGroupingTranscript = require("./SuperGroupingTranscript.cjs");
9
+ const toolPartPlacement = require("./tool-part-placement.cjs");
9
10
  const turnSegments = require("./turn-segments.cjs");
10
11
  const turnTiming = require("./turn-timing.cjs");
11
12
  const toolkitMap = require("./toolkit-map.cjs");
13
+ const inlineTools = require("../../tools/inline-tools.cjs");
12
14
  exports.buildActivityTimeline = activityTimeline.buildActivityTimeline;
15
+ exports.countActivityDelegations = activityTimeline.countActivityDelegations;
13
16
  exports.countActivityTools = activityTimeline.countActivityTools;
14
17
  exports.excludeFinalTextFromGroups = activityTimeline.excludeFinalTextFromGroups;
15
18
  exports.excludePartsFromGroups = activityTimeline.excludePartsFromGroups;
@@ -32,6 +35,8 @@ exports.SuperGroupingFinalText = SuperGroupingCard.SuperGroupingFinalText;
32
35
  exports.resetRememberedExpansionsForTests = SuperGroupingCard.resetRememberedExpansionsForTests;
33
36
  exports.useActivityExpansion = SuperGroupingCard.useActivityExpansion;
34
37
  exports.SuperGroupingTranscript = SuperGroupingTranscript.SuperGroupingTranscript;
38
+ exports.ToolPartPlacementProvider = toolPartPlacement.ToolPartPlacementProvider;
39
+ exports.useToolPartPlacement = toolPartPlacement.useToolPartPlacement;
35
40
  exports.scopeGroupingToSegment = turnSegments.scopeGroupingToSegment;
36
41
  exports.splitTurnSegments = turnSegments.splitTurnSegments;
37
42
  exports.summarizeSegment = turnSegments.summarizeSegment;
@@ -39,4 +44,5 @@ exports.formatWorkDuration = turnTiming.formatWorkDuration;
39
44
  exports.readTurnTiming = turnTiming.readTurnTiming;
40
45
  exports.workedDurationMs = turnTiming.workedDurationMs;
41
46
  exports.defaultGetToolGroupKey = toolkitMap.defaultGetToolGroupKey;
47
+ exports.isSdkInlineTool = inlineTools.isSdkInlineTool;
42
48
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -5,17 +5,20 @@
5
5
  * them mounted as the turn grows, the timeline derivation behind them, the
6
6
  * tool-based grouping function, and the transcript layout (the agent's
7
7
  * sentences in order with the work between them folded, under a "Working
8
- * for …" header).
8
+ * for …" header), and where the card renders a call's tool UI outside its
9
+ * details (`useToolPartPlacement`).
9
10
  * A lean entry so hosts with their own thread (Olympus, the Chrome extension)
10
11
  * mount it from source without the SDK's composer stack.
11
12
  */
12
- export { type ActivityItem, type ActivityPhase, type ActivityTimelineOptions, type ActivityToolState, buildActivityTimeline, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, type FinalTextPart, type FinalTextSegment, getActivityItemLabel, getActivitySummary, getReasoningLabel, getActivityToolState, isStreamingToolPlaceholder, getFinalText, getFinalTextParts, resolveActivityPhase, } from './activity-timeline';
13
+ export { type ActivityItem, type ActivityPhase, type ActivityTimelineOptions, type ActivityToolState, buildActivityTimeline, countActivityDelegations, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, type FinalTextPart, type FinalTextSegment, getActivityItemLabel, getActivitySummary, getReasoningLabel, getActivityToolState, isStreamingToolPlaceholder, getFinalText, getFinalTextParts, resolveActivityPhase, } from './activity-timeline';
13
14
  export { CollapsibleGroup, type CollapsibleGroupProps, DEFAULT_TOOLKIT_THEME, SuperGroupingProvider, TOOLKIT_THEMES, type ToolkitTheme, } from './CollapsibleGroup';
14
15
  export { GroupedMessageParts, type GroupedMessagePartsProps } from './GroupedMessageParts';
15
16
  export { createToolBasedGroupingFunction, type GroupablePart, type GroupingFunction, type MessagePartGroup, } from './grouping-function';
16
17
  export { resetRememberedExpansionsForTests, SuperGroupingCard, type SuperGroupingCardProps, SuperGroupingFinalText, useActivityExpansion, } from './SuperGroupingCard';
17
18
  export { SuperGroupingTranscript, type SuperGroupingTranscriptProps } from './SuperGroupingTranscript';
18
19
  export type { TimelineStep } from './timeline-step';
20
+ export { type ToolPartPlacement, ToolPartPlacementProvider, useToolPartPlacement } from './tool-part-placement';
19
21
  export { scopeGroupingToSegment, type SegmentablePart, type SegmentSummary, splitTurnSegments, summarizeSegment, type TurnSegment, } from './turn-segments';
20
22
  export { formatWorkDuration, readTurnTiming, type TurnTiming, type TurnTimingSources, workedDurationMs, } from './turn-timing';
21
23
  export { defaultGetToolGroupKey, type GetToolGroupKey, type ToolGroupKeyOptions } from './toolkit-map';
24
+ export { isSdkInlineTool } from '../../tools/inline-tools';
@@ -1,12 +1,14 @@
1
- import { buildActivityTimeline, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, getActivityItemLabel, getActivitySummary, getActivityToolState, getFinalText, getFinalTextParts, getReasoningLabel, isStreamingToolPlaceholder, resolveActivityPhase } from "./activity-timeline.js";
1
+ import { buildActivityTimeline, countActivityDelegations, countActivityTools, excludeFinalTextFromGroups, excludePartsFromGroups, getActivityItemLabel, getActivitySummary, getActivityToolState, getFinalText, getFinalTextParts, getReasoningLabel, isStreamingToolPlaceholder, resolveActivityPhase } from "./activity-timeline.js";
2
2
  import { CollapsibleGroup, DEFAULT_TOOLKIT_THEME, SuperGroupingProvider, TOOLKIT_THEMES } from "./CollapsibleGroup.js";
3
3
  import { GroupedMessageParts } from "./GroupedMessageParts.js";
4
4
  import { createToolBasedGroupingFunction } from "./grouping-function.js";
5
5
  import { SuperGroupingCard, SuperGroupingFinalText, resetRememberedExpansionsForTests, useActivityExpansion } from "./SuperGroupingCard.js";
6
6
  import { SuperGroupingTranscript } from "./SuperGroupingTranscript.js";
7
+ import { ToolPartPlacementProvider, useToolPartPlacement } from "./tool-part-placement.js";
7
8
  import { scopeGroupingToSegment, splitTurnSegments, summarizeSegment } from "./turn-segments.js";
8
9
  import { formatWorkDuration, readTurnTiming, workedDurationMs } from "./turn-timing.js";
9
10
  import { defaultGetToolGroupKey } from "./toolkit-map.js";
11
+ import { isSdkInlineTool } from "../../tools/inline-tools.js";
10
12
  export {
11
13
  CollapsibleGroup,
12
14
  DEFAULT_TOOLKIT_THEME,
@@ -16,7 +18,9 @@ export {
16
18
  SuperGroupingProvider,
17
19
  SuperGroupingTranscript,
18
20
  TOOLKIT_THEMES,
21
+ ToolPartPlacementProvider,
19
22
  buildActivityTimeline,
23
+ countActivityDelegations,
20
24
  countActivityTools,
21
25
  createToolBasedGroupingFunction,
22
26
  defaultGetToolGroupKey,
@@ -29,6 +33,7 @@ export {
29
33
  getFinalText,
30
34
  getFinalTextParts,
31
35
  getReasoningLabel,
36
+ isSdkInlineTool,
32
37
  isStreamingToolPlaceholder,
33
38
  readTurnTiming,
34
39
  resetRememberedExpansionsForTests,
@@ -37,6 +42,7 @@ export {
37
42
  splitTurnSegments,
38
43
  summarizeSegment,
39
44
  useActivityExpansion,
45
+ useToolPartPlacement,
40
46
  workedDurationMs
41
47
  };
42
48
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}