@adea-ai/ui 0.140.0 → 0.142.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/dist/components/composites/appearance-editor/appearance-editor.js +2 -2
  2. package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
  3. package/dist/components/composites/catalog-browser/catalog-browser-group.js +1 -1
  4. package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts +56 -0
  5. package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts.map +1 -0
  6. package/dist/components/composites/chain-of-thought/chain-of-thought.js +117 -0
  7. package/dist/components/composites/chain-of-thought/chain-of-thought.js.map +1 -0
  8. package/dist/components/composites/chain-of-thought/index.d.ts +2 -0
  9. package/dist/components/composites/chain-of-thought/index.d.ts.map +1 -0
  10. package/dist/components/composites/chain-of-thought/index.js +2 -0
  11. package/dist/components/composites/chat/chat.d.ts +67 -0
  12. package/dist/components/composites/chat/chat.d.ts.map +1 -0
  13. package/dist/components/composites/chat/chat.js +179 -0
  14. package/dist/components/composites/chat/chat.js.map +1 -0
  15. package/dist/components/composites/chat/index.d.ts +2 -0
  16. package/dist/components/composites/chat/index.d.ts.map +1 -0
  17. package/dist/components/composites/chat/index.js +2 -0
  18. package/dist/components/composites/checkpoint/checkpoint-model.d.ts +34 -0
  19. package/dist/components/composites/checkpoint/checkpoint-model.d.ts.map +1 -0
  20. package/dist/components/composites/checkpoint/checkpoint-model.js +48 -0
  21. package/dist/components/composites/checkpoint/checkpoint-model.js.map +1 -0
  22. package/dist/components/composites/checkpoint/checkpoint.d.ts +48 -0
  23. package/dist/components/composites/checkpoint/checkpoint.d.ts.map +1 -0
  24. package/dist/components/composites/checkpoint/checkpoint.js +160 -0
  25. package/dist/components/composites/checkpoint/checkpoint.js.map +1 -0
  26. package/dist/components/composites/checkpoint/index.d.ts +3 -0
  27. package/dist/components/composites/checkpoint/index.d.ts.map +1 -0
  28. package/dist/components/composites/checkpoint/index.js +3 -0
  29. package/dist/components/composites/confirmation/confirmation-model.d.ts +45 -0
  30. package/dist/components/composites/confirmation/confirmation-model.d.ts.map +1 -0
  31. package/dist/components/composites/confirmation/confirmation-model.js +51 -0
  32. package/dist/components/composites/confirmation/confirmation-model.js.map +1 -0
  33. package/dist/components/composites/confirmation/confirmation.d.ts +72 -0
  34. package/dist/components/composites/confirmation/confirmation.d.ts.map +1 -0
  35. package/dist/components/composites/confirmation/confirmation.js +300 -0
  36. package/dist/components/composites/confirmation/confirmation.js.map +1 -0
  37. package/dist/components/composites/confirmation/index.d.ts +3 -0
  38. package/dist/components/composites/confirmation/index.d.ts.map +1 -0
  39. package/dist/components/composites/confirmation/index.js +3 -0
  40. package/dist/components/composites/context/context-model.d.ts +69 -0
  41. package/dist/components/composites/context/context-model.d.ts.map +1 -0
  42. package/dist/components/composites/context/context-model.js +122 -0
  43. package/dist/components/composites/context/context-model.js.map +1 -0
  44. package/dist/components/composites/context/context.d.ts +38 -0
  45. package/dist/components/composites/context/context.d.ts.map +1 -0
  46. package/dist/components/composites/context/context.js +234 -0
  47. package/dist/components/composites/context/context.js.map +1 -0
  48. package/dist/components/composites/context/index.d.ts +3 -0
  49. package/dist/components/composites/context/index.d.ts.map +1 -0
  50. package/dist/components/composites/context/index.js +3 -0
  51. package/dist/components/composites/file-tree/build-file-tree.d.ts +138 -0
  52. package/dist/components/composites/file-tree/build-file-tree.d.ts.map +1 -0
  53. package/dist/components/composites/file-tree/build-file-tree.js +325 -0
  54. package/dist/components/composites/file-tree/build-file-tree.js.map +1 -0
  55. package/dist/components/composites/file-tree/file-tree.d.ts +74 -0
  56. package/dist/components/composites/file-tree/file-tree.d.ts.map +1 -0
  57. package/dist/components/composites/file-tree/file-tree.js +389 -0
  58. package/dist/components/composites/file-tree/file-tree.js.map +1 -0
  59. package/dist/components/composites/file-tree/index.d.ts +3 -0
  60. package/dist/components/composites/file-tree/index.d.ts.map +1 -0
  61. package/dist/components/composites/file-tree/index.js +3 -0
  62. package/dist/components/composites/inline-citation/citation.d.ts +37 -0
  63. package/dist/components/composites/inline-citation/citation.d.ts.map +1 -0
  64. package/dist/components/composites/inline-citation/citation.js +52 -0
  65. package/dist/components/composites/inline-citation/citation.js.map +1 -0
  66. package/dist/components/composites/inline-citation/index.d.ts +3 -0
  67. package/dist/components/composites/inline-citation/index.d.ts.map +1 -0
  68. package/dist/components/composites/inline-citation/index.js +3 -0
  69. package/dist/components/composites/inline-citation/inline-citation.d.ts +64 -0
  70. package/dist/components/composites/inline-citation/inline-citation.d.ts.map +1 -0
  71. package/dist/components/composites/inline-citation/inline-citation.js +272 -0
  72. package/dist/components/composites/inline-citation/inline-citation.js.map +1 -0
  73. package/dist/components/composites/message-scroller/index.d.ts +3 -0
  74. package/dist/components/composites/message-scroller/index.d.ts.map +1 -0
  75. package/dist/components/composites/message-scroller/index.js +3 -0
  76. package/dist/components/composites/message-scroller/message-scroller.d.ts +55 -0
  77. package/dist/components/composites/message-scroller/message-scroller.d.ts.map +1 -0
  78. package/dist/components/composites/message-scroller/message-scroller.js +201 -0
  79. package/dist/components/composites/message-scroller/message-scroller.js.map +1 -0
  80. package/dist/components/composites/message-scroller/scroll-anchor.d.ts +66 -0
  81. package/dist/components/composites/message-scroller/scroll-anchor.d.ts.map +1 -0
  82. package/dist/components/composites/message-scroller/scroll-anchor.js +122 -0
  83. package/dist/components/composites/message-scroller/scroll-anchor.js.map +1 -0
  84. package/dist/components/composites/model-selector/index.d.ts +3 -0
  85. package/dist/components/composites/model-selector/index.d.ts.map +1 -0
  86. package/dist/components/composites/model-selector/index.js +3 -0
  87. package/dist/components/composites/model-selector/model-selector.d.ts +55 -0
  88. package/dist/components/composites/model-selector/model-selector.d.ts.map +1 -0
  89. package/dist/components/composites/model-selector/model-selector.js +490 -0
  90. package/dist/components/composites/model-selector/model-selector.js.map +1 -0
  91. package/dist/components/composites/model-selector/models.d.ts +51 -0
  92. package/dist/components/composites/model-selector/models.d.ts.map +1 -0
  93. package/dist/components/composites/model-selector/models.js +71 -0
  94. package/dist/components/composites/model-selector/models.js.map +1 -0
  95. package/dist/components/composites/plan/index.d.ts +2 -0
  96. package/dist/components/composites/plan/index.d.ts.map +1 -0
  97. package/dist/components/composites/plan/index.js +2 -0
  98. package/dist/components/composites/plan/plan.d.ts +61 -0
  99. package/dist/components/composites/plan/plan.d.ts.map +1 -0
  100. package/dist/components/composites/plan/plan.js +130 -0
  101. package/dist/components/composites/plan/plan.js.map +1 -0
  102. package/dist/components/composites/queue/index.d.ts +2 -0
  103. package/dist/components/composites/queue/index.d.ts.map +1 -0
  104. package/dist/components/composites/queue/index.js +2 -0
  105. package/dist/components/composites/queue/queue.d.ts +77 -0
  106. package/dist/components/composites/queue/queue.d.ts.map +1 -0
  107. package/dist/components/composites/queue/queue.js +271 -0
  108. package/dist/components/composites/queue/queue.js.map +1 -0
  109. package/dist/components/composites/reasoning/index.d.ts +2 -0
  110. package/dist/components/composites/reasoning/index.d.ts.map +1 -0
  111. package/dist/components/composites/reasoning/index.js +2 -0
  112. package/dist/components/composites/reasoning/reasoning.d.ts +62 -0
  113. package/dist/components/composites/reasoning/reasoning.d.ts.map +1 -0
  114. package/dist/components/composites/reasoning/reasoning.js +156 -0
  115. package/dist/components/composites/reasoning/reasoning.js.map +1 -0
  116. package/dist/components/composites/sources/index.d.ts +3 -0
  117. package/dist/components/composites/sources/index.d.ts.map +1 -0
  118. package/dist/components/composites/sources/index.js +3 -0
  119. package/dist/components/composites/sources/source.d.ts +46 -0
  120. package/dist/components/composites/sources/source.d.ts.map +1 -0
  121. package/dist/components/composites/sources/source.js +74 -0
  122. package/dist/components/composites/sources/source.js.map +1 -0
  123. package/dist/components/composites/sources/sources.d.ts +45 -0
  124. package/dist/components/composites/sources/sources.d.ts.map +1 -0
  125. package/dist/components/composites/sources/sources.js +175 -0
  126. package/dist/components/composites/sources/sources.js.map +1 -0
  127. package/dist/components/composites/stack-trace/index.d.ts +3 -0
  128. package/dist/components/composites/stack-trace/index.d.ts.map +1 -0
  129. package/dist/components/composites/stack-trace/index.js +3 -0
  130. package/dist/components/composites/stack-trace/parse-stack-trace.d.ts +118 -0
  131. package/dist/components/composites/stack-trace/parse-stack-trace.d.ts.map +1 -0
  132. package/dist/components/composites/stack-trace/parse-stack-trace.js +376 -0
  133. package/dist/components/composites/stack-trace/parse-stack-trace.js.map +1 -0
  134. package/dist/components/composites/stack-trace/stack-trace.d.ts +63 -0
  135. package/dist/components/composites/stack-trace/stack-trace.d.ts.map +1 -0
  136. package/dist/components/composites/stack-trace/stack-trace.js +491 -0
  137. package/dist/components/composites/stack-trace/stack-trace.js.map +1 -0
  138. package/dist/components/composites/subagent/index.d.ts +2 -0
  139. package/dist/components/composites/subagent/index.d.ts.map +1 -0
  140. package/dist/components/composites/subagent/index.js +2 -0
  141. package/dist/components/composites/subagent/subagent.d.ts +55 -0
  142. package/dist/components/composites/subagent/subagent.d.ts.map +1 -0
  143. package/dist/components/composites/subagent/subagent.js +138 -0
  144. package/dist/components/composites/subagent/subagent.js.map +1 -0
  145. package/dist/components/composites/suggestion/index.d.ts +2 -0
  146. package/dist/components/composites/suggestion/index.d.ts.map +1 -0
  147. package/dist/components/composites/suggestion/index.js +2 -0
  148. package/dist/components/composites/suggestion/suggestion.d.ts +37 -0
  149. package/dist/components/composites/suggestion/suggestion.d.ts.map +1 -0
  150. package/dist/components/composites/suggestion/suggestion.js +100 -0
  151. package/dist/components/composites/suggestion/suggestion.js.map +1 -0
  152. package/dist/components/composites/task/index.d.ts +2 -0
  153. package/dist/components/composites/task/index.d.ts.map +1 -0
  154. package/dist/components/composites/task/index.js +2 -0
  155. package/dist/components/composites/task/task.d.ts +96 -0
  156. package/dist/components/composites/task/task.d.ts.map +1 -0
  157. package/dist/components/composites/task/task.js +311 -0
  158. package/dist/components/composites/task/task.js.map +1 -0
  159. package/dist/components/composites/terminal/ansi.d.ts +101 -0
  160. package/dist/components/composites/terminal/ansi.d.ts.map +1 -0
  161. package/dist/components/composites/terminal/ansi.js +544 -0
  162. package/dist/components/composites/terminal/ansi.js.map +1 -0
  163. package/dist/components/composites/terminal/index.d.ts +4 -0
  164. package/dist/components/composites/terminal/index.d.ts.map +1 -0
  165. package/dist/components/composites/terminal/index.js +4 -0
  166. package/dist/components/composites/terminal/terminal-model.d.ts +63 -0
  167. package/dist/components/composites/terminal/terminal-model.d.ts.map +1 -0
  168. package/dist/components/composites/terminal/terminal-model.js +69 -0
  169. package/dist/components/composites/terminal/terminal-model.js.map +1 -0
  170. package/dist/components/composites/terminal/terminal.d.ts +88 -0
  171. package/dist/components/composites/terminal/terminal.d.ts.map +1 -0
  172. package/dist/components/composites/terminal/terminal.js +500 -0
  173. package/dist/components/composites/terminal/terminal.js.map +1 -0
  174. package/dist/components/composites/test-results/index.d.ts +3 -0
  175. package/dist/components/composites/test-results/index.d.ts.map +1 -0
  176. package/dist/components/composites/test-results/index.js +3 -0
  177. package/dist/components/composites/test-results/test-results-model.d.ts +154 -0
  178. package/dist/components/composites/test-results/test-results-model.d.ts.map +1 -0
  179. package/dist/components/composites/test-results/test-results-model.js +252 -0
  180. package/dist/components/composites/test-results/test-results-model.js.map +1 -0
  181. package/dist/components/composites/test-results/test-results.d.ts +60 -0
  182. package/dist/components/composites/test-results/test-results.d.ts.map +1 -0
  183. package/dist/components/composites/test-results/test-results.js +631 -0
  184. package/dist/components/composites/test-results/test-results.js.map +1 -0
  185. package/dist/components/composites/tool/format-tool-value.d.ts +37 -0
  186. package/dist/components/composites/tool/format-tool-value.d.ts.map +1 -0
  187. package/dist/components/composites/tool/format-tool-value.js +135 -0
  188. package/dist/components/composites/tool/format-tool-value.js.map +1 -0
  189. package/dist/components/composites/tool/index.d.ts +3 -0
  190. package/dist/components/composites/tool/index.d.ts.map +1 -0
  191. package/dist/components/composites/tool/index.js +3 -0
  192. package/dist/components/composites/tool/tool.d.ts +69 -0
  193. package/dist/components/composites/tool/tool.d.ts.map +1 -0
  194. package/dist/components/composites/tool/tool.js +214 -0
  195. package/dist/components/composites/tool/tool.js.map +1 -0
  196. package/dist/components/composites/update-dialog/update-dialog.js +1 -1
  197. package/dist/components/conversation/conversation-surface.d.ts +7 -0
  198. package/dist/components/conversation/conversation-surface.d.ts.map +1 -1
  199. package/dist/components/conversation/conversation-surface.js +2 -0
  200. package/dist/components/conversation/conversation-surface.js.map +1 -1
  201. package/dist/components/conversation/scroll-follow-core.d.ts +24 -0
  202. package/dist/components/conversation/scroll-follow-core.d.ts.map +1 -1
  203. package/dist/components/conversation/scroll-follow-core.js +23 -1
  204. package/dist/components/conversation/scroll-follow-core.js.map +1 -1
  205. package/dist/components/conversation/scroll-follow.d.ts +3 -0
  206. package/dist/components/conversation/scroll-follow.d.ts.map +1 -1
  207. package/dist/components/conversation/scroll-follow.js +80 -1
  208. package/dist/components/conversation/scroll-follow.js.map +1 -1
  209. package/dist/components/ui/attachment/attachment.d.ts +58 -0
  210. package/dist/components/ui/attachment/attachment.d.ts.map +1 -0
  211. package/dist/components/ui/attachment/attachment.js +279 -0
  212. package/dist/components/ui/attachment/attachment.js.map +1 -0
  213. package/dist/components/ui/attachment/index.d.ts +2 -0
  214. package/dist/components/ui/attachment/index.d.ts.map +1 -0
  215. package/dist/components/ui/attachment/index.js +2 -0
  216. package/dist/components/ui/badge/badge.d.ts +1 -1
  217. package/dist/components/ui/bubble/bubble.d.ts +33 -0
  218. package/dist/components/ui/bubble/bubble.d.ts.map +1 -0
  219. package/dist/components/ui/bubble/bubble.js +95 -0
  220. package/dist/components/ui/bubble/bubble.js.map +1 -0
  221. package/dist/components/ui/bubble/index.d.ts +2 -0
  222. package/dist/components/ui/bubble/index.d.ts.map +1 -0
  223. package/dist/components/ui/bubble/index.js +2 -0
  224. package/dist/components/ui/button/button.d.ts +1 -1
  225. package/dist/components/ui/code-block/code-block.d.ts +56 -3
  226. package/dist/components/ui/code-block/code-block.d.ts.map +1 -1
  227. package/dist/components/ui/code-block/code-block.js +231 -50
  228. package/dist/components/ui/code-block/code-block.js.map +1 -1
  229. package/dist/components/ui/code-block/index.d.ts +1 -1
  230. package/dist/components/ui/code-block/index.d.ts.map +1 -1
  231. package/dist/components/ui/code-block/index.js +2 -2
  232. package/dist/components/ui/field/number-field.d.ts +21 -4
  233. package/dist/components/ui/field/number-field.d.ts.map +1 -1
  234. package/dist/components/ui/field/number-field.js +22 -11
  235. package/dist/components/ui/field/number-field.js.map +1 -1
  236. package/dist/components/ui/marker/index.d.ts +2 -0
  237. package/dist/components/ui/marker/index.d.ts.map +1 -0
  238. package/dist/components/ui/marker/index.js +2 -0
  239. package/dist/components/ui/marker/marker.d.ts +35 -0
  240. package/dist/components/ui/marker/marker.d.ts.map +1 -0
  241. package/dist/components/ui/marker/marker.js +123 -0
  242. package/dist/components/ui/marker/marker.js.map +1 -0
  243. package/dist/components/ui/message/cite-ranges.d.ts +42 -0
  244. package/dist/components/ui/message/cite-ranges.d.ts.map +1 -0
  245. package/dist/components/ui/message/cite-ranges.js +105 -0
  246. package/dist/components/ui/message/cite-ranges.js.map +1 -0
  247. package/dist/components/ui/message/index.d.ts +4 -0
  248. package/dist/components/ui/message/index.d.ts.map +1 -0
  249. package/dist/components/ui/message/index.js +4 -0
  250. package/dist/components/ui/message/message.d.ts +95 -0
  251. package/dist/components/ui/message/message.d.ts.map +1 -0
  252. package/dist/components/ui/message/message.js +443 -0
  253. package/dist/components/ui/message/message.js.map +1 -0
  254. package/dist/components/ui/message/parse-message-text.d.ts +93 -0
  255. package/dist/components/ui/message/parse-message-text.d.ts.map +1 -0
  256. package/dist/components/ui/message/parse-message-text.js +365 -0
  257. package/dist/components/ui/message/parse-message-text.js.map +1 -0
  258. package/dist/components/ui/questionnaire/index.d.ts +2 -0
  259. package/dist/components/ui/questionnaire/index.d.ts.map +1 -0
  260. package/dist/components/ui/questionnaire/index.js +2 -0
  261. package/dist/components/ui/questionnaire/questionnaire.d.ts +83 -0
  262. package/dist/components/ui/questionnaire/questionnaire.d.ts.map +1 -0
  263. package/dist/components/ui/questionnaire/questionnaire.js +470 -0
  264. package/dist/components/ui/questionnaire/questionnaire.js.map +1 -0
  265. package/dist/components/ui/status-chip/status-chip.d.ts +1 -1
  266. package/dist/components/ui/switch/switch.js +11 -11
  267. package/dist/components/ui/switch/switch.js.map +1 -1
  268. package/dist/components/ui/trace/index.d.ts +2 -0
  269. package/dist/components/ui/trace/index.d.ts.map +1 -0
  270. package/dist/components/ui/trace/index.js +2 -0
  271. package/dist/components/ui/trace/trace.d.ts +72 -0
  272. package/dist/components/ui/trace/trace.d.ts.map +1 -0
  273. package/dist/components/ui/trace/trace.js +340 -0
  274. package/dist/components/ui/trace/trace.js.map +1 -0
  275. package/dist/index.d.ts +26 -0
  276. package/dist/index.d.ts.map +1 -1
  277. package/dist/index.js +46 -5
  278. package/dist/r/attachment.json +25 -0
  279. package/dist/r/bubble.json +22 -0
  280. package/dist/r/chain-of-thought.json +26 -0
  281. package/dist/r/chat.json +24 -0
  282. package/dist/r/checkpoint.json +35 -0
  283. package/dist/r/confirmation.json +34 -0
  284. package/dist/r/context.json +33 -0
  285. package/dist/r/file-tree.json +32 -0
  286. package/dist/r/inline-citation.json +35 -0
  287. package/dist/r/marker.json +22 -0
  288. package/dist/r/message-scroller.json +31 -0
  289. package/dist/r/message.json +33 -0
  290. package/dist/r/model-selector.json +34 -0
  291. package/dist/r/plan.json +26 -0
  292. package/dist/r/questionnaire.json +28 -0
  293. package/dist/r/queue.json +26 -0
  294. package/dist/r/reasoning.json +26 -0
  295. package/dist/r/registry.json +811 -52
  296. package/dist/r/sources.json +32 -0
  297. package/dist/r/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
  298. package/dist/r/src/components/composites/chain-of-thought/index.ts +11 -0
  299. package/dist/r/src/components/composites/chat/chat.tsx +190 -0
  300. package/dist/r/src/components/composites/chat/index.ts +11 -0
  301. package/dist/r/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
  302. package/dist/r/src/components/composites/checkpoint/checkpoint.tsx +214 -0
  303. package/dist/r/src/components/composites/checkpoint/index.ts +8 -0
  304. package/dist/r/src/components/composites/confirmation/confirmation-model.ts +83 -0
  305. package/dist/r/src/components/composites/confirmation/confirmation.tsx +311 -0
  306. package/dist/r/src/components/composites/confirmation/index.ts +9 -0
  307. package/dist/r/src/components/composites/context/context-model.ts +168 -0
  308. package/dist/r/src/components/composites/context/context.tsx +187 -0
  309. package/dist/r/src/components/composites/context/index.ts +18 -0
  310. package/dist/r/src/components/composites/file-tree/build-file-tree.ts +456 -0
  311. package/dist/r/src/components/composites/file-tree/file-tree.tsx +405 -0
  312. package/dist/r/src/components/composites/file-tree/index.ts +25 -0
  313. package/dist/r/src/components/composites/inline-citation/citation.ts +78 -0
  314. package/dist/r/src/components/composites/inline-citation/index.ts +9 -0
  315. package/dist/r/src/components/composites/inline-citation/inline-citation.tsx +285 -0
  316. package/dist/r/src/components/composites/message-scroller/index.ts +2 -0
  317. package/dist/r/src/components/composites/message-scroller/message-scroller.tsx +301 -0
  318. package/dist/r/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
  319. package/dist/r/src/components/composites/model-selector/index.ts +14 -0
  320. package/dist/r/src/components/composites/model-selector/model-selector.tsx +420 -0
  321. package/dist/r/src/components/composites/model-selector/models.ts +103 -0
  322. package/dist/r/src/components/composites/plan/index.ts +1 -0
  323. package/dist/r/src/components/composites/plan/plan.tsx +155 -0
  324. package/dist/r/src/components/composites/queue/index.ts +10 -0
  325. package/dist/r/src/components/composites/queue/queue.tsx +264 -0
  326. package/dist/r/src/components/composites/reasoning/index.ts +1 -0
  327. package/dist/r/src/components/composites/reasoning/reasoning.tsx +176 -0
  328. package/dist/r/src/components/composites/sources/index.ts +11 -0
  329. package/dist/r/src/components/composites/sources/source.ts +116 -0
  330. package/dist/r/src/components/composites/sources/sources.tsx +163 -0
  331. package/dist/r/src/components/composites/stack-trace/index.ts +19 -0
  332. package/dist/r/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
  333. package/dist/r/src/components/composites/stack-trace/stack-trace.tsx +395 -0
  334. package/dist/r/src/components/composites/subagent/index.ts +1 -0
  335. package/dist/r/src/components/composites/subagent/subagent.tsx +159 -0
  336. package/dist/r/src/components/composites/suggestion/index.ts +1 -0
  337. package/dist/r/src/components/composites/suggestion/suggestion.tsx +140 -0
  338. package/dist/r/src/components/composites/task/index.ts +14 -0
  339. package/dist/r/src/components/composites/task/task.tsx +317 -0
  340. package/dist/r/src/components/composites/terminal/ansi.ts +674 -0
  341. package/dist/r/src/components/composites/terminal/index.ts +20 -0
  342. package/dist/r/src/components/composites/terminal/terminal-model.ts +111 -0
  343. package/dist/r/src/components/composites/terminal/terminal.tsx +574 -0
  344. package/dist/r/src/components/composites/test-results/index.ts +20 -0
  345. package/dist/r/src/components/composites/test-results/test-results-model.ts +368 -0
  346. package/dist/r/src/components/composites/test-results/test-results.tsx +586 -0
  347. package/dist/r/src/components/composites/tool/format-tool-value.ts +221 -0
  348. package/dist/r/src/components/composites/tool/index.ts +2 -0
  349. package/dist/r/src/components/composites/tool/tool.tsx +228 -0
  350. package/dist/r/src/components/conversation/conversation-surface.tsx +9 -0
  351. package/dist/r/src/components/conversation/scroll-follow-core.ts +31 -0
  352. package/dist/r/src/components/conversation/scroll-follow.ts +92 -0
  353. package/dist/r/src/components/ui/attachment/attachment.tsx +282 -0
  354. package/dist/r/src/components/ui/attachment/index.ts +10 -0
  355. package/dist/r/src/components/ui/bubble/bubble.tsx +86 -0
  356. package/dist/r/src/components/ui/bubble/index.ts +1 -0
  357. package/dist/r/src/components/ui/code-block/code-block.tsx +256 -26
  358. package/dist/r/src/components/ui/code-block/index.ts +9 -1
  359. package/dist/r/src/components/ui/field/number-field.tsx +51 -14
  360. package/dist/r/src/components/ui/marker/index.ts +1 -0
  361. package/dist/r/src/components/ui/marker/marker.tsx +90 -0
  362. package/dist/r/src/components/ui/message/cite-ranges.ts +144 -0
  363. package/dist/r/src/components/ui/message/index.ts +23 -0
  364. package/dist/r/src/components/ui/message/message.tsx +434 -0
  365. package/dist/r/src/components/ui/message/parse-message-text.ts +450 -0
  366. package/dist/r/src/components/ui/questionnaire/index.ts +10 -0
  367. package/dist/r/src/components/ui/questionnaire/questionnaire.tsx +446 -0
  368. package/dist/r/src/components/ui/trace/index.ts +9 -0
  369. package/dist/r/src/components/ui/trace/trace.tsx +334 -0
  370. package/dist/r/src/styles/base.css +34 -0
  371. package/dist/r/stack-trace.json +32 -0
  372. package/dist/r/subagent.json +27 -0
  373. package/dist/r/suggestion.json +24 -0
  374. package/dist/r/task.json +28 -0
  375. package/dist/r/terminal.json +35 -0
  376. package/dist/r/test-results.json +33 -0
  377. package/dist/r/tool.json +31 -0
  378. package/dist/r/trace.json +25 -0
  379. package/package.json +6 -3
  380. package/registry.json +811 -52
  381. package/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
  382. package/src/components/composites/chain-of-thought/index.ts +11 -0
  383. package/src/components/composites/chat/chat.tsx +190 -0
  384. package/src/components/composites/chat/index.ts +11 -0
  385. package/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
  386. package/src/components/composites/checkpoint/checkpoint.tsx +214 -0
  387. package/src/components/composites/checkpoint/index.ts +8 -0
  388. package/src/components/composites/confirmation/confirmation-model.ts +83 -0
  389. package/src/components/composites/confirmation/confirmation.tsx +311 -0
  390. package/src/components/composites/confirmation/index.ts +9 -0
  391. package/src/components/composites/context/context-model.ts +168 -0
  392. package/src/components/composites/context/context.tsx +187 -0
  393. package/src/components/composites/context/index.ts +18 -0
  394. package/src/components/composites/file-tree/build-file-tree.ts +456 -0
  395. package/src/components/composites/file-tree/file-tree.tsx +405 -0
  396. package/src/components/composites/file-tree/index.ts +25 -0
  397. package/src/components/composites/inline-citation/citation.ts +78 -0
  398. package/src/components/composites/inline-citation/index.ts +9 -0
  399. package/src/components/composites/inline-citation/inline-citation.tsx +285 -0
  400. package/src/components/composites/message-scroller/index.ts +2 -0
  401. package/src/components/composites/message-scroller/message-scroller.tsx +301 -0
  402. package/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
  403. package/src/components/composites/model-selector/index.ts +14 -0
  404. package/src/components/composites/model-selector/model-selector.tsx +420 -0
  405. package/src/components/composites/model-selector/models.ts +103 -0
  406. package/src/components/composites/plan/index.ts +1 -0
  407. package/src/components/composites/plan/plan.tsx +155 -0
  408. package/src/components/composites/queue/index.ts +10 -0
  409. package/src/components/composites/queue/queue.tsx +264 -0
  410. package/src/components/composites/reasoning/index.ts +1 -0
  411. package/src/components/composites/reasoning/reasoning.tsx +176 -0
  412. package/src/components/composites/sources/index.ts +11 -0
  413. package/src/components/composites/sources/source.ts +116 -0
  414. package/src/components/composites/sources/sources.tsx +163 -0
  415. package/src/components/composites/stack-trace/index.ts +19 -0
  416. package/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
  417. package/src/components/composites/stack-trace/stack-trace.tsx +395 -0
  418. package/src/components/composites/subagent/index.ts +1 -0
  419. package/src/components/composites/subagent/subagent.tsx +159 -0
  420. package/src/components/composites/suggestion/index.ts +1 -0
  421. package/src/components/composites/suggestion/suggestion.tsx +140 -0
  422. package/src/components/composites/task/index.ts +14 -0
  423. package/src/components/composites/task/task.tsx +317 -0
  424. package/src/components/composites/terminal/ansi.ts +674 -0
  425. package/src/components/composites/terminal/index.ts +20 -0
  426. package/src/components/composites/terminal/terminal-model.ts +111 -0
  427. package/src/components/composites/terminal/terminal.tsx +574 -0
  428. package/src/components/composites/test-results/index.ts +20 -0
  429. package/src/components/composites/test-results/test-results-model.ts +368 -0
  430. package/src/components/composites/test-results/test-results.tsx +586 -0
  431. package/src/components/composites/tool/format-tool-value.ts +221 -0
  432. package/src/components/composites/tool/index.ts +2 -0
  433. package/src/components/composites/tool/tool.tsx +228 -0
  434. package/src/components/conversation/conversation-surface.tsx +9 -0
  435. package/src/components/conversation/scroll-follow-core.ts +31 -0
  436. package/src/components/conversation/scroll-follow.ts +92 -0
  437. package/src/components/ui/attachment/attachment.tsx +282 -0
  438. package/src/components/ui/attachment/index.ts +10 -0
  439. package/src/components/ui/bubble/bubble.tsx +86 -0
  440. package/src/components/ui/bubble/index.ts +1 -0
  441. package/src/components/ui/code-block/code-block.tsx +256 -26
  442. package/src/components/ui/code-block/index.ts +9 -1
  443. package/src/components/ui/field/number-field.tsx +51 -14
  444. package/src/components/ui/marker/index.ts +1 -0
  445. package/src/components/ui/marker/marker.tsx +90 -0
  446. package/src/components/ui/message/cite-ranges.ts +144 -0
  447. package/src/components/ui/message/index.ts +23 -0
  448. package/src/components/ui/message/message.tsx +434 -0
  449. package/src/components/ui/message/parse-message-text.ts +450 -0
  450. package/src/components/ui/questionnaire/index.ts +10 -0
  451. package/src/components/ui/questionnaire/questionnaire.tsx +446 -0
  452. package/src/components/ui/trace/index.ts +9 -0
  453. package/src/components/ui/trace/trace.tsx +334 -0
  454. package/src/index.ts +26 -0
  455. package/src/styles/base.css +34 -0
