@mastra/playground-ui 68.0.0-alpha.2 → 68.0.0-alpha.3

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 (338) hide show
  1. package/dist/KnowledgePageGraph.css +55 -0
  2. package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
  3. package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
  4. package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
  5. package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
  6. package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
  7. package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
  8. package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
  9. package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
  10. package/dist/components/MarkdownRenderer.cjs.js +1 -1
  11. package/dist/components/MarkdownRenderer.es.js +1 -1
  12. package/dist/components/SavedViews.cjs.js +1 -1
  13. package/dist/components/SavedViews.es.js +1 -1
  14. package/dist/components/ai/activity.cjs.js +1 -1
  15. package/dist/components/ai/activity.es.js +1 -1
  16. package/dist/components/ai/plan.cjs.js +1 -1
  17. package/dist/components/ai/plan.es.js +1 -1
  18. package/dist/components/ai/tool-approval.cjs.js +1 -1
  19. package/dist/components/ai/tool-approval.es.js +1 -1
  20. package/dist/components/ai/tool-call.cjs.js +2 -2
  21. package/dist/components/ai/tool-call.es.js +2 -2
  22. package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
  23. package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
  24. package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
  25. package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
  26. package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
  27. package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
  28. package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
  29. package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
  30. package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
  31. package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
  32. package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
  33. package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
  34. package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
  35. package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
  36. package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
  37. package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
  38. package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
  39. package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
  40. package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
  41. package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
  42. package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
  43. package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
  44. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
  45. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
  46. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
  47. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
  48. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
  49. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
  50. package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
  51. package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
  52. package/dist/domains/chat/knowledge.cjs.js +2 -0
  53. package/dist/domains/chat/knowledge.es.js +2 -2
  54. package/dist/domains/chat/messages/message-row.cjs.js +3 -3
  55. package/dist/domains/chat/messages/message-row.es.js +3 -3
  56. package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
  57. package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
  58. package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
  59. package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
  60. package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
  61. package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
  62. package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
  63. package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
  64. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
  65. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
  66. package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
  67. package/dist/domains/chat/messages/signal-badge.es.js +1 -1
  68. package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
  69. package/dist/domains/chat/messages/skill-message.es.js +2 -2
  70. package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
  71. package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
  72. package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
  73. package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
  74. package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
  75. package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
  76. package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
  77. package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
  78. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
  79. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
  80. package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
  81. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
  82. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
  83. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
  84. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
  85. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
  86. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
  87. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
  88. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
  89. package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
  90. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
  91. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
  92. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
  93. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
  94. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
  95. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
  96. package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
  97. package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
  98. package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
  99. package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
  100. package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
  101. package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
  102. package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
  103. package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
  104. package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
  105. package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
  106. package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
  107. package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
  108. package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
  109. package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
  110. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
  111. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
  112. package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
  113. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
  114. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
  115. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
  116. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
  117. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
  118. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
  119. package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
  120. package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
  121. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +240 -0
  122. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
  123. package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
  124. package/dist/domains/chat/tools/mcp-input-request-tool.es.js +239 -0
  125. package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
  126. package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
  127. package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
  128. package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
  129. package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
  130. package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
  131. package/dist/domains/chat/tools/tool-card-kind.cjs.js +8 -3
  132. package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
  133. package/dist/domains/chat/tools/tool-card-kind.es.js +8 -4
  134. package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
  135. package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
  136. package/dist/domains/chat/tools/tool-card.es.js +1 -1
  137. package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
  138. package/dist/domains/chat/tools/tool-groups.es.js +1 -1
  139. package/dist/domains/chat.cjs.js +5 -3
  140. package/dist/domains/chat.es.js +4 -4
  141. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
  142. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
  143. package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
  144. package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
  145. package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
  146. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
  147. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
  148. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
  149. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
  150. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
  151. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
  152. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
  153. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
  154. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
  155. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
  156. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
  157. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
  158. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
  159. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
  160. package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
  161. package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
  162. package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
  163. package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
  164. package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
  165. package/dist/domains/knowledge/lib/circleText.es.js +8 -0
  166. package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
  167. package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
  168. package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
  169. package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
  170. package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
  171. package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
  172. package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
  173. package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
  174. package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
  175. package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
  176. package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
  177. package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
  178. package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
  179. package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
  180. package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
  181. package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
  182. package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
  183. package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
  184. package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
  185. package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
  186. package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
  187. package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
  188. package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
  189. package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
  190. package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
  191. package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
  192. package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
  193. package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
  194. package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
  195. package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
  196. package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
  197. package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
  198. package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
  199. package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
  200. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
  201. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
  202. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
  203. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
  204. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
  205. package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
  206. package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
  207. package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
  208. package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
  209. package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
  210. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
  211. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
  212. package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
  213. package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
  214. package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
  215. package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
  216. package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
  217. package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
  218. package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
  219. package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
  220. package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
  221. package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
  222. package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
  223. package/dist/domains/skills/skill-simple-form.es.js +1 -1
  224. package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
  225. package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
  226. package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
  227. package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
  228. package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
  229. package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
  230. package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
  231. package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
  232. package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
  233. package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
  234. package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
  235. package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
  236. package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
  237. package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
  238. package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
  239. package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
  240. package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
  241. package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
  242. package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
  243. package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
  244. package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
  245. package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
  246. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +8 -2
  247. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  248. package/dist/domains/traces/components/trace-data-panel-view.es.js +8 -2
  249. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  250. package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
  251. package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
  252. package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
  253. package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
  254. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +2 -2
  255. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +2 -2
  256. package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
  257. package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
  258. package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
  259. package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
  260. package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
  261. package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
  262. package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
  263. package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
  264. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
  265. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
  266. package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
  267. package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
  268. package/dist/lib/form/dynamic-form.cjs.js +2 -2
  269. package/dist/lib/form/dynamic-form.es.js +2 -2
  270. package/dist/lib/form/json-draft.cjs.js +1 -1
  271. package/dist/lib/form/json-draft.es.js +1 -1
  272. package/dist/lib/form/zod-provider.cjs.js +1 -1
  273. package/dist/lib/form/zod-provider.es.js +1 -1
  274. package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
  275. package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
  276. package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
  277. package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
  278. package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
  279. package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
  280. package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
  281. package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
  282. package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
  283. package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
  284. package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
  285. package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
  286. package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
  287. package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
  288. package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
  289. package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
  290. package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
  291. package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
  292. package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
  293. package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
  294. package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
  295. package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
  296. package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
  297. package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
  298. package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
  299. package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
  300. package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
  301. package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
  302. package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
  303. package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
  304. package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
  305. package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
  306. package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
  307. package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
  308. package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
  309. package/dist/style.css +69 -2
  310. package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
  311. package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
  312. package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
  313. package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
  314. package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
  315. package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
  316. package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
  317. package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
  318. package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-rxhTDpk_.cjs} +164 -126
  319. package/dist/tool-card-rxhTDpk_.cjs.map +1 -0
  320. package/dist/{tool-card-sO6P2Qj4.js → tool-card-toDgoZzJ.js} +165 -127
  321. package/dist/tool-card-toDgoZzJ.js.map +1 -0
  322. package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
  323. package/dist/tool-presentation-CvibOP1J.js.map +1 -0
  324. package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
  325. package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
  326. package/package.json +10 -10
  327. package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
  328. package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
  329. package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
  330. package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
  331. package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
  332. package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
  333. package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
  334. package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
  335. package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
  336. package/dist/tool-card-sO6P2Qj4.js.map +0 -1
  337. package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
  338. package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
@@ -9,3 +9,58 @@
9
9
  outline: 2px solid var(--knowledge-color);
10
10
  outline-offset: 5px;
11
11
  }
12
+
13
+ /* The focused page: a heavier border and a soft halo, so it reads as the centre of the graph. */
14
+ .knowledge-circle[data-selected='true'] {
15
+ border-width: 4px;
16
+ box-shadow: 0 0 22px 4px color-mix(in srgb, var(--knowledge-color) 45%, transparent);
17
+ }
18
+
19
+ /* A refocus: pages in both views glide and resize to their new place, new ones fade in, and ones that
20
+ leave are faded out (the graph keeps them a moment). Under reduced motion every one of these is off. */
21
+ .knowledge-graph {
22
+ /* Keep in step with KNOWLEDGE_GRAPH_TRANSITION_MS in lib/useLeavingNodes.ts. */
23
+ --knowledge-graph-transition: 700ms cubic-bezier(0.65, 0, 0.35, 1);
24
+ }
25
+
26
+ .knowledge-graph .react-flow__node {
27
+ transition:
28
+ transform var(--knowledge-graph-transition),
29
+ width var(--knowledge-graph-transition),
30
+ height var(--knowledge-graph-transition),
31
+ opacity var(--knowledge-graph-transition);
32
+ animation: knowledge-node-in var(--knowledge-graph-transition) both;
33
+ }
34
+
35
+ @keyframes knowledge-node-in {
36
+ from {
37
+ opacity: 0;
38
+ }
39
+ }
40
+
41
+ @media (prefers-reduced-motion: reduce) {
42
+ .knowledge-graph .react-flow__node {
43
+ transition: none;
44
+ animation: none;
45
+ }
46
+ }
47
+
48
+ /* With a page hovered or selected, everything but its neighbourhood fades. It fades the node's content, not
49
+ the node: the node's own opacity belongs to the view change, and a short fade keeps pointing responsive. */
50
+ .knowledge-graph .react-flow__node > *,
51
+ .knowledge-graph .react-flow__edge {
52
+ transition: opacity 150ms ease-out;
53
+ }
54
+
55
+ .knowledge-graph[data-emphasis] .react-flow__node:not(.knowledge-neighbour) > * {
56
+ opacity: 0.35;
57
+ }
58
+
59
+ .knowledge-graph[data-emphasis] .react-flow__edge:not(.knowledge-neighbour) {
60
+ opacity: 0.2;
61
+ }
62
+
63
+ /* A hovered dot's tooltip sits above every other circle. */
64
+ .knowledge-graph .react-flow__node:hover {
65
+ z-index: 1000 !important;
66
+ }
@@ -329,11 +329,15 @@ function useSettledWords(words, streaming) {
329
329
  * halfway through reading would be both a lie and a screenful of animations at
330
330
  * once.
331
331
  */
332
- var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false }) {
332
+ var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false, remarkPlugins: extraRemarkPlugins, components: extraComponents }) {
333
333
  const shown = decodeEscapedNewlines(children);
334
334
  const blocks = useMemo(() => splitBlocks(shown), [shown]);
335
335
  const last = blocks.length - 1;
336
- const components = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
336
+ const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
337
+ const components = useMemo(() => extraComponents ? {
338
+ ...baseComponents,
339
+ ...extraComponents
340
+ } : baseComponents, [baseComponents, extraComponents]);
337
341
  const spans = wordSpans(blocks);
338
342
  const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);
339
343
  const settledWords = (span) => !span || settled >= span.end ? void 0 : Math.max(0, settled - span.start);
@@ -346,15 +350,24 @@ var MarkdownRenderer = memo(function MarkdownRenderer({ children, className, ext
346
350
  settledWords: settledWords(spans[index]),
347
351
  components,
348
352
  streaming,
349
- tableActions
353
+ tableActions,
354
+ extraRemarkPlugins
350
355
  }, index))
351
356
  });
352
357
  });
353
358
  /** Keyed by position at the call site: a content key remounts on every character. */
