@athenaintel/react 0.22.4 → 0.23.1

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 (350) hide show
  1. package/README.md +394 -4
  2. package/dist/chat/AthenaChat.cjs +346 -244
  3. package/dist/chat/AthenaChat.cjs.map +1 -1
  4. package/dist/chat/AthenaChat.d.ts +19 -8
  5. package/dist/chat/AthenaChat.js +350 -248
  6. package/dist/chat/AthenaChat.js.map +1 -1
  7. package/dist/chat/StatewireApprovalCard.cjs +2 -1
  8. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  9. package/dist/chat/StatewireApprovalCard.js +2 -1
  10. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  11. package/dist/chat/StatewireClientToolBridge.cjs +1 -0
  12. package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
  13. package/dist/chat/StatewireClientToolBridge.js +1 -0
  14. package/dist/chat/StatewireClientToolBridge.js.map +1 -1
  15. package/dist/chat/StatewireQueuedMessages.cjs +1 -0
  16. package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
  17. package/dist/chat/StatewireQueuedMessages.js +1 -0
  18. package/dist/chat/StatewireQueuedMessages.js.map +1 -1
  19. package/dist/chat/WaitingOnYouBanner.cjs +100 -0
  20. package/dist/chat/WaitingOnYouBanner.cjs.map +1 -0
  21. package/dist/chat/WaitingOnYouBanner.d.ts +29 -0
  22. package/dist/chat/WaitingOnYouBanner.js +100 -0
  23. package/dist/chat/WaitingOnYouBanner.js.map +1 -0
  24. package/dist/chat/athena-chat-welcome.cjs +148 -0
  25. package/dist/chat/athena-chat-welcome.cjs.map +1 -0
  26. package/dist/chat/athena-chat-welcome.d.ts +54 -0
  27. package/dist/chat/athena-chat-welcome.js +148 -0
  28. package/dist/chat/athena-chat-welcome.js.map +1 -0
  29. package/dist/chat/athena-composer-controls.cjs +76 -0
  30. package/dist/chat/athena-composer-controls.cjs.map +1 -0
  31. package/dist/chat/athena-composer-controls.d.ts +21 -0
  32. package/dist/chat/athena-composer-controls.js +76 -0
  33. package/dist/chat/athena-composer-controls.js.map +1 -0
  34. package/dist/chat/composer-keyboard-hint.cjs +61 -0
  35. package/dist/chat/composer-keyboard-hint.cjs.map +1 -0
  36. package/dist/chat/composer-keyboard-hint.d.ts +33 -0
  37. package/dist/chat/composer-keyboard-hint.js +61 -0
  38. package/dist/chat/composer-keyboard-hint.js.map +1 -0
  39. package/dist/chat/message-time.cjs +64 -0
  40. package/dist/chat/message-time.cjs.map +1 -0
  41. package/dist/chat/message-time.d.ts +45 -0
  42. package/dist/chat/message-time.js +64 -0
  43. package/dist/chat/message-time.js.map +1 -0
  44. package/dist/chat/run-activity.cjs +38 -7
  45. package/dist/chat/run-activity.cjs.map +1 -1
  46. package/dist/chat/run-activity.d.ts +14 -3
  47. package/dist/chat/run-activity.js +39 -8
  48. package/dist/chat/run-activity.js.map +1 -1
  49. package/dist/chat/statewire-client-tools.cjs +2 -1
  50. package/dist/chat/statewire-client-tools.cjs.map +1 -1
  51. package/dist/chat/statewire-client-tools.js +2 -1
  52. package/dist/chat/statewire-client-tools.js.map +1 -1
  53. package/dist/chat/super-grouping/activity-timeline.cjs +2 -1
  54. package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
  55. package/dist/chat/super-grouping/activity-timeline.js +2 -1
  56. package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
  57. package/dist/chat/thread-scroll-to-bottom.cjs +24 -0
  58. package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -0
  59. package/dist/chat/thread-scroll-to-bottom.d.ts +11 -0
  60. package/dist/chat/thread-scroll-to-bottom.js +24 -0
  61. package/dist/chat/thread-scroll-to-bottom.js.map +1 -0
  62. package/dist/chat/tiptap-text.cjs +26 -95
  63. package/dist/chat/tiptap-text.cjs.map +1 -1
  64. package/dist/chat/tiptap-text.d.ts +13 -0
  65. package/dist/chat/tiptap-text.js +26 -95
  66. package/dist/chat/tiptap-text.js.map +1 -1
  67. package/dist/chat/use-athena-run-live.cjs +2 -1
  68. package/dist/chat/use-athena-run-live.cjs.map +1 -1
  69. package/dist/chat/use-athena-run-live.js +2 -1
  70. package/dist/chat/use-athena-run-live.js.map +1 -1
  71. package/dist/chat/use-statewire-approval-request.cjs +1 -0
  72. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  73. package/dist/chat/use-statewire-approval-request.js +1 -0
  74. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  75. package/dist/chat-ui/composer/tiptap-composer.cjs +39 -4
  76. package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
  77. package/dist/chat-ui/composer/tiptap-composer.d.ts +21 -0
  78. package/dist/chat-ui/composer/tiptap-composer.js +39 -4
  79. package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
  80. package/dist/chat-ui/index.cjs +15 -1
  81. package/dist/chat-ui/index.cjs.map +1 -1
  82. package/dist/chat-ui/index.d.ts +6 -3
  83. package/dist/chat-ui/index.js +16 -2
  84. package/dist/chat-ui/index.js.map +1 -1
  85. package/dist/chat-ui/mentions/mention-chip.cjs +31 -4
  86. package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
  87. package/dist/chat-ui/mentions/mention-chip.js +31 -4
  88. package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
  89. package/dist/chat-ui/messages/message-components.cjs +19 -1
  90. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  91. package/dist/chat-ui/messages/message-components.d.ts +13 -0
  92. package/dist/chat-ui/messages/message-components.js +19 -1
  93. package/dist/chat-ui/messages/message-components.js.map +1 -1
  94. package/dist/chat-ui/messages/runtime-message.cjs +2 -1
  95. package/dist/chat-ui/messages/runtime-message.cjs.map +1 -1
  96. package/dist/chat-ui/messages/runtime-message.js +2 -1
  97. package/dist/chat-ui/messages/runtime-message.js.map +1 -1
  98. package/dist/chat-ui/messages/statewire-continue-run.cjs +1 -0
  99. package/dist/chat-ui/messages/statewire-continue-run.cjs.map +1 -1
  100. package/dist/chat-ui/messages/statewire-continue-run.js +1 -0
  101. package/dist/chat-ui/messages/statewire-continue-run.js.map +1 -1
  102. package/dist/chat-ui/messages/user-edit-composer.cjs +3 -1
  103. package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
  104. package/dist/chat-ui/messages/user-edit-composer.js +3 -1
  105. package/dist/chat-ui/messages/user-edit-composer.js.map +1 -1
  106. package/dist/chat-ui/messages/wake-marker.cjs +84 -0
  107. package/dist/chat-ui/messages/wake-marker.cjs.map +1 -0
  108. package/dist/chat-ui/messages/wake-marker.d.ts +16 -0
  109. package/dist/chat-ui/messages/wake-marker.js +84 -0
  110. package/dist/chat-ui/messages/wake-marker.js.map +1 -0
  111. package/dist/chat-ui/rich-text/chat-blocks.cjs +177 -0
  112. package/dist/chat-ui/rich-text/chat-blocks.cjs.map +1 -0
  113. package/dist/chat-ui/rich-text/chat-blocks.d.ts +58 -0
  114. package/dist/chat-ui/rich-text/chat-blocks.js +177 -0
  115. package/dist/chat-ui/rich-text/chat-blocks.js.map +1 -0
  116. package/dist/chat-ui/rich-text/chat-link.cjs +69 -0
  117. package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -0
  118. package/dist/chat-ui/rich-text/chat-link.d.ts +24 -0
  119. package/dist/chat-ui/rich-text/chat-link.js +69 -0
  120. package/dist/chat-ui/rich-text/chat-link.js.map +1 -0
  121. package/dist/chat-ui/rich-text/chat-message-body.cjs +144 -18
  122. package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
  123. package/dist/chat-ui/rich-text/chat-message-body.d.ts +10 -1
  124. package/dist/chat-ui/rich-text/chat-message-body.js +149 -23
  125. package/dist/chat-ui/rich-text/chat-message-body.js.map +1 -1
  126. package/dist/chat-ui/rich-text/chat-node-views.cjs +38 -5
  127. package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
  128. package/dist/chat-ui/rich-text/chat-node-views.d.ts +11 -0
  129. package/dist/chat-ui/rich-text/chat-node-views.js +39 -6
  130. package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -1
  131. package/dist/chat-ui/rich-text/chat-text-schema.cjs +20 -3
  132. package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -1
  133. package/dist/chat-ui/rich-text/chat-text-schema.d.ts +15 -2
  134. package/dist/chat-ui/rich-text/chat-text-schema.js +20 -3
  135. package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -1
  136. package/dist/chat-ui/rich-text/citation-anchors.cjs +139 -0
  137. package/dist/chat-ui/rich-text/citation-anchors.cjs.map +1 -0
  138. package/dist/chat-ui/rich-text/citation-anchors.d.ts +74 -0
  139. package/dist/chat-ui/rich-text/citation-anchors.js +139 -0
  140. package/dist/chat-ui/rich-text/citation-anchors.js.map +1 -0
  141. package/dist/chat-ui/statewire.cjs +8 -1
  142. package/dist/chat-ui/statewire.cjs.map +1 -1
  143. package/dist/chat-ui/statewire.d.ts +2 -0
  144. package/dist/chat-ui/statewire.js +8 -1
  145. package/dist/chat-ui/statewire.js.map +1 -1
  146. package/dist/chat-ui/thread/chat-composer-dock.cjs +27 -6
  147. package/dist/chat-ui/thread/chat-composer-dock.cjs.map +1 -1
  148. package/dist/chat-ui/thread/chat-composer-dock.d.ts +21 -1
  149. package/dist/chat-ui/thread/chat-composer-dock.js +28 -7
  150. package/dist/chat-ui/thread/chat-composer-dock.js.map +1 -1
  151. package/dist/chat-ui/thread/statewire-history-edge.cjs +12 -13
  152. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  153. package/dist/chat-ui/thread/statewire-history-edge.d.ts +11 -10
  154. package/dist/chat-ui/thread/statewire-history-edge.js +13 -14
  155. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  156. package/dist/chat-ui/thread/thread-loading-overlay.cjs +31 -0
  157. package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -0
  158. package/dist/chat-ui/thread/thread-loading-overlay.d.ts +14 -0
  159. package/dist/chat-ui/thread/thread-loading-overlay.js +31 -0
  160. package/dist/chat-ui/thread/thread-loading-overlay.js.map +1 -0
  161. package/dist/composer/ComposerDropZone.cjs +8 -1
  162. package/dist/composer/ComposerDropZone.cjs.map +1 -1
  163. package/dist/composer/ComposerDropZone.d.ts +6 -0
  164. package/dist/composer/ComposerDropZone.js +9 -2
  165. package/dist/composer/ComposerDropZone.js.map +1 -1
  166. package/dist/diagnostics/errors.cjs +20 -0
  167. package/dist/diagnostics/errors.cjs.map +1 -1
  168. package/dist/diagnostics/errors.d.ts +20 -0
  169. package/dist/diagnostics/errors.js +20 -0
  170. package/dist/diagnostics/errors.js.map +1 -1
  171. package/dist/index.cjs +47 -1
  172. package/dist/index.cjs.map +1 -1
  173. package/dist/index.d.ts +26 -7
  174. package/dist/index.js +51 -5
  175. package/dist/index.js.map +1 -1
  176. package/dist/lib/use-prefers-reduced-motion.cjs +29 -0
  177. package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -0
  178. package/dist/lib/use-prefers-reduced-motion.d.ts +6 -0
  179. package/dist/lib/use-prefers-reduced-motion.js +29 -0
  180. package/dist/lib/use-prefers-reduced-motion.js.map +1 -0
  181. package/dist/packages/agent-runtime/src/conversation-index.cjs.map +1 -1
  182. package/dist/packages/agent-runtime/src/conversation-index.js.map +1 -1
  183. package/dist/packages/agent-runtime/src/conversation-list.cjs +59 -0
  184. package/dist/packages/agent-runtime/src/conversation-list.cjs.map +1 -1
  185. package/dist/packages/agent-runtime/src/conversation-list.js +60 -1
  186. package/dist/packages/agent-runtime/src/conversation-list.js.map +1 -1
  187. package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.cjs +5 -3
  188. package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
  189. package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.js +5 -3
  190. package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  191. package/dist/packages/agent-runtime/src/edit-command.cjs +21 -17
  192. package/dist/packages/agent-runtime/src/edit-command.cjs.map +1 -1
  193. package/dist/packages/agent-runtime/src/edit-command.js +22 -18
  194. package/dist/packages/agent-runtime/src/edit-command.js.map +1 -1
  195. package/dist/packages/agent-runtime/src/generated/runconfig-contract.cjs +9 -11
  196. package/dist/packages/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  197. package/dist/packages/agent-runtime/src/generated/runconfig-contract.js +9 -11
  198. package/dist/packages/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  199. package/dist/packages/agent-runtime/src/github-wake-event.cjs +86 -0
  200. package/dist/packages/agent-runtime/src/github-wake-event.cjs.map +1 -0
  201. package/dist/packages/agent-runtime/src/github-wake-event.js +86 -0
  202. package/dist/packages/agent-runtime/src/github-wake-event.js.map +1 -0
  203. package/dist/packages/agent-runtime/src/message-window.cjs +150 -42
  204. package/dist/packages/agent-runtime/src/message-window.cjs.map +1 -1
  205. package/dist/packages/agent-runtime/src/message-window.js +151 -43
  206. package/dist/packages/agent-runtime/src/message-window.js.map +1 -1
  207. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.cjs +13 -9
  208. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
  209. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.js +13 -9
  210. package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
  211. package/dist/packages/agent-runtime/src/statewire-suspended.cjs +1 -3
  212. package/dist/packages/agent-runtime/src/statewire-suspended.cjs.map +1 -1
  213. package/dist/packages/agent-runtime/src/statewire-suspended.js +1 -3
  214. package/dist/packages/agent-runtime/src/statewire-suspended.js.map +1 -1
  215. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
  216. package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -1
  217. package/dist/packages/agent-runtime/src/use-deep-agent-thread.cjs +61 -30
  218. package/dist/packages/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  219. package/dist/packages/agent-runtime/src/use-deep-agent-thread.js +59 -28
  220. package/dist/packages/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  221. package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.cjs +56 -36
  222. package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  223. package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.js +59 -39
  224. package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -1
  225. package/dist/packages/react/package.json.cjs +1 -1
  226. package/dist/packages/react/package.json.js +1 -1
  227. package/dist/provider/AthenaContext.cjs.map +1 -1
  228. package/dist/provider/AthenaContext.d.ts +3 -0
  229. package/dist/provider/AthenaContext.js.map +1 -1
  230. package/dist/provider/AthenaProvider.cjs +93 -45
  231. package/dist/provider/AthenaProvider.cjs.map +1 -1
  232. package/dist/provider/AthenaProvider.d.ts +6 -1
  233. package/dist/provider/AthenaProvider.js +97 -49
  234. package/dist/provider/AthenaProvider.js.map +1 -1
  235. package/dist/runtime/statewire-lifecycle.cjs +2 -1
  236. package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
  237. package/dist/runtime/statewire-lifecycle.js +2 -1
  238. package/dist/runtime/statewire-lifecycle.js.map +1 -1
  239. package/dist/runtime/useAthenaStatewireRuntime.cjs +3 -2
  240. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  241. package/dist/runtime/useAthenaStatewireRuntime.d.ts +8 -12
  242. package/dist/runtime/useAthenaStatewireRuntime.js +3 -2
  243. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  244. package/dist/search/useAthenaRepoSearch.cjs +94 -0
  245. package/dist/search/useAthenaRepoSearch.cjs.map +1 -0
  246. package/dist/search/useAthenaRepoSearch.d.ts +95 -0
  247. package/dist/search/useAthenaRepoSearch.js +94 -0
  248. package/dist/search/useAthenaRepoSearch.js.map +1 -0
  249. package/dist/styles.css +1 -1
  250. package/dist/threads/SessionList.cjs +486 -0
  251. package/dist/threads/SessionList.cjs.map +1 -0
  252. package/dist/threads/SessionList.d.ts +60 -0
  253. package/dist/threads/SessionList.js +486 -0
  254. package/dist/threads/SessionList.js.map +1 -0
  255. package/dist/threads/api.cjs +112 -4
  256. package/dist/threads/api.cjs.map +1 -1
  257. package/dist/threads/api.d.ts +128 -1
  258. package/dist/threads/api.js +113 -5
  259. package/dist/threads/api.js.map +1 -1
  260. package/dist/threads/conversation-list-fetcher.cjs +27 -3
  261. package/dist/threads/conversation-list-fetcher.cjs.map +1 -1
  262. package/dist/threads/conversation-list-fetcher.d.ts +16 -3
  263. package/dist/threads/conversation-list-fetcher.js +27 -3
  264. package/dist/threads/conversation-list-fetcher.js.map +1 -1
  265. package/dist/threads/index.d.ts +5 -1
  266. package/dist/threads/session-list-model.cjs +130 -0
  267. package/dist/threads/session-list-model.cjs.map +1 -0
  268. package/dist/threads/session-list-model.d.ts +62 -0
  269. package/dist/threads/session-list-model.js +130 -0
  270. package/dist/threads/session-list-model.js.map +1 -0
  271. package/dist/threads/statewire-thread-list.cjs +220 -38
  272. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  273. package/dist/threads/statewire-thread-list.d.ts +152 -2
  274. package/dist/threads/statewire-thread-list.js +222 -40
  275. package/dist/threads/statewire-thread-list.js.map +1 -1
  276. package/dist/threads/thread-prefetcher.cjs +63 -0
  277. package/dist/threads/thread-prefetcher.cjs.map +1 -0
  278. package/dist/threads/thread-prefetcher.d.ts +54 -0
  279. package/dist/threads/thread-prefetcher.js +63 -0
  280. package/dist/threads/thread-prefetcher.js.map +1 -0
  281. package/dist/threads/use-athena-session-attention.cjs +22 -0
  282. package/dist/threads/use-athena-session-attention.cjs.map +1 -0
  283. package/dist/threads/use-athena-session-attention.d.ts +24 -0
  284. package/dist/threads/use-athena-session-attention.js +22 -0
  285. package/dist/threads/use-athena-session-attention.js.map +1 -0
  286. package/dist/threads/use-rest-conversation-history.cjs +25 -2
  287. package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
  288. package/dist/threads/use-rest-conversation-history.d.ts +8 -1
  289. package/dist/threads/use-rest-conversation-history.js +25 -2
  290. package/dist/threads/use-rest-conversation-history.js.map +1 -1
  291. package/dist/threads/use-statewire-conversation-history.cjs +40 -16
  292. package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
  293. package/dist/threads/use-statewire-conversation-history.d.ts +13 -0
  294. package/dist/threads/use-statewire-conversation-history.js +40 -16
  295. package/dist/threads/use-statewire-conversation-history.js.map +1 -1
  296. package/dist/threads/use-thread-archive.cjs +128 -0
  297. package/dist/threads/use-thread-archive.cjs.map +1 -0
  298. package/dist/threads/use-thread-archive.d.ts +26 -0
  299. package/dist/threads/use-thread-archive.js +128 -0
  300. package/dist/threads/use-thread-archive.js.map +1 -0
  301. package/dist/threads/use-thread-favorite.cjs +53 -0
  302. package/dist/threads/use-thread-favorite.cjs.map +1 -0
  303. package/dist/threads/use-thread-favorite.d.ts +49 -0
  304. package/dist/threads/use-thread-favorite.js +53 -0
  305. package/dist/threads/use-thread-favorite.js.map +1 -0
  306. package/dist/threads/use-thread-field-override.cjs +184 -0
  307. package/dist/threads/use-thread-field-override.cjs.map +1 -0
  308. package/dist/threads/use-thread-field-override.d.ts +55 -0
  309. package/dist/threads/use-thread-field-override.js +184 -0
  310. package/dist/threads/use-thread-field-override.js.map +1 -0
  311. package/dist/threads/use-thread-rename.cjs +53 -0
  312. package/dist/threads/use-thread-rename.cjs.map +1 -0
  313. package/dist/threads/use-thread-rename.d.ts +48 -0
  314. package/dist/threads/use-thread-rename.js +53 -0
  315. package/dist/threads/use-thread-rename.js.map +1 -0
  316. package/dist/tools/index.cjs +5 -1
  317. package/dist/tools/index.cjs.map +1 -1
  318. package/dist/tools/index.d.ts +1 -1
  319. package/dist/tools/index.js +7 -3
  320. package/dist/tools/index.js.map +1 -1
  321. package/dist/tools/misc-tool-uis.cjs +2 -1
  322. package/dist/tools/misc-tool-uis.cjs.map +1 -1
  323. package/dist/tools/misc-tool-uis.js +2 -1
  324. package/dist/tools/misc-tool-uis.js.map +1 -1
  325. package/dist/tools/primitives.cjs +25 -2
  326. package/dist/tools/primitives.cjs.map +1 -1
  327. package/dist/tools/primitives.d.ts +9 -2
  328. package/dist/tools/primitives.js +26 -3
  329. package/dist/tools/primitives.js.map +1 -1
  330. package/dist/tools/tool-appearance.cjs +11 -0
  331. package/dist/tools/tool-appearance.cjs.map +1 -0
  332. package/dist/tools/tool-appearance.d.ts +29 -0
  333. package/dist/tools/tool-appearance.js +11 -0
  334. package/dist/tools/tool-appearance.js.map +1 -0
  335. package/dist/tools/tool-fallback.cjs +211 -13
  336. package/dist/tools/tool-fallback.cjs.map +1 -1
  337. package/dist/tools/tool-fallback.d.ts +31 -4
  338. package/dist/tools/tool-fallback.js +214 -16
  339. package/dist/tools/tool-fallback.js.map +1 -1
  340. package/dist/tools/use-elapsed-seconds.cjs +24 -0
  341. package/dist/tools/use-elapsed-seconds.cjs.map +1 -0
  342. package/dist/tools/use-elapsed-seconds.d.ts +10 -0
  343. package/dist/tools/use-elapsed-seconds.js +24 -0
  344. package/dist/tools/use-elapsed-seconds.js.map +1 -0
  345. package/dist/tools/voice-update-tool-ui.cjs +2 -1
  346. package/dist/tools/voice-update-tool-ui.cjs.map +1 -1
  347. package/dist/tools/voice-update-tool-ui.js +2 -1
  348. package/dist/tools/voice-update-tool-ui.js.map +1 -1
  349. package/package.json +3 -3
  350. package/src/chat-ui/tailwind-preset.js +14 -1
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The top-level blocks of a streamed markdown message, so a message body can
3
+ * parse each block once and re-parse only the one still being written.
4
+ *
5
+ * Streaming appends: every block before the last is settled the moment the
6
+ * blank line after it arrives, and only the trailing block changes with the
7
+ * next token. A body that re-parses the whole message per token does work
8
+ * quadratic in the answer's length and re-renders every finished paragraph,
9
+ * list and table each time; split into blocks, a finished block's text never
10
+ * changes again, so its parse and its DOM are kept as they are.
11
+ *
12
+ * The split follows CommonMark's block boundaries as far as a linear scan
13
+ * can: a blank line ends a block, except inside a fenced code block (whose
14
+ * blank lines are content). A fence may sit inside a blockquote; it closes at
15
+ * a fence line in the same quote depth with a matching marker, or implicitly
16
+ * when a line leaves the quote — a fence at the margin after that opens a new
17
+ * one, as CommonMark reads it. A fence that has not closed marks the trailing
18
+ * block as open code, which the body draws as plain `<pre>` until the closing
19
+ * fence lands. Constructs that legitimately span blank lines are stitched
20
+ * back together: a block that starts indented continues the block before it
21
+ * (a list item's second paragraph, a nested list, indented code), and a list
22
+ * that follows a list of the same kind is one loose list. Link reference
23
+ * definitions (`[1]: https://…`, with a destination or title on a following
24
+ * indented line) are collected apart and handed to every block's parse, since
25
+ * a `[label][1]` in one block may resolve to a definition written after it —
26
+ * only runs that are definitions by CommonMark's shape (a destination without
27
+ * spaces or in `<…>`, an optional quoted or parenthesized title, nothing
28
+ * after) are lifted; a definition-shaped line the parser would show as text
29
+ * stays text. A definition run still being streamed at the very end of the
30
+ * text stays the trailing block (rendering nothing) until it settles, so the
31
+ * settled blocks are not re-parsed on every token of its URL. Pure string
32
+ * work, linear in the text.
33
+ */
34
+ export interface OpenFence {
35
+ /** The fence's info string up to its first space (the language), possibly empty. */
36
+ language: string;
37
+ /** The code written so far, without the fence line (and without the quote markers of a fence inside a blockquote). */
38
+ code: string;
39
+ }
40
+ export interface ChatBlock {
41
+ /** The block's markdown, blank lines around it removed. */
42
+ text: string;
43
+ /** Set on the trailing block while its fenced code has not closed. */
44
+ openFence: OpenFence | null;
45
+ }
46
+ export interface ChatBlocks {
47
+ blocks: ChatBlock[];
48
+ /** Settled link reference definitions, one per line, to append to every block's parse. */
49
+ definitions: string;
50
+ }
51
+ export interface SplitChatBlocksOptions {
52
+ /** The text is still streaming: a definition run at its very end is not settled yet. */
53
+ streaming?: boolean;
54
+ }
55
+ /** Whether a run of lines is a link reference definition the parser would swallow. */
56
+ export declare function isReferenceDefinition(lines: readonly string[]): boolean;
57
+ /** Split a message's markdown into its top-level blocks. */
58
+ export declare function splitChatBlocks(markdown: string, { streaming }?: SplitChatBlocksOptions): ChatBlocks;
@@ -0,0 +1,177 @@
1
+ const FENCE_LINE = /^((?:\s*>)*\s*)(`{3,}|~{3,})(.*)$/;
2
+ const BLOCKQUOTE_PREFIX = /^(?:\s*>\s?)+/;
3
+ const LEADING_QUOTES = /^(?:\s*>)*/;
4
+ const DEFINITION_START = /^ {0,3}\[[^\]]+\]:\s*(\S.*)?$/;
5
+ const DESTINATION_WITH_TITLE = /^\s*\S+\s+(?:"[^"]*"|'[^']*'|\([^)]*\))\s*$/;
6
+ const TITLE_LINE = /^\s+(?:"[^"]*"|'[^']*'|\([^)]*\))\s*$/;
7
+ const DEFINITION = /^ {0,3}\[[^\]]+\]:[ \t]*\n?[ \t]*(<[^<>\n]*>|[^\s<][^\s]*)(?:[ \t]*\n?[ \t]*("[^"\n]*"|'[^'\n]*'|\([^()\n]*\)))?[ \t]*$/;
8
+ const LIST_MARKER = /^ {0,3}(?:([-*+])|\d{1,9}[.)])(?:\s|$)/;
9
+ function firstLine(text) {
10
+ const end = text.indexOf("\n");
11
+ return end === -1 ? text : text.slice(0, end);
12
+ }
13
+ function quoteDepth(line) {
14
+ var _a;
15
+ const markers = ((_a = LEADING_QUOTES.exec(line)) == null ? void 0 : _a[0]) ?? "";
16
+ let depth = 0;
17
+ for (const character of markers) if (character === ">") depth += 1;
18
+ return depth;
19
+ }
20
+ function balancedParentheses(destination) {
21
+ if (destination.startsWith("<")) return true;
22
+ let open = 0;
23
+ for (const character of destination) {
24
+ if (character === "(") open += 1;
25
+ else if (character === ")") {
26
+ open -= 1;
27
+ if (open < 0) return false;
28
+ }
29
+ }
30
+ return open === 0;
31
+ }
32
+ function isReferenceDefinition(lines) {
33
+ const match = DEFINITION.exec(lines.join("\n"));
34
+ return match !== null && balancedParentheses(match[1]);
35
+ }
36
+ function continuesPrevious(previous, next) {
37
+ if (/^\s/.test(next)) return true;
38
+ const before = LIST_MARKER.exec(firstLine(previous));
39
+ const after = LIST_MARKER.exec(firstLine(next));
40
+ return before !== null && after !== null && before[1] !== void 0 === (after[1] !== void 0);
41
+ }
42
+ function mergeContinuations(blocks) {
43
+ const merged = [];
44
+ for (const block of blocks) {
45
+ const previous = merged[merged.length - 1];
46
+ if (previous && previous.openFence === null && continuesPrevious(previous.text, block.text)) {
47
+ merged[merged.length - 1] = {
48
+ text: `${previous.text}
49
+
50
+ ${block.text}`,
51
+ openFence: block.openFence
52
+ };
53
+ } else {
54
+ merged.push(block);
55
+ }
56
+ }
57
+ return merged;
58
+ }
59
+ function splitChatBlocks(markdown, { streaming = false } = {}) {
60
+ const blocks = [];
61
+ const definitions = [];
62
+ let current = [];
63
+ let fence = null;
64
+ let pending = [];
65
+ let continuation = null;
66
+ const closeBlock = () => {
67
+ while (current.length > 0 && current[current.length - 1].trim() === "") {
68
+ current.pop();
69
+ }
70
+ if (current.length > 0) blocks.push({ text: current.join("\n"), openFence: null });
71
+ current = [];
72
+ };
73
+ const settleDefinitions = () => {
74
+ if (pending.length > 0) {
75
+ if (isReferenceDefinition(pending)) definitions.push(...pending);
76
+ else current.push(...pending);
77
+ }
78
+ pending = [];
79
+ continuation = null;
80
+ };
81
+ const openFence = (opening, line) => {
82
+ settleDefinitions();
83
+ if (opening[1].length === 0) closeBlock();
84
+ const state = {
85
+ marker: opening[2],
86
+ language: opening[3].trim().split(/\s+/)[0] ?? "",
87
+ depth: quoteDepth(opening[1]),
88
+ start: current.length
89
+ };
90
+ current.push(line);
91
+ return state;
92
+ };
93
+ const asOpening = (line) => {
94
+ const opening = FENCE_LINE.exec(line);
95
+ if (!opening) return null;
96
+ return opening[2][0] === "`" && opening[3].includes("`") ? null : opening;
97
+ };
98
+ for (const line of markdown.split("\n")) {
99
+ if (fence) {
100
+ const depth = quoteDepth(line);
101
+ if (depth >= fence.depth) {
102
+ current.push(line);
103
+ const closing = FENCE_LINE.exec(line);
104
+ if (closing && quoteDepth(closing[1]) === fence.depth && closing[2][0] === fence.marker[0] && closing[2].length >= fence.marker.length && closing[3].trim() === "") {
105
+ fence = null;
106
+ }
107
+ continue;
108
+ }
109
+ fence = null;
110
+ }
111
+ const opening = asOpening(line);
112
+ if (opening) {
113
+ fence = openFence(opening, line);
114
+ continue;
115
+ }
116
+ if (line.trim() === "") {
117
+ settleDefinitions();
118
+ closeBlock();
119
+ continue;
120
+ }
121
+ if (continuation !== null && /^\s/.test(line)) {
122
+ if (continuation === "destination") {
123
+ pending.push(line);
124
+ continuation = DESTINATION_WITH_TITLE.test(line) ? null : "title";
125
+ continue;
126
+ }
127
+ if (TITLE_LINE.test(line)) {
128
+ pending.push(line);
129
+ continuation = null;
130
+ continue;
131
+ }
132
+ }
133
+ continuation = null;
134
+ if (current.length === 0) {
135
+ if (pending.length > 0 && !isReferenceDefinition(pending)) {
136
+ settleDefinitions();
137
+ } else {
138
+ const definition = DEFINITION_START.exec(line);
139
+ if (definition) {
140
+ if (pending.length > 0) {
141
+ definitions.push(...pending);
142
+ pending = [];
143
+ }
144
+ pending.push(line);
145
+ const rest = definition[1];
146
+ continuation = rest === void 0 ? "destination" : DESTINATION_WITH_TITLE.test(rest) ? null : "title";
147
+ continue;
148
+ }
149
+ }
150
+ }
151
+ settleDefinitions();
152
+ current.push(line);
153
+ }
154
+ if (fence) {
155
+ const lead = current.slice(0, fence.start);
156
+ const quoted = fence.depth > 0;
157
+ const code = current.slice(fence.start + 1).map((codeLine) => quoted ? codeLine.replace(BLOCKQUOTE_PREFIX, "") : codeLine);
158
+ blocks.push({
159
+ text: [...lead, ...current.slice(fence.start)].join("\n"),
160
+ openFence: { language: fence.language, code: code.join("\n") }
161
+ });
162
+ } else {
163
+ if (pending.length > 0 && streaming) {
164
+ current.push(...pending);
165
+ pending = [];
166
+ } else {
167
+ settleDefinitions();
168
+ }
169
+ closeBlock();
170
+ }
171
+ return { blocks: mergeContinuations(blocks), definitions: definitions.join("\n") };
172
+ }
173
+ export {
174
+ isReferenceDefinition,
175
+ splitChatBlocks
176
+ };
177
+ //# sourceMappingURL=chat-blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-blocks.js","sources":["../../../src/chat-ui/rich-text/chat-blocks.ts"],"sourcesContent":["/**\n * The top-level blocks of a streamed markdown message, so a message body can\n * parse each block once and re-parse only the one still being written.\n *\n * Streaming appends: every block before the last is settled the moment the\n * blank line after it arrives, and only the trailing block changes with the\n * next token. A body that re-parses the whole message per token does work\n * quadratic in the answer's length and re-renders every finished paragraph,\n * list and table each time; split into blocks, a finished block's text never\n * changes again, so its parse and its DOM are kept as they are.\n *\n * The split follows CommonMark's block boundaries as far as a linear scan\n * can: a blank line ends a block, except inside a fenced code block (whose\n * blank lines are content). A fence may sit inside a blockquote; it closes at\n * a fence line in the same quote depth with a matching marker, or implicitly\n * when a line leaves the quote — a fence at the margin after that opens a new\n * one, as CommonMark reads it. A fence that has not closed marks the trailing\n * block as open code, which the body draws as plain `<pre>` until the closing\n * fence lands. Constructs that legitimately span blank lines are stitched\n * back together: a block that starts indented continues the block before it\n * (a list item's second paragraph, a nested list, indented code), and a list\n * that follows a list of the same kind is one loose list. Link reference\n * definitions (`[1]: https://…`, with a destination or title on a following\n * indented line) are collected apart and handed to every block's parse, since\n * a `[label][1]` in one block may resolve to a definition written after it —\n * only runs that are definitions by CommonMark's shape (a destination without\n * spaces or in `<…>`, an optional quoted or parenthesized title, nothing\n * after) are lifted; a definition-shaped line the parser would show as text\n * stays text. A definition run still being streamed at the very end of the\n * text stays the trailing block (rendering nothing) until it settles, so the\n * settled blocks are not re-parsed on every token of its URL. Pure string\n * work, linear in the text.\n */\n\nexport interface OpenFence {\n /** The fence's info string up to its first space (the language), possibly empty. */\n language: string;\n /** The code written so far, without the fence line (and without the quote markers of a fence inside a blockquote). */\n code: string;\n}\n\nexport interface ChatBlock {\n /** The block's markdown, blank lines around it removed. */\n text: string;\n /** Set on the trailing block while its fenced code has not closed. */\n openFence: OpenFence | null;\n}\n\nexport interface ChatBlocks {\n blocks: ChatBlock[];\n /** Settled link reference definitions, one per line, to append to every block's parse. */\n definitions: string;\n}\n\nexport interface SplitChatBlocksOptions {\n /** The text is still streaming: a definition run at its very end is not settled yet. */\n streaming?: boolean;\n}\n\n/** A fence line: blockquote markers and indent, three or more backticks or tildes, the info string. */\nconst FENCE_LINE = /^((?:\\s*>)*\\s*)(`{3,}|~{3,})(.*)$/;\n/** Leading blockquote markers (`> `, `>>`), stripped from the code of a fence inside a quote. */\nconst BLOCKQUOTE_PREFIX = /^(?:\\s*>\\s?)+/;\n/** The blockquote markers a line opens with. */\nconst LEADING_QUOTES = /^(?:\\s*>)*/;\n/** `[label]:` at the start of a block; the destination follows on this line or, indented, on the next. */\nconst DEFINITION_START = /^ {0,3}\\[[^\\]]+\\]:\\s*(\\S.*)?$/;\n/** A definition's destination (and optional title) already carrying a title. */\nconst DESTINATION_WITH_TITLE = /^\\s*\\S+\\s+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\))\\s*$/;\n/** A definition title alone on an indented line. */\nconst TITLE_LINE = /^\\s+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\))\\s*$/;\n/**\n * A whole link reference definition as CommonMark shapes it: the label, a\n * destination in `<…>` or without whitespace, an optional title, nothing else.\n * Anything looser (`[x]:` with no destination, `[1]: two words`) is text.\n */\nconst DEFINITION =\n /^ {0,3}\\[[^\\]]+\\]:[ \\t]*\\n?[ \\t]*(<[^<>\\n]*>|[^\\s<][^\\s]*)(?:[ \\t]*\\n?[ \\t]*(\"[^\"\\n]*\"|'[^'\\n]*'|\\([^()\\n]*\\)))?[ \\t]*$/;\n/** A bullet (`-`, `*`, `+`) or ordered (`1.`, `1)`) list marker starting a line. */\nconst LIST_MARKER = /^ {0,3}(?:([-*+])|\\d{1,9}[.)])(?:\\s|$)/;\n\ninterface FenceState {\n marker: string;\n language: string;\n /** How many blockquote markers the fence line opened with (0 at the margin). */\n depth: number;\n /** Index of the fence line within the current block's lines. */\n start: number;\n}\n\n/** What the definition being read could still take from the next indented line. */\ntype DefinitionContinuation = \"destination\" | \"title\" | null;\n\nfunction firstLine(text: string): string {\n const end = text.indexOf(\"\\n\");\n return end === -1 ? text : text.slice(0, end);\n}\n\nfunction quoteDepth(line: string): number {\n const markers = LEADING_QUOTES.exec(line)?.[0] ?? \"\";\n let depth = 0;\n for (const character of markers) if (character === \">\") depth += 1;\n return depth;\n}\n\n/** A bare destination's parentheses must balance (`[1]: /a(b` is text). */\nfunction balancedParentheses(destination: string): boolean {\n if (destination.startsWith(\"<\")) return true;\n let open = 0;\n for (const character of destination) {\n if (character === \"(\") open += 1;\n else if (character === \")\") {\n open -= 1;\n if (open < 0) return false;\n }\n }\n return open === 0;\n}\n\n/** Whether a run of lines is a link reference definition the parser would swallow. */\nexport function isReferenceDefinition(lines: readonly string[]): boolean {\n const match = DEFINITION.exec(lines.join(\"\\n\"));\n return match !== null && balancedParentheses(match[1]!);\n}\n\n/** Whether `next` continues `previous`: an indented continuation, or another list of the same kind. */\nfunction continuesPrevious(previous: string, next: string): boolean {\n if (/^\\s/.test(next)) return true;\n const before = LIST_MARKER.exec(firstLine(previous));\n const after = LIST_MARKER.exec(firstLine(next));\n return (\n before !== null &&\n after !== null &&\n (before[1] !== undefined) === (after[1] !== undefined)\n );\n}\n\nfunction mergeContinuations(blocks: readonly ChatBlock[]): ChatBlock[] {\n const merged: ChatBlock[] = [];\n for (const block of blocks) {\n const previous = merged[merged.length - 1];\n if (\n previous &&\n previous.openFence === null &&\n continuesPrevious(previous.text, block.text)\n ) {\n merged[merged.length - 1] = {\n text: `${previous.text}\\n\\n${block.text}`,\n openFence: block.openFence,\n };\n } else {\n merged.push(block);\n }\n }\n return merged;\n}\n\n/** Split a message's markdown into its top-level blocks. */\nexport function splitChatBlocks(\n markdown: string,\n { streaming = false }: SplitChatBlocksOptions = {},\n): ChatBlocks {\n const blocks: ChatBlock[] = [];\n const definitions: string[] = [];\n let current: string[] = [];\n let fence: FenceState | null = null;\n /** The one definition being read (its label line plus any indented continuation); settled by the next label, blank line, fence or block. */\n let pending: string[] = [];\n let continuation: DefinitionContinuation = null;\n\n const closeBlock = (): void => {\n while (current.length > 0 && current[current.length - 1]!.trim() === \"\") {\n current.pop();\n }\n if (current.length > 0) blocks.push({ text: current.join(\"\\n\"), openFence: null });\n current = [];\n };\n /**\n * The pending run is a definition (lifted) or it is text (the start of the\n * block being read — `current` is empty whenever a run is pending).\n */\n const settleDefinitions = (): void => {\n if (pending.length > 0) {\n if (isReferenceDefinition(pending)) definitions.push(...pending);\n else current.push(...pending);\n }\n pending = [];\n continuation = null;\n };\n /** Start a fence at `line`; the caller assigns the state (an assignment inside a closure is invisible to narrowing). */\n const openFence = (opening: RegExpExecArray, line: string): FenceState => {\n settleDefinitions();\n // A fence at the margin interrupts a paragraph: it is its own block. An\n // indented or quoted fence belongs to the list item or quote around it.\n if (opening[1]!.length === 0) closeBlock();\n const state: FenceState = {\n marker: opening[2]!,\n language: opening[3]!.trim().split(/\\s+/)[0] ?? \"\",\n depth: quoteDepth(opening[1]!),\n start: current.length,\n };\n current.push(line);\n return state;\n };\n /** A fence line may open a fence: a backtick fence's info string cannot contain a backtick (that is inline code). */\n const asOpening = (line: string): RegExpExecArray | null => {\n const opening = FENCE_LINE.exec(line);\n if (!opening) return null;\n return opening[2]![0] === \"`\" && opening[3]!.includes(\"`\") ? null : opening;\n };\n\n for (const line of markdown.split(\"\\n\")) {\n if (fence) {\n const depth = quoteDepth(line);\n if (depth >= fence.depth) {\n current.push(line);\n const closing = FENCE_LINE.exec(line);\n if (\n closing &&\n quoteDepth(closing[1]!) === fence.depth &&\n closing[2]![0] === fence.marker[0] &&\n closing[2]!.length >= fence.marker.length &&\n closing[3]!.trim() === \"\"\n ) {\n fence = null;\n }\n continue;\n }\n // The line left the fence's blockquote, which ends the quote and the\n // fence with it; the line itself is read like any other.\n fence = null;\n }\n const opening = asOpening(line);\n if (opening) {\n fence = openFence(opening, line);\n continue;\n }\n if (line.trim() === \"\") {\n settleDefinitions();\n closeBlock();\n continue;\n }\n if (continuation !== null && /^\\s/.test(line)) {\n if (continuation === \"destination\") {\n pending.push(line);\n continuation = DESTINATION_WITH_TITLE.test(line) ? null : \"title\";\n continue;\n }\n if (TITLE_LINE.test(line)) {\n pending.push(line);\n continuation = null;\n continue;\n }\n }\n continuation = null;\n if (current.length === 0) {\n if (pending.length > 0 && !isReferenceDefinition(pending)) {\n // The run so far is not a definition: it is the paragraph this line continues.\n settleDefinitions();\n } else {\n const definition = DEFINITION_START.exec(line);\n if (definition) {\n // A new label ends the definition before it, which is complete and valid here.\n if (pending.length > 0) {\n definitions.push(...pending);\n pending = [];\n }\n pending.push(line);\n const rest = definition[1];\n continuation =\n rest === undefined\n ? \"destination\"\n : DESTINATION_WITH_TITLE.test(rest)\n ? null\n : \"title\";\n continue;\n }\n }\n }\n settleDefinitions();\n current.push(line);\n }\n\n if (fence) {\n const lead = current.slice(0, fence.start);\n const quoted = fence.depth > 0;\n const code = current\n .slice(fence.start + 1)\n .map((codeLine) => (quoted ? codeLine.replace(BLOCKQUOTE_PREFIX, \"\") : codeLine));\n blocks.push({\n text: [...lead, ...current.slice(fence.start)].join(\"\\n\"),\n openFence: { language: fence.language, code: code.join(\"\\n\") },\n });\n } else {\n // A definition run that ends still-streaming text is not settled: it stays\n // the trailing block (a valid one parses to nothing visible) so the blocks\n // before it keep their parse while its URL streams. Settled text lifts it.\n if (pending.length > 0 && streaming) {\n current.push(...pending);\n pending = [];\n } else {\n settleDefinitions();\n }\n closeBlock();\n }\n\n return { blocks: mergeContinuations(blocks), definitions: definitions.join(\"\\n\") };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const lucideReact = require("lucide-react");
5
+ const react = require("react");
6
+ const mentionChip = require("../mentions/mention-chip.cjs");
7
+ const citationAnchors = require("./citation-anchors.cjs");
8
+ function ChatLink({
9
+ href,
10
+ excerpt,
11
+ children
12
+ }) {
13
+ if (href && excerpt && citationAnchors.isWebHref(href)) {
14
+ return /* @__PURE__ */ jsxRuntime.jsx(SourceChip, { href, excerpt, children });
15
+ }
16
+ return /* @__PURE__ */ jsxRuntime.jsx(mentionChip.MentionLink, { href: href ?? void 0, children });
17
+ }
18
+ function SourceChip({
19
+ href,
20
+ excerpt,
21
+ children
22
+ }) {
23
+ return /* @__PURE__ */ jsxRuntime.jsxs(
24
+ "a",
25
+ {
26
+ href: citationAnchors.buildScrollToTextUrl(href, excerpt),
27
+ target: "_blank",
28
+ rel: "noopener noreferrer",
29
+ title: excerpt,
30
+ "data-chat-source": "",
31
+ "data-excerpt": excerpt,
32
+ className: "not-prose inline-flex max-w-[240px] items-center gap-1 whitespace-nowrap rounded-md border border-slate-300 bg-white px-1.5 py-px align-middle text-[0.85em] font-medium leading-[1.4] text-slate-600 no-underline transition-colors hover:border-slate-400 hover:bg-slate-50 hover:text-slate-800 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1",
33
+ children: [
34
+ /* @__PURE__ */ jsxRuntime.jsx(SourceFavicon, { href }),
35
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[200px] overflow-hidden text-ellipsis", children })
36
+ ]
37
+ }
38
+ );
39
+ }
40
+ function SourceFavicon({ href }) {
41
+ const [failed, setFailed] = react.useState(false);
42
+ const src = failed ? null : citationAnchors.sourceFaviconUrl(href);
43
+ if (!src) {
44
+ return /* @__PURE__ */ jsxRuntime.jsx(
45
+ lucideReact.Globe2Icon,
46
+ {
47
+ className: "size-3.5 shrink-0 text-slate-400",
48
+ "aria-hidden": "true"
49
+ }
50
+ );
51
+ }
52
+ return /* @__PURE__ */ jsxRuntime.jsx(
53
+ "img",
54
+ {
55
+ src,
56
+ alt: "",
57
+ width: 14,
58
+ height: 14,
59
+ className: "size-3.5 shrink-0 rounded-[3px]",
60
+ loading: "lazy",
61
+ referrerPolicy: "no-referrer",
62
+ draggable: false,
63
+ onError: () => setFailed(true)
64
+ }
65
+ );
66
+ }
67
+ exports.ChatLink = ChatLink;
68
+ exports.SourceChip = SourceChip;
69
+ //# sourceMappingURL=chat-link.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-link.cjs","sources":["../../../src/chat-ui/rich-text/chat-link.tsx"],"sourcesContent":["import { Globe2Icon } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport { MentionLink } from \"../mentions/mention-chip\";\nimport {\n buildScrollToTextUrl,\n isWebHref,\n sourceFaviconUrl,\n} from \"./citation-anchors\";\n\n/**\n * A link mark of the static message body. A web source the model cited with\n * an excerpt renders as a source chip; everything else goes through\n * `MentionLink`, which draws mention and Spaces hrefs as asset chips,\n * screen points as coordinate chips, and the rest as a plain link.\n */\nexport function ChatLink({\n href,\n excerpt,\n children,\n}: {\n href: string | null | undefined;\n excerpt?: string | null;\n children: ReactNode;\n}) {\n if (href && excerpt && isWebHref(href)) {\n return (\n <SourceChip href={href} excerpt={excerpt}>\n {children}\n </SourceChip>\n );\n }\n return <MentionLink href={href ?? undefined}>{children}</MentionLink>;\n}\n\n/**\n * A cited web page: the site's favicon, the model's label, the excerpt as\n * the tooltip, opening the page at the excerpt (scroll-to-text) in a new tab.\n * Same geometry as the asset mention chip so a sentence that cites a PDF and\n * a web page reads as one row of sources. `not-prose` keeps Tailwind\n * Typography's `img` margins off the favicon.\n */\nexport function SourceChip({\n href,\n excerpt,\n children,\n}: {\n href: string;\n excerpt: string;\n children: ReactNode;\n}) {\n return (\n <a\n href={buildScrollToTextUrl(href, excerpt)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={excerpt}\n data-chat-source=\"\"\n data-excerpt={excerpt}\n className=\"not-prose inline-flex max-w-[240px] items-center gap-1 whitespace-nowrap rounded-md border border-slate-300 bg-white px-1.5 py-px align-middle text-[0.85em] font-medium leading-[1.4] text-slate-600 no-underline transition-colors hover:border-slate-400 hover:bg-slate-50 hover:text-slate-800 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1\"\n >\n <SourceFavicon href={href} />\n <span className=\"max-w-[200px] overflow-hidden text-ellipsis\">\n {children}\n </span>\n </a>\n );\n}\n\n/** The site's favicon; a globe once the favicon service has no icon for the host. */\nfunction SourceFavicon({ href }: { href: string }) {\n const [failed, setFailed] = useState(false);\n const src = failed ? null : sourceFaviconUrl(href);\n if (!src) {\n return (\n <Globe2Icon\n className=\"size-3.5 shrink-0 text-slate-400\"\n aria-hidden=\"true\"\n />\n );\n }\n return (\n <img\n src={src}\n alt=\"\"\n width={14}\n height={14}\n className=\"size-3.5 shrink-0 rounded-[3px]\"\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n draggable={false}\n onError={() => setFailed(true)}\n />\n );\n}\n"],"names":["isWebHref","jsx","MentionLink","jsxs","buildScrollToTextUrl","useState","sourceFaviconUrl","Globe2Icon"],"mappings":";;;;;;;AAeO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,QAAQ,WAAWA,gBAAAA,UAAU,IAAI,GAAG;AACtC,WACEC,2BAAAA,IAAC,YAAA,EAAW,MAAY,SACrB,SAAA,CACH;AAAA,EAEJ;AACA,SAAOA,2BAAAA,IAACC,YAAAA,aAAA,EAAY,MAAM,QAAQ,QAAY,UAAS;AACzD;AASO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACEC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAMC,gBAAAA,qBAAqB,MAAM,OAAO;AAAA,MACxC,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,OAAO;AAAA,MACP,oBAAiB;AAAA,MACjB,gBAAc;AAAA,MACd,WAAU;AAAA,MAEV,UAAA;AAAA,QAAAH,+BAAC,iBAAc,MAAY;AAAA,QAC3BA,2BAAAA,IAAC,QAAA,EAAK,WAAU,+CACb,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAGA,SAAS,cAAc,EAAE,QAA0B;AACjD,QAAM,CAAC,QAAQ,SAAS,IAAII,MAAAA,SAAS,KAAK;AAC1C,QAAM,MAAM,SAAS,OAAOC,gBAAAA,iBAAiB,IAAI;AACjD,MAAI,CAAC,KAAK;AACR,WACEL,2BAAAA;AAAAA,MAACM,YAAAA;AAAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAY;AAAA,MAAA;AAAA,IAAA;AAAA,EAGlB;AACA,SACEN,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,KAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAU;AAAA,MACV,SAAQ;AAAA,MACR,gBAAe;AAAA,MACf,WAAW;AAAA,MACX,SAAS,MAAM,UAAU,IAAI;AAAA,IAAA;AAAA,EAAA;AAGnC;;;"}
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * A link mark of the static message body. A web source the model cited with
4
+ * an excerpt renders as a source chip; everything else goes through
5
+ * `MentionLink`, which draws mention and Spaces hrefs as asset chips,
6
+ * screen points as coordinate chips, and the rest as a plain link.
7
+ */
8
+ export declare function ChatLink({ href, excerpt, children, }: {
9
+ href: string | null | undefined;
10
+ excerpt?: string | null;
11
+ children: ReactNode;
12
+ }): import("react/jsx-runtime").JSX.Element;
13
+ /**
14
+ * A cited web page: the site's favicon, the model's label, the excerpt as
15
+ * the tooltip, opening the page at the excerpt (scroll-to-text) in a new tab.
16
+ * Same geometry as the asset mention chip so a sentence that cites a PDF and
17
+ * a web page reads as one row of sources. `not-prose` keeps Tailwind
18
+ * Typography's `img` margins off the favicon.
19
+ */
20
+ export declare function SourceChip({ href, excerpt, children, }: {
21
+ href: string;
22
+ excerpt: string;
23
+ children: ReactNode;
24
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Globe2Icon } from "lucide-react";
3
+ import { useState } from "react";
4
+ import { MentionLink } from "../mentions/mention-chip.js";
5
+ import { isWebHref, buildScrollToTextUrl, sourceFaviconUrl } from "./citation-anchors.js";
6
+ function ChatLink({
7
+ href,
8
+ excerpt,
9
+ children
10
+ }) {
11
+ if (href && excerpt && isWebHref(href)) {
12
+ return /* @__PURE__ */ jsx(SourceChip, { href, excerpt, children });
13
+ }
14
+ return /* @__PURE__ */ jsx(MentionLink, { href: href ?? void 0, children });
15
+ }
16
+ function SourceChip({
17
+ href,
18
+ excerpt,
19
+ children
20
+ }) {
21
+ return /* @__PURE__ */ jsxs(
22
+ "a",
23
+ {
24
+ href: buildScrollToTextUrl(href, excerpt),
25
+ target: "_blank",
26
+ rel: "noopener noreferrer",
27
+ title: excerpt,
28
+ "data-chat-source": "",
29
+ "data-excerpt": excerpt,
30
+ className: "not-prose inline-flex max-w-[240px] items-center gap-1 whitespace-nowrap rounded-md border border-slate-300 bg-white px-1.5 py-px align-middle text-[0.85em] font-medium leading-[1.4] text-slate-600 no-underline transition-colors hover:border-slate-400 hover:bg-slate-50 hover:text-slate-800 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1",
31
+ children: [
32
+ /* @__PURE__ */ jsx(SourceFavicon, { href }),
33
+ /* @__PURE__ */ jsx("span", { className: "max-w-[200px] overflow-hidden text-ellipsis", children })
34
+ ]
35
+ }
36
+ );
37
+ }
38
+ function SourceFavicon({ href }) {
39
+ const [failed, setFailed] = useState(false);
40
+ const src = failed ? null : sourceFaviconUrl(href);
41
+ if (!src) {
42
+ return /* @__PURE__ */ jsx(
43
+ Globe2Icon,
44
+ {
45
+ className: "size-3.5 shrink-0 text-slate-400",
46
+ "aria-hidden": "true"
47
+ }
48
+ );
49
+ }
50
+ return /* @__PURE__ */ jsx(
51
+ "img",
52
+ {
53
+ src,
54
+ alt: "",
55
+ width: 14,
56
+ height: 14,
57
+ className: "size-3.5 shrink-0 rounded-[3px]",
58
+ loading: "lazy",
59
+ referrerPolicy: "no-referrer",
60
+ draggable: false,
61
+ onError: () => setFailed(true)
62
+ }
63
+ );
64
+ }
65
+ export {
66
+ ChatLink,
67
+ SourceChip
68
+ };
69
+ //# sourceMappingURL=chat-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-link.js","sources":["../../../src/chat-ui/rich-text/chat-link.tsx"],"sourcesContent":["import { Globe2Icon } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport { MentionLink } from \"../mentions/mention-chip\";\nimport {\n buildScrollToTextUrl,\n isWebHref,\n sourceFaviconUrl,\n} from \"./citation-anchors\";\n\n/**\n * A link mark of the static message body. A web source the model cited with\n * an excerpt renders as a source chip; everything else goes through\n * `MentionLink`, which draws mention and Spaces hrefs as asset chips,\n * screen points as coordinate chips, and the rest as a plain link.\n */\nexport function ChatLink({\n href,\n excerpt,\n children,\n}: {\n href: string | null | undefined;\n excerpt?: string | null;\n children: ReactNode;\n}) {\n if (href && excerpt && isWebHref(href)) {\n return (\n <SourceChip href={href} excerpt={excerpt}>\n {children}\n </SourceChip>\n );\n }\n return <MentionLink href={href ?? undefined}>{children}</MentionLink>;\n}\n\n/**\n * A cited web page: the site's favicon, the model's label, the excerpt as\n * the tooltip, opening the page at the excerpt (scroll-to-text) in a new tab.\n * Same geometry as the asset mention chip so a sentence that cites a PDF and\n * a web page reads as one row of sources. `not-prose` keeps Tailwind\n * Typography's `img` margins off the favicon.\n */\nexport function SourceChip({\n href,\n excerpt,\n children,\n}: {\n href: string;\n excerpt: string;\n children: ReactNode;\n}) {\n return (\n <a\n href={buildScrollToTextUrl(href, excerpt)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title={excerpt}\n data-chat-source=\"\"\n data-excerpt={excerpt}\n className=\"not-prose inline-flex max-w-[240px] items-center gap-1 whitespace-nowrap rounded-md border border-slate-300 bg-white px-1.5 py-px align-middle text-[0.85em] font-medium leading-[1.4] text-slate-600 no-underline transition-colors hover:border-slate-400 hover:bg-slate-50 hover:text-slate-800 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1\"\n >\n <SourceFavicon href={href} />\n <span className=\"max-w-[200px] overflow-hidden text-ellipsis\">\n {children}\n </span>\n </a>\n );\n}\n\n/** The site's favicon; a globe once the favicon service has no icon for the host. */\nfunction SourceFavicon({ href }: { href: string }) {\n const [failed, setFailed] = useState(false);\n const src = failed ? null : sourceFaviconUrl(href);\n if (!src) {\n return (\n <Globe2Icon\n className=\"size-3.5 shrink-0 text-slate-400\"\n aria-hidden=\"true\"\n />\n );\n }\n return (\n <img\n src={src}\n alt=\"\"\n width={14}\n height={14}\n className=\"size-3.5 shrink-0 rounded-[3px]\"\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n draggable={false}\n onError={() => setFailed(true)}\n />\n );\n}\n"],"names":[],"mappings":";;;;;AAeO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,QAAQ,WAAW,UAAU,IAAI,GAAG;AACtC,WACE,oBAAC,YAAA,EAAW,MAAY,SACrB,SAAA,CACH;AAAA,EAEJ;AACA,SAAO,oBAAC,aAAA,EAAY,MAAM,QAAQ,QAAY,UAAS;AACzD;AASO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM,qBAAqB,MAAM,OAAO;AAAA,MACxC,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,OAAO;AAAA,MACP,oBAAiB;AAAA,MACjB,gBAAc;AAAA,MACd,WAAU;AAAA,MAEV,UAAA;AAAA,QAAA,oBAAC,iBAAc,MAAY;AAAA,QAC3B,oBAAC,QAAA,EAAK,WAAU,+CACb,SAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAGA,SAAS,cAAc,EAAE,QAA0B;AACjD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,MAAM,SAAS,OAAO,iBAAiB,IAAI;AACjD,MAAI,CAAC,KAAK;AACR,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAY;AAAA,MAAA;AAAA,IAAA;AAAA,EAGlB;AACA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,KAAI;AAAA,MACJ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAU;AAAA,MACV,SAAQ;AAAA,MACR,gBAAe;AAAA,MACf,WAAW;AAAA,MACX,SAAS,MAAM,UAAU,IAAI;AAAA,IAAA;AAAA,EAAA;AAGnC;"}
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
- const mentionChip = require("../mentions/mention-chip.cjs");
5
+ const athenaCitationLinks = require("../../chat/athena-citation-links.cjs");
6
+ const chatBlocks = require("./chat-blocks.cjs");
7
+ const chatLink = require("./chat-link.cjs");
6
8
  const chatNodeViews = require("./chat-node-views.cjs");
7
9
  const chatTextSchema = require("./chat-text-schema.cjs");
8
10
  const domOutputSpec = require("./dom-output-spec.cjs");
@@ -19,37 +21,161 @@ function ChatMessageBody({
19
21
  browserSnapshot,
20
22
  serverSnapshot
21
23
  );
24
+ const onClick = useChatLinkClick();
25
+ const { blocks, definitions } = react.useMemo(
26
+ () => chatBlocks.splitChatBlocks(text, { streaming: isRunning }),
27
+ [text, isRunning]
28
+ );
29
+ return (
30
+ // The click handler only delegates for the anchors inside, which are
31
+ // themselves focusable and keyboard-operable; the wrapper is not a control.
32
+ /* @__PURE__ */ jsxRuntime.jsx(
33
+ "div",
34
+ {
35
+ className: chatTextSchema.CHAT_TEXT_CLASS,
36
+ "data-chat-text": "",
37
+ "data-status": isRunning ? "running" : "complete",
38
+ onClick,
39
+ children: hasDom ? blocks.map((block, index) => /* @__PURE__ */ jsxRuntime.jsx(
40
+ ChatBlock,
41
+ {
42
+ text: block.text,
43
+ definitions,
44
+ openFence: block.openFence,
45
+ streaming: isRunning && index === blocks.length - 1
46
+ },
47
+ index
48
+ )) : text
49
+ }
50
+ )
51
+ );
52
+ }
53
+ const ChatBlock = react.memo(function ChatBlock2({
54
+ text,
55
+ definitions,
56
+ openFence,
57
+ streaming
58
+ }) {
59
+ const open = streaming ? openFence : null;
22
60
  const doc = react.useMemo(
23
- () => hasDom ? chatTextSchema.parseChatText(mentionChip.normalizeAthenaMentionHtml(text)) : null,
24
- [hasDom, text]
61
+ () => open ? null : chatTextSchema.parseChatText(definitions ? `${text}
62
+
63
+ ${definitions}` : text),
64
+ [text, definitions, open]
65
+ );
66
+ if (open) {
67
+ return /* @__PURE__ */ jsxRuntime.jsx(
68
+ chatNodeViews.StreamingCodeBlock,
69
+ {
70
+ language: open.language,
71
+ code: open.code,
72
+ caret: /* @__PURE__ */ jsxRuntime.jsx(StreamingCaret, {})
73
+ }
74
+ );
75
+ }
76
+ if (!doc || isEmptyDoc(doc)) return null;
77
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderContent(doc, streaming ? findStreamingTail(doc) : null) });
78
+ });
79
+ function isEmptyDoc(doc) {
80
+ if (doc.childCount === 0) return true;
81
+ const only = doc.firstChild;
82
+ return doc.childCount === 1 && only !== null && only.isTextblock && only.content.size === 0;
83
+ }
84
+ function useChatLinkClick() {
85
+ const handleLinkClick = athenaCitationLinks.useAthenaLinkClickHandler();
86
+ return react.useCallback(
87
+ (event) => {
88
+ if (event.button !== 0 || event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
89
+ return;
90
+ }
91
+ const target = event.target;
92
+ const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
93
+ const anchor = element == null ? void 0 : element.closest("a[href]");
94
+ if (!(anchor instanceof HTMLAnchorElement) || !event.currentTarget.contains(anchor)) {
95
+ return;
96
+ }
97
+ const handled = handleLinkClick({
98
+ href: anchor.getAttribute("href") ?? anchor.href,
99
+ linkText: anchor.textContent,
100
+ target: anchor.target,
101
+ nativeEvent: event.nativeEvent
102
+ });
103
+ if (handled) event.preventDefault();
104
+ },
105
+ [handleLinkClick]
25
106
  );
107
+ }
108
+ function findStreamingTail(doc) {
109
+ const tail = { textblock: null, text: null };
110
+ doc.descendants((node) => {
111
+ if (node.isTextblock) {
112
+ tail.textblock = node;
113
+ tail.text = null;
114
+ } else if (node.isText && tail.textblock && tail.textblock.type.name !== "codeBlock") {
115
+ tail.text = node;
116
+ }
117
+ return true;
118
+ });
119
+ return tail;
120
+ }
121
+ const FRESH_WORD_WINDOW = 6;
122
+ const WORD = /\s*\S+/g;
123
+ function renderFreshWords(text) {
124
+ const words = [...text.matchAll(WORD)];
125
+ if (words.length === 0) return text;
126
+ const from = Math.max(0, words.length - FRESH_WORD_WINDOW);
127
+ const first = words[from];
128
+ const last = words[words.length - 1];
129
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
130
+ text.slice(0, first.index),
131
+ words.slice(from).map((word, offset) => /* @__PURE__ */ jsxRuntime.jsx(
132
+ "span",
133
+ {
134
+ className: "animate-chat-word-settle motion-reduce:animate-none",
135
+ "data-chat-fresh": "",
136
+ children: word[0]
137
+ },
138
+ from + offset
139
+ )),
140
+ text.slice(last.index + last[0].length)
141
+ ] });
142
+ }
143
+ function StreamingCaret() {
26
144
  return /* @__PURE__ */ jsxRuntime.jsx(
27
- "div",
145
+ "span",
28
146
  {
29
- className: chatTextSchema.CHAT_TEXT_CLASS,
30
- "data-chat-text": "",
31
- "data-status": isRunning ? "running" : "complete",
32
- children: doc ? renderContent(doc) : text
147
+ "aria-hidden": "true",
148
+ "data-chat-caret": "",
149
+ className: "ml-0.5 inline-block h-[1em] w-0.5 rounded-full bg-primary align-[-0.125em] animate-chat-caret-blink motion-reduce:animate-none"
33
150
  }
34
151
  );
35
152
  }
