@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,141 @@
1
+ import { ListOrdered } from 'lucide-solid'
2
+ import { children as resolveChildren, splitProps, type ComponentProps, type JSX } from 'solid-js'
3
+ import { cn } from '#lib/utils'
4
+ import { Badge } from '../../ui/badge'
5
+ import { Trace, TraceLine, type TraceLineProps, type TraceStatus } from '../../ui/trace'
6
+
7
+ // A function child runs once, when the content mounts (see `deferred` in `tool.tsx`).
8
+ const deferred = (render: () => JSX.Element) => render as unknown as JSX.Element
9
+
10
+ /**
11
+ * ChainOfThought.
12
+ *
13
+ * A summary line that opens onto the steps behind it: "Searched 3 sources and
14
+ * compared them", then each source and each comparison as its own line. Reach for
15
+ * `Reasoning` when the thinking is prose, for `Plan` when the steps are a
16
+ * proposal still to be carried out, and for a plain `Trace` when each line is a
17
+ * tool call — a step here is a statement about the agent's *method*, whatever
18
+ * the host chooses to put in it.
19
+ *
20
+ * Nothing here knows how the steps were produced. The host passes the summary and
21
+ * the steps it wants shown; the component does not imply there is more, and a
22
+ * summary with no steps is a plain line.
23
+ *
24
+ * ## Steps
25
+ *
26
+ * A `ChainOfThoughtStep` is a `TraceLine` with a three-state `status` — `complete`
27
+ * (keeps its own icon, or a tick), `active` (running mark and shimmer) and
28
+ * `pending` (dashed mark). Every status is also spoken. A step without a status
29
+ * makes no claim at all. A step's `children` are its evidence — search-result
30
+ * badges, a snippet — and are open by default: someone who unfolded the summary
31
+ * to see the working wants to see what the working found, and one more click per
32
+ * step to read it defeats the point of the summary.
33
+ *
34
+ * `description` is a single truncated row beside the label. Anything longer
35
+ * belongs in `children`.
36
+ *
37
+ * Both parts are lines: put a `ChainOfThought` inside a `Trace`, next to the
38
+ * other activity of the turn.
39
+ */
40
+ export type ChainOfThoughtStepStatus = 'complete' | 'active' | 'pending'
41
+
42
+ /** The words spoken for each step status. */
43
+ export const CHAIN_OF_THOUGHT_STATUS_LABELS: Readonly<Record<ChainOfThoughtStepStatus, string>> = {
44
+ complete: 'Done',
45
+ active: 'In progress',
46
+ pending: 'Pending',
47
+ }
48
+
49
+ const TRACE_STATUS: Readonly<Record<ChainOfThoughtStepStatus, TraceStatus>> = {
50
+ complete: 'success',
51
+ active: 'running',
52
+ pending: 'pending',
53
+ }
54
+
55
+ export type ChainOfThoughtProps = Omit<
56
+ TraceLineProps,
57
+ 'title' | 'href' | 'onSelect' | 'selectHaspopup'
58
+ > & {
59
+ /** The one-line account of what the steps add up to. */
60
+ summary?: JSX.Element
61
+ /** The steps' accessible name. */
62
+ stepsLabel?: string
63
+ }
64
+
65
+ export function ChainOfThought(props: ChainOfThoughtProps) {
66
+ const [local, rest] = splitProps(props, ['summary', 'stepsLabel', 'icon', 'children'])
67
+ // Resolved once so the steps are created once: a step keeps its own open state
68
+ // and its DOM while the summary is folded and unfolded.
69
+ const steps = resolveChildren(() => local.children)
70
+ const hasSteps = () => steps.toArray().length > 0
71
+ // A function child runs only when the content mounts, and once.
72
+ const stepList = () => (
73
+ <Trace size="sm" aria-label={local.stepsLabel ?? 'Steps'}>
74
+ {steps()}
75
+ </Trace>
76
+ )
77
+
78
+ return (
79
+ <TraceLine icon={local.icon ?? <ListOrdered />} title={local.summary ?? 'Steps'} {...rest}>
80
+ {hasSteps() ? deferred(stepList) : undefined}
81
+ </TraceLine>
82
+ )
83
+ }
84
+
85
+ export type ChainOfThoughtStepProps = Omit<
86
+ TraceLineProps,
87
+ 'title' | 'status' | 'href' | 'onSelect' | 'selectHaspopup'
88
+ > & {
89
+ label: JSX.Element
90
+ status?: ChainOfThoughtStepStatus
91
+ }
92
+
93
+ export function ChainOfThoughtStep(props: ChainOfThoughtStepProps) {
94
+ const [local, rest] = splitProps(props, ['label', 'status', 'statusLabel', 'defaultOpen'])
95
+ return (
96
+ <TraceLine
97
+ title={local.label}
98
+ status={local.status ? TRACE_STATUS[local.status] : undefined}
99
+ statusLabel={
100
+ local.status
101
+ ? (local.statusLabel ?? CHAIN_OF_THOUGHT_STATUS_LABELS[local.status])
102
+ : undefined
103
+ }
104
+ defaultOpen={local.defaultOpen ?? true}
105
+ {...rest}
106
+ />
107
+ )
108
+ }
109
+
110
+ /** Evidence for a step: the sources it searched, as a wrapping row of badges. */
111
+ export function ChainOfThoughtResults(props: ComponentProps<'ul'>) {
112
+ const [local, rest] = splitProps(props, ['class', 'children'])
113
+ return (
114
+ <ul
115
+ role="list"
116
+ data-slot="chain-of-thought-results"
117
+ class={cn('m-0 flex min-w-0 list-none flex-wrap gap-1.5 p-0', local.class)}
118
+ {...rest}
119
+ >
120
+ {local.children}
121
+ </ul>
122
+ )
123
+ }
124
+
125
+ export type ChainOfThoughtResultProps = Omit<ComponentProps<'li'>, 'children'> & {
126
+ /** Rendered as text. A long label truncates and keeps its full text in `title`. */
127
+ label: string
128
+ icon?: JSX.Element
129
+ }
130
+
131
+ export function ChainOfThoughtResult(props: ChainOfThoughtResultProps) {
132
+ const [local, rest] = splitProps(props, ['class', 'label', 'icon'])
133
+ return (
134
+ <li data-slot="chain-of-thought-result" class={cn('min-w-0 max-w-full', local.class)} {...rest}>
135
+ <Badge variant="outline" class="max-w-full min-w-0" title={local.label}>
136
+ {local.icon}
137
+ <span class="truncate">{local.label}</span>
138
+ </Badge>
139
+ </li>
140
+ )
141
+ }
@@ -0,0 +1,11 @@
1
+ export {
2
+ CHAIN_OF_THOUGHT_STATUS_LABELS,
3
+ ChainOfThought,
4
+ ChainOfThoughtResult,
5
+ ChainOfThoughtResults,
6
+ ChainOfThoughtStep,
7
+ type ChainOfThoughtProps,
8
+ type ChainOfThoughtResultProps,
9
+ type ChainOfThoughtStepProps,
10
+ type ChainOfThoughtStepStatus,
11
+ } from './chain-of-thought'
@@ -0,0 +1,190 @@
1
+ import { CircleAlert, Info, TriangleAlert } from 'lucide-solid'
2
+ import { Show, splitProps, type ComponentProps, type JSX } from 'solid-js'
3
+ import { Dynamic } from 'solid-js/web'
4
+ import { cn } from '#lib/utils'
5
+ import { cva, type VariantProps } from '#lib/variants'
6
+
7
+ /**
8
+ * Chat.
9
+ *
10
+ * The frame a conversation lives in: a header, a strip for things the reader
11
+ * must know before reading anything else, the thread, and the composer. It is a
12
+ * layout and nothing more — the thread is a `MessageScroller`, the input is a
13
+ * composer, and what happens in between is the host's — which is why it takes
14
+ * slots instead of data.
15
+ *
16
+ * ## Why notices have their own row
17
+ *
18
+ * "The connection dropped", "this transcript has a gap", "this session is
19
+ * read-only" are about the whole conversation, not about a turn, and they must
20
+ * not scroll away with the turns. They sit between the header and the thread in
21
+ * their own grid track, so a notice appearing never steals the thread's row and
22
+ * collapses to zero height when there are none. Each notice states its cause in
23
+ * words and carries its own remedy (`action`); one that reports a *change*
24
+ * (`live`) is announced, one that describes a standing condition is not.
25
+ *
26
+ * ## Layout
27
+ *
28
+ * `h-full min-h-0`, so the thread scrolls inside the frame rather than the page
29
+ * growing, and a `min-w-0` track, so a long unbroken token in a turn cannot widen
30
+ * the whole conversation. Nothing here sets a width: the reading column is the
31
+ * turn's, and the composer sets its own measure.
32
+ */
33
+ export type ChatProps = ComponentProps<'section'> & {
34
+ header?: JSX.Element
35
+ /** `ChatNotice`s. The row collapses when this is empty. */
36
+ notices?: JSX.Element
37
+ /** The composer. */
38
+ composer?: JSX.Element
39
+ }
40
+
41
+ export function Chat(props: ChatProps) {
42
+ const [local, rest] = splitProps(props, ['class', 'header', 'notices', 'composer', 'children'])
43
+ return (
44
+ <section
45
+ data-slot="chat"
46
+ class={cn(
47
+ 'grid h-full min-h-0 min-w-0 grid-cols-[minmax(0,1fr)] grid-rows-[auto_auto_minmax(0,1fr)_auto] bg-background text-foreground',
48
+ local.class
49
+ )}
50
+ {...rest}
51
+ >
52
+ <div class="row-start-1 min-w-0">{local.header}</div>
53
+ <div class="row-start-2 flex min-w-0 flex-col">{local.notices}</div>
54
+ <div class="row-start-3 flex min-h-0 min-w-0 flex-col">{local.children}</div>
55
+ <div class="row-start-4 min-w-0">{local.composer}</div>
56
+ </section>
57
+ )
58
+ }
59
+
60
+ export type ChatHeaderProps = Omit<ComponentProps<'header'>, 'title'> & {
61
+ title: JSX.Element
62
+ /** One line under the title: identity, scope, generation. */
63
+ subtitle?: JSX.Element
64
+ /** The conversation's state in words (a `StatusChip`). */
65
+ status?: JSX.Element
66
+ /** Host actions: rename, archive, hand off. */
67
+ actions?: JSX.Element
68
+ }
69
+
70
+ export function ChatHeader(props: ChatHeaderProps) {
71
+ const [local, rest] = splitProps(props, ['class', 'title', 'subtitle', 'status', 'actions'])
72
+ return (
73
+ <header
74
+ data-slot="chat-header"
75
+ class={cn(
76
+ 'flex min-h-topbar min-w-0 items-center gap-3 border-b border-border px-4 py-2',
77
+ local.class
78
+ )}
79
+ {...rest}
80
+ >
81
+ <div class="flex min-w-0 flex-1 flex-col">
82
+ <h2 class="m-0 truncate text-sm font-semibold tracking-tight">{local.title}</h2>
83
+ <Show when={local.subtitle}>
84
+ <p class="m-0 truncate text-xs text-muted-foreground">{local.subtitle}</p>
85
+ </Show>
86
+ </div>
87
+ <Show when={local.status}>{local.status}</Show>
88
+ <Show when={local.actions}>
89
+ <div class="flex shrink-0 items-center gap-1">{local.actions}</div>
90
+ </Show>
91
+ </header>
92
+ )
93
+ }
94
+
95
+ export const chatNoticeVariants = cva(
96
+ 'flex min-w-0 items-start gap-2.5 border-b px-4 py-2 text-sm',
97
+ {
98
+ variants: {
99
+ tone: {
100
+ info: 'border-border bg-muted/40',
101
+ warning: 'border-warning/30 bg-warning-subtle',
102
+ danger: 'border-destructive/30 bg-destructive-subtle',
103
+ },
104
+ },
105
+ defaultVariants: { tone: 'info' },
106
+ }
107
+ )
108
+
109
+ export type ChatNoticeProps = Omit<ComponentProps<'div'>, 'title'> &
110
+ VariantProps<typeof chatNoticeVariants> & {
111
+ title: JSX.Element
112
+ description?: JSX.Element
113
+ /** The remedy: Reconnect, Jump to terminal. */
114
+ action?: JSX.Element
115
+ /** Announce it. Use for a change (connection lost), not a standing condition. */
116
+ live?: 'polite' | 'assertive'
117
+ }
118
+
119
+ export function ChatNotice(props: ChatNoticeProps) {
120
+ const [local, rest] = splitProps(props, [
121
+ 'class',
122
+ 'tone',
123
+ 'title',
124
+ 'description',
125
+ 'action',
126
+ 'live',
127
+ ])
128
+ const Glyph = () =>
129
+ local.tone === 'danger' ? CircleAlert : local.tone === 'warning' ? TriangleAlert : Info
130
+ return (
131
+ <div
132
+ data-slot="chat-notice"
133
+ role={local.live === 'assertive' ? 'alert' : local.live === 'polite' ? 'status' : undefined}
134
+ class={cn(chatNoticeVariants({ tone: local.tone }), local.class)}
135
+ {...rest}
136
+ >
137
+ <span
138
+ aria-hidden="true"
139
+ class={cn('mt-0.5 shrink-0 [&_svg]:size-4', {
140
+ 'text-muted-foreground': (local.tone ?? 'info') === 'info',
141
+ 'text-warning': local.tone === 'warning',
142
+ 'text-destructive': local.tone === 'danger',
143
+ })}
144
+ >
145
+ <Dynamic component={Glyph()} />
146
+ </span>
147
+ <div class="min-w-0 flex-1">
148
+ <p class="m-0 font-medium [overflow-wrap:anywhere]">{local.title}</p>
149
+ <Show when={local.description}>
150
+ <p class="m-0 text-xs text-muted-foreground [overflow-wrap:anywhere]">
151
+ {local.description}
152
+ </p>
153
+ </Show>
154
+ </div>
155
+ <Show when={local.action}>
156
+ <div class="flex shrink-0 items-center gap-1.5">{local.action}</div>
157
+ </Show>
158
+ </div>
159
+ )
160
+ }
161
+
162
+ export type ChatEmptyProps = Omit<ComponentProps<'div'>, 'title'> & {
163
+ title: JSX.Element
164
+ description?: JSX.Element
165
+ /** Prompt chips (`Suggestions`), shown only when the host has real ones. */
166
+ suggestions?: JSX.Element
167
+ }
168
+
169
+ /** A conversation with no turns yet. Centred in the thread, never in a card. */
170
+ export function ChatEmpty(props: ChatEmptyProps) {
171
+ const [local, rest] = splitProps(props, ['class', 'title', 'description', 'suggestions'])
172
+ return (
173
+ <div
174
+ data-slot="chat-empty"
175
+ class={cn(
176
+ 'mx-auto flex min-h-full w-full max-w-xl flex-col items-center justify-center gap-4 px-6 py-10 text-center',
177
+ local.class
178
+ )}
179
+ {...rest}
180
+ >
181
+ <div class="flex flex-col gap-1">
182
+ <h3 class="m-0 text-base font-semibold tracking-tight text-balance">{local.title}</h3>
183
+ <Show when={local.description}>
184
+ <p class="m-0 text-sm text-muted-foreground text-balance">{local.description}</p>
185
+ </Show>
186
+ </div>
187
+ <Show when={local.suggestions}>{local.suggestions}</Show>
188
+ </div>
189
+ )
190
+ }
@@ -0,0 +1,11 @@
1
+ export {
2
+ Chat,
3
+ ChatEmpty,
4
+ ChatHeader,
5
+ ChatNotice,
6
+ chatNoticeVariants,
7
+ type ChatEmptyProps,
8
+ type ChatHeaderProps,
9
+ type ChatNoticeProps,
10
+ type ChatProps,
11
+ } from './chat'
@@ -0,0 +1,71 @@
1
+ import { boundText } from '../sources/source'
2
+
3
+ /**
4
+ * Where a restore stands. `idle` is the resting state of a checkpoint that has
5
+ * not been restored from; the other three are only ever set because something
6
+ * happened — the host passes them, or the component sets them from the promise
7
+ * `onRestore` returned.
8
+ */
9
+ export type CheckpointState = 'idle' | 'restoring' | 'restored' | 'failed'
10
+
11
+ /** The checkpoint's name as drawn; a blank label is the honest generic word. */
12
+ export function checkpointLabel(label: string | undefined): string {
13
+ return (label ? boundText(label, 80) : '') || 'Checkpoint'
14
+ }
15
+
16
+ /**
17
+ * The sentence for the status region. `idle` says nothing, because a
18
+ * checkpoint that has not been touched makes no statement. A failure carries the
19
+ * host's text when there is one.
20
+ */
21
+ export function checkpointStatus(
22
+ state: CheckpointState,
23
+ error?: string,
24
+ disabledReason?: string
25
+ ): string | undefined {
26
+ switch (state) {
27
+ case 'restoring':
28
+ return 'Restoring…'
29
+ case 'restored':
30
+ return 'Restored'
31
+ case 'failed': {
32
+ const detail = error ? boundText(error, 240) : ''
33
+ return detail ? `Restore failed: ${detail}` : 'Restore failed'
34
+ }
35
+ case 'idle':
36
+ return disabledReason ? boundText(disabledReason, 240) : undefined
37
+ }
38
+ }
39
+
40
+ /**
41
+ * The confirmation dialog's words. The host's `consequence` is what actually
42
+ * names what will change, so it is used verbatim (bounded); without one the dialog
43
+ * says only what a restore always means and does not guess at the rest.
44
+ */
45
+ export function restoreDialogCopy(
46
+ label: string | undefined,
47
+ consequence: string | undefined
48
+ ): { title: string; description: string } {
49
+ return {
50
+ title: `Restore to “${checkpointLabel(label)}”?`,
51
+ description: consequence
52
+ ? boundText(consequence, 400)
53
+ : 'Restoring returns to this checkpoint.',
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Whether the Restore control exists, and whether it can be used. It exists only
59
+ * when the host passed a handler — a checkpoint that cannot be restored must not
60
+ * look as if it can — and goes once the restore has succeeded.
61
+ */
62
+ export function restoreControl(
63
+ hasHandler: boolean,
64
+ state: CheckpointState,
65
+ disabledReason: string | undefined
66
+ ): { visible: boolean; disabled: boolean } {
67
+ return {
68
+ visible: hasHandler && state !== 'restored',
69
+ disabled: state === 'restoring' || disabledReason !== undefined,
70
+ }
71
+ }
@@ -0,0 +1,214 @@
1
+ import { Flag } from 'lucide-solid'
2
+ import {
3
+ createEffect,
4
+ createMemo,
5
+ createSignal,
6
+ createUniqueId,
7
+ on,
8
+ Show,
9
+ splitProps,
10
+ type ComponentProps,
11
+ } from 'solid-js'
12
+ import { cn } from '#lib/utils'
13
+ import { Button } from '../../ui/button'
14
+ import {
15
+ AlertDialog,
16
+ AlertDialogAction,
17
+ AlertDialogCancel,
18
+ AlertDialogContent,
19
+ AlertDialogDescription,
20
+ AlertDialogFooter,
21
+ AlertDialogHeader,
22
+ AlertDialogTitle,
23
+ AlertDialogTrigger,
24
+ } from '../../ui/alert-dialog'
25
+ import { Marker } from '../../ui/marker'
26
+ import { Spinner } from '../../ui/spinner'
27
+ import { settleDecision } from '../confirmation/confirmation-model'
28
+ import { boundText } from '../sources/source'
29
+ import {
30
+ checkpointLabel,
31
+ checkpointStatus,
32
+ restoreControl,
33
+ restoreDialogCopy,
34
+ type CheckpointState,
35
+ } from './checkpoint-model'
36
+
37
+ /**
38
+ * Checkpoint.
39
+ *
40
+ * A point in the conversation the host can name: a divider in the transcript with
41
+ * a label and a time. It always renders — as a `Marker`, the quietest thing in the
42
+ * column — and it is honest about what it is:
43
+ *
44
+ * - **Without `onRestore` it is only a marker.** Not a disabled button, not a
45
+ * greyed-out "Restore": nothing. Whether a checkpoint can be returned to is a
46
+ * fact about the host's storage and permissions, and a control that implies it
47
+ * can would be a claim nobody made.
48
+ * - **With `onRestore` it offers Restore, and Restore asks first.** An
49
+ * `AlertDialog` (Escape and the scrim do nothing; every exit is a named choice)
50
+ * states what will change in the host's own words (`consequence`) before the
51
+ * handler is called. A restore throws work away; the confirmation is the point.
52
+ *
53
+ * ## States
54
+ *
55
+ * `idle` → `restoring` → `restored`, or `failed` with `error`. Pass `state` to
56
+ * drive it from the host; omit it and the component follows the promise
57
+ * `onRestore` returns. The status sentence is a live region that exists from the
58
+ * start, so a change is announced. While restoring, the control stays focusable
59
+ * (`aria-disabled`, not `disabled`) so focus is not dropped when the dialog hands
60
+ * it back; once restored the control goes and focus moves to the status line.
61
+ *
62
+ * A restore that cannot happen now takes `disabledReason`, shown in words under
63
+ * the divider; the host decides, the component explains.
64
+ */
65
+ export type CheckpointProps = Omit<ComponentProps<'div'>, 'children' | 'onError'> & {
66
+ /** The checkpoint's name. Defaults to "Checkpoint". */
67
+ label?: string
68
+ /** When it was taken, already formatted for the reader. */
69
+ time?: string
70
+ state?: CheckpointState
71
+ /** Supplying this is what makes the checkpoint restorable. */
72
+ onRestore?: () => void | Promise<void>
73
+ /** What restoring will change, in the host's words. Shown in the confirmation. */
74
+ consequence?: string
75
+ restoreLabel?: string
76
+ /** Why Restore cannot be used right now. */
77
+ disabledReason?: string
78
+ /** Why a restore failed. */
79
+ error?: string
80
+ }
81
+
82
+ export function Checkpoint(props: CheckpointProps) {
83
+ const [local, rest] = splitProps(props, [
84
+ 'class',
85
+ 'label',
86
+ 'time',
87
+ 'state',
88
+ 'onRestore',
89
+ 'consequence',
90
+ 'restoreLabel',
91
+ 'disabledReason',
92
+ 'error',
93
+ ])
94
+ const uid = createUniqueId()
95
+ const reasonId = `${uid}-status`
96
+ const [followed, setFollowed] = createSignal<CheckpointState>('idle')
97
+ const [failure, setFailure] = createSignal<string | undefined>(undefined)
98
+ const [confirming, setConfirming] = createSignal(false)
99
+ let inflight = false
100
+ let root: HTMLDivElement | undefined
101
+ let status: HTMLParagraphElement | undefined
102
+
103
+ const state = (): CheckpointState => local.state ?? followed()
104
+ const error = () => local.error ?? failure()
105
+ const control = () => restoreControl(local.onRestore !== undefined, state(), local.disabledReason)
106
+ const copy = () => restoreDialogCopy(local.label, local.consequence)
107
+ const statusText = () => checkpointStatus(state(), error(), local.disabledReason)
108
+
109
+ const restore = async () => {
110
+ if (inflight || control().disabled) return
111
+ inflight = true
112
+ setFailure(undefined)
113
+ setFollowed('restoring')
114
+ const result = await settleDecision(local.onRestore)
115
+ inflight = false
116
+ if (result.ok) {
117
+ setFollowed('restored')
118
+ } else {
119
+ setFailure(result.message)
120
+ setFollowed('failed')
121
+ }
122
+ }
123
+
124
+ // The control is replaced by the status line on success; do not strand focus.
125
+ createEffect(
126
+ on(
127
+ () => state() === 'restored',
128
+ (restored) => {
129
+ if (!restored) return
130
+ const active = document.activeElement
131
+ if (active === null || active === document.body || root?.contains(active)) {
132
+ status?.focus()
133
+ }
134
+ },
135
+ { defer: true }
136
+ )
137
+ )
138
+
139
+ // Built once. `Marker` reads `action` twice (to test it, then to draw it), and a
140
+ // JSX prop re-creates its component on every read: a second AlertDialog root
141
+ // would portal a second, invisible-to-the-tree dialog when this one opens.
142
+ const restoreAction = createMemo(() => (
143
+ <Show when={control().visible}>
144
+ <AlertDialog
145
+ open={confirming()}
146
+ onOpenChange={(open) => setConfirming(open && !control().disabled)}
147
+ >
148
+ <AlertDialogTrigger
149
+ as={Button}
150
+ variant="ghost"
151
+ size="2xs"
152
+ aria-disabled={control().disabled || undefined}
153
+ aria-describedby={statusText() ? reasonId : undefined}
154
+ >
155
+ <Show when={state() === 'restoring'}>
156
+ <Spinner size="xs" label={false} />
157
+ </Show>
158
+ {state() === 'restoring'
159
+ ? 'Restoring…'
160
+ : (local.restoreLabel ?? (state() === 'failed' ? 'Try again' : 'Restore'))}
161
+ </AlertDialogTrigger>
162
+ <AlertDialogContent>
163
+ <AlertDialogHeader>
164
+ <AlertDialogTitle>{copy().title}</AlertDialogTitle>
165
+ <AlertDialogDescription class="[overflow-wrap:anywhere]">
166
+ {copy().description}
167
+ </AlertDialogDescription>
168
+ </AlertDialogHeader>
169
+ <AlertDialogFooter>
170
+ <AlertDialogCancel as={Button} variant="ghost">
171
+ Do not restore
172
+ </AlertDialogCancel>
173
+ <AlertDialogAction as={Button} onClick={() => void restore()}>
174
+ {local.restoreLabel ?? 'Restore'}
175
+ </AlertDialogAction>
176
+ </AlertDialogFooter>
177
+ </AlertDialogContent>
178
+ </AlertDialog>
179
+ </Show>
180
+ ))
181
+
182
+ return (
183
+ <div
184
+ ref={(element) => (root = element)}
185
+ data-slot="checkpoint"
186
+ data-state={state()}
187
+ class={local.class}
188
+ {...rest}
189
+ >
190
+ <Marker
191
+ variant="rule"
192
+ icon={<Flag />}
193
+ tone={state() === 'failed' ? 'danger' : 'neutral'}
194
+ label={checkpointLabel(local.label)}
195
+ description={local.time ? boundText(local.time, 60) : undefined}
196
+ action={restoreAction()}
197
+ />
198
+ {/* Always present, so a state change is a change to a live region rather than
199
+ the arrival of one. Empty while idle, which takes no space. */}
200
+ <p
201
+ id={reasonId}
202
+ ref={(element) => (status = element)}
203
+ role="status"
204
+ tabindex="-1"
205
+ class={cn('m-0 text-center text-xs outline-none [overflow-wrap:anywhere]', {
206
+ 'text-destructive': state() === 'failed',
207
+ 'text-muted-foreground': state() !== 'failed',
208
+ })}
209
+ >
210
+ {statusText()}
211
+ </p>
212
+ </div>
213
+ )
214
+ }
@@ -0,0 +1,8 @@
1
+ export { Checkpoint, type CheckpointProps } from './checkpoint'
2
+ export {
3
+ checkpointLabel,
4
+ checkpointStatus,
5
+ restoreControl,
6
+ restoreDialogCopy,
7
+ type CheckpointState,
8
+ } from './checkpoint-model'