354
- var MarkdownBlock = memo(function MarkdownBlock({ components, content, settledWords, streaming, tableActions }) {
359
+ var MarkdownBlock = memo(function MarkdownBlock({ components, content, settledWords, streaming, tableActions, extraRemarkPlugins }) {
360
+ const remarkPlugins = useMemo(() => {
361
+ const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;
362
+ return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;
363
+ }, [
364
+ tableActions,
365
+ streaming,
366
+ extraRemarkPlugins
367
+ ]);
355
368
  const rehypePlugins = useMemo(() => settledWords === void 0 ? SETTLED : [rehypeArriving(settledWords)], [settledWords]);
356
369
  return /* @__PURE__ */ jsx(Markdown, {
357
- remarkPlugins: tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS,
370
+ remarkPlugins,
358
371
  rehypePlugins,
359
372
  components,
360
373
  children: content
@@ -465,4 +478,4 @@ var TABLE_COMPONENTS = {
465
478
  };
466
479
  export { MarkdownRenderer as t };
467
480
 
468
- //# sourceMappingURL=MarkdownRenderer-2GOXQJEv.js.map
481
+ //# sourceMappingURL=MarkdownRenderer-CI30RqdB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer-CI30RqdB.js","names":[],"sources":["../src/ds/components/MarkdownRenderer/arriving.ts","../src/ds/components/MarkdownRenderer/blocks.ts","../src/ds/components/MarkdownRenderer/table-csv.ts","../src/ds/components/MarkdownRenderer/markdown-table.tsx","../src/ds/components/MarkdownRenderer/table-markdown.ts","../src/ds/components/MarkdownRenderer/use-settled.ts","../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { ExtraProps } from 'react-markdown';\n\nimport { ARRIVING_CLASS } from '@/ds/tokens';\n\nimport '@/ds/components/Arrival/arrival.css';\n\ntype MarkdownElement = NonNullable<ExtraProps['node']>;\ntype MarkdownChild = MarkdownElement['children'][number];\n\n/** Fades whole: a fence renders through `CodeBlock`, and inline code carries a background. */\nconst UNBROKEN = new Set(['pre', 'code']);\n\nconst wrap = (value: string, arriving: boolean): MarkdownChild => ({\n type: 'element',\n tagName: 'span',\n properties: arriving ? { className: [ARRIVING_CLASS] } : {},\n children: [{ type: 'text', value }],\n});\n\nfunction markArriving(node: MarkdownElement): void {\n const classes = node.properties.className;\n\n node.properties.className = Array.isArray(classes) ? [...classes, ARRIVING_CLASS] : [ARRIVING_CLASS];\n}\n\nfunction rebuild(nodes: MarkdownChild[], arriving: () => boolean): MarkdownChild[] {\n const out: MarkdownChild[] = [];\n\n for (const node of nodes) {\n if (node.type === 'text') {\n for (const piece of node.value.match(/\\S+|\\s+/g) ?? []) {\n if (/\\S/.test(piece)) out.push(wrap(piece, arriving()));\n else out.push({ type: 'text', value: piece });\n }\n\n continue;\n }\n\n out.push(node);\n\n if (node.type !== 'element') continue;\n\n if (!UNBROKEN.has(node.tagName)) node.children = rebuild(node.children, arriving);\n else if (arriving()) markArriving(node);\n }\n\n return out;\n}\n\n/**\n * Gives every word of a block an element of its own, and the entrance class to\n * those past the first `settled` — the words that were not on screen yet when\n * the reader joined this reply.\n *\n * Every word, not just the arriving ones: react-markdown parses afresh on each\n * landing and React matches the children it already mounted by position, so a\n * wrapper that came and went would land where a bare text node used to be and\n * remount half the paragraph, replaying entrances that had long finished.\n * Wrapping the lot keeps every position fixed — a new word only ever appends —\n * and a word never gains the class it did not mount with, so nothing replays.\n */\nexport function rehypeArriving(settled: number) {\n return function attach() {\n return (tree: { children: MarkdownChild[] }) => {\n let word = 0;\n\n tree.children = rebuild(tree.children, () => word++ >= settled);\n };\n };\n}\n","const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;\nconst FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/;\nconst LIST_ITEM = /^ {0,3}(?:[-*+]|\\d{1,9}[.)])(?:[ \\t]|$)/;\nconst INDENTED = /^(?:\\t| {2,})/;\nconst DEFINITION = /^ {0,3}\\[[^\\]]+\\]:/;\n\nfunction fenceOpenedBy(line: string): string | undefined {\n return FENCE_OPEN.exec(line)?.[1];\n}\n\n// Both are runs of one character, so `startsWith` is \"same marker, at least as long\".\nfunction closesFence(line: string, marker: string): boolean {\n return FENCE_CLOSE.exec(line)?.[1]?.startsWith(marker) ?? false;\n}\n\nfunction startsBlock(line: string, inList: boolean): boolean {\n if (INDENTED.test(line)) return false;\n\n return !(inList && LIST_ITEM.test(line));\n}\n\n/**\n * Cuts markdown into top-level blocks so a growing reply re-parses its last\n * block instead of all of them. Rejoining the result returns the input, and\n * every block renders as it would have inside the whole.\n *\n * Each rule only ever merges: over-merging costs a re-parse, while cutting a\n * construct in two changes what it renders as. Link reference and footnote\n * definitions resolve across blank lines, which no line-level rule can see, so\n * reaching one outside a fence abandons the split for the whole text.\n */\nexport function splitBlocks(markdown: string): string[] {\n const lines = markdown.split('\\n');\n const starts = [0];\n let fence: string | undefined;\n let started = false;\n let broken = false;\n let inList = false;\n\n for (const [index, line] of lines.entries()) {\n if (fence) {\n if (closesFence(line, fence)) fence = undefined;\n continue;\n }\n\n if (line.trim() === '') {\n broken = started;\n continue;\n }\n\n if (DEFINITION.test(line)) return [markdown];\n\n if (broken && startsBlock(line, inList)) {\n starts.push(index);\n started = false;\n }\n\n if (!started) inList = LIST_ITEM.test(line);\n\n started = true;\n broken = false;\n fence = fenceOpenedBy(line);\n }\n\n return starts.map((start, position) => {\n const end = starts[position + 1];\n const block = lines.slice(start, end ?? lines.length).join('\\n');\n\n return end === undefined ? block : `${block}\\n`;\n });\n}\n","function spreadsheetCell(value: string): string {\n // Quoting alone does not stop spreadsheet apps from evaluating formulas.\n const numeric = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(value.trim());\n const formula = /^[\\s\\uFEFF]*[=+\\-@=+-@]/u.test(value);\n const controlPrefix = /^[\\t\\r\\n]/.test(value);\n const safe = controlPrefix || (formula && !numeric) ? `'${value}` : value;\n return `\"${safe.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function tableToCsv(rows: string[][]): string {\n return rows.map(row => row.map(spreadsheetCell).join(',')).join('\\r\\n');\n}\n\nexport function downloadTableCsv(csv: string): void {\n const blob = new Blob(['\\uFEFF', csv], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = 'table.csv';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n","import { CheckIcon, ChevronDownIcon, CopyIcon, DownloadIcon } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport type { ExtraProps } from 'react-markdown';\nimport { downloadTableCsv } from './table-csv';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\n\nexport function MarkdownTable({ node, children }: ComponentProps<'table'> & ExtraProps) {\n const markdown = node?.properties.tableMarkdown;\n const csv = node?.properties.tableCsv;\n const { isCopied, copyToClipboard } = useCopyToClipboard({ copyMessage: 'Copied table markdown' });\n\n return (\n <div className=\"my-3 w-fit max-w-full min-w-0\">\n <div className=\"flex justify-end\">\n <ButtonsGroup size=\"sm\" aria-label=\"Table actions\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={typeof markdown !== 'string'}\n onClick={() => {\n if (typeof markdown === 'string') copyToClipboard(markdown);\n }}\n aria-label=\"Copy table as markdown\"\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n {isCopied ? 'Copied!' : 'Copy table as markdown'}\n </Button>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={typeof csv !== 'string'}\n render={\n <Button type=\"button\" size=\"icon-sm\" variant=\"ghost\" aria-label=\"More table options\">\n <ChevronDownIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" size=\"sm\" className=\"w-max min-w-0\">\n <DropdownMenu.Item\n size=\"sm\"\n onClick={() => {\n if (typeof csv === 'string') downloadTableCsv(csv);\n }}\n >\n <DownloadIcon />\n Download CSV\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </ButtonsGroup>\n </div>\n <div className=\"max-w-full overflow-x-auto\">\n <table className=\"table min-w-full\">{children}</table>\n </div>\n </div>\n );\n}\n","import type { Definition, FootnoteDefinition, Nodes, Root, Table } from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport { tableToCsv } from './table-csv';\n\nfunction cellText(node: Nodes): string {\n if (node.type === 'footnoteReference') return `[^${node.label ?? node.identifier}]`;\n if ('value' in node) return node.value;\n if (node.type === 'image' || node.type === 'imageReference') return node.alt ?? '';\n return 'children' in node ? node.children.map(cellText).join('') : '';\n}\n\nfunction walk(node: Nodes, visit: (node: Nodes) => void): void {\n visit(node);\n if ('children' in node) node.children.forEach(child => walk(child, visit));\n}\n\nconst SERIALIZE_OPTIONS = { extensions: [gfmToMarkdown()] };\n\n/** Capture table exports before rehype replaces text with animation spans. */\nexport function remarkTableMarkdown() {\n return (tree: Root, file: { value: unknown }) => {\n const source = String(file.value);\n const definitions = new Map<string, Definition | FootnoteDefinition>();\n const tables: Table[] = [];\n walk(tree, node => {\n if (node.type === 'definition' || node.type === 'footnoteDefinition') {\n const key = `${node.type}:${node.identifier}`;\n if (!definitions.has(key)) definitions.set(key, node);\n }\n if (node.type === 'table') tables.push(node);\n });\n\n const lines = source.split(/\\r\\n|\\r|\\n/);\n for (const table of tables) {\n const header = table.children[0];\n if (!header?.position) continue;\n const rows = table.children.map(row => {\n const start = row.position?.start.offset;\n const end = row.position?.end.offset;\n return start === undefined || end === undefined ? undefined : source.slice(start, end);\n });\n // Only offer exports when the parser supplied the original row locations.\n if (!rows.every(row => row !== undefined)) continue;\n // Row positions exclude list/blockquote prefixes. The delimiter has no AST node.\n const delimiter = lines[header.position.start.line]?.replace(/^[\\t >]*/, '');\n if (delimiter === undefined) continue;\n const markdown = [rows[0], delimiter, ...rows.slice(1)];\n const used = new Set<string>();\n const collectReference = (node: Nodes) => {\n if (node.type === 'linkReference' || node.type === 'imageReference') {\n used.add(`definition:${node.identifier}`);\n } else if (node.type === 'footnoteReference') {\n used.add(`footnoteDefinition:${node.identifier}`);\n }\n };\n walk(table, collectReference);\n // Visiting appended definitions also collects links/footnotes they depend on.\n // The set prevents duplicates and cycles, including self-referencing footnotes.\n for (const key of used) {\n const definition = definitions.get(key);\n if (!definition) continue;\n markdown.push('', toMarkdown(definition, SERIALIZE_OPTIONS).trimEnd());\n walk(definition, collectReference);\n }\n const cells = table.children.map(row =>\n Array.from({ length: header.children.length }, (_, index) => {\n const cell = row.children[index];\n return cell ? cellText(cell) : '';\n }),\n );\n table.data = {\n ...table.data,\n hProperties: {\n ...table.data?.hProperties,\n tableMarkdown: markdown.join('\\n'),\n tableCsv: tableToCsv(cells),\n },\n };\n }\n };\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useWatched } from '@/ds/components/Arrival';\nimport { ARRIVING_MS } from '@/ds/tokens';\n\ninterface Landing {\n words: number;\n at: number;\n}\n\n/**\n * How many of a reply's words have been on screen long enough that their entrance is over.\n *\n * The entrance plays on whatever mounts carrying the class, so it replays every time a\n * word's element is rebuilt — and markdown rebuilds a growing tail constantly: a `-`\n * turns a paragraph into a list item, a closing `**` splits it around a `<strong>`, the\n * stream ends and the mend comes off. Each of those swaps the element a settled word\n * lives in, which is what makes a word already read fade in again.\n *\n * Ageing them out is the whole answer: a word carries the class only while it is new,\n * so however often the tail is rebuilt, only what is genuinely arriving animates.\n *\n * What counts as new at mount is not this hook's call. A reply the reader was handed\n * is already there, and a block that mounts complete — a card's output, an expanded\n * body — enters with its container. Only a passage born streaming under the reader's\n * eyes is new from its first word: the reveal often lands several words in its first\n * commit, and they enter like every word after them.\n */\nexport function useSettledWords(words: number, streaming: boolean): number {\n const watched = useWatched();\n const [settled, setSettled] = useState(() => (watched && streaming ? 0 : words));\n const landings = useRef<Landing[]>([]);\n const recorded = useRef(settled);\n\n useEffect(() => {\n if (recorded.current !== words) {\n landings.current.push({ words, at: performance.now() });\n recorded.current = words;\n }\n\n const waiting = landings.current[0];\n if (!waiting) return;\n\n const timer = setTimeout(\n () => {\n landings.current.shift();\n setSettled(waiting.words);\n },\n Math.max(0, waiting.at + ARRIVING_MS - performance.now()),\n );\n\n return () => clearTimeout(timer);\n }, [settled, words]);\n\n // A shorter reply replacing the one on screen settles at once: nothing of it is new.\n return Math.min(settled, words);\n}\n","import { memo, useMemo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps, Options } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remend from 'remend';\n\nimport { rehypeArriving } from './arriving';\nimport { splitBlocks } from './blocks';\nimport { MarkdownTable } from './markdown-table';\nimport { remarkTableMarkdown } from './table-markdown';\nimport { useSettledWords } from './use-settled';\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\ntype RemarkPlugins = NonNullable<Options['remarkPlugins']>;\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n /** The text is a prefix of one still being written: close the markers the stream has not reached. */\n streaming?: boolean;\n /** Opt in to table copy/download controls; disabled while this text is streaming. */\n tableActions?: boolean;\n /** Remark plugins run after the built-in ones, e.g. to turn a syntax of the host's into elements. Keep it stable. */\n remarkPlugins?: RemarkPlugins;\n /** Element overrides merged over the built-in ones. Keep it stable: a new object re-renders every block. */\n components?: Components;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * react-markdown re-parses on every render, and a streaming reply re-renders\n * its whole transcript on every delta. Memoizing spares the settled messages;\n * rendering block by block — streaming or not — spares every block of the live\n * one but the last, and lets a reply settle without remounting what is already\n * on screen.\n *\n * The text is drawn as given: pacing a stream is `useRevealedText`, and belongs to\n * whoever owns the whole of what is being laid down — a reply is prose, tool rows\n * and cards, and they have to arrive in the order they were written. Only what\n * lands after the reader joined plays an entrance, and only while it is still new:\n * a reply opened part-written is already there, and fading in what someone is\n * halfway through reading would be both a lie and a screenful of animations at\n * once.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n streaming = false,\n tableActions = false,\n remarkPlugins: extraRemarkPlugins,\n components: extraComponents,\n}: MarkdownRendererProps) {\n const shown = decodeEscapedNewlines(children);\n const blocks = useMemo(() => splitBlocks(shown), [shown]);\n const last = blocks.length - 1;\n const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];\n const components = useMemo(\n () => (extraComponents ? { ...baseComponents, ...extraComponents } : baseComponents),\n [baseComponents, extraComponents],\n );\n\n const spans = wordSpans(blocks);\n const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);\n\n // A block whose words have all finished their entrance has nothing left to play,\n // which is what `undefined` says: leave it as plain text, no spans at all.\n const settledWords = (span: WordSpan | undefined): number | undefined =>\n !span || settled >= span.end ? undefined : Math.max(0, settled - span.start);\n\n const tail = blocks[last] ?? '';\n const mended = useMemo(() => (streaming ? remend(tail, REMEND_OPTIONS) : tail), [streaming, tail]);\n\n return (\n <div className={cn('mastra-markdown', className)}>\n {blocks.map((block, index) => (\n <MarkdownBlock\n key={index}\n content={index === last ? mended : block}\n settledWords={settledWords(spans[index])}\n components={components}\n streaming={streaming}\n tableActions={tableActions}\n extraRemarkPlugins={extraRemarkPlugins}\n />\n ))}\n </div>\n );\n});\n\n/** Keyed by position at the call site: a content key remounts on every character. */\nconst MarkdownBlock = memo(function MarkdownBlock({\n components,\n content,\n settledWords,\n streaming,\n tableActions,\n extraRemarkPlugins,\n}: {\n components: Components;\n content: string;\n settledWords?: number;\n streaming: boolean;\n tableActions: boolean;\n extraRemarkPlugins?: RemarkPlugins;\n}) {\n const remarkPlugins = useMemo(() => {\n const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;\n return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;\n }, [tableActions, streaming, extraRemarkPlugins]);\n const rehypePlugins = useMemo(\n () => (settledWords === undefined ? SETTLED : [rehypeArriving(settledWords)]),\n [settledWords],\n );\n\n return (\n <Markdown remarkPlugins={remarkPlugins} rehypePlugins={rehypePlugins} components={components}>\n {content}\n </Markdown>\n );\n});\n\nconst SETTLED: Options['rehypePlugins'] = [];\n\ninterface WordSpan {\n start: number;\n end: number;\n}\n\n/**\n * Where each block's words fall in the reply's own count, so one settled count covers\n * them all. Counting the source counts its markers too, so the boundary only ever errs\n * towards leaving a word unanimated.\n */\nfunction wordSpans(blocks: string[]): WordSpan[] {\n let read = 0;\n\n return blocks.map(block => {\n const span = { start: read, end: read + countWords(block) };\n read = span.end;\n\n return span;\n });\n}\n\nfunction countWords(text: string): number {\n return text.match(/\\S+/g)?.length ?? 0;\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({\n node,\n children,\n className,\n}: {\n node?: MarkdownNode;\n children?: ReactNode;\n className?: string;\n}) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre className={className}>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className={cn('my-3 bg-sidebar', className)}\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\nconst REMARK_PLUGINS = [remarkGfm];\nconst COPYABLE_REMARK_PLUGINS = [remarkGfm, remarkTableMarkdown];\n\n// Links stay text until their URL lands: remend's placeholder href would render\n// a live anchor to nowhere. No math is rendered here, so pairing `$$` would only\n// turn one literal into another.\nconst REMEND_OPTIONS = { katex: false, linkMode: 'text-only' } as const;\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n\nconst DEFAULT_COMPONENTS = { tab: COMPONENTS, window: WINDOW_COMPONENTS };\nconst TABLE_COMPONENTS = {\n tab: { ...COMPONENTS, table: MarkdownTable },\n window: { ...WINDOW_COMPONENTS, table: MarkdownTable },\n};\n"],"mappings":"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"}
@@ -333,11 +333,15 @@ function useSettledWords(words, streaming) {
333
333
  * halfway through reading would be both a lie and a screenful of animations at
334
334
  * once.
335
335
  */
336
- var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false }) {
336
+ var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, className, externalLinkTarget = "tab", streaming = false, tableActions = false, remarkPlugins: extraRemarkPlugins, components: extraComponents }) {
337
337
  const shown = decodeEscapedNewlines(children);
338
338
  const blocks = (0, react.useMemo)(() => splitBlocks(shown), [shown]);
339
339
  const last = blocks.length - 1;
340
- const components = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
340
+ const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];
341
+ const components = (0, react.useMemo)(() => extraComponents ? {
342
+ ...baseComponents,
343
+ ...extraComponents
344
+ } : baseComponents, [baseComponents, extraComponents]);
341
345
  const spans = wordSpans(blocks);
342
346
  const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);
343
347
  const settledWords = (span) => !span || settled >= span.end ? void 0 : Math.max(0, settled - span.start);
@@ -350,15 +354,24 @@ var MarkdownRenderer = (0, react.memo)(function MarkdownRenderer({ children, cla
350
354
  settledWords: settledWords(spans[index]),
351
355
  components,
352
356
  streaming,
353
- tableActions
357
+ tableActions,
358
+ extraRemarkPlugins
354
359
  }, index))
355
360
  });
356
361
  });