36
- function renderNode(node) {
37
- if (node.isText) return node.text;
153
+ function renderNode(node, tail) {
154
+ if (node.isText) {
155
+ return (tail == null ? void 0 : tail.text) === node ? renderFreshWords(node.text ?? "") : node.text;
156
+ }
38
157
  if (node.type.name === "mention") return /* @__PURE__ */ jsxRuntime.jsx(chatNodeViews.ChatMention, { node });
39
158
  if (node.type.name === "codeBlock") {
40
- return /* @__PURE__ */ jsxRuntime.jsx(chatNodeViews.ChatCodeBlock, { node, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: node.textContent }) });
159
+ return /* @__PURE__ */ jsxRuntime.jsx(chatNodeViews.ChatCodeBlock, { node, children: /* @__PURE__ */ jsxRuntime.jsxs("code", { children: [
160
+ node.textContent,
161
+ (tail == null ? void 0 : tail.textblock) === node ? /* @__PURE__ */ jsxRuntime.jsx(StreamingCaret, {}) : null
162
+ ] }) });
41
163
  }
42
164
  const toDOM = node.type.spec.toDOM;
43
- return toDOM ? domOutputSpec.renderDOMOutputSpec(toDOM(node), node.isLeaf ? null : renderContent(node)) : null;
165
+ if (!toDOM) return null;
166
+ if (node.isLeaf) return domOutputSpec.renderDOMOutputSpec(toDOM(node), null);
167
+ const content = renderContent(node, tail);
168
+ if ((tail == null ? void 0 : tail.textblock) === node) content.push(/* @__PURE__ */ jsxRuntime.jsx(StreamingCaret, {}, "caret"));
169
+ return domOutputSpec.renderDOMOutputSpec(toDOM(node), content);
44
170
  }