@@ -0,0 +1,586 @@
1
+ import {
2
+ Check,
3
+ CircleCheck,
4
+ CircleMinus,
5
+ CircleX,
6
+ Copy,
7
+ FlaskConical,
8
+ LoaderCircle,
9
+ } from 'lucide-solid'
10
+ import {
11
+ createComputed,
12
+ createMemo,
13
+ createEffect,
14
+ createSignal,
15
+ For,
16
+ Show,
17
+ splitProps,
18
+ type Accessor,
19
+ type ComponentProps,
20
+ type JSX,
21
+ } from 'solid-js'
22
+ import { writeClipboardText } from '../../../lib/clipboard'
23
+ import { cn } from '../../../lib/utils'
24
+ import { Button } from '../../ui/button'
25
+ import { DiffBlock } from '../../ui/diff-block'
26
+ import { Trace, TraceDetail, TraceLine, type TraceStatus } from '../../ui/trace'
27
+ import { StackTrace, type StackTraceProps } from '../stack-trace'
28
+ import {
29
+ boundedEntries,
30
+ describeCount,
31
+ firstFailureRenderPath,
32
+ formatDuration,
33
+ listedCounts,
34
+ reconcileCounts,
35
+ sameFailure,
36
+ siblingKey,
37
+ suiteState,
38
+ type CountLine,
39
+ type TestCase,
40
+ type TestCaseStatus,
41
+ type TestOutcome,
42
+ type TestSuite,
43
+ type TestSummary,
44
+ type FirstFailureRenderPath,
45
+ } from './test-results-model'
46
+
47
+ /**
48
+ * TestResults.
49
+ *
50
+ * A test run: how it went in words and in a segmented bar, then the suites it
51
+ * ran as `Trace` lines, each opening onto its tests, and a failing test opening
52
+ * onto its message, diff and stack. It is for a run the host can structure; reach
53
+ * for `Terminal` when all there is to show is the command's output, and for
54
+ * `StackTrace` alone when one call failed outside a test.
55
+ *
56
+ * ## Counts are claims
57
+ *
58
+ * Nothing is computed that the host did not supply data for, and nothing the host
59
+ * supplied is quietly recomputed. `summary` is the host's own tally and is shown
60
+ * as given. If tests are listed and their number for an outcome does not match, the
61
+ * listed number is shown beside it — "40 passed (2 listed)" — which is also how a
62
+ * host that lists only its failures reads. Without a `summary` the counts shown are
63
+ * those of the tests listed, and the component says so; it does not present them as
64
+ * the run's totals. A suite is marked failed or passed only from the tests listed in
65
+ * it, and its spoken label says "listed" so it claims no more than that.
66
+ *
67
+ * ## Not colour-only
68
+ *
69
+ * The bar is decoration: every segment has a counterpart in the words beside it,
70
+ * each with its own shape (a cross, a tick, a dash). Segments are separated by a
71
+ * gap and never narrower than a visible sliver, so one failure in five thousand
72
+ * tests is still on the bar.
73
+ *
74
+ * ## Bounded
75
+ *
76
+ * Suites and tests are listed `listLimit` at a time with "show more", and a suite's
77
+ * tests are not rendered until it is open. The first failure in reading order opens
78
+ * when its row is visible; a failure beyond a "show more" boundary stays unmounted
79
+ * until its page is revealed. When a running result first reports a failure, its
80
+ * suite and test open once. Later updates preserve the user's disclosure choices.
81
+ *
82
+ * Failure details are text: the message is a `pre`, the diff goes to `DiffBlock`
83
+ * and the stack to `StackTrace`. If a stack already begins with the message, pass
84
+ * only the stack; nothing here de-duplicates what the host sends.
85
+ */
86
+ export type TestResultsProps = Omit<ComponentProps<'section'>, 'children'> & {
87
+ suites: readonly TestSuite[]
88
+ /** The host's own counts. Shown as given; see the component comment. */
89
+ summary?: TestSummary
90
+ /** The run is still going. */
91
+ running?: boolean
92
+ /** Suites, or tests within a suite, listed before "show more". Default 50. */
93
+ listLimit?: number
94
+ /** Passed to each failure's `StackTrace`. */
95
+ onOpenFrame?: StackTraceProps['onOpenFrame']
96
+ /** The section's accessible name. Default "Test results". */
97
+ label?: string
98
+ }
99
+
100
+ export const TEST_RESULTS_LIST_LIMIT = 50
101
+
102
+ const OUTCOME_ICON: Readonly<Record<TestOutcome, () => JSX.Element>> = {
103
+ failed: () => <CircleX aria-hidden="true" class="size-3.5 text-destructive" />,
104
+ passed: () => <CircleCheck aria-hidden="true" class="size-3.5 text-success" />,
105
+ skipped: () => <CircleMinus aria-hidden="true" class="size-3.5 text-muted-foreground" />,
106
+ }
107
+
108
+ function CountReadout(props: { line: CountLine }) {
109
+ return (
110
+ <span class="flex items-center gap-1 whitespace-nowrap" data-outcome={props.line.outcome}>
111
+ {OUTCOME_ICON[props.line.outcome]()}
112
+ {describeCount(props.line)}
113
+ </span>
114
+ )
115
+ }
116
+
117
+ // Segments are drawn in this order so the bar reads the same in every run.
118
+ const SEGMENT_CLASS: Readonly<Record<TestOutcome, string>> = {
119
+ failed: 'bg-destructive',
120
+ passed: 'bg-success',
121
+ skipped: 'bg-muted-foreground/40',
122
+ }
123
+
124
+ function SummaryBar(props: { lines: readonly CountLine[] }) {
125
+ const visible = () => props.lines.filter((line) => line.count > 0)
126
+ return (
127
+ <Show when={visible().length > 0}>
128
+ <div
129
+ aria-hidden="true"
130
+ data-slot="test-results-bar"
131
+ class="flex h-1.5 w-full gap-px overflow-hidden rounded-full bg-muted"
132
+ >
133
+ <For each={visible()}>
134
+ {(line) => (
135
+ <span
136
+ class={cn('min-w-1', SEGMENT_CLASS[line.outcome])}
137
+ style={{ flex: `${line.count} 1 0` }}
138
+ />
139
+ )}
140
+ </For>
141
+ </div>
142
+ </Show>
143
+ )
144
+ }
145
+
146
+ const TRACE_STATUS: Readonly<Record<TestCaseStatus, { status: TraceStatus; label: string }>> = {
147
+ passed: { status: 'success', label: 'Passed' },
148
+ failed: { status: 'error', label: 'Failed' },
149
+ skipped: { status: 'cancelled', label: 'Skipped' },
150
+ running: { status: 'running', label: 'Running' },
151
+ pending: { status: 'pending', label: 'Not run yet' },
152
+ }
153
+
154
+ /**
155
+ * Keep keyboard focus through a reorder. Solid moves a keyed row's node instead
156
+ * of replacing it, and a browser blurs a focused element that is moved, so an
157
+ * immutable reorder would drop the reader's place onto the body even though the
158
+ * node and its open state survive. The focused element is noted just before the
159
+ * rows move and given focus back just after, but only when nothing else has taken
160
+ * focus meanwhile, and only inside a test run, so a reader who has moved on is
161
+ * never pulled back and an unrelated element is never refocused.
162
+ */
163
+ function keepFocusThroughReorder(keys: Accessor<readonly string[]>) {
164
+ let noted: HTMLElement | undefined
165
+ createComputed(() => {
166
+ keys()
167
+ const active = typeof document === 'undefined' ? null : document.activeElement
168
+ noted =
169
+ active instanceof HTMLElement && active.closest('[data-slot="test-results"]')
170
+ ? active
171
+ : undefined
172
+ })
173
+ createEffect(() => {
174
+ keys()
175
+ const element = noted
176
+ noted = undefined
177
+ if (!element || !element.isConnected) return
178
+ const active = document.activeElement
179
+ if (active === null || active === document.body) element.focus({ preventScroll: true })
180
+ })
181
+ }
182
+
183
+ /** A list that shows its first `limit` items and offers the rest. */
184
+ function Bounded<T>(props: {
185
+ items: readonly T[]
186
+ itemKey: (item: T, index: number) => string
187
+ limit: number
188
+ noun: string
189
+ children: (item: Accessor<T>, index: Accessor<number>, key: string) => JSX.Element
190
+ }) {
191
+ const [shown, setShown] = createSignal(props.limit)
192
+ const page = createMemo(() => boundedEntries(props.items, shown(), props.itemKey))
193
+ const visible = () => page().entries
194
+ const visibleKeys = createMemo(() => visible().map((entry) => entry.key))
195
+ keepFocusThroughReorder(visibleKeys)
196
+ const hidden = () => props.items.length - visible().length
197
+ return (
198
+ <>
199
+ <For each={visibleKeys()}>
200
+ {(key) => {
201
+ const entry = createMemo(() => page().byKey.get(key)!)
202
+ return props.children(
203
+ () => entry().item,
204
+ () => entry().index,
205
+ key
206
+ )
207
+ }}
208
+ </For>
209
+ <Show when={hidden() > 0}>
210
+ <li class="px-1.5 py-0.5">
211
+ <Button variant="ghost" size="2xs" onClick={() => setShown(shown() + props.limit)}>
212
+ Show {Math.min(hidden(), props.limit).toLocaleString()} more {props.noun} (
213
+ {hidden().toLocaleString()} hidden)
214
+ </Button>
215
+ </li>
216
+ </Show>
217
+ </>
218
+ )
219
+ }
220
+
221
+ /** Characters of a failure message drawn before the rest is offered. */
222
+ export const TEST_RESULTS_MESSAGE_LIMIT = 4_000
223
+
224
+ /**
225
+ * A failed test's message, which a runner may print at any length: a captured
226
+ * log, a serialized object, a long assertion. It opens on its own for the first
227
+ * failure, so it is bounded where the diff and stack are already bounded: the
228
+ * body scrolls past a fixed height, only the first characters are drawn until the
229
+ * reader asks for the rest, and Copy writes all of it.
230
+ */
231
+ function FailureMessage(props: { text: string; onCopy?: (ok: boolean) => void }) {
232
+ const [all, setAll] = createSignal(false)
233
+ const [copied, setCopied] = createSignal(false)
234
+ const [copyFailed, setCopyFailed] = createSignal(false)
235
+ const clipped = () => props.text.length > TEST_RESULTS_MESSAGE_LIMIT
236
+ const cut = () => {
237
+ // Never inside a surrogate pair, which would draw a replacement character.
238
+ const last = props.text.charCodeAt(TEST_RESULTS_MESSAGE_LIMIT - 1)
239
+ return last >= 0xd800 && last <= 0xdbff
240
+ ? TEST_RESULTS_MESSAGE_LIMIT - 1
241
+ : TEST_RESULTS_MESSAGE_LIMIT
242
+ }
243
+ const shown = () => (clipped() && !all() ? props.text.slice(0, cut()) : props.text)
244
+ const copy = async () => {
245
+ let ok = true
246
+ try {
247
+ await writeClipboardText(props.text)
248
+ } catch {
249
+ ok = false
250
+ }
251
+ setCopied(ok)
252
+ setCopyFailed(!ok)
253
+ props.onCopy?.(ok)
254
+ if (ok) setTimeout(() => setCopied(false), 1500)
255
+ }
256
+ return (
257
+ <>
258
+ {/* A region that scrolls is a tab stop and needs a name. */}
259
+ <pre
260
+ data-slot="test-results-message"
261
+ tabindex="0"
262
+ role="group"
263
+ aria-label="Failure message"
264
+ class="m-0 max-h-64 overflow-auto font-code text-code whitespace-pre-wrap text-foreground [overflow-wrap:anywhere]"
265
+ >
266
+ {shown()}
267
+ </pre>
268
+ <Show when={clipped()}>
269
+ <div class="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
270
+ <span class="italic">
271
+ <Show
272
+ when={!all()}
273
+ fallback={`All ${props.text.length.toLocaleString()} characters shown.`}
274
+ >
275
+ Showing the first {cut().toLocaleString()} of {props.text.length.toLocaleString()}{' '}
276
+ characters (copy has all of it).
277
+ </Show>
278
+ </span>
279
+ <Show when={!all()}>
280
+ <Button variant="ghost" size="2xs" onClick={() => setAll(true)}>
281
+ Show all {props.text.length.toLocaleString()} characters
282
+ </Button>
283
+ </Show>
284
+ <Button
285
+ variant="ghost"
286
+ size="2xs"
287
+ title={copyFailed() ? 'Copying is unavailable in this context' : undefined}
288
+ onClick={() => void copy()}
289
+ >
290
+ <Show when={copied()} fallback={<Copy aria-hidden="true" />}>
291
+ <Check aria-hidden="true" />
292
+ </Show>
293
+ {copied() ? 'Copied' : 'Copy message'}
294
+ </Button>
295
+ </div>
296
+ </Show>
297
+ </>
298
+ )
299
+ }
300
+
301
+ function TestLine(props: {
302
+ test: Accessor<TestCase>
303
+ keyed: string
304
+ failure?: FirstFailureRenderPath
305
+ onOpenFrame?: TestResultsProps['onOpenFrame']
306
+ }) {
307
+ const test = () => props.test()
308
+ const state = () => (test().status ? TRACE_STATUS[test().status as TestCaseStatus] : undefined)
309
+ // Whether there is anything to disclose. Read once per change, so the disclosure
310
+ // exists while closed without anything below it being built.
311
+ const hasDetail = createMemo(() => Boolean(test().message || test().diff || test().stack))
312
+ // Only the last suite on the failure's path is given it, so a key among
313
+ // this suite's tests is enough to know the failure is this test.
314
+ const failureKey = createMemo(
315
+ () => (props.failure?.test === props.keyed ? props.failure : undefined),
316
+ undefined,
317
+ { equals: sameFailure }
318
+ )
319
+ const [open, setOpen] = createSignal(failureKey() !== undefined)
320
+ let previousFailure = failureKey()
321
+ let collapsedFailure: FirstFailureRenderPath | undefined
322
+
323
+ createEffect(() => {
324
+ const currentFailure = failureKey()
325
+ if (
326
+ currentFailure &&
327
+ !sameFailure(currentFailure, previousFailure) &&
328
+ !sameFailure(currentFailure, collapsedFailure)
329
+ ) {
330
+ setOpen(true)
331
+ }
332
+ previousFailure = currentFailure
333
+ })
334
+
335
+ const handleOpenChange = (next: boolean) => {
336
+ if (!next && failureKey()) collapsedFailure = failureKey()
337
+ else if (next) collapsedFailure = undefined
338
+ setOpen(next)
339
+ }
340
+
341
+ return (
342
+ <TraceLine
343
+ title={test().name}
344
+ status={state()?.status}
345
+ statusLabel={state()?.label}
346
+ meta={formatDuration(test().durationMs)}
347
+ open={open()}
348
+ onOpenChange={handleOpenChange}
349
+ >
350
+ {hasDetail() ? (
351
+ // A closed test builds nothing: the body is made when it is opened, so a diff or
352
+ // stack is not parsed for every test of an open suite.
353
+ <Show when={open()}>
354
+ <TraceDetail class="flex flex-col gap-2">
355
+ <Show when={test().message}>
356
+ <FailureMessage text={test().message!} />
357
+ </Show>
358
+ <Show when={test().diff}>
359
+ <DiffBlock patch={test().diff!} complete title="Expected and received" />
360
+ </Show>
361
+ <Show when={test().stack}>
362
+ <StackTrace text={test().stack!} onOpenFrame={props.onOpenFrame} />
363
+ </Show>
364
+ </TraceDetail>
365
+ </Show>
366
+ ) : undefined}
367
+ </TraceLine>
368
+ )
369
+ }
370
+
371
+ function SuiteLine(props: {
372
+ suite: Accessor<TestSuite>
373
+ /** This suite's key among its siblings. */
374
+ keyed: string
375
+ /** How many suites enclose this one. */
376
+ depth: number
377
+ limit: number
378
+ /** The first failure, given only to suites on the way to it. */
379
+ failure?: FirstFailureRenderPath
380
+ onOpenFrame?: TestResultsProps['onOpenFrame']
381
+ }) {
382
+ const suite = () => props.suite()
383
+ const counts = createMemo(() => listedCounts([suite()]))
384
+ const state = createMemo(() => suiteState(counts()))
385
+ const children = () => (suite().tests?.length ?? 0) + (suite().suites?.length ?? 0) > 0
386
+ const [open, setOpen] = createSignal(state() === 'failed')
387
+ // The parent passes the failure down only while it is on the way to it, so
388
+ // one comparison at this suite's own depth settles whether it is on the path.
389
+ // Memoised: each level reads its parent's, so a bare function would re-run the
390
+ // whole chain above it on every read and cost exponential time in the depth.
391
+ const failure = createMemo(
392
+ () => (props.failure?.suites[props.depth] === props.keyed ? props.failure : undefined),
393
+ undefined,
394
+ { equals: sameFailure }
395
+ )
396
+ const holdsFailure = createMemo(() => failure()?.suites.length === props.depth + 1)
397
+ let previousFailure = failure()
398
+ let collapsedFailure: FirstFailureRenderPath | undefined
399
+
400
+ createEffect(() => {
401
+ const currentFailure = failure()
402
+ if (
403
+ currentFailure &&
404
+ !sameFailure(currentFailure, previousFailure) &&
405
+ !sameFailure(currentFailure, collapsedFailure)
406
+ ) {
407
+ setOpen(true)
408
+ }
409
+ previousFailure = currentFailure
410
+ })
411
+
412
+ const handleOpenChange = (next: boolean) => {
413
+ if (!next && failure()) collapsedFailure = failure()
414
+ else if (next) collapsedFailure = undefined
415
+ setOpen(next)
416
+ }
417
+
418
+ const description = () => {
419
+ const parts = [
420
+ suite().file,
421
+ counts().failed > 0 ? `${counts().failed.toLocaleString()} failed` : undefined,
422
+ ]
423
+ return parts.filter(Boolean).join(' · ') || undefined
424
+ }
425
+ return (
426
+ <TraceLine
427
+ icon={<FlaskConical />}
428
+ title={suite().name}
429
+ description={description()}
430
+ status={
431
+ state() === 'failed'
432
+ ? 'error'
433
+ : state() === 'running'
434
+ ? 'running'
435
+ : state() === 'passed'
436
+ ? 'success'
437
+ : undefined
438
+ }
439
+ statusLabel={
440
+ state() === 'failed'
441
+ ? 'Has failing tests'
442
+ : state() === 'passed'
443
+ ? 'All listed tests passed'
444
+ : undefined
445
+ }
446
+ meta={formatDuration(suite().durationMs)}
447
+ open={open()}
448
+ onOpenChange={handleOpenChange}
449
+ >
450
+ {children() ? (
451
+ <div>
452
+ <Show when={open()}>
453
+ <Trace size="sm" aria-label={`${suite().name} tests`}>
454
+ <Bounded
455
+ items={suite().tests ?? []}
456
+ itemKey={siblingKey}
457
+ limit={props.limit}
458
+ noun="tests"
459
+ >
460
+ {(test, _index, key) => (
461
+ <TestLine
462
+ test={test}
463
+ keyed={key}
464
+ failure={holdsFailure() ? failure() : undefined}
465
+ onOpenFrame={props.onOpenFrame}
466
+ />
467
+ )}
468
+ </Bounded>
469
+ <Bounded
470
+ items={suite().suites ?? []}
471
+ itemKey={siblingKey}
472
+ limit={props.limit}
473
+ noun="suites"
474
+ >
475
+ {(nested, _index, key) => (
476
+ <SuiteLine
477
+ suite={nested}
478
+ keyed={key}
479
+ depth={props.depth + 1}
480
+ limit={props.limit}
481
+ failure={failure()}
482
+ onOpenFrame={props.onOpenFrame}
483
+ />
484
+ )}
485
+ </Bounded>
486
+ </Trace>
487
+ </Show>
488
+ </div>
489
+ ) : undefined}
490
+ </TraceLine>
491
+ )
492
+ }
493
+
494
+ export function TestResults(props: TestResultsProps) {
495
+ const [local, rest] = splitProps(props, [
496
+ 'suites',
497
+ 'summary',
498
+ 'running',
499
+ 'listLimit',
500
+ 'onOpenFrame',
501
+ 'label',
502
+ 'class',
503
+ ])
504
+
505
+ const listed = createMemo(() => listedCounts(local.suites))
506
+ const counts = createMemo(() => reconcileCounts(local.summary, listed()))
507
+ const limit = () => Math.max(1, Math.floor(local.listLimit ?? TEST_RESULTS_LIST_LIMIT))
508
+ const failure = createMemo(() => firstFailureRenderPath(local.suites), undefined, {
509
+ equals: sameFailure,
510
+ })
511
+ const duration = () => formatDuration(local.summary?.durationMs, 'long')
512
+ const nothing = () =>
513
+ counts().lines.length === 0 &&
514
+ counts().reportedTotal === undefined &&
515
+ local.suites.length === 0 &&
516
+ !local.running
517
+
518
+ return (
519
+ <section
520
+ data-slot="test-results"
521
+ aria-label={local.label ?? 'Test results'}
522
+ aria-busy={local.running || undefined}
523
+ class={cn('flex min-w-0 flex-col gap-2', local.class)}
524
+ {...rest}
525
+ >
526
+ <Show
527
+ when={!nothing()}
528
+ fallback={<p class="m-0 text-sm text-muted-foreground">No test results</p>}
529
+ >
530
+ <div class="flex flex-col gap-1.5">
531
+ <div class="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm">
532
+ <Show when={local.running}>
533
+ <span class="flex items-center gap-1 text-info">
534
+ <LoaderCircle aria-hidden="true" class="size-3.5 motion-safe:animate-spin" />
535
+ Running
536
+ </span>
537
+ </Show>
538
+ <For each={counts().lines}>{(line) => <CountReadout line={line} />}</For>
539
+ <Show
540
+ when={
541
+ counts().lines.length === 0 &&
542
+ !counts().totalNote &&
543
+ counts().reportedTotal !== undefined
544
+ }
545
+ >
546
+ <span class="text-muted-foreground">
547
+ {counts().reportedTotal?.toLocaleString()} tests reported
548
+ </span>
549
+ </Show>
550
+ <Show when={counts().totalNote}>
551
+ {(note) => (
552
+ <span class="text-muted-foreground">
553
+ {note().reported.toLocaleString()} tests reported (
554
+ {note().listed.toLocaleString()} listed)
555
+ </span>
556
+ )}
557
+ </Show>
558
+ <Show when={duration()}>
559
+ <span class="text-muted-foreground">in {duration()}</span>
560
+ </Show>
561
+ </div>
562
+ <SummaryBar lines={counts().lines} />
563
+ <Show when={counts().basis === 'listed' && counts().lines.length > 0}>
564
+ <p class="m-0 text-xs text-muted-foreground">Counts are from the tests listed below.</p>
565
+ </Show>
566
+ </div>
567
+ <Show when={local.suites.length > 0}>
568
+ <Trace aria-label="Test suites">
569
+ <Bounded items={local.suites} itemKey={siblingKey} limit={limit()} noun="suites">
570
+ {(suite, _index, key) => (
571
+ <SuiteLine
572
+ suite={suite}
573
+ keyed={key}
574
+ depth={0}
575
+ limit={limit()}
576
+ failure={failure()}
577
+ onOpenFrame={local.onOpenFrame}
578
+ />
579
+ )}
580
+ </Bounded>
581
+ </Trace>
582
+ </Show>
583
+ </Show>
584
+ </section>
585
+ )
586
+ }