357
362
  /** Keyed by position at the call site: a content key remounts on every character. */
358
- var MarkdownBlock = (0, react.memo)(function MarkdownBlock({ components, content, settledWords, streaming, tableActions }) {
363
+ var MarkdownBlock = (0, react.memo)(function MarkdownBlock({ components, content, settledWords, streaming, tableActions, extraRemarkPlugins }) {
364
+ const remarkPlugins = (0, react.useMemo)(() => {
365
+ const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;
366
+ return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;
367
+ }, [
368
+ tableActions,
369
+ streaming,
370
+ extraRemarkPlugins
371
+ ]);
359
372
  const rehypePlugins = (0, react.useMemo)(() => settledWords === void 0 ? SETTLED : [rehypeArriving(settledWords)], [settledWords]);
360
373
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_markdown.default, {
361
- remarkPlugins: tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS,
374
+ remarkPlugins,
362
375
  rehypePlugins,
363
376
  components,
364
377
  children: content
@@ -474,4 +487,4 @@ Object.defineProperty(exports, "MarkdownRenderer", {
474
487
  }
475
488
  });
476
489
 
477
- //# sourceMappingURL=MarkdownRenderer-CB8Z_CHc.cjs.map
490
+ //# sourceMappingURL=MarkdownRenderer-y65WGBhC.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer-y65WGBhC.cjs","names":["ARRIVING_CLASS","useCopyToClipboard","ButtonsGroup","Button","CheckIcon","CopyIcon","DropdownMenu","ChevronDownIcon","DownloadIcon","gfmToMarkdown","toMarkdown","useWatched","useState","useRef","memo","useMemo","cn","Markdown","CodeBlock","remarkGfm"],"sources":["../src/ds/components/MarkdownRenderer/arriving.ts","../src/ds/components/MarkdownRenderer/blocks.ts","../src/ds/components/MarkdownRenderer/table-csv.ts","../src/ds/components/MarkdownRenderer/markdown-table.tsx","../src/ds/components/MarkdownRenderer/table-markdown.ts","../src/ds/components/MarkdownRenderer/use-settled.ts","../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { ExtraProps } from 'react-markdown';\n\nimport { ARRIVING_CLASS } from '@/ds/tokens';\n\nimport '@/ds/components/Arrival/arrival.css';\n\ntype MarkdownElement = NonNullable<ExtraProps['node']>;\ntype MarkdownChild = MarkdownElement['children'][number];\n\n/** Fades whole: a fence renders through `CodeBlock`, and inline code carries a background. */\nconst UNBROKEN = new Set(['pre', 'code']);\n\nconst wrap = (value: string, arriving: boolean): MarkdownChild => ({\n type: 'element',\n tagName: 'span',\n properties: arriving ? { className: [ARRIVING_CLASS] } : {},\n children: [{ type: 'text', value }],\n});\n\nfunction markArriving(node: MarkdownElement): void {\n const classes = node.properties.className;\n\n node.properties.className = Array.isArray(classes) ? [...classes, ARRIVING_CLASS] : [ARRIVING_CLASS];\n}\n\nfunction rebuild(nodes: MarkdownChild[], arriving: () => boolean): MarkdownChild[] {\n const out: MarkdownChild[] = [];\n\n for (const node of nodes) {\n if (node.type === 'text') {\n for (const piece of node.value.match(/\\S+|\\s+/g) ?? []) {\n if (/\\S/.test(piece)) out.push(wrap(piece, arriving()));\n else out.push({ type: 'text', value: piece });\n }\n\n continue;\n }\n\n out.push(node);\n\n if (node.type !== 'element') continue;\n\n if (!UNBROKEN.has(node.tagName)) node.children = rebuild(node.children, arriving);\n else if (arriving()) markArriving(node);\n }\n\n return out;\n}\n\n/**\n * Gives every word of a block an element of its own, and the entrance class to\n * those past the first `settled` — the words that were not on screen yet when\n * the reader joined this reply.\n *\n * Every word, not just the arriving ones: react-markdown parses afresh on each\n * landing and React matches the children it already mounted by position, so a\n * wrapper that came and went would land where a bare text node used to be and\n * remount half the paragraph, replaying entrances that had long finished.\n * Wrapping the lot keeps every position fixed — a new word only ever appends —\n * and a word never gains the class it did not mount with, so nothing replays.\n */\nexport function rehypeArriving(settled: number) {\n return function attach() {\n return (tree: { children: MarkdownChild[] }) => {\n let word = 0;\n\n tree.children = rebuild(tree.children, () => word++ >= settled);\n };\n };\n}\n","const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;\nconst FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/;\nconst LIST_ITEM = /^ {0,3}(?:[-*+]|\\d{1,9}[.)])(?:[ \\t]|$)/;\nconst INDENTED = /^(?:\\t| {2,})/;\nconst DEFINITION = /^ {0,3}\\[[^\\]]+\\]:/;\n\nfunction fenceOpenedBy(line: string): string | undefined {\n return FENCE_OPEN.exec(line)?.[1];\n}\n\n// Both are runs of one character, so `startsWith` is \"same marker, at least as long\".\nfunction closesFence(line: string, marker: string): boolean {\n return FENCE_CLOSE.exec(line)?.[1]?.startsWith(marker) ?? false;\n}\n\nfunction startsBlock(line: string, inList: boolean): boolean {\n if (INDENTED.test(line)) return false;\n\n return !(inList && LIST_ITEM.test(line));\n}\n\n/**\n * Cuts markdown into top-level blocks so a growing reply re-parses its last\n * block instead of all of them. Rejoining the result returns the input, and\n * every block renders as it would have inside the whole.\n *\n * Each rule only ever merges: over-merging costs a re-parse, while cutting a\n * construct in two changes what it renders as. Link reference and footnote\n * definitions resolve across blank lines, which no line-level rule can see, so\n * reaching one outside a fence abandons the split for the whole text.\n */\nexport function splitBlocks(markdown: string): string[] {\n const lines = markdown.split('\\n');\n const starts = [0];\n let fence: string | undefined;\n let started = false;\n let broken = false;\n let inList = false;\n\n for (const [index, line] of lines.entries()) {\n if (fence) {\n if (closesFence(line, fence)) fence = undefined;\n continue;\n }\n\n if (line.trim() === '') {\n broken = started;\n continue;\n }\n\n if (DEFINITION.test(line)) return [markdown];\n\n if (broken && startsBlock(line, inList)) {\n starts.push(index);\n started = false;\n }\n\n if (!started) inList = LIST_ITEM.test(line);\n\n started = true;\n broken = false;\n fence = fenceOpenedBy(line);\n }\n\n return starts.map((start, position) => {\n const end = starts[position + 1];\n const block = lines.slice(start, end ?? lines.length).join('\\n');\n\n return end === undefined ? block : `${block}\\n`;\n });\n}\n","function spreadsheetCell(value: string): string {\n // Quoting alone does not stop spreadsheet apps from evaluating formulas.\n const numeric = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(value.trim());\n const formula = /^[\\s\\uFEFF]*[=+\\-@=+-@]/u.test(value);\n const controlPrefix = /^[\\t\\r\\n]/.test(value);\n const safe = controlPrefix || (formula && !numeric) ? `'${value}` : value;\n return `\"${safe.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function tableToCsv(rows: string[][]): string {\n return rows.map(row => row.map(spreadsheetCell).join(',')).join('\\r\\n');\n}\n\nexport function downloadTableCsv(csv: string): void {\n const blob = new Blob(['\\uFEFF', csv], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = 'table.csv';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n","import { CheckIcon, ChevronDownIcon, CopyIcon, DownloadIcon } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport type { ExtraProps } from 'react-markdown';\nimport { downloadTableCsv } from './table-csv';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\n\nexport function MarkdownTable({ node, children }: ComponentProps<'table'> & ExtraProps) {\n const markdown = node?.properties.tableMarkdown;\n const csv = node?.properties.tableCsv;\n const { isCopied, copyToClipboard } = useCopyToClipboard({ copyMessage: 'Copied table markdown' });\n\n return (\n <div className=\"my-3 w-fit max-w-full min-w-0\">\n <div className=\"flex justify-end\">\n <ButtonsGroup size=\"sm\" aria-label=\"Table actions\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={typeof markdown !== 'string'}\n onClick={() => {\n if (typeof markdown === 'string') copyToClipboard(markdown);\n }}\n aria-label=\"Copy table as markdown\"\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n {isCopied ? 'Copied!' : 'Copy table as markdown'}\n </Button>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={typeof csv !== 'string'}\n render={\n <Button type=\"button\" size=\"icon-sm\" variant=\"ghost\" aria-label=\"More table options\">\n <ChevronDownIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" size=\"sm\" className=\"w-max min-w-0\">\n <DropdownMenu.Item\n size=\"sm\"\n onClick={() => {\n if (typeof csv === 'string') downloadTableCsv(csv);\n }}\n >\n <DownloadIcon />\n Download CSV\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </ButtonsGroup>\n </div>\n <div className=\"max-w-full overflow-x-auto\">\n <table className=\"table min-w-full\">{children}</table>\n </div>\n </div>\n );\n}\n","import type { Definition, FootnoteDefinition, Nodes, Root, Table } from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport { tableToCsv } from './table-csv';\n\nfunction cellText(node: Nodes): string {\n if (node.type === 'footnoteReference') return `[^${node.label ?? node.identifier}]`;\n if ('value' in node) return node.value;\n if (node.type === 'image' || node.type === 'imageReference') return node.alt ?? '';\n return 'children' in node ? node.children.map(cellText).join('') : '';\n}\n\nfunction walk(node: Nodes, visit: (node: Nodes) => void): void {\n visit(node);\n if ('children' in node) node.children.forEach(child => walk(child, visit));\n}\n\nconst SERIALIZE_OPTIONS = { extensions: [gfmToMarkdown()] };\n\n/** Capture table exports before rehype replaces text with animation spans. */\nexport function remarkTableMarkdown() {\n return (tree: Root, file: { value: unknown }) => {\n const source = String(file.value);\n const definitions = new Map<string, Definition | FootnoteDefinition>();\n const tables: Table[] = [];\n walk(tree, node => {\n if (node.type === 'definition' || node.type === 'footnoteDefinition') {\n const key = `${node.type}:${node.identifier}`;\n if (!definitions.has(key)) definitions.set(key, node);\n }\n if (node.type === 'table') tables.push(node);\n });\n\n const lines = source.split(/\\r\\n|\\r|\\n/);\n for (const table of tables) {\n const header = table.children[0];\n if (!header?.position) continue;\n const rows = table.children.map(row => {\n const start = row.position?.start.offset;\n const end = row.position?.end.offset;\n return start === undefined || end === undefined ? undefined : source.slice(start, end);\n });\n // Only offer exports when the parser supplied the original row locations.\n if (!rows.every(row => row !== undefined)) continue;\n // Row positions exclude list/blockquote prefixes. The delimiter has no AST node.\n const delimiter = lines[header.position.start.line]?.replace(/^[\\t >]*/, '');\n if (delimiter === undefined) continue;\n const markdown = [rows[0], delimiter, ...rows.slice(1)];\n const used = new Set<string>();\n const collectReference = (node: Nodes) => {\n if (node.type === 'linkReference' || node.type === 'imageReference') {\n used.add(`definition:${node.identifier}`);\n } else if (node.type === 'footnoteReference') {\n used.add(`footnoteDefinition:${node.identifier}`);\n }\n };\n walk(table, collectReference);\n // Visiting appended definitions also collects links/footnotes they depend on.\n // The set prevents duplicates and cycles, including self-referencing footnotes.\n for (const key of used) {\n const definition = definitions.get(key);\n if (!definition) continue;\n markdown.push('', toMarkdown(definition, SERIALIZE_OPTIONS).trimEnd());\n walk(definition, collectReference);\n }\n const cells = table.children.map(row =>\n Array.from({ length: header.children.length }, (_, index) => {\n const cell = row.children[index];\n return cell ? cellText(cell) : '';\n }),\n );\n table.data = {\n ...table.data,\n hProperties: {\n ...table.data?.hProperties,\n tableMarkdown: markdown.join('\\n'),\n tableCsv: tableToCsv(cells),\n },\n };\n }\n };\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useWatched } from '@/ds/components/Arrival';\nimport { ARRIVING_MS } from '@/ds/tokens';\n\ninterface Landing {\n words: number;\n at: number;\n}\n\n/**\n * How many of a reply's words have been on screen long enough that their entrance is over.\n *\n * The entrance plays on whatever mounts carrying the class, so it replays every time a\n * word's element is rebuilt — and markdown rebuilds a growing tail constantly: a `-`\n * turns a paragraph into a list item, a closing `**` splits it around a `<strong>`, the\n * stream ends and the mend comes off. Each of those swaps the element a settled word\n * lives in, which is what makes a word already read fade in again.\n *\n * Ageing them out is the whole answer: a word carries the class only while it is new,\n * so however often the tail is rebuilt, only what is genuinely arriving animates.\n *\n * What counts as new at mount is not this hook's call. A reply the reader was handed\n * is already there, and a block that mounts complete — a card's output, an expanded\n * body — enters with its container. Only a passage born streaming under the reader's\n * eyes is new from its first word: the reveal often lands several words in its first\n * commit, and they enter like every word after them.\n */\nexport function useSettledWords(words: number, streaming: boolean): number {\n const watched = useWatched();\n const [settled, setSettled] = useState(() => (watched && streaming ? 0 : words));\n const landings = useRef<Landing[]>([]);\n const recorded = useRef(settled);\n\n useEffect(() => {\n if (recorded.current !== words) {\n landings.current.push({ words, at: performance.now() });\n recorded.current = words;\n }\n\n const waiting = landings.current[0];\n if (!waiting) return;\n\n const timer = setTimeout(\n () => {\n landings.current.shift();\n setSettled(waiting.words);\n },\n Math.max(0, waiting.at + ARRIVING_MS - performance.now()),\n );\n\n return () => clearTimeout(timer);\n }, [settled, words]);\n\n // A shorter reply replacing the one on screen settles at once: nothing of it is new.\n return Math.min(settled, words);\n}\n","import { memo, useMemo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps, Options } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remend from 'remend';\n\nimport { rehypeArriving } from './arriving';\nimport { splitBlocks } from './blocks';\nimport { MarkdownTable } from './markdown-table';\nimport { remarkTableMarkdown } from './table-markdown';\nimport { useSettledWords } from './use-settled';\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\ntype RemarkPlugins = NonNullable<Options['remarkPlugins']>;\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n /** The text is a prefix of one still being written: close the markers the stream has not reached. */\n streaming?: boolean;\n /** Opt in to table copy/download controls; disabled while this text is streaming. */\n tableActions?: boolean;\n /** Remark plugins run after the built-in ones, e.g. to turn a syntax of the host's into elements. Keep it stable. */\n remarkPlugins?: RemarkPlugins;\n /** Element overrides merged over the built-in ones. Keep it stable: a new object re-renders every block. */\n components?: Components;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * react-markdown re-parses on every render, and a streaming reply re-renders\n * its whole transcript on every delta. Memoizing spares the settled messages;\n * rendering block by block — streaming or not — spares every block of the live\n * one but the last, and lets a reply settle without remounting what is already\n * on screen.\n *\n * The text is drawn as given: pacing a stream is `useRevealedText`, and belongs to\n * whoever owns the whole of what is being laid down — a reply is prose, tool rows\n * and cards, and they have to arrive in the order they were written. Only what\n * lands after the reader joined plays an entrance, and only while it is still new:\n * a reply opened part-written is already there, and fading in what someone is\n * halfway through reading would be both a lie and a screenful of animations at\n * once.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n streaming = false,\n tableActions = false,\n remarkPlugins: extraRemarkPlugins,\n components: extraComponents,\n}: MarkdownRendererProps) {\n const shown = decodeEscapedNewlines(children);\n const blocks = useMemo(() => splitBlocks(shown), [shown]);\n const last = blocks.length - 1;\n const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];\n const components = useMemo(\n () => (extraComponents ? { ...baseComponents, ...extraComponents } : baseComponents),\n [baseComponents, extraComponents],\n );\n\n const spans = wordSpans(blocks);\n const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);\n\n // A block whose words have all finished their entrance has nothing left to play,\n // which is what `undefined` says: leave it as plain text, no spans at all.\n const settledWords = (span: WordSpan | undefined): number | undefined =>\n !span || settled >= span.end ? undefined : Math.max(0, settled - span.start);\n\n const tail = blocks[last] ?? '';\n const mended = useMemo(() => (streaming ? remend(tail, REMEND_OPTIONS) : tail), [streaming, tail]);\n\n return (\n <div className={cn('mastra-markdown', className)}>\n {blocks.map((block, index) => (\n <MarkdownBlock\n key={index}\n content={index === last ? mended : block}\n settledWords={settledWords(spans[index])}\n components={components}\n streaming={streaming}\n tableActions={tableActions}\n extraRemarkPlugins={extraRemarkPlugins}\n />\n ))}\n </div>\n );\n});\n\n/** Keyed by position at the call site: a content key remounts on every character. */\nconst MarkdownBlock = memo(function MarkdownBlock({\n components,\n content,\n settledWords,\n streaming,\n tableActions,\n extraRemarkPlugins,\n}: {\n components: Components;\n content: string;\n settledWords?: number;\n streaming: boolean;\n tableActions: boolean;\n extraRemarkPlugins?: RemarkPlugins;\n}) {\n const remarkPlugins = useMemo(() => {\n const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;\n return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;\n }, [tableActions, streaming, extraRemarkPlugins]);\n const rehypePlugins = useMemo(\n () => (settledWords === undefined ? SETTLED : [rehypeArriving(settledWords)]),\n [settledWords],\n );\n\n return (\n <Markdown remarkPlugins={remarkPlugins} rehypePlugins={rehypePlugins} components={components}>\n {content}\n </Markdown>\n );\n});\n\nconst SETTLED: Options['rehypePlugins'] = [];\n\ninterface WordSpan {\n start: number;\n end: number;\n}\n\n/**\n * Where each block's words fall in the reply's own count, so one settled count covers\n * them all. Counting the source counts its markers too, so the boundary only ever errs\n * towards leaving a word unanimated.\n */\nfunction wordSpans(blocks: string[]): WordSpan[] {\n let read = 0;\n\n return blocks.map(block => {\n const span = { start: read, end: read + countWords(block) };\n read = span.end;\n\n return span;\n });\n}\n\nfunction countWords(text: string): number {\n return text.match(/\\S+/g)?.length ?? 0;\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({\n node,\n children,\n className,\n}: {\n node?: MarkdownNode;\n children?: ReactNode;\n className?: string;\n}) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre className={className}>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className={cn('my-3 bg-sidebar', className)}\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\nconst REMARK_PLUGINS = [remarkGfm];\nconst COPYABLE_REMARK_PLUGINS = [remarkGfm, remarkTableMarkdown];\n\n// Links stay text until their URL lands: remend's placeholder href would render\n// a live anchor to nowhere. No math is rendered here, so pairing `$$` would only\n// turn one literal into another.\nconst REMEND_OPTIONS = { katex: false, linkMode: 'text-only' } as const;\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n\nconst DEFAULT_COMPONENTS = { tab: COMPONENTS, window: WINDOW_COMPONENTS };\nconst TABLE_COMPONENTS = {\n tab: { ...COMPONENTS, table: MarkdownTable },\n window: { ...WINDOW_COMPONENTS, table: MarkdownTable },\n};\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./component
8
8
  import { DisclosureChevron } from "./components/DisclosureChevron.es.js";
9
9
  import { Shimmer } from "./components/Shimmer.es.js";
10
10
  import { t as Badge } from "./Badge-aVu5iGAF.js";
11
- import { t as MarkdownRenderer } from "./MarkdownRenderer-2GOXQJEv.js";
11
+ import { t as MarkdownRenderer } from "./MarkdownRenderer-CI30RqdB.js";
12
12
  import { createContext, useContext, useId, useState } from "react";
13
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { Bell, ExternalLink, X } from "lucide-react";
@@ -447,4 +447,4 @@ function SignalActivity({ appearance = "row", ...signal }) {
447
447
  }
448
448
  export { useRelativePaths as S, ActivitySpacer as _, ReasoningText as a, ActivityTrigger as b, ActivityContent as c, ActivityHeader as d, ActivityHeadline as f, ActivityLeading as g, ActivityLabel as h, hasVisibleReasoning as i, ActivityDetail as l, ActivityItem as m, ReasoningActivity as n, NotificationActivity as o, ActivityIcon$1 as p, hasReasoningText as r, Activity as s, SignalActivity as t, ActivityDisclosure as u, ActivitySummary as v, ActivityWorkingDirectory as x, ActivityTrailing as y };
449
449
 
450
- //# sourceMappingURL=activity-rJ1NQl_2.js.map
450
+ //# sourceMappingURL=activity-C8Ql81WM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity-rJ1NQl_2.js","names":["ActivityIcon","_Fragment","ActivityIcon","_Fragment"],"sources":["../src/ds/components/ai/activity/use-relative-paths.ts","../src/ds/components/ai/activity/activity.tsx","../src/ds/components/ai/activity/presets/message-preview.ts","../src/ds/components/ai/activity/presets/notification-activity.tsx","../src/ds/components/ai/activity/presets/reasoning-text.tsx","../src/ds/components/ai/activity/presets/reasoning-visibility.ts","../src/ds/components/ai/activity/presets/reasoning-activity.tsx","../src/ds/components/ai/activity/presets/signal-activity.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport const WorkingDirectoryContext = createContext<string | undefined>(undefined);\n\nfunction relativeTo(directory: string | undefined, text: string): string {\n const root = directory?.replace(/\\/+$/, '');\n if (!root) return text;\n const escaped = root.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return text.replace(new RegExp(`(?<![^\\\\s'\"=(])${escaped}(?:/(?=[^\\\\s/])|(?![\\\\w.-]))`, 'g'), match =>\n match.endsWith('/') ? '' : '.',\n );\n}\n\n/** Rewrites text the way `ActivityDetail` shows it, for names that must say the same thing. */\nexport function useRelativePaths(): (text: string) => string {\n const directory = useContext(WorkingDirectoryContext);\n return text => relativeTo(directory, text);\n}\n","import { X } from 'lucide-react';\nimport { createContext, useContext, useId, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { useRelativePaths, WorkingDirectoryContext } from './use-relative-paths';\nimport { ArrivalScope, useArriving } from '@/ds/components/Arrival';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { DisclosureChevron } from '@/ds/components/DisclosureChevron';\nimport { Shimmer } from '@/ds/components/Shimmer';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\ntype ActivityStatus = 'idle' | 'running' | 'error';\n\n/** `row` sits on a hover surface; `inline` reads as text beside prose: no surface, no inset, the line lifts on hover. */\ntype ActivityAppearance = 'row' | 'inline';\n\ninterface ActivityContextValue {\n open: boolean;\n foldable: boolean;\n status: ActivityStatus;\n appearance: ActivityAppearance;\n nested: boolean;\n toggle: () => void;\n}\n\nconst LIFTS = 'transition-colors motion-reduce:transition-none';\nconst LIFTS_TO_FOREGROUND = `${LIFTS} group-hover/row:text-foreground group-has-focus-visible/row:text-foreground`;\nconst LIFTS_TO_MUTED = `${LIFTS} group-hover/row:text-muted-foreground group-has-focus-visible/row:text-muted-foreground`;\n\nconst ActivityContext = createContext<ActivityContextValue | undefined>(undefined);\n\n// Stryker disable next-line ArrowFunction: the default callback is intentionally behaviorless.\nconst noopOpenChange = () => {};\n\nfunction useActivity() {\n const context = useContext(ActivityContext);\n if (!context) throw new Error('Activity compounds must be rendered within Activity');\n return context;\n}\n\nfunction useInline() {\n return useContext(ActivityContext)?.appearance === 'inline';\n}\n\nexport interface ActivityProps extends Omit<\n ComponentProps<typeof Collapsible>,\n 'defaultOpen' | 'onOpenChange' | 'open'\n> {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n foldable?: boolean;\n status?: ActivityStatus;\n appearance?: ActivityAppearance;\n}\n\nexport function Activity({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange = noopOpenChange,\n foldable = true,\n status = 'idle',\n appearance = 'row',\n className,\n children,\n ...props\n}: ActivityProps) {\n const nested = useContext(ActivityContext) !== undefined;\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const open = controlledOpen ?? (foldable && uncontrolledOpen);\n const statusId = useId();\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange(nextOpen);\n };\n\n return (\n <ActivityContext.Provider\n value={{ open, foldable, status, appearance, nested, toggle: () => handleOpenChange(!open) }}\n >\n <Collapsible\n open={open}\n onOpenChange={handleOpenChange}\n className={cn('max-w-full min-w-0', className)}\n role=\"group\"\n aria-busy={status === 'running'}\n aria-invalid={status === 'error' || undefined}\n aria-describedby={status === 'idle' ? undefined : statusId}\n data-status={status}\n {...props}\n >\n {children}\n <span id={statusId} className=\"sr-only\" aria-live=\"polite\">\n {status === 'running' && 'Running'}\n {status === 'error' && 'Failed'}\n </span>\n </Collapsible>\n </ActivityContext.Provider>\n );\n}\n\nexport const ActivityTrigger = ({ className, children, ...props }: ComponentProps<'div'>) => {\n const { foldable, appearance } = useActivity();\n const lineId = useId();\n\n return (\n <div\n className={cn(\n 'group/row relative w-full min-w-0 rounded-md transition-colors motion-reduce:transition-none',\n foldable && appearance === 'row' && 'hover:bg-fill',\n className,\n )}\n {...props}\n >\n {foldable && (\n <CollapsibleTrigger\n aria-labelledby={lineId}\n className=\"absolute inset-0 cursor-pointer rounded-md focus-visible:ring-1 focus-visible:ring-border-focus focus-visible:outline-hidden\"\n />\n )}\n <div id={lineId} className={cn(foldable && 'pointer-events-none relative')}>\n {children}\n </div>\n </div>\n );\n};\n\nexport const ActivityHeader = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { status, appearance } = useActivity();\n\n return (\n <Shimmer\n active={status === 'running'}\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1',\n appearance === 'inline' ? 'w-fit max-w-full' : 'w-full px-1.5',\n className,\n )}\n {...props}\n >\n {children}\n </Shimmer>\n );\n};\n\nexport const ActivityLeading = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { foldable, toggle } = useActivity();\n\n if (!children) return null;\n\n return (\n <span\n className={cn('pointer-events-auto flex shrink-0 empty:hidden', foldable && 'cursor-pointer', className)}\n onClick={foldable ? toggle : undefined}\n {...props}\n >\n {children}\n </span>\n );\n};\n\nexport const ActivityIcon = ({ className, ...props }: ComponentProps<'span'>) => {\n const { status, appearance } = useActivity();\n\n return (\n <span\n className={cn(\n 'flex size-4 shrink-0 items-center justify-center [&_svg]:size-3.5 [&_svg]:shrink-0',\n status === 'error' ? 'text-destructive-foreground' : 'text-placeholder',\n status !== 'error' && appearance === 'inline' && LIFTS_TO_MUTED,\n className,\n )}\n {...props}\n />\n );\n};\n\nexport interface ActivityLabelProps extends ComponentProps<typeof Txt> {\n wrap?: boolean;\n}\n\nexport const ActivityLabel = ({ wrap = false, className, ...props }: ActivityLabelProps) => {\n const inline = useInline();\n\n return (\n <Txt\n as=\"span\"\n variant=\"caption\"\n tone=\"muted\"\n className={cn(\n wrap ? 'min-w-0 break-words' : 'shrink-0 truncate',\n inline ? `max-w-none ${LIFTS_TO_FOREGROUND}` : 'max-w-[55%]',\n className,\n )}\n {...props}\n />\n );\n};\n\n/** Paths under the agent's working directory read relative to it, the way the agent itself refers to them. */\nexport function ActivityWorkingDirectory({ path, children }: { path: string | undefined; children: ReactNode }) {\n return <WorkingDirectoryContext value={path}>{children}</WorkingDirectoryContext>;\n}\n\nexport interface ActivityDetailProps extends Omit<ComponentProps<typeof Txt>, 'font'> {\n wrap?: boolean;\n}\n\nexport const ActivityDetail = ({ wrap = false, className, children, ...props }: ActivityDetailProps) => {\n const arriving = useArriving();\n const inline = useInline();\n const relative = useRelativePaths();\n\n return (\n <Txt\n as=\"span\"\n variant=\"caption\"\n tone=\"muted\"\n className={cn('min-w-0', wrap ? 'break-words' : 'truncate', inline && LIFTS_TO_FOREGROUND, arriving, className)}\n {...props}\n >\n {typeof children === 'string' ? relative(children) : children}\n </Txt>\n );\n};\n\nexport const ActivitySummary = ({ className, ...props }: ComponentProps<'span'>) => (\n <span className={cn('flex min-w-0 items-center gap-1', className)} {...props} />\n);\n\nexport interface ActivitySpacerProps extends ComponentProps<'span'> {\n rule?: boolean;\n}\n\nexport const ActivitySpacer = ({ rule, className, ...props }: ActivitySpacerProps) => {\n const inline = useInline();\n\n return (\n <span\n aria-hidden\n className={cn(\n 'min-w-2 flex-1',\n rule && 'h-px bg-border mask-r-from-[calc(100%-min(100%,160px))]',\n inline && !rule && 'hidden',\n className,\n )}\n {...props}\n />\n );\n};\n\nexport const ActivityTrailing = ({ className, ...props }: ComponentProps<'span'>) => (\n <span className={cn('flex shrink-0 items-center', className)} {...props} />\n);\n\nexport const ActivityDisclosure = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { open, foldable, nested } = useActivity();\n\n return (\n <span\n className={cn(\n 'flex size-4 shrink-0 items-center justify-center transition-opacity duration-150 motion-reduce:transition-none starting:opacity-0',\n !foldable && 'hidden',\n foldable && nested && 'hidden group-hover/row:flex group-has-focus-visible/row:flex',\n className,\n )}\n {...props}\n >\n <span\n aria-hidden\n className={cn(\n 'flex shrink-0 items-center text-muted-foreground/60 transition duration-150 motion-reduce:transition-none',\n 'group-hover/row:text-muted-foreground group-has-focus-visible/row:text-muted-foreground',\n open && 'text-muted-foreground',\n open && children != null && 'rotate-90',\n )}\n >\n {children ?? <DisclosureChevron direction=\"right\" open={open} className=\"size-3.25\" />}\n </span>\n </span>\n );\n};\n\nexport interface ActivityHeadlineProps extends Omit<ComponentProps<typeof ActivityHeader>, 'children'> {\n leading?: ReactNode;\n icon: ReactNode;\n label: ReactNode;\n detail?: string;\n description?: string;\n wrapDetail?: boolean;\n badges?: ReactNode;\n}\n\nexport const ActivityHeadline = ({\n leading,\n icon,\n label,\n detail,\n description,\n wrapDetail,\n badges,\n ...props\n}: ActivityHeadlineProps) => {\n const { status, appearance } = useActivity();\n const hasBadges = Boolean(badges);\n const labelShrinks = Boolean(description) || (appearance === 'inline' && !detail);\n\n return (\n <ActivityHeader {...props}>\n <ActivityLeading>{leading}</ActivityLeading>\n <ActivityIcon>{icon}</ActivityIcon>\n <span className={cn('contents', hasBadges && 'flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1')}>\n <ActivityLabel className={cn(labelShrinks && 'max-w-none min-w-0 shrink')}>\n {description || label}\n </ActivityLabel>\n {badges}\n {!description && detail && (\n <ActivityDetail wrap={wrapDetail} className={cn(hasBadges && 'grow basis-40')}>\n {detail}\n </ActivityDetail>\n )}\n </span>\n <ActivitySpacer className={cn(hasBadges && 'flex-none')} />\n {status === 'error' && (\n <ActivityTrailing>\n <X size={13} role=\"img\" aria-label=\"Failed\" className=\"shrink-0 text-destructive-foreground\" />\n </ActivityTrailing>\n )}\n <ActivityDisclosure />\n </ActivityHeader>\n );\n};\n\nexport interface ActivityContentProps extends ComponentProps<typeof CollapsibleContent> {\n /** Drop the rail and its indent, so the content lines up with the text around the line. */\n flush?: boolean;\n}\n\nexport const ActivityContent = ({ flush = false, className, children, ...props }: ActivityContentProps) => {\n const inline = useInline();\n\n return (\n <CollapsibleContent className=\"max-w-full min-w-0\" {...props}>\n <div\n className={cn(\n 'relative flex max-w-full min-w-0 flex-col py-1.5',\n !flush &&\n \"gap-1.5 pr-1 pl-4 before:absolute before:inset-y-0 before:left-0 before:w-px before:bg-border before:mask-b-from-[calc(100%-min(40%,80px))] before:content-['']\",\n !flush && (inline ? 'ml-2' : 'ml-[14px]'),\n className,\n )}\n >\n <ArrivalScope>{children}</ArrivalScope>\n </div>\n </CollapsibleContent>\n );\n};\n\nexport interface ActivityItemProps extends Omit<ActivityProps, 'children' | 'open' | 'onOpenChange' | 'foldable'> {\n icon: ReactNode;\n label: string;\n detail?: string;\n badges?: ReactNode;\n collapsible?: boolean;\n children?: ReactNode;\n 'aria-label': string;\n}\n\nexport function ActivityItem({\n icon,\n label,\n detail,\n badges,\n collapsible = true,\n children,\n ...props\n}: ActivityItemProps) {\n const folds = collapsible && Boolean(children);\n\n return (\n <Activity {...props} foldable={folds} open={collapsible ? undefined : true}>\n <ActivityTrigger>\n <ActivityHeadline icon={icon} label={label} detail={detail} wrapDetail={!folds} badges={badges} />\n </ActivityTrigger>\n {children && <ActivityContent>{children}</ActivityContent>}\n </Activity>\n );\n}\n\nexport type { ActivityAppearance, ActivityStatus };\n","import { truncateString } from '@/lib/truncate-string';\n\nexport function messagePreview(message: string): string {\n return truncateString(message, 72);\n}\n\nexport function messagePreviewShowsAll(message: string): boolean {\n return !message.includes('\\n') && messagePreview(message) === message;\n}\n","import { Bell, ExternalLink } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { ActivityItem } from '../activity';\nimport { messagePreview, messagePreviewShowsAll } from './message-preview';\nimport { Badge } from '@/ds/components/Badge';\nimport type { BadgeVariant } from '@/ds/components/Badge';\nimport { Txt } from '@/ds/components/Txt';\n\nexport interface NotificationActivityProps {\n label: string;\n message: string;\n state?: string;\n icon?: ReactNode;\n priority?: string;\n status?: string;\n pending?: string;\n link?: { href: string; label: string };\n defaultOpen?: boolean;\n /** Badges rendered after the priority, status and pending badges. */\n extraBadges?: ReactNode;\n /** A label shown above the message once opened, e.g. to flag it as untrusted. */\n messageLabel?: string;\n}\n\nconst priorityBadgeVariants: Partial<Record<string, BadgeVariant>> = {\n urgent: 'red',\n high: 'orange',\n medium: 'blue',\n};\n\nexport function NotificationActivity({\n label,\n message,\n state = 'notification',\n icon,\n priority,\n status,\n pending,\n link,\n defaultOpen,\n extraBadges,\n messageLabel,\n}: NotificationActivityProps) {\n const lineHoldsMessage = messagePreviewShowsAll(message) && !messageLabel;\n const hasBadges = Boolean(priority || status || pending || extraBadges);\n\n return (\n <ActivityItem\n label={label}\n detail={messagePreview(message)}\n icon={icon ?? <Bell className=\"text-warning-foreground\" aria-hidden />}\n badges={\n hasBadges && (\n <>\n {priority && (\n <Badge size=\"xs\" variant={priorityBadgeVariants[priority]}>\n {priority}\n </Badge>\n )}\n {status && <Badge size=\"xs\">{status}</Badge>}\n {pending && <Badge size=\"xs\">{pending} pending</Badge>}\n {extraBadges}\n </>\n )\n }\n defaultOpen={defaultOpen}\n data-notification-state={state}\n aria-label={`Notification: ${label}`}\n >\n {(!lineHoldsMessage || link) && (\n <div className=\"flex flex-col gap-2\">\n {messageLabel && (\n <Txt variant=\"caption\" tone=\"muted\">\n {messageLabel}\n </Txt>\n )}\n {message && (\n <Txt variant=\"caption\" className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n )}\n {link && <NotificationLink link={link} message={message} />}\n </div>\n )}\n </ActivityItem>\n );\n}\n\nfunction NotificationLink({\n link,\n message,\n}: {\n link: NonNullable<NotificationActivityProps['link']>;\n message: string;\n}) {\n return (\n <a\n href={link.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${link.label}: ${messagePreview(message)}`}\n className=\"flex w-fit items-center gap-1 text-meta text-muted-foreground hover:text-foreground\"\n >\n {link.label}\n <ExternalLink size={12} aria-hidden />\n </a>\n );\n}\n","import type { ReasoningContent } from './reasoning-visibility';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\n\nexport interface ReasoningTextProps {\n content: ReasoningContent;\n className?: string;\n}\n\nexport function ReasoningText({ content: { text, redacted, streaming }, className }: ReasoningTextProps) {\n return (\n <MarkdownRenderer className={className} streaming={streaming && !redacted}>\n {redacted ? 'Reasoning was redacted by the provider.' : text}\n </MarkdownRenderer>\n );\n}\n","export interface ReasoningContent {\n text: string;\n redacted?: boolean;\n streaming?: boolean;\n}\n\nexport function hasVisibleReasoning({ text, redacted, streaming }: ReasoningContent): boolean {\n return Boolean(streaming || redacted) || hasReasoningText({ text, redacted });\n}\n\n/** Whether the passage has something to read: its text, or the notice that it was redacted. */\nexport function hasReasoningText({ text, redacted }: ReasoningContent): boolean {\n return Boolean(redacted) || text.trim().length > 0;\n}\n","import { ActivityItem } from '../activity';\nimport { ReasoningText } from './reasoning-text';\nimport { hasReasoningText, hasVisibleReasoning } from './reasoning-visibility';\nimport type { ReasoningContent } from './reasoning-visibility';\nimport { agentGlyph } from '@/ds/components/AgentIndicator';\n\nconst ThinkingGlyph = agentGlyph('thinking');\n\nexport interface ReasoningActivityProps extends ReasoningContent {\n defaultOpen?: boolean;\n}\n\nexport function ReasoningActivity({ defaultOpen = true, ...content }: ReasoningActivityProps) {\n if (!hasVisibleReasoning(content)) return null;\n\n return (\n <ActivityItem\n icon={<ThinkingGlyph aria-hidden />}\n label=\"Reasoning\"\n status={content.streaming ? 'running' : 'idle'}\n defaultOpen={defaultOpen}\n aria-label=\"Reasoning\"\n >\n {hasReasoningText(content) && (\n <ReasoningText content={content} className=\"text-caption text-muted-foreground [&_p]:my-0.5\" />\n )}\n </ActivityItem>\n );\n}\n","import {\n Activity,\n ActivityContent,\n ActivityDetail,\n ActivityDisclosure,\n ActivityHeader,\n ActivityIcon,\n ActivityItem,\n ActivityLabel,\n ActivityTrigger,\n} from '../activity';\nimport type { ActivityAppearance } from '../activity';\nimport { messagePreview, messagePreviewShowsAll } from './message-preview';\nimport { agentGlyph } from '@/ds/components/AgentIndicator';\nimport { Badge } from '@/ds/components/Badge';\nimport { Txt } from '@/ds/components/Txt';\nimport { humanize } from '@/lib/string';\n\nexport interface SignalActivityProps {\n kind: 'state' | 'reactive' | 'reminder';\n label: string;\n message: string;\n detail?: string;\n mode?: string;\n defaultOpen?: boolean;\n /** `inline` reads like the agent's own lines: their glyph, type and weight, the message as prose. */\n appearance?: ActivityAppearance;\n}\n\nconst signalKinds = {\n state: {\n Icon: agentGlyph('context'),\n accent: 'text-badge-purple-indicator',\n body: { variant: 'caption' },\n },\n reactive: {\n Icon: agentGlyph('notice'),\n accent: undefined,\n body: { variant: 'caption' },\n },\n reminder: {\n Icon: agentGlyph('notice'),\n accent: 'text-info-indicator',\n body: { variant: 'meta', font: 'mono' },\n },\n} as const;\n\nfunction SignalLine({ kind, label, message, detail, mode, defaultOpen }: Omit<SignalActivityProps, 'appearance'>) {\n const { Icon } = signalKinds[kind];\n const name = humanize(label);\n const lineHoldsMessage = detail === undefined && messagePreviewShowsAll(message);\n\n return (\n <Activity\n appearance=\"inline\"\n foldable={!lineHoldsMessage}\n defaultOpen={defaultOpen}\n data-signal-kind={kind}\n aria-label={`Signal: ${name}`}\n >\n <ActivityTrigger>\n <ActivityHeader>\n <ActivityIcon className=\"[&_svg]:size-4\">\n <Icon />\n </ActivityIcon>\n <ActivityLabel className=\"text-body font-medium\">{name}</ActivityLabel>\n {mode && <ActivityLabel className=\"-ml-1 text-body before:content-['·_']\">{mode}</ActivityLabel>}\n {detail && <ActivityDetail className=\"text-body-sm\">{detail}</ActivityDetail>}\n {lineHoldsMessage && message && (\n <ActivityLabel wrap className=\"text-body\">\n {message}\n </ActivityLabel>\n )}\n <ActivityDisclosure />\n </ActivityHeader>\n </ActivityTrigger>\n {!lineHoldsMessage && (\n <ActivityContent>\n <Txt tone=\"muted\" className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n </ActivityContent>\n )}\n </Activity>\n );\n}\n\nexport function SignalActivity({ appearance = 'row', ...signal }: SignalActivityProps) {\n if (appearance === 'inline') return <SignalLine {...signal} />;\n const { kind, label, message, detail, mode, defaultOpen } = signal;\n const { Icon, accent, body } = signalKinds[kind];\n const lineHoldsMessage = detail === undefined && messagePreviewShowsAll(message);\n\n return (\n <ActivityItem\n icon={<Icon className={accent} aria-hidden />}\n label={label}\n detail={detail ?? messagePreview(message)}\n badges={mode ? <Badge size=\"xs\">{mode}</Badge> : undefined}\n defaultOpen={defaultOpen}\n data-signal-kind={kind}\n aria-label={`Signal: ${label}`}\n >\n {message && !lineHoldsMessage && (\n <>\n {detail && (\n <Txt variant=\"meta\" font=\"mono\" tone=\"muted\" className=\"break-all\">\n {detail}\n </Txt>\n )}\n <Txt {...body} className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n </>\n )}\n </ActivityItem>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"activity-C8Ql81WM.js","names":["ActivityIcon","_Fragment","ActivityIcon","_Fragment"],"sources":["../src/ds/components/ai/activity/use-relative-paths.ts","../src/ds/components/ai/activity/activity.tsx","../src/ds/components/ai/activity/presets/message-preview.ts","../src/ds/components/ai/activity/presets/notification-activity.tsx","../src/ds/components/ai/activity/presets/reasoning-text.tsx","../src/ds/components/ai/activity/presets/reasoning-visibility.ts","../src/ds/components/ai/activity/presets/reasoning-activity.tsx","../src/ds/components/ai/activity/presets/signal-activity.tsx"],"sourcesContent":["import { createContext, useContext } from 'react';\n\nexport const WorkingDirectoryContext = createContext<string | undefined>(undefined);\n\nfunction relativeTo(directory: string | undefined, text: string): string {\n const root = directory?.replace(/\\/+$/, '');\n if (!root) return text;\n const escaped = root.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return text.replace(new RegExp(`(?<![^\\\\s'\"=(])${escaped}(?:/(?=[^\\\\s/])|(?![\\\\w.-]))`, 'g'), match =>\n match.endsWith('/') ? '' : '.',\n );\n}\n\n/** Rewrites text the way `ActivityDetail` shows it, for names that must say the same thing. */\nexport function useRelativePaths(): (text: string) => string {\n const directory = useContext(WorkingDirectoryContext);\n return text => relativeTo(directory, text);\n}\n","import { X } from 'lucide-react';\nimport { createContext, useContext, useId, useState } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { useRelativePaths, WorkingDirectoryContext } from './use-relative-paths';\nimport { ArrivalScope, useArriving } from '@/ds/components/Arrival';\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/ds/components/Collapsible';\nimport { DisclosureChevron } from '@/ds/components/DisclosureChevron';\nimport { Shimmer } from '@/ds/components/Shimmer';\nimport { Txt } from '@/ds/components/Txt';\nimport { cn } from '@/lib/utils';\n\ntype ActivityStatus = 'idle' | 'running' | 'error';\n\n/** `row` sits on a hover surface; `inline` reads as text beside prose: no surface, no inset, the line lifts on hover. */\ntype ActivityAppearance = 'row' | 'inline';\n\ninterface ActivityContextValue {\n open: boolean;\n foldable: boolean;\n status: ActivityStatus;\n appearance: ActivityAppearance;\n nested: boolean;\n toggle: () => void;\n}\n\nconst LIFTS = 'transition-colors motion-reduce:transition-none';\nconst LIFTS_TO_FOREGROUND = `${LIFTS} group-hover/row:text-foreground group-has-focus-visible/row:text-foreground`;\nconst LIFTS_TO_MUTED = `${LIFTS} group-hover/row:text-muted-foreground group-has-focus-visible/row:text-muted-foreground`;\n\nconst ActivityContext = createContext<ActivityContextValue | undefined>(undefined);\n\n// Stryker disable next-line ArrowFunction: the default callback is intentionally behaviorless.\nconst noopOpenChange = () => {};\n\nfunction useActivity() {\n const context = useContext(ActivityContext);\n if (!context) throw new Error('Activity compounds must be rendered within Activity');\n return context;\n}\n\nfunction useInline() {\n return useContext(ActivityContext)?.appearance === 'inline';\n}\n\nexport interface ActivityProps extends Omit<\n ComponentProps<typeof Collapsible>,\n 'defaultOpen' | 'onOpenChange' | 'open'\n> {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n foldable?: boolean;\n status?: ActivityStatus;\n appearance?: ActivityAppearance;\n}\n\nexport function Activity({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange = noopOpenChange,\n foldable = true,\n status = 'idle',\n appearance = 'row',\n className,\n children,\n ...props\n}: ActivityProps) {\n const nested = useContext(ActivityContext) !== undefined;\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const open = controlledOpen ?? (foldable && uncontrolledOpen);\n const statusId = useId();\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (controlledOpen === undefined) setUncontrolledOpen(nextOpen);\n onOpenChange(nextOpen);\n };\n\n return (\n <ActivityContext.Provider\n value={{ open, foldable, status, appearance, nested, toggle: () => handleOpenChange(!open) }}\n >\n <Collapsible\n open={open}\n onOpenChange={handleOpenChange}\n className={cn('max-w-full min-w-0', className)}\n role=\"group\"\n aria-busy={status === 'running'}\n aria-invalid={status === 'error' || undefined}\n aria-describedby={status === 'idle' ? undefined : statusId}\n data-status={status}\n {...props}\n >\n {children}\n <span id={statusId} className=\"sr-only\" aria-live=\"polite\">\n {status === 'running' && 'Running'}\n {status === 'error' && 'Failed'}\n </span>\n </Collapsible>\n </ActivityContext.Provider>\n );\n}\n\nexport const ActivityTrigger = ({ className, children, ...props }: ComponentProps<'div'>) => {\n const { foldable, appearance } = useActivity();\n const lineId = useId();\n\n return (\n <div\n className={cn(\n 'group/row relative w-full min-w-0 rounded-md transition-colors motion-reduce:transition-none',\n foldable && appearance === 'row' && 'hover:bg-fill',\n className,\n )}\n {...props}\n >\n {foldable && (\n <CollapsibleTrigger\n aria-labelledby={lineId}\n className=\"absolute inset-0 cursor-pointer rounded-md focus-visible:ring-1 focus-visible:ring-border-focus focus-visible:outline-hidden\"\n />\n )}\n <div id={lineId} className={cn(foldable && 'pointer-events-none relative')}>\n {children}\n </div>\n </div>\n );\n};\n\nexport const ActivityHeader = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { status, appearance } = useActivity();\n\n return (\n <Shimmer\n active={status === 'running'}\n className={cn(\n 'flex min-w-0 items-center gap-2 py-1',\n appearance === 'inline' ? 'w-fit max-w-full' : 'w-full px-1.5',\n className,\n )}\n {...props}\n >\n {children}\n </Shimmer>\n );\n};\n\nexport const ActivityLeading = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { foldable, toggle } = useActivity();\n\n if (!children) return null;\n\n return (\n <span\n className={cn('pointer-events-auto flex shrink-0 empty:hidden', foldable && 'cursor-pointer', className)}\n onClick={foldable ? toggle : undefined}\n {...props}\n >\n {children}\n </span>\n );\n};\n\nexport const ActivityIcon = ({ className, ...props }: ComponentProps<'span'>) => {\n const { status, appearance } = useActivity();\n\n return (\n <span\n className={cn(\n 'flex size-4 shrink-0 items-center justify-center [&_svg]:size-3.5 [&_svg]:shrink-0',\n status === 'error' ? 'text-destructive-foreground' : 'text-placeholder',\n status !== 'error' && appearance === 'inline' && LIFTS_TO_MUTED,\n className,\n )}\n {...props}\n />\n );\n};\n\nexport interface ActivityLabelProps extends ComponentProps<typeof Txt> {\n wrap?: boolean;\n}\n\nexport const ActivityLabel = ({ wrap = false, className, ...props }: ActivityLabelProps) => {\n const inline = useInline();\n\n return (\n <Txt\n as=\"span\"\n variant=\"caption\"\n tone=\"muted\"\n className={cn(\n wrap ? 'min-w-0 break-words' : 'shrink-0 truncate',\n inline ? `max-w-none ${LIFTS_TO_FOREGROUND}` : 'max-w-[55%]',\n className,\n )}\n {...props}\n />\n );\n};\n\n/** Paths under the agent's working directory read relative to it, the way the agent itself refers to them. */\nexport function ActivityWorkingDirectory({ path, children }: { path: string | undefined; children: ReactNode }) {\n return <WorkingDirectoryContext value={path}>{children}</WorkingDirectoryContext>;\n}\n\nexport interface ActivityDetailProps extends Omit<ComponentProps<typeof Txt>, 'font'> {\n wrap?: boolean;\n}\n\nexport const ActivityDetail = ({ wrap = false, className, children, ...props }: ActivityDetailProps) => {\n const arriving = useArriving();\n const inline = useInline();\n const relative = useRelativePaths();\n\n return (\n <Txt\n as=\"span\"\n variant=\"caption\"\n tone=\"muted\"\n className={cn('min-w-0', wrap ? 'break-words' : 'truncate', inline && LIFTS_TO_FOREGROUND, arriving, className)}\n {...props}\n >\n {typeof children === 'string' ? relative(children) : children}\n </Txt>\n );\n};\n\nexport const ActivitySummary = ({ className, ...props }: ComponentProps<'span'>) => (\n <span className={cn('flex min-w-0 items-center gap-1', className)} {...props} />\n);\n\nexport interface ActivitySpacerProps extends ComponentProps<'span'> {\n rule?: boolean;\n}\n\nexport const ActivitySpacer = ({ rule, className, ...props }: ActivitySpacerProps) => {\n const inline = useInline();\n\n return (\n <span\n aria-hidden\n className={cn(\n 'min-w-2 flex-1',\n rule && 'h-px bg-border mask-r-from-[calc(100%-min(100%,160px))]',\n inline && !rule && 'hidden',\n className,\n )}\n {...props}\n />\n );\n};\n\nexport const ActivityTrailing = ({ className, ...props }: ComponentProps<'span'>) => (\n <span className={cn('flex shrink-0 items-center', className)} {...props} />\n);\n\nexport const ActivityDisclosure = ({ className, children, ...props }: ComponentProps<'span'>) => {\n const { open, foldable, nested } = useActivity();\n\n return (\n <span\n className={cn(\n 'flex size-4 shrink-0 items-center justify-center transition-opacity duration-150 motion-reduce:transition-none starting:opacity-0',\n !foldable && 'hidden',\n foldable && nested && 'hidden group-hover/row:flex group-has-focus-visible/row:flex',\n className,\n )}\n {...props}\n >\n <span\n aria-hidden\n className={cn(\n 'flex shrink-0 items-center text-muted-foreground/60 transition duration-150 motion-reduce:transition-none',\n 'group-hover/row:text-muted-foreground group-has-focus-visible/row:text-muted-foreground',\n open && 'text-muted-foreground',\n open && children != null && 'rotate-90',\n )}\n >\n {children ?? <DisclosureChevron direction=\"right\" open={open} className=\"size-3.25\" />}\n </span>\n </span>\n );\n};\n\nexport interface ActivityHeadlineProps extends Omit<ComponentProps<typeof ActivityHeader>, 'children'> {\n leading?: ReactNode;\n icon: ReactNode;\n label: ReactNode;\n detail?: string;\n description?: string;\n wrapDetail?: boolean;\n badges?: ReactNode;\n}\n\nexport const ActivityHeadline = ({\n leading,\n icon,\n label,\n detail,\n description,\n wrapDetail,\n badges,\n ...props\n}: ActivityHeadlineProps) => {\n const { status, appearance } = useActivity();\n const hasBadges = Boolean(badges);\n const labelShrinks = Boolean(description) || (appearance === 'inline' && !detail);\n\n return (\n <ActivityHeader {...props}>\n <ActivityLeading>{leading}</ActivityLeading>\n <ActivityIcon>{icon}</ActivityIcon>\n <span className={cn('contents', hasBadges && 'flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1')}>\n <ActivityLabel className={cn(labelShrinks && 'max-w-none min-w-0 shrink')}>\n {description || label}\n </ActivityLabel>\n {badges}\n {!description && detail && (\n <ActivityDetail wrap={wrapDetail} className={cn(hasBadges && 'grow basis-40')}>\n {detail}\n </ActivityDetail>\n )}\n </span>\n <ActivitySpacer className={cn(hasBadges && 'flex-none')} />\n {status === 'error' && (\n <ActivityTrailing>\n <X size={13} role=\"img\" aria-label=\"Failed\" className=\"shrink-0 text-destructive-foreground\" />\n </ActivityTrailing>\n )}\n <ActivityDisclosure />\n </ActivityHeader>\n );\n};\n\nexport interface ActivityContentProps extends ComponentProps<typeof CollapsibleContent> {\n /** Drop the rail and its indent, so the content lines up with the text around the line. */\n flush?: boolean;\n}\n\nexport const ActivityContent = ({ flush = false, className, children, ...props }: ActivityContentProps) => {\n const inline = useInline();\n\n return (\n <CollapsibleContent className=\"max-w-full min-w-0\" {...props}>\n <div\n className={cn(\n 'relative flex max-w-full min-w-0 flex-col py-1.5',\n !flush &&\n \"gap-1.5 pr-1 pl-4 before:absolute before:inset-y-0 before:left-0 before:w-px before:bg-border before:mask-b-from-[calc(100%-min(40%,80px))] before:content-['']\",\n !flush && (inline ? 'ml-2' : 'ml-[14px]'),\n className,\n )}\n >\n <ArrivalScope>{children}</ArrivalScope>\n </div>\n </CollapsibleContent>\n );\n};\n\nexport interface ActivityItemProps extends Omit<ActivityProps, 'children' | 'open' | 'onOpenChange' | 'foldable'> {\n icon: ReactNode;\n label: string;\n detail?: string;\n badges?: ReactNode;\n collapsible?: boolean;\n children?: ReactNode;\n 'aria-label': string;\n}\n\nexport function ActivityItem({\n icon,\n label,\n detail,\n badges,\n collapsible = true,\n children,\n ...props\n}: ActivityItemProps) {\n const folds = collapsible && Boolean(children);\n\n return (\n <Activity {...props} foldable={folds} open={collapsible ? undefined : true}>\n <ActivityTrigger>\n <ActivityHeadline icon={icon} label={label} detail={detail} wrapDetail={!folds} badges={badges} />\n </ActivityTrigger>\n {children && <ActivityContent>{children}</ActivityContent>}\n </Activity>\n );\n}\n\nexport type { ActivityAppearance, ActivityStatus };\n","import { truncateString } from '@/lib/truncate-string';\n\nexport function messagePreview(message: string): string {\n return truncateString(message, 72);\n}\n\nexport function messagePreviewShowsAll(message: string): boolean {\n return !message.includes('\\n') && messagePreview(message) === message;\n}\n","import { Bell, ExternalLink } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { ActivityItem } from '../activity';\nimport { messagePreview, messagePreviewShowsAll } from './message-preview';\nimport { Badge } from '@/ds/components/Badge';\nimport type { BadgeVariant } from '@/ds/components/Badge';\nimport { Txt } from '@/ds/components/Txt';\n\nexport interface NotificationActivityProps {\n label: string;\n message: string;\n state?: string;\n icon?: ReactNode;\n priority?: string;\n status?: string;\n pending?: string;\n link?: { href: string; label: string };\n defaultOpen?: boolean;\n /** Badges rendered after the priority, status and pending badges. */\n extraBadges?: ReactNode;\n /** A label shown above the message once opened, e.g. to flag it as untrusted. */\n messageLabel?: string;\n}\n\nconst priorityBadgeVariants: Partial<Record<string, BadgeVariant>> = {\n urgent: 'red',\n high: 'orange',\n medium: 'blue',\n};\n\nexport function NotificationActivity({\n label,\n message,\n state = 'notification',\n icon,\n priority,\n status,\n pending,\n link,\n defaultOpen,\n extraBadges,\n messageLabel,\n}: NotificationActivityProps) {\n const lineHoldsMessage = messagePreviewShowsAll(message) && !messageLabel;\n const hasBadges = Boolean(priority || status || pending || extraBadges);\n\n return (\n <ActivityItem\n label={label}\n detail={messagePreview(message)}\n icon={icon ?? <Bell className=\"text-warning-foreground\" aria-hidden />}\n badges={\n hasBadges && (\n <>\n {priority && (\n <Badge size=\"xs\" variant={priorityBadgeVariants[priority]}>\n {priority}\n </Badge>\n )}\n {status && <Badge size=\"xs\">{status}</Badge>}\n {pending && <Badge size=\"xs\">{pending} pending</Badge>}\n {extraBadges}\n </>\n )\n }\n defaultOpen={defaultOpen}\n data-notification-state={state}\n aria-label={`Notification: ${label}`}\n >\n {(!lineHoldsMessage || link) && (\n <div className=\"flex flex-col gap-2\">\n {messageLabel && (\n <Txt variant=\"caption\" tone=\"muted\">\n {messageLabel}\n </Txt>\n )}\n {message && (\n <Txt variant=\"caption\" className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n )}\n {link && <NotificationLink link={link} message={message} />}\n </div>\n )}\n </ActivityItem>\n );\n}\n\nfunction NotificationLink({\n link,\n message,\n}: {\n link: NonNullable<NotificationActivityProps['link']>;\n message: string;\n}) {\n return (\n <a\n href={link.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label={`${link.label}: ${messagePreview(message)}`}\n className=\"flex w-fit items-center gap-1 text-meta text-muted-foreground hover:text-foreground\"\n >\n {link.label}\n <ExternalLink size={12} aria-hidden />\n </a>\n );\n}\n","import type { ReasoningContent } from './reasoning-visibility';\nimport { MarkdownRenderer } from '@/ds/components/MarkdownRenderer';\n\nexport interface ReasoningTextProps {\n content: ReasoningContent;\n className?: string;\n}\n\nexport function ReasoningText({ content: { text, redacted, streaming }, className }: ReasoningTextProps) {\n return (\n <MarkdownRenderer className={className} streaming={streaming && !redacted}>\n {redacted ? 'Reasoning was redacted by the provider.' : text}\n </MarkdownRenderer>\n );\n}\n","export interface ReasoningContent {\n text: string;\n redacted?: boolean;\n streaming?: boolean;\n}\n\nexport function hasVisibleReasoning({ text, redacted, streaming }: ReasoningContent): boolean {\n return Boolean(streaming || redacted) || hasReasoningText({ text, redacted });\n}\n\n/** Whether the passage has something to read: its text, or the notice that it was redacted. */\nexport function hasReasoningText({ text, redacted }: ReasoningContent): boolean {\n return Boolean(redacted) || text.trim().length > 0;\n}\n","import { ActivityItem } from '../activity';\nimport { ReasoningText } from './reasoning-text';\nimport { hasReasoningText, hasVisibleReasoning } from './reasoning-visibility';\nimport type { ReasoningContent } from './reasoning-visibility';\nimport { agentGlyph } from '@/ds/components/AgentIndicator';\n\nconst ThinkingGlyph = agentGlyph('thinking');\n\nexport interface ReasoningActivityProps extends ReasoningContent {\n defaultOpen?: boolean;\n}\n\nexport function ReasoningActivity({ defaultOpen = true, ...content }: ReasoningActivityProps) {\n if (!hasVisibleReasoning(content)) return null;\n\n return (\n <ActivityItem\n icon={<ThinkingGlyph aria-hidden />}\n label=\"Reasoning\"\n status={content.streaming ? 'running' : 'idle'}\n defaultOpen={defaultOpen}\n aria-label=\"Reasoning\"\n >\n {hasReasoningText(content) && (\n <ReasoningText content={content} className=\"text-caption text-muted-foreground [&_p]:my-0.5\" />\n )}\n </ActivityItem>\n );\n}\n","import {\n Activity,\n ActivityContent,\n ActivityDetail,\n ActivityDisclosure,\n ActivityHeader,\n ActivityIcon,\n ActivityItem,\n ActivityLabel,\n ActivityTrigger,\n} from '../activity';\nimport type { ActivityAppearance } from '../activity';\nimport { messagePreview, messagePreviewShowsAll } from './message-preview';\nimport { agentGlyph } from '@/ds/components/AgentIndicator';\nimport { Badge } from '@/ds/components/Badge';\nimport { Txt } from '@/ds/components/Txt';\nimport { humanize } from '@/lib/string';\n\nexport interface SignalActivityProps {\n kind: 'state' | 'reactive' | 'reminder';\n label: string;\n message: string;\n detail?: string;\n mode?: string;\n defaultOpen?: boolean;\n /** `inline` reads like the agent's own lines: their glyph, type and weight, the message as prose. */\n appearance?: ActivityAppearance;\n}\n\nconst signalKinds = {\n state: {\n Icon: agentGlyph('context'),\n accent: 'text-badge-purple-indicator',\n body: { variant: 'caption' },\n },\n reactive: {\n Icon: agentGlyph('notice'),\n accent: undefined,\n body: { variant: 'caption' },\n },\n reminder: {\n Icon: agentGlyph('notice'),\n accent: 'text-info-indicator',\n body: { variant: 'meta', font: 'mono' },\n },\n} as const;\n\nfunction SignalLine({ kind, label, message, detail, mode, defaultOpen }: Omit<SignalActivityProps, 'appearance'>) {\n const { Icon } = signalKinds[kind];\n const name = humanize(label);\n const lineHoldsMessage = detail === undefined && messagePreviewShowsAll(message);\n\n return (\n <Activity\n appearance=\"inline\"\n foldable={!lineHoldsMessage}\n defaultOpen={defaultOpen}\n data-signal-kind={kind}\n aria-label={`Signal: ${name}`}\n >\n <ActivityTrigger>\n <ActivityHeader>\n <ActivityIcon className=\"[&_svg]:size-4\">\n <Icon />\n </ActivityIcon>\n <ActivityLabel className=\"text-body font-medium\">{name}</ActivityLabel>\n {mode && <ActivityLabel className=\"-ml-1 text-body before:content-['·_']\">{mode}</ActivityLabel>}\n {detail && <ActivityDetail className=\"text-body-sm\">{detail}</ActivityDetail>}\n {lineHoldsMessage && message && (\n <ActivityLabel wrap className=\"text-body\">\n {message}\n </ActivityLabel>\n )}\n <ActivityDisclosure />\n </ActivityHeader>\n </ActivityTrigger>\n {!lineHoldsMessage && (\n <ActivityContent>\n <Txt tone=\"muted\" className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n </ActivityContent>\n )}\n </Activity>\n );\n}\n\nexport function SignalActivity({ appearance = 'row', ...signal }: SignalActivityProps) {\n if (appearance === 'inline') return <SignalLine {...signal} />;\n const { kind, label, message, detail, mode, defaultOpen } = signal;\n const { Icon, accent, body } = signalKinds[kind];\n const lineHoldsMessage = detail === undefined && messagePreviewShowsAll(message);\n\n return (\n <ActivityItem\n icon={<Icon className={accent} aria-hidden />}\n label={label}\n detail={detail ?? messagePreview(message)}\n badges={mode ? <Badge size=\"xs\">{mode}</Badge> : undefined}\n defaultOpen={defaultOpen}\n data-signal-kind={kind}\n aria-label={`Signal: ${label}`}\n >\n {message && !lineHoldsMessage && (\n <>\n {detail && (\n <Txt variant=\"meta\" font=\"mono\" tone=\"muted\" className=\"break-all\">\n {detail}\n </Txt>\n )}\n <Txt {...body} className=\"break-words whitespace-pre-wrap\">\n {message}\n </Txt>\n </>\n )}\n </ActivityItem>\n );\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ const require_components_Collapsible = require("./components/Collapsible.cjs.js"
8
8
  const require_components_DisclosureChevron = require("./components/DisclosureChevron.cjs.js");
9
9
  const require_components_Shimmer = require("./components/Shimmer.cjs.js");
10
10
  const require_Badge = require("./Badge-DZ6r6bcw.cjs");
11
- const require_MarkdownRenderer = require("./MarkdownRenderer-CB8Z_CHc.cjs");
11
+ const require_MarkdownRenderer = require("./MarkdownRenderer-y65WGBhC.cjs");
12
12
  let react = require("react");
13
13
  let react_jsx_runtime = require("react/jsx-runtime");
14
14
  let lucide_react = require("lucide-react");
@@ -578,4 +578,4 @@ Object.defineProperty(exports, "useRelativePaths", {
578
578
  }
579
579
  });
580
580
 
581
- //# sourceMappingURL=activity-DyB5H3gF.cjs.map
581
+ //# sourceMappingURL=activity-CcQZeDYi.cjs.map