45
- function renderContent(parent) {
171
+ function renderContent(parent, tail) {
46
172
  const nodes = [];
47
173
  parent.forEach((node) => {
48
174
  nodes.push(node);
49
175
  });
50
- return renderMarkRuns(nodes, 0);
176
+ return renderMarkRuns(nodes, 0, tail);
51
177
  }
52
- function renderMarkRuns(nodes, depth) {
178
+ function renderMarkRuns(nodes, depth, tail) {
53
179
  var _a, _b;
54
180
  const children = [];
55
181
  let index = 0;
@@ -57,7 +183,7 @@ function renderMarkRuns(nodes, depth) {
57
183
  const node = nodes[index];
58
184
  const mark = node.marks[depth];
59
185
  if (!mark) {
60
- children.push(/* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, index));
186
+ children.push(/* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node, tail) }, index));
61
187
  index++;
62
188
  continue;
63
189
  }
@@ -65,8 +191,8 @@ function renderMarkRuns(nodes, depth) {
65
191
  if (mark.type.spec.spanning !== false) {
66
192
  while (end < nodes.length && ((_b = (_a = nodes[end]) == null ? void 0 : _a.marks[depth]) == null ? void 0 : _b.eq(mark))) end++;
67
193
  }
68
- const content = renderMarkRuns(nodes.slice(index, end), depth + 1);
69
- const rendered = mark.type.name === "link" ? /* @__PURE__ */ jsxRuntime.jsx(mentionChip.MentionLink, { href: mark.attrs.href, children: content }) : mark.type.spec.toDOM ? domOutputSpec.renderDOMOutputSpec(mark.type.spec.toDOM(mark, true), content) : content;
194
+ const content = renderMarkRuns(nodes.slice(index, end), depth + 1, tail);
195
+ const rendered = mark.type.name === "link" ? /* @__PURE__ */ jsxRuntime.jsx(chatLink.ChatLink, { href: mark.attrs.href, excerpt: mark.attrs.excerpt, children: content }) : mark.type.spec.toDOM ? domOutputSpec.renderDOMOutputSpec(mark.type.spec.toDOM(mark, true), content) : content;
70
196
  children.push(/* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: rendered }, index));
71
197
  index = end;
72
198
  }