@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,507 @@
1
+ /**
2
+ * Stack traces, read without being trusted or trimmed.
3
+ *
4
+ * A trace is text a runtime wrote about itself, and every language writes it
5
+ * differently. This parses the three a coding agent meets most — V8/Node
6
+ * (`at fn (file:line:col)`), Python (`File "x", line N, in fn`) and Rust panic
7
+ * backtraces (` 0: symbol` then `at file:line:col`) — into frames, and does
8
+ * three things a formatter would not:
9
+ *
10
+ * - **It never hides a line.** Every input line ends up in `entries`, as a frame
11
+ * or as text, in order. A line the parser does not recognise is text, and a
12
+ * trace it recognises nothing in has `format: 'unknown'` and `frames: []`, so a
13
+ * caller falls back to showing the raw string. The header (error type and
14
+ * message) is lifted out of the entries only when it is unambiguous.
15
+ * - **It makes no claim about whose code a frame is without evidence.** A frame
16
+ * is a dependency when its path says so (`node_modules`, `site-packages`,
17
+ * `.cargo/registry`), internal when it belongs to the runtime (`node:` URLs,
18
+ * Python's frozen modules, Rust's `std`), and first-party otherwise. A host that
19
+ * knows better passes `classify`.
20
+ * - **It is bounded.** Lines over 4 000 characters are never run through a
21
+ * pattern, and input past 10 000 lines is kept as one trailing text entry. Every
22
+ * pattern is anchored and linear, so a hostile trace cannot make parsing slow.
23
+ *
24
+ * Parsing is line-oriented and each line is classified on its own, so a trace
25
+ * that mixes formats (a Node process that shells out to Python) keeps both.
26
+ */
27
+
28
+ export type StackFrameKind = 'first-party' | 'dependency' | 'internal'
29
+ export type StackTraceFormat = 'v8' | 'python' | 'rust' | 'unknown'
30
+
31
+ export type StackFrame = Readonly<{
32
+ /** The line exactly as written, minus its line ending. */
33
+ raw: string
34
+ function?: string
35
+ /** The path or URL as written. Undefined for `<anonymous>`, `native` and the like. */
36
+ file?: string
37
+ line?: number
38
+ column?: number
39
+ kind: StackFrameKind
40
+ async?: true
41
+ /** Lines the runtime printed beneath the frame, such as Python's source line. */
42
+ detail?: readonly string[]
43
+ }>
44
+
45
+ export type StackEntry =
46
+ | Readonly<{ type: 'frame'; frame: StackFrame }>
47
+ | Readonly<{ type: 'text'; text: string }>
48
+
49
+ export type StackTraceHeader = Readonly<{
50
+ /** `TypeError`, `ValueError`, `thread 'main' panicked`. */
51
+ type?: string
52
+ message: string
53
+ /** Where a Rust panic says it happened. */
54
+ location?: string
55
+ }>
56
+
57
+ export type ParsedStackTrace = Readonly<{
58
+ format: StackTraceFormat
59
+ header?: StackTraceHeader
60
+ /** Everything that is not the header, in order. */
61
+ entries: readonly StackEntry[]
62
+ frames: readonly StackFrame[]
63
+ }>
64
+
65
+ export type ParseStackTraceOptions = {
66
+ /** Override the built-in first-party/dependency/internal guess for a frame. */
67
+ classify?: (frame: StackFrame) => StackFrameKind | undefined
68
+ }
69
+
70
+ export const STACK_MAX_LINES = 10_000
71
+ const LINE_PATTERN_LIMIT = 4000
72
+
73
+ type Draft = {
74
+ raw: string
75
+ function?: string
76
+ file?: string
77
+ line?: number
78
+ column?: number
79
+ async?: true
80
+ detail?: string[]
81
+ format: 'v8' | 'python' | 'rust'
82
+ }
83
+
84
+ function trailingNumber(value: string): { value: number; rest: string } | undefined {
85
+ let i = value.length
86
+ while (i > 0 && value.charCodeAt(i - 1) >= 48 && value.charCodeAt(i - 1) <= 57) i -= 1
87
+ if (i === value.length || i === 0 || value[i - 1] !== ':' || value.length - i > 9)
88
+ return undefined
89
+ return { value: Number(value.slice(i)), rest: value.slice(0, i - 1) }
90
+ }
91
+
92
+ /** Split `path:line:col` from the right, so a Windows drive or a URL port stays in the path. */
93
+ export function splitLocation(location: string): { file: string; line?: number; column?: number } {
94
+ const last = trailingNumber(location)
95
+ if (!last || last.rest === '') return { file: location }
96
+ const before = trailingNumber(last.rest)
97
+ if (before && before.rest !== '') {
98
+ return { file: before.rest, line: before.value, column: last.value }
99
+ }
100
+ return { file: last.rest, line: last.value }
101
+ }
102
+
103
+ const FILE_LIKE = /[\\/]|\.[A-Za-z0-9]{1,6}$/
104
+ const URL_LIKE = /^node:/i
105
+
106
+ /** Whether a V8 location is a place in a file rather than a runtime annotation. */
107
+ function v8Location(location: string): Partial<Draft> | undefined {
108
+ if (location === '<anonymous>' || location === 'native' || /^index \d+$/.test(location)) {
109
+ return {}
110
+ }
111
+ if (location.startsWith('eval at ')) return {}
112
+ const split = splitLocation(location)
113
+ if (split.line !== undefined || FILE_LIKE.test(split.file) || URL_LIKE.test(split.file)) {
114
+ return { file: split.file, line: split.line, column: split.column }
115
+ }
116
+ return undefined
117
+ }
118
+
119
+ function parseV8(trimmed: string): Draft | undefined {
120
+ if (!trimmed.startsWith('at ')) return undefined
121
+ const rest = trimmed.slice(3)
122
+ if (rest === '') return undefined
123
+
124
+ let fn: string | undefined
125
+ let location: string
126
+ if (rest.endsWith(')') && rest.includes(' (')) {
127
+ const open = rest.indexOf(' (')
128
+ fn = rest.slice(0, open)
129
+ location = rest.slice(open + 2, -1)
130
+ } else {
131
+ location = rest
132
+ }
133
+ const parsed = v8Location(location)
134
+ if (!parsed) return undefined
135
+ // Without parentheses the whole remainder was the location, and it must carry
136
+ // a line or a path — otherwise "at the end of the day" would be a frame.
137
+ if (
138
+ fn === undefined &&
139
+ parsed.file === undefined &&
140
+ location !== '<anonymous>' &&
141
+ location !== 'native'
142
+ ) {
143
+ return undefined
144
+ }
145
+
146
+ const draft: Draft = { raw: trimmed, format: 'v8', ...parsed }
147
+ if (fn !== undefined) {
148
+ if (fn.startsWith('async ')) {
149
+ draft.async = true
150
+ fn = fn.slice(6)
151
+ }
152
+ if (fn !== '') draft.function = fn
153
+ }
154
+ return draft
155
+ }
156
+
157
+ const PYTHON_FRAME = /^File "(.*)", line (\d+)(?:, in (.*))?$/
158
+
159
+ function parsePython(trimmed: string): Draft | undefined {
160
+ const match = PYTHON_FRAME.exec(trimmed)
161
+ if (!match) return undefined
162
+ const draft: Draft = { raw: trimmed, format: 'python', file: match[1], line: Number(match[2]) }
163
+ if (match[3]) draft.function = match[3]
164
+ return draft
165
+ }
166
+
167
+ const RUST_FRAME = /^(\d+):\s+(?:0x[0-9a-fA-F]+ - )?(\S.*)$/
168
+ const RUST_LOCATION = /^at\s+(\S.*)$/
169
+
170
+ function parseRustFrame(trimmed: string, rustContext: boolean): Draft | undefined {
171
+ const match = RUST_FRAME.exec(trimmed)
172
+ if (!match) return undefined
173
+ const symbol = match[2]!
174
+ if (!rustContext && !symbol.includes('::')) return undefined
175
+ return { raw: trimmed, format: 'rust', function: symbol }
176
+ }
177
+
178
+ const INTERNAL_RUST_SYMBOLS =
179
+ /^(?:std|core|alloc)::|^<?(?:\w+ as )?(?:std|core|alloc)::|^(?:rust_begin_unwind|rust_panic|__rust_|_start$|__libc_|_main$)/
180
+
181
+ /** The built-in guess at whose code a frame is. See the module comment. */
182
+ export function classifyFrame(
183
+ frame: Omit<StackFrame, 'kind'>,
184
+ format: StackTraceFormat
185
+ ): StackFrameKind {
186
+ const file = frame.file?.replaceAll('\\', '/')
187
+ if (format === 'rust') {
188
+ if (file !== undefined) {
189
+ if (file.startsWith('/rustc/') || /\/library\/(?:std|core|alloc)\//.test(file))
190
+ return 'internal'
191
+ if (/\/\.cargo\/(?:registry|git)\/|\/registry\/src\//.test(file)) return 'dependency'
192
+ return 'first-party'
193
+ }
194
+ return frame.function !== undefined && INTERNAL_RUST_SYMBOLS.test(frame.function)
195
+ ? 'internal'
196
+ : 'first-party'
197
+ }
198
+ if (file === undefined) return 'internal'
199
+ if (format === 'python') {
200
+ if (/\/(?:site|dist)-packages\//.test(file)) return 'dependency'
201
+ if (
202
+ file.startsWith('<') ||
203
+ /\/lib\/python\d/i.test(file) ||
204
+ /\/python\d[\d.]*\/lib\//i.test(file)
205
+ ) {
206
+ return 'internal'
207
+ }
208
+ return 'first-party'
209
+ }
210
+ if (file.startsWith('node:') || file.startsWith('internal/') || file.startsWith('wasm://')) {
211
+ return 'internal'
212
+ }
213
+ if (file.includes('/node_modules/') || file.startsWith('node_modules/')) return 'dependency'
214
+ return 'first-party'
215
+ }
216
+
217
+ function finishFrame(draft: Draft, options: ParseStackTraceOptions | undefined): StackFrame {
218
+ const { format, detail, ...base } = draft
219
+ const shape: Omit<StackFrame, 'kind'> = detail && detail.length > 0 ? { ...base, detail } : base
220
+ // Classified by the frame's own format, so a mixed trace keeps both languages' rules.
221
+ const guess = classifyFrame(shape, format)
222
+ const override = options?.classify?.({ ...shape, kind: guess })
223
+ return { ...shape, kind: override ?? guess }
224
+ }
225
+
226
+ const TYPE_AND_MESSAGE = /^([A-Za-z_$][\w$.]*)(?::\s?([\s\S]*))?$/
227
+
228
+ function splitTypeAndMessage(lines: readonly string[]): StackTraceHeader {
229
+ const first = lines[0] ?? ''
230
+ const match = TYPE_AND_MESSAGE.exec(first)
231
+ const tail = lines.slice(1)
232
+ if (!match) return { message: lines.join('\n') }
233
+ const message = [match[2] ?? '', ...tail].join('\n').replace(/^\n+/, '')
234
+ return { type: match[1], message }
235
+ }
236
+
237
+ /** Parse a stack trace. Never throws, and every input line appears in the result. */
238
+ export function parseStackTrace(text: string, options?: ParseStackTraceOptions): ParsedStackTrace {
239
+ const rawLines = text.split('\n')
240
+ const overflow = rawLines.length > STACK_MAX_LINES ? rawLines.splice(STACK_MAX_LINES) : []
241
+ const rustContext = /panicked at|stack backtrace|RUST_BACKTRACE/.test(text.slice(0, 200_000))
242
+
243
+ type Item = { type: 'text'; text: string } | { type: 'frame'; draft: Draft }
244
+ const items: Item[] = []
245
+ let python: Draft | undefined
246
+ let rust: Draft | undefined
247
+
248
+ for (const original of rawLines) {
249
+ const line = original.endsWith('\r') ? original.slice(0, -1) : original
250
+ const trimmed = line.trim()
251
+
252
+ if (line.length > LINE_PATTERN_LIMIT || trimmed === '') {
253
+ python = rust = undefined
254
+ items.push({ type: 'text', text: line })
255
+ continue
256
+ }
257
+
258
+ // Python prints the offending source line, indented, under its frame.
259
+ if (python && /^\s/.test(line) && !trimmed.startsWith('File "')) {
260
+ ;(python.detail ??= []).push(line)
261
+ continue
262
+ }
263
+
264
+ if (rust && rust.file === undefined && RUST_LOCATION.test(trimmed)) {
265
+ const split = splitLocation(RUST_LOCATION.exec(trimmed)![1]!)
266
+ rust.file = split.file
267
+ rust.line = split.line
268
+ rust.column = split.column
269
+ rust.raw = `${rust.raw}\n${line}`
270
+ continue
271
+ }
272
+
273
+ const draft = parsePython(trimmed) ?? parseRustFrame(trimmed, rustContext) ?? parseV8(trimmed)
274
+ python = draft?.format === 'python' ? draft : undefined
275
+ rust = draft?.format === 'rust' ? draft : undefined
276
+ if (draft) items.push({ type: 'frame', draft })
277
+ else items.push({ type: 'text', text: line })
278
+ }
279
+ if (overflow.length > 0) items.push({ type: 'text', text: overflow.join('\n') })
280
+
281
+ const counts = { v8: 0, python: 0, rust: 0 }
282
+ for (const item of items) if (item.type === 'frame') counts[item.draft.format] += 1
283
+ const total = counts.v8 + counts.python + counts.rust
284
+ const format: StackTraceFormat =
285
+ total === 0
286
+ ? 'unknown'
287
+ : counts.python >= counts.v8 && counts.python >= counts.rust
288
+ ? 'python'
289
+ : counts.rust >= counts.v8
290
+ ? 'rust'
291
+ : 'v8'
292
+
293
+ const entries: StackEntry[] = items.map((item) =>
294
+ item.type === 'text' ? item : { type: 'frame', frame: finishFrame(item.draft, options) }
295
+ )
296
+
297
+ if (format === 'unknown') return { format, entries, frames: [] }
298
+
299
+ const header = liftHeader(entries, format)
300
+ const frames = entries.flatMap((entry) => (entry.type === 'frame' ? [entry.frame] : []))
301
+ return { format, ...(header && { header }), entries, frames }
302
+ }
303
+
304
+ /**
305
+ * Take the header out of the entries it came from. V8 and Rust print it before
306
+ * the frames; Python prints it after. The lifted lines are removed so they are
307
+ * drawn once, as the header, and nothing else is touched.
308
+ */
309
+ function liftHeader(entries: StackEntry[], format: StackTraceFormat): StackTraceHeader | undefined {
310
+ const firstFrame = entries.findIndex((entry) => entry.type === 'frame')
311
+
312
+ if (format === 'python') {
313
+ let last = entries.length - 1
314
+ while (last >= 0 && (entries[last]!.type !== 'text' || isBlank(entries[last]!))) last -= 1
315
+ let lastFrame = entries.length - 1
316
+ while (lastFrame >= 0 && entries[lastFrame]!.type !== 'frame') lastFrame -= 1
317
+ const entry = entries[last]
318
+ // Only a line shaped like `Type: message` is taken as the header; anything
319
+ // else after the last frame (`[Previous line repeated …]`) stays where it is.
320
+ if (
321
+ !entry ||
322
+ entry.type !== 'text' ||
323
+ last < lastFrame ||
324
+ /^\s/.test(entry.text) ||
325
+ !TYPE_AND_MESSAGE.test(entry.text.trim())
326
+ ) {
327
+ return undefined
328
+ }
329
+ entries.splice(last, 1)
330
+ return splitTypeAndMessage([entry.text.trim()])
331
+ }
332
+
333
+ if (format === 'rust') {
334
+ const panicAt = entries.findIndex(
335
+ (entry, index) =>
336
+ index < firstFrame && entry.type === 'text' && /panicked at/.test(entry.text)
337
+ )
338
+ if (panicAt < 0) return undefined
339
+ const first = (entries[panicAt] as { text: string }).text.trim()
340
+ const at = first.indexOf(' at ')
341
+ if (at < 0) return undefined
342
+ const type = first.slice(0, at).trim()
343
+ const after = first.slice(at + 4)
344
+ const old = /^'(.*)', (\S.*)$/.exec(after)
345
+ let consumed = 1
346
+ let message: string
347
+ let location: string | undefined
348
+ if (old) {
349
+ message = old[1]!
350
+ location = old[2]
351
+ } else {
352
+ location = after.replace(/:$/, '')
353
+ const body: string[] = []
354
+ for (let i = panicAt + 1; i < firstFrame; i += 1) {
355
+ const entry = entries[i]!
356
+ if (
357
+ entry.type !== 'text' ||
358
+ isBlank(entry) ||
359
+ /^(?:note:|stack backtrace:)/.test(entry.text.trim())
360
+ )
361
+ break
362
+ body.push(entry.text)
363
+ consumed += 1
364
+ }
365
+ message = body.join('\n')
366
+ }
367
+ entries.splice(panicAt, consumed)
368
+ return { type, message, ...(location && { location }) }
369
+ }
370
+
371
+ // V8: the block of non-blank lines directly above the first frame. Anything
372
+ // above a blank line — Node prints the source line that threw — stays as text.
373
+ if (firstFrame <= 0) return undefined
374
+ let start = firstFrame
375
+ while (start > 0 && entries[start - 1]!.type === 'text' && !isBlank(entries[start - 1]!))
376
+ start -= 1
377
+ if (start === firstFrame) return undefined
378
+ const lines = entries.slice(start, firstFrame).map((entry) => (entry as { text: string }).text)
379
+ entries.splice(start, firstFrame - start)
380
+ return splitTypeAndMessage(lines)
381
+ }
382
+
383
+ function isBlank(entry: StackEntry): boolean {
384
+ return entry.type === 'text' && entry.text.trim() === ''
385
+ }
386
+
387
+ // ---------------------------------------------------------------------------
388
+ // Grouping
389
+ // ---------------------------------------------------------------------------
390
+
391
+ export type StackBlock =
392
+ | Readonly<{ type: 'frame'; frame: StackFrame }>
393
+ | Readonly<{ type: 'text'; text: string }>
394
+ | Readonly<{ type: 'group'; frames: readonly StackFrame[] }>
395
+
396
+ /**
397
+ * Fold runs of dependency and runtime frames into groups, so a trace reads as
398
+ * the code the reader owns with the framework's frames one click away.
399
+ *
400
+ * A run of one stays a frame — a disclosure around a single line costs more than
401
+ * it saves. When there is no first-party frame at all nothing is grouped:
402
+ * collapsing everything would hide the entire trace behind a button, which is the
403
+ * opposite of what a reader who owns none of the frames needs.
404
+ */
405
+ export function groupStackEntries(
406
+ entries: readonly StackEntry[],
407
+ collapse = true
408
+ ): readonly StackBlock[] {
409
+ const hasFirstParty = entries.some(
410
+ (entry) => entry.type === 'frame' && entry.frame.kind === 'first-party'
411
+ )
412
+ if (!collapse || !hasFirstParty) return entries
413
+
414
+ const blocks: StackBlock[] = []
415
+ let run: StackFrame[] = []
416
+ const flush = () => {
417
+ if (run.length >= 2) blocks.push({ type: 'group', frames: run })
418
+ else for (const frame of run) blocks.push({ type: 'frame', frame })
419
+ run = []
420
+ }
421
+ for (const entry of entries) {
422
+ if (entry.type === 'frame' && entry.frame.kind !== 'first-party') {
423
+ run.push(entry.frame)
424
+ continue
425
+ }
426
+ flush()
427
+ blocks.push(entry)
428
+ }
429
+ flush()
430
+ return blocks
431
+ }
432
+
433
+ const framesNoun = (count: number, word: string) =>
434
+ `${count.toLocaleString()} ${word} ${count === 1 ? 'frame' : 'frames'}`
435
+
436
+ /** What a collapsed group says it holds. */
437
+ export function describeFrameGroup(frames: readonly StackFrame[]): string {
438
+ const count = frames.length
439
+ const dependency = frames.filter((frame) => frame.kind === 'dependency').length
440
+ if (dependency === count) return framesNoun(count, 'dependency')
441
+ if (dependency === 0) return framesNoun(count, 'runtime')
442
+ return `${count.toLocaleString()} dependency and runtime frames`
443
+ }
444
+
445
+ /** `file:line:col`, with whichever parts the frame has. */
446
+ export function frameLocation(frame: StackFrame): string | undefined {
447
+ if (frame.file === undefined) return undefined
448
+ const column = frame.column === undefined ? '' : `:${frame.column}`
449
+ const line = frame.line === undefined ? '' : `:${frame.line}`
450
+ return `${frame.file}${line}${line ? column : ''}`
451
+ }
452
+
453
+ const LEADING_SPACE = /^[ \t]*/
454
+
455
+ /** Remove the indentation every non-blank line shares, so a source snippet sits flush. */
456
+ export function dedentLines(lines: readonly string[]): string[] {
457
+ let indent = Infinity
458
+ for (const line of lines) {
459
+ if (line.trim() !== '') indent = Math.min(indent, LEADING_SPACE.exec(line)![0].length)
460
+ }
461
+ if (indent === Infinity) return [...lines]
462
+ return lines.map((line) => line.slice(Math.min(indent, LEADING_SPACE.exec(line)![0].length)))
463
+ }
464
+
465
+ export type BoundedLines = Readonly<{
466
+ lines: string[]
467
+ /** Lines beyond the bound that are not in `lines` at all. */
468
+ omittedLines: number
469
+ /** Characters beyond the bound, in omitted lines and in the cut end of the last shown line. */
470
+ omittedChars: number
471
+ }>
472
+
473
+ /**
474
+ * The first lines of `lines`, up to `maxLines` of them and `maxChars` characters
475
+ * between them, with what was left out counted rather than dropped silently. It
476
+ * visits the shown lines and adds up the length of the rest, so the cost does not
477
+ * depend on how much text there is to omit.
478
+ */
479
+ export function boundLines(
480
+ lines: readonly string[],
481
+ maxLines: number,
482
+ maxChars: number
483
+ ): BoundedLines {
484
+ const shown: string[] = []
485
+ let chars = 0
486
+ let index = 0
487
+ let partial = 0
488
+ while (index < lines.length && shown.length < maxLines) {
489
+ const line = lines[index]!
490
+ const room = maxChars - chars
491
+ if (line.length <= room) {
492
+ shown.push(line)
493
+ chars += line.length
494
+ index += 1
495
+ continue
496
+ }
497
+ if (room > 0) {
498
+ shown.push(line.slice(0, room))
499
+ partial = line.length - room
500
+ index += 1
501
+ }
502
+ break
503
+ }
504
+ let omittedChars = partial
505
+ for (let rest = index; rest < lines.length; rest += 1) omittedChars += lines[rest]!.length
506
+ return { lines: shown, omittedLines: lines.length - index, omittedChars }
507
+ }