@kortix/ui 0.0.0-stage → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/README.md +155 -2
  2. package/dist/_vendor/kortix-shared.js +341 -0
  3. package/dist/chat/agent-picker.d.ts +8 -0
  4. package/dist/chat/agent-picker.js +18 -0
  5. package/dist/chat/composer.d.ts +31 -0
  6. package/dist/chat/composer.js +114 -0
  7. package/dist/chat/index.d.ts +22 -0
  8. package/dist/chat/index.js +22 -0
  9. package/dist/chat/markdown.d.ts +10 -0
  10. package/dist/chat/markdown.js +36 -0
  11. package/dist/chat/message-list.d.ts +25 -0
  12. package/dist/chat/message-list.js +73 -0
  13. package/dist/chat/message-view.d.ts +17 -0
  14. package/dist/chat/message-view.js +86 -0
  15. package/dist/chat/model-picker.d.ts +10 -0
  16. package/dist/chat/model-picker.js +68 -0
  17. package/dist/chat/permission-prompt.d.ts +10 -0
  18. package/dist/chat/permission-prompt.js +40 -0
  19. package/dist/chat/question-prompt.d.ts +8 -0
  20. package/dist/chat/question-prompt.js +60 -0
  21. package/dist/chat/send-failure.d.ts +9 -0
  22. package/dist/chat/send-failure.js +21 -0
  23. package/dist/chat/session-thread.d.ts +28 -0
  24. package/dist/chat/session-thread.js +47 -0
  25. package/dist/chat/streaming-markdown.d.ts +21 -0
  26. package/dist/chat/streaming-markdown.js +59 -0
  27. package/dist/chat/tool-call.d.ts +4 -0
  28. package/dist/chat/tool-call.js +150 -0
  29. package/dist/chat/user-message-parts.d.ts +6 -0
  30. package/dist/chat/user-message-parts.js +11 -0
  31. package/dist/components/ui/accordion.d.ts +7 -0
  32. package/dist/components/ui/accordion.js +18 -0
  33. package/dist/components/ui/alert-dialog.d.ts +19 -0
  34. package/dist/components/ui/alert-dialog.js +48 -0
  35. package/dist/components/ui/alert.d.ts +13 -0
  36. package/dist/components/ui/alert.js +67 -0
  37. package/dist/components/ui/avatar.d.ts +11 -0
  38. package/dist/components/ui/avatar.js +23 -0
  39. package/dist/components/ui/back-pill.d.ts +13 -0
  40. package/dist/components/ui/back-pill.js +18 -0
  41. package/dist/components/ui/badge.d.ts +10 -0
  42. package/dist/components/ui/badge.js +42 -0
  43. package/dist/components/ui/breadcrumb.d.ts +11 -0
  44. package/dist/components/ui/breadcrumb.js +28 -0
  45. package/dist/components/ui/bubble.d.ts +20 -0
  46. package/dist/components/ui/bubble.js +38 -0
  47. package/dist/components/ui/button-group.d.ts +9 -0
  48. package/dist/components/ui/button-group.js +32 -0
  49. package/dist/components/ui/button.d.ts +13 -0
  50. package/dist/components/ui/button.js +67 -0
  51. package/dist/components/ui/calendar.d.ts +4 -0
  52. package/dist/components/ui/calendar.js +39 -0
  53. package/dist/components/ui/card.d.ts +96 -0
  54. package/dist/components/ui/card.js +291 -0
  55. package/dist/components/ui/chain-of-thought.d.ts +75 -0
  56. package/dist/components/ui/chain-of-thought.js +66 -0
  57. package/dist/components/ui/chart.d.ts +65 -0
  58. package/dist/components/ui/chart.js +118 -0
  59. package/dist/components/ui/checkbox-group.d.ts +19 -0
  60. package/dist/components/ui/checkbox-group.js +41 -0
  61. package/dist/components/ui/checkbox.d.ts +14 -0
  62. package/dist/components/ui/checkbox.js +27 -0
  63. package/dist/components/ui/collapsible.d.ts +5 -0
  64. package/dist/components/ui/collapsible.js +14 -0
  65. package/dist/components/ui/command.d.ts +58 -0
  66. package/dist/components/ui/command.js +135 -0
  67. package/dist/components/ui/confirm-dialog.d.ts +19 -0
  68. package/dist/components/ui/confirm-dialog.js +30 -0
  69. package/dist/components/ui/context-menu.d.ts +45 -0
  70. package/dist/components/ui/context-menu.js +93 -0
  71. package/dist/components/ui/count-badge.d.ts +26 -0
  72. package/dist/components/ui/count-badge.js +26 -0
  73. package/dist/components/ui/data-grid.d.ts +24 -0
  74. package/dist/components/ui/data-grid.js +107 -0
  75. package/dist/components/ui/date-range-picker.d.ts +119 -0
  76. package/dist/components/ui/date-range-picker.js +190 -0
  77. package/dist/components/ui/definition-list.d.ts +15 -0
  78. package/dist/components/ui/definition-list.js +26 -0
  79. package/dist/components/ui/dialog.d.ts +29 -0
  80. package/dist/components/ui/dialog.js +52 -0
  81. package/dist/components/ui/disclosure.d.ts +121 -0
  82. package/dist/components/ui/disclosure.js +138 -0
  83. package/dist/components/ui/dot-matrix/dotm-3x3-10.d.ts +4 -0
  84. package/dist/components/ui/dot-matrix/dotm-3x3-10.js +29 -0
  85. package/dist/components/ui/dot-matrix/dotm-3x3-12.d.ts +4 -0
  86. package/dist/components/ui/dot-matrix/dotm-3x3-12.js +19 -0
  87. package/dist/components/ui/dot-matrix/dotm-3x3-13.d.ts +4 -0
  88. package/dist/components/ui/dot-matrix/dotm-3x3-13.js +19 -0
  89. package/dist/components/ui/dot-matrix/dotm-3x3-15.d.ts +4 -0
  90. package/dist/components/ui/dot-matrix/dotm-3x3-15.js +22 -0
  91. package/dist/components/ui/dot-matrix/dotm-3x3-16.d.ts +4 -0
  92. package/dist/components/ui/dot-matrix/dotm-3x3-16.js +5 -0
  93. package/dist/components/ui/dot-matrix/dotm-3x3-18.d.ts +4 -0
  94. package/dist/components/ui/dot-matrix/dotm-3x3-18.js +5 -0
  95. package/dist/components/ui/dot-matrix/dotm-3x3-19.d.ts +4 -0
  96. package/dist/components/ui/dot-matrix/dotm-3x3-19.js +5 -0
  97. package/dist/components/ui/dot-matrix/dotm-3x3-2.d.ts +4 -0
  98. package/dist/components/ui/dot-matrix/dotm-3x3-2.js +3 -0
  99. package/dist/components/ui/dot-matrix/dotm-3x3-20.d.ts +4 -0
  100. package/dist/components/ui/dot-matrix/dotm-3x3-20.js +5 -0
  101. package/dist/components/ui/dot-matrix/dotm-3x3-21.d.ts +4 -0
  102. package/dist/components/ui/dot-matrix/dotm-3x3-21.js +5 -0
  103. package/dist/components/ui/dot-matrix/dotm-3x3-3.d.ts +4 -0
  104. package/dist/components/ui/dot-matrix/dotm-3x3-3.js +3 -0
  105. package/dist/components/ui/dot-matrix/dotm-3x3-4.d.ts +4 -0
  106. package/dist/components/ui/dot-matrix/dotm-3x3-4.js +3 -0
  107. package/dist/components/ui/dot-matrix/dotm-3x3-5.d.ts +4 -0
  108. package/dist/components/ui/dot-matrix/dotm-3x3-5.js +3 -0
  109. package/dist/components/ui/dot-matrix/dotm-3x3-6.d.ts +4 -0
  110. package/dist/components/ui/dot-matrix/dotm-3x3-6.js +19 -0
  111. package/dist/components/ui/dot-matrix/dotm-3x3-7.d.ts +4 -0
  112. package/dist/components/ui/dot-matrix/dotm-3x3-7.js +19 -0
  113. package/dist/components/ui/dot-matrix/dotm-3x3-8.d.ts +4 -0
  114. package/dist/components/ui/dot-matrix/dotm-3x3-8.js +19 -0
  115. package/dist/components/ui/dot-matrix/dotm-3x3-9.d.ts +4 -0
  116. package/dist/components/ui/dot-matrix/dotm-3x3-9.js +23 -0
  117. package/dist/components/ui/dot-matrix/dotm-circular-1.d.ts +4 -0
  118. package/dist/components/ui/dot-matrix/dotm-circular-1.js +28 -0
  119. package/dist/components/ui/dot-matrix/dotm-circular-10.d.ts +4 -0
  120. package/dist/components/ui/dot-matrix/dotm-circular-10.js +40 -0
  121. package/dist/components/ui/dot-matrix/dotm-circular-11.d.ts +4 -0
  122. package/dist/components/ui/dot-matrix/dotm-circular-11.js +37 -0
  123. package/dist/components/ui/dot-matrix/dotm-circular-12.d.ts +4 -0
  124. package/dist/components/ui/dot-matrix/dotm-circular-12.js +42 -0
  125. package/dist/components/ui/dot-matrix/dotm-circular-14.d.ts +4 -0
  126. package/dist/components/ui/dot-matrix/dotm-circular-14.js +37 -0
  127. package/dist/components/ui/dot-matrix/dotm-circular-15.d.ts +4 -0
  128. package/dist/components/ui/dot-matrix/dotm-circular-15.js +49 -0
  129. package/dist/components/ui/dot-matrix/dotm-circular-17.d.ts +4 -0
  130. package/dist/components/ui/dot-matrix/dotm-circular-17.js +31 -0
  131. package/dist/components/ui/dot-matrix/dotm-circular-2.d.ts +4 -0
  132. package/dist/components/ui/dot-matrix/dotm-circular-2.js +37 -0
  133. package/dist/components/ui/dot-matrix/dotm-circular-3.d.ts +4 -0
  134. package/dist/components/ui/dot-matrix/dotm-circular-3.js +54 -0
  135. package/dist/components/ui/dot-matrix/dotm-circular-4.d.ts +4 -0
  136. package/dist/components/ui/dot-matrix/dotm-circular-4.js +35 -0
  137. package/dist/components/ui/dot-matrix/dotm-circular-5.d.ts +4 -0
  138. package/dist/components/ui/dot-matrix/dotm-circular-5.js +30 -0
  139. package/dist/components/ui/dot-matrix/dotm-circular-6.d.ts +4 -0
  140. package/dist/components/ui/dot-matrix/dotm-circular-6.js +37 -0
  141. package/dist/components/ui/dot-matrix/dotm-circular-7.d.ts +4 -0
  142. package/dist/components/ui/dot-matrix/dotm-circular-7.js +25 -0
  143. package/dist/components/ui/dot-matrix/dotm-circular-8.d.ts +4 -0
  144. package/dist/components/ui/dot-matrix/dotm-circular-8.js +26 -0
  145. package/dist/components/ui/dot-matrix/dotm-circular-9.d.ts +4 -0
  146. package/dist/components/ui/dot-matrix/dotm-circular-9.js +41 -0
  147. package/dist/components/ui/dot-matrix/dotm-square-1.d.ts +4 -0
  148. package/dist/components/ui/dot-matrix/dotm-square-1.js +27 -0
  149. package/dist/components/ui/dot-matrix/dotm-square-10.d.ts +4 -0
  150. package/dist/components/ui/dot-matrix/dotm-square-10.js +27 -0
  151. package/dist/components/ui/dot-matrix/dotm-square-11.d.ts +4 -0
  152. package/dist/components/ui/dot-matrix/dotm-square-11.js +25 -0
  153. package/dist/components/ui/dot-matrix/dotm-square-12.d.ts +4 -0
  154. package/dist/components/ui/dot-matrix/dotm-square-12.js +28 -0
  155. package/dist/components/ui/dot-matrix/dotm-square-13.d.ts +4 -0
  156. package/dist/components/ui/dot-matrix/dotm-square-13.js +45 -0
  157. package/dist/components/ui/dot-matrix/dotm-square-14.d.ts +4 -0
  158. package/dist/components/ui/dot-matrix/dotm-square-14.js +38 -0
  159. package/dist/components/ui/dot-matrix/dotm-square-15.d.ts +4 -0
  160. package/dist/components/ui/dot-matrix/dotm-square-15.js +31 -0
  161. package/dist/components/ui/dot-matrix/dotm-square-16.d.ts +4 -0
  162. package/dist/components/ui/dot-matrix/dotm-square-16.js +33 -0
  163. package/dist/components/ui/dot-matrix/dotm-square-17.d.ts +4 -0
  164. package/dist/components/ui/dot-matrix/dotm-square-17.js +27 -0
  165. package/dist/components/ui/dot-matrix/dotm-square-18.d.ts +4 -0
  166. package/dist/components/ui/dot-matrix/dotm-square-18.js +29 -0
  167. package/dist/components/ui/dot-matrix/dotm-square-19.d.ts +4 -0
  168. package/dist/components/ui/dot-matrix/dotm-square-19.js +74 -0
  169. package/dist/components/ui/dot-matrix/dotm-square-2.d.ts +4 -0
  170. package/dist/components/ui/dot-matrix/dotm-square-2.js +72 -0
  171. package/dist/components/ui/dot-matrix/dotm-square-20.d.ts +4 -0
  172. package/dist/components/ui/dot-matrix/dotm-square-20.js +79 -0
  173. package/dist/components/ui/dot-matrix/dotm-square-3.d.ts +4 -0
  174. package/dist/components/ui/dot-matrix/dotm-square-3.js +23 -0
  175. package/dist/components/ui/dot-matrix/dotm-square-4.d.ts +4 -0
  176. package/dist/components/ui/dot-matrix/dotm-square-4.js +41 -0
  177. package/dist/components/ui/dot-matrix/dotm-square-5.d.ts +4 -0
  178. package/dist/components/ui/dot-matrix/dotm-square-5.js +23 -0
  179. package/dist/components/ui/dot-matrix/dotm-square-6.d.ts +4 -0
  180. package/dist/components/ui/dot-matrix/dotm-square-6.js +20 -0
  181. package/dist/components/ui/dot-matrix/dotm-square-7.d.ts +4 -0
  182. package/dist/components/ui/dot-matrix/dotm-square-7.js +43 -0
  183. package/dist/components/ui/dot-matrix/dotm-square-8.d.ts +4 -0
  184. package/dist/components/ui/dot-matrix/dotm-square-8.js +57 -0
  185. package/dist/components/ui/dot-matrix/dotm-square-9.d.ts +4 -0
  186. package/dist/components/ui/dot-matrix/dotm-square-9.js +89 -0
  187. package/dist/components/ui/dot-matrix/session-dot-matrix.d.ts +46 -0
  188. package/dist/components/ui/dot-matrix/session-dot-matrix.js +153 -0
  189. package/dist/components/ui/drawer.d.ts +15 -0
  190. package/dist/components/ui/drawer.js +35 -0
  191. package/dist/components/ui/dropdown-menu.d.ts +49 -0
  192. package/dist/components/ui/dropdown-menu.js +113 -0
  193. package/dist/components/ui/emoji-picker.d.ts +15 -0
  194. package/dist/components/ui/emoji-picker.js +137 -0
  195. package/dist/components/ui/emoji-tint.d.ts +41 -0
  196. package/dist/components/ui/emoji-tint.js +131 -0
  197. package/dist/components/ui/empty.d.ts +11 -0
  198. package/dist/components/ui/empty.js +33 -0
  199. package/dist/components/ui/entity-avatar.d.ts +84 -0
  200. package/dist/components/ui/entity-avatar.js +106 -0
  201. package/dist/components/ui/faded-scroll-area.d.ts +8 -0
  202. package/dist/components/ui/faded-scroll-area.js +80 -0
  203. package/dist/components/ui/favicon-avatar.d.ts +32 -0
  204. package/dist/components/ui/favicon-avatar.js +18 -0
  205. package/dist/components/ui/field.d.ts +15 -0
  206. package/dist/components/ui/field.js +48 -0
  207. package/dist/components/ui/file-tree.d.ts +32 -0
  208. package/dist/components/ui/file-tree.js +30 -0
  209. package/dist/components/ui/glyph-face.d.ts +18 -0
  210. package/dist/components/ui/glyph-face.js +37 -0
  211. package/dist/components/ui/glyph-paths-source.d.ts +2 -0
  212. package/dist/components/ui/glyph-paths-source.js +40 -0
  213. package/dist/components/ui/glyph-paths.generated.d.ts +2 -0
  214. package/dist/components/ui/glyph-paths.generated.js +207 -0
  215. package/dist/components/ui/glyph-picker.d.ts +22 -0
  216. package/dist/components/ui/glyph-picker.js +118 -0
  217. package/dist/components/ui/glyph-registry.d.ts +36 -0
  218. package/dist/components/ui/glyph-registry.js +479 -0
  219. package/dist/components/ui/glyph-tint.d.ts +6 -0
  220. package/dist/components/ui/glyph-tint.js +93 -0
  221. package/dist/components/ui/hint.d.ts +14 -0
  222. package/dist/components/ui/hint.js +12 -0
  223. package/dist/components/ui/histogram-bars.d.ts +38 -0
  224. package/dist/components/ui/histogram-bars.js +93 -0
  225. package/dist/components/ui/hover-card.d.ts +28 -0
  226. package/dist/components/ui/hover-card.js +35 -0
  227. package/dist/components/ui/icon-provider.d.ts +23 -0
  228. package/dist/components/ui/icon-provider.js +30 -0
  229. package/dist/components/ui/info-banner.d.ts +14 -0
  230. package/dist/components/ui/info-banner.js +72 -0
  231. package/dist/components/ui/inline-meta.d.ts +6 -0
  232. package/dist/components/ui/inline-meta.js +8 -0
  233. package/dist/components/ui/input-group.d.ts +19 -0
  234. package/dist/components/ui/input-group.js +73 -0
  235. package/dist/components/ui/input.d.ts +26 -0
  236. package/dist/components/ui/input.js +23 -0
  237. package/dist/components/ui/item.d.ts +23 -0
  238. package/dist/components/ui/item.js +67 -0
  239. package/dist/components/ui/kbd.d.ts +3 -0
  240. package/dist/components/ui/kbd.js +20 -0
  241. package/dist/components/ui/kortix-asterisk.d.ts +6 -0
  242. package/dist/components/ui/kortix-asterisk.js +17 -0
  243. package/dist/components/ui/kortix-icons.d.ts +2 -0
  244. package/dist/components/ui/kortix-icons.js +17 -0
  245. package/dist/components/ui/kortix-loader.d.ts +76 -0
  246. package/dist/components/ui/kortix-loader.js +74 -0
  247. package/dist/components/ui/kortix-logo.d.ts +30 -0
  248. package/dist/components/ui/kortix-logo.js +47 -0
  249. package/dist/components/ui/label.d.ts +4 -0
  250. package/dist/components/ui/label.js +9 -0
  251. package/dist/components/ui/list.d.ts +15 -0
  252. package/dist/components/ui/list.js +25 -0
  253. package/dist/components/ui/loading.d.ts +19 -0
  254. package/dist/components/ui/loading.js +31 -0
  255. package/dist/components/ui/local-time.d.ts +34 -0
  256. package/dist/components/ui/local-time.js +60 -0
  257. package/dist/components/ui/map.d.ts +101 -0
  258. package/dist/components/ui/map.js +257 -0
  259. package/dist/components/ui/marker.d.ts +14 -0
  260. package/dist/components/ui/marker.js +28 -0
  261. package/dist/components/ui/menu-recipe.d.ts +102 -0
  262. package/dist/components/ui/menu-recipe.js +129 -0
  263. package/dist/components/ui/mermaid-render.d.ts +51 -0
  264. package/dist/components/ui/mermaid-render.js +65 -0
  265. package/dist/components/ui/mermaid-renderer.d.ts +13 -0
  266. package/dist/components/ui/mermaid-renderer.js +340 -0
  267. package/dist/components/ui/message.d.ts +15 -0
  268. package/dist/components/ui/message.js +26 -0
  269. package/dist/components/ui/modal.d.ts +104 -0
  270. package/dist/components/ui/modal.js +180 -0
  271. package/dist/components/ui/navigation-menu.d.ts +16 -0
  272. package/dist/components/ui/navigation-menu.js +35 -0
  273. package/dist/components/ui/page-search-bar.d.ts +11 -0
  274. package/dist/components/ui/page-search-bar.js +13 -0
  275. package/dist/components/ui/phone-input.d.ts +7 -0
  276. package/dist/components/ui/phone-input.js +59 -0
  277. package/dist/components/ui/pixel-kortix-mark.d.ts +13 -0
  278. package/dist/components/ui/pixel-kortix-mark.js +40 -0
  279. package/dist/components/ui/popover.d.ts +10 -0
  280. package/dist/components/ui/popover.js +38 -0
  281. package/dist/components/ui/portal.d.ts +5 -0
  282. package/dist/components/ui/portal.js +15 -0
  283. package/dist/components/ui/preview-image.d.ts +14 -0
  284. package/dist/components/ui/preview-image.js +58 -0
  285. package/dist/components/ui/progress-ring.d.ts +6 -0
  286. package/dist/components/ui/progress-ring.js +9 -0
  287. package/dist/components/ui/progress.d.ts +6 -0
  288. package/dist/components/ui/progress.js +8 -0
  289. package/dist/components/ui/radio-group.d.ts +12 -0
  290. package/dist/components/ui/radio-group.js +20 -0
  291. package/dist/components/ui/resizable.d.ts +24 -0
  292. package/dist/components/ui/resizable.js +16 -0
  293. package/dist/components/ui/scroll-area.d.ts +5 -0
  294. package/dist/components/ui/scroll-area.js +11 -0
  295. package/dist/components/ui/section-card.d.ts +37 -0
  296. package/dist/components/ui/section-card.js +14 -0
  297. package/dist/components/ui/section.d.ts +10 -0
  298. package/dist/components/ui/section.js +22 -0
  299. package/dist/components/ui/select.d.ts +25 -0
  300. package/dist/components/ui/select.js +59 -0
  301. package/dist/components/ui/separator.d.ts +4 -0
  302. package/dist/components/ui/separator.js +8 -0
  303. package/dist/components/ui/shader-safe.d.ts +48 -0
  304. package/dist/components/ui/shader-safe.js +74 -0
  305. package/dist/components/ui/sheet.d.ts +32 -0
  306. package/dist/components/ui/sheet.js +55 -0
  307. package/dist/components/ui/sidebar-context.d.ts +72 -0
  308. package/dist/components/ui/sidebar-context.js +36 -0
  309. package/dist/components/ui/sidebar-menu-primitives.d.ts +38 -0
  310. package/dist/components/ui/sidebar-menu-primitives.js +97 -0
  311. package/dist/components/ui/sidebar-panel.d.ts +36 -0
  312. package/dist/components/ui/sidebar-panel.js +265 -0
  313. package/dist/components/ui/sidebar-peek.d.ts +27 -0
  314. package/dist/components/ui/sidebar-peek.js +70 -0
  315. package/dist/components/ui/sidebar-width.d.ts +48 -0
  316. package/dist/components/ui/sidebar-width.js +62 -0
  317. package/dist/components/ui/sidebar.d.ts +18 -0
  318. package/dist/components/ui/sidebar.js +194 -0
  319. package/dist/components/ui/skeleton.d.ts +3 -0
  320. package/dist/components/ui/skeleton.js +6 -0
  321. package/dist/components/ui/slider-native.d.ts +7 -0
  322. package/dist/components/ui/slider-native.js +16 -0
  323. package/dist/components/ui/slider.d.ts +14 -0
  324. package/dist/components/ui/slider.js +48 -0
  325. package/dist/components/ui/sliding-tab-indicator.d.ts +61 -0
  326. package/dist/components/ui/sliding-tab-indicator.js +128 -0
  327. package/dist/components/ui/split-sheet.d.ts +61 -0
  328. package/dist/components/ui/split-sheet.js +239 -0
  329. package/dist/components/ui/spotlight-card.d.ts +8 -0
  330. package/dist/components/ui/spotlight-card.js +43 -0
  331. package/dist/components/ui/status-ring.d.ts +38 -0
  332. package/dist/components/ui/status-ring.js +38 -0
  333. package/dist/components/ui/status.d.ts +58 -0
  334. package/dist/components/ui/status.js +76 -0
  335. package/dist/components/ui/stepper.d.ts +28 -0
  336. package/dist/components/ui/stepper.js +73 -0
  337. package/dist/components/ui/switch.d.ts +8 -0
  338. package/dist/components/ui/switch.js +131 -0
  339. package/dist/components/ui/system-message.d.ts +23 -0
  340. package/dist/components/ui/system-message.js +51 -0
  341. package/dist/components/ui/table.d.ts +10 -0
  342. package/dist/components/ui/table.js +28 -0
  343. package/dist/components/ui/tabs.d.ts +73 -0
  344. package/dist/components/ui/tabs.js +207 -0
  345. package/dist/components/ui/tag.d.ts +7 -0
  346. package/dist/components/ui/tag.js +22 -0
  347. package/dist/components/ui/text-shimmer.d.ts +13 -0
  348. package/dist/components/ui/text-shimmer.js +91 -0
  349. package/dist/components/ui/textarea.d.ts +33 -0
  350. package/dist/components/ui/textarea.js +87 -0
  351. package/dist/components/ui/toast.d.ts +105 -0
  352. package/dist/components/ui/toast.js +233 -0
  353. package/dist/components/ui/toggle.d.ts +12 -0
  354. package/dist/components/ui/toggle.js +26 -0
  355. package/dist/components/ui/tooltip.d.ts +9 -0
  356. package/dist/components/ui/tooltip.js +16 -0
  357. package/dist/components/ui/trigger-variants.d.ts +14 -0
  358. package/dist/components/ui/trigger-variants.js +67 -0
  359. package/dist/components/ui/type-to-confirm-dialog.d.ts +88 -0
  360. package/dist/components/ui/type-to-confirm-dialog.js +101 -0
  361. package/dist/components/ui/typed-title-logic.d.ts +22 -0
  362. package/dist/components/ui/typed-title-logic.js +33 -0
  363. package/dist/components/ui/typed-title.d.ts +38 -0
  364. package/dist/components/ui/typed-title.js +66 -0
  365. package/dist/components/ui/typing-animation.d.ts +36 -0
  366. package/dist/components/ui/typing-animation.js +141 -0
  367. package/dist/components/ui/user-avatar.d.ts +47 -0
  368. package/dist/components/ui/user-avatar.js +46 -0
  369. package/dist/hooks/use-debounce.d.ts +4 -0
  370. package/dist/hooks/use-debounce.js +17 -0
  371. package/dist/hooks/use-is-dark.d.ts +2 -0
  372. package/dist/hooks/use-is-dark.js +27 -0
  373. package/dist/hooks/use-mobile.d.ts +2 -0
  374. package/dist/hooks/use-mobile.js +15 -0
  375. package/dist/hooks/use-proximity-hover.d.ts +52 -0
  376. package/dist/hooks/use-proximity-hover.js +232 -0
  377. package/dist/icons/close.d.ts +2 -0
  378. package/dist/icons/close.js +7 -0
  379. package/dist/icons/copy.d.ts +3 -0
  380. package/dist/icons/copy.js +6 -0
  381. package/dist/icons/sidebar-toggle.d.ts +13 -0
  382. package/dist/icons/sidebar-toggle.js +13 -0
  383. package/dist/index.d.ts +24 -0
  384. package/dist/index.js +33 -0
  385. package/dist/lib/dotmatrix-core.d.ts +113 -0
  386. package/dist/lib/dotmatrix-core.js +920 -0
  387. package/dist/lib/dotmatrix-hooks.d.ts +28 -0
  388. package/dist/lib/dotmatrix-hooks.js +151 -0
  389. package/dist/lib/favicon.d.ts +4 -0
  390. package/dist/lib/favicon.js +21 -0
  391. package/dist/lib/font-weight.d.ts +6 -0
  392. package/dist/lib/font-weight.js +6 -0
  393. package/dist/lib/icon-config.d.ts +33 -0
  394. package/dist/lib/icon-config.js +22 -0
  395. package/dist/lib/icon-context.d.ts +34 -0
  396. package/dist/lib/icon-context.js +81 -0
  397. package/dist/lib/portal-root.d.ts +8 -0
  398. package/dist/lib/portal-root.js +26 -0
  399. package/dist/lib/settle.d.ts +16 -0
  400. package/dist/lib/settle.js +29 -0
  401. package/dist/lib/springs.d.ts +31 -0
  402. package/dist/lib/springs.js +29 -0
  403. package/dist/lib/utils.d.ts +2 -0
  404. package/dist/lib/utils.js +5 -0
  405. package/dist/lib/z-stack.d.ts +55 -0
  406. package/dist/lib/z-stack.js +130 -0
  407. package/dist/providers/ui-provider.d.ts +141 -0
  408. package/dist/providers/ui-provider.js +93 -0
  409. package/dist/styles/dotmatrix-loader.css +1239 -0
  410. package/dist/styles/fonts.css +46 -0
  411. package/dist/styles/tailwind.css +10 -0
  412. package/dist/styles/theme.css +1019 -0
  413. package/dist/styles/tokens.css +146 -0
  414. package/dist/styles.css +2 -0
  415. package/package.json +881 -4
  416. package/skills/kortix-ui/SKILL.md +150 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @kortix/ui/chat — the Kortix chat for `@kortix/sdk` sessions.
3
+ *
4
+ * const session = useSession(projectId, sessionId);
5
+ * return <SessionThread session={session} />;
6
+ *
7
+ * Every piece is exported, so a host can compose its own layout from
8
+ * MessageList, MessageView, Composer and the prompts.
9
+ */
10
+ export { AgentPicker } from './agent-picker.js';
11
+ export { Composer, type ComposerCommand, parseCommand, slashQuery } from './composer.js';
12
+ export { Markdown } from './markdown.js';
13
+ export { DefaultEmptyState, MessageList } from './message-list.js';
14
+ export { type MessageRenderers, MessageView, type RenderTool } from './message-view.js';
15
+ export { filterModels, ModelPicker } from './model-picker.js';
16
+ export { type ChatErrorHandler, type PermissionDecision, PermissionPrompt } from './permission-prompt.js';
17
+ export { QuestionPrompt } from './question-prompt.js';
18
+ export { sendFailureTitle } from './send-failure.js';
19
+ export { SessionPickers, SessionThread, type SessionThreadProps } from './session-thread.js';
20
+ export { closeUnterminatedCodeFence, holdBackFenceOpener, holdBackTableHeader, streamingMarkdown, } from './streaming-markdown.js';
21
+ export { ToolCall } from './tool-call.js';
22
+ export { userMessageParts } from './user-message-parts.js';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @kortix/ui/chat — the Kortix chat for `@kortix/sdk` sessions.
3
+ *
4
+ * const session = useSession(projectId, sessionId);
5
+ * return <SessionThread session={session} />;
6
+ *
7
+ * Every piece is exported, so a host can compose its own layout from
8
+ * MessageList, MessageView, Composer and the prompts.
9
+ */
10
+ export { AgentPicker } from './agent-picker.js';
11
+ export { Composer, parseCommand, slashQuery } from './composer.js';
12
+ export { Markdown } from './markdown.js';
13
+ export { DefaultEmptyState, MessageList } from './message-list.js';
14
+ export { MessageView } from './message-view.js';
15
+ export { filterModels, ModelPicker } from './model-picker.js';
16
+ export { PermissionPrompt } from './permission-prompt.js';
17
+ export { QuestionPrompt } from './question-prompt.js';
18
+ export { sendFailureTitle } from './send-failure.js';
19
+ export { SessionPickers, SessionThread } from './session-thread.js';
20
+ export { closeUnterminatedCodeFence, holdBackFenceOpener, holdBackTableHeader, streamingMarkdown, } from './streaming-markdown.js';
21
+ export { ToolCall } from './tool-call.js';
22
+ export { userMessageParts } from './user-message-parts.js';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Assistant markdown (GitHub-flavored), styled by the Kortix tokens.
3
+ * `streaming` holds back a half-written table header or fence opener and
4
+ * closes an open code fence, so a turn in progress never flashes raw syntax.
5
+ */
6
+ export declare const Markdown: import("react").NamedExoticComponent<{
7
+ children: string;
8
+ className?: string;
9
+ streaming?: boolean;
10
+ }>;
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { memo, useMemo } from 'react';
4
+ import ReactMarkdown from 'react-markdown';
5
+ import remarkGfm from 'remark-gfm';
6
+ import { cn } from '../lib/utils.js';
7
+ import { streamingMarkdown } from './streaming-markdown.js';
8
+ const COMPONENTS = {
9
+ p: ({ children }) => _jsx("p", { className: "my-2 first:mt-0 last:mb-0", children: children }),
10
+ h1: ({ children }) => _jsx("h1", { className: "mt-4 mb-2 text-base font-semibold first:mt-0", children: children }),
11
+ h2: ({ children }) => _jsx("h2", { className: "mt-4 mb-2 text-sm font-semibold first:mt-0", children: children }),
12
+ h3: ({ children }) => _jsx("h3", { className: "mt-3 mb-1.5 text-sm font-semibold first:mt-0", children: children }),
13
+ ul: ({ children }) => (_jsx("ul", { className: "marker:text-muted-foreground my-2 ml-4 list-disc space-y-1", children: children })),
14
+ ol: ({ children }) => (_jsx("ol", { className: "marker:text-muted-foreground my-2 ml-4 list-decimal space-y-1", children: children })),
15
+ li: ({ children }) => _jsx("li", { className: "pl-1", children: children }),
16
+ a: ({ children, href }) => (_jsx("a", { href: href, target: "_blank", rel: "noreferrer noopener", className: "text-foreground underline underline-offset-2 hover:no-underline", children: children })),
17
+ strong: ({ children }) => _jsx("strong", { className: "font-semibold", children: children }),
18
+ blockquote: ({ children }) => (_jsx("blockquote", { className: "border-border text-muted-foreground my-2 border-l-2 pl-3", children: children })),
19
+ hr: () => _jsx("hr", { className: "border-border my-3" }),
20
+ code: ({ className, children }) => String(className ?? '').includes('language-') ? (_jsx("code", { className: "font-mono text-xs", children: children })) : (_jsx("code", { className: "bg-muted rounded-sm px-1.5 py-0.5 font-mono text-xs", children: children })),
21
+ pre: ({ children }) => (_jsx("pre", { className: "border-border bg-muted scrollbar-thin my-2 overflow-x-auto rounded-md border p-3 font-mono text-xs leading-relaxed", children: children })),
22
+ table: ({ children }) => (_jsx("div", { className: "my-2 overflow-x-auto", children: _jsx("table", { className: "w-full border-collapse text-xs", children: children }) })),
23
+ th: ({ children }) => _jsx("th", { className: "border-border border px-2 py-1 text-left font-medium", children: children }),
24
+ td: ({ children }) => _jsx("td", { className: "border-border border px-2 py-1", children: children }),
25
+ };
26
+ /**
27
+ * Assistant markdown (GitHub-flavored), styled by the Kortix tokens.
28
+ * `streaming` holds back a half-written table header or fence opener and
29
+ * closes an open code fence, so a turn in progress never flashes raw syntax.
30
+ */
31
+ export const Markdown = memo(function Markdown({ children, className, streaming = false, }) {
32
+ const text = useMemo(() => (streaming ? streamingMarkdown(children) : children), [children, streaming]);
33
+ if (!text)
34
+ return null;
35
+ return (_jsx("div", { "data-slot": "markdown", className: cn('text-foreground text-sm leading-relaxed', className), children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: COMPONENTS, children: text }) }));
36
+ });
@@ -0,0 +1,25 @@
1
+ import { type SessionLogThread } from '@kortix/sdk';
2
+ import { type UseSessionResult } from '@kortix/sdk/react';
3
+ import { type ReactNode } from 'react';
4
+ import { type MessageRenderers, type RenderTool } from './message-view.js';
5
+ import { type ChatErrorHandler } from './permission-prompt.js';
6
+ /** How the transcript treats each message of an auto-recovery chain, from the SDK turn model. */
7
+ export interface AutoRecovery {
8
+ /** User messages that are the harness's own continuation prompt: no bubble. */
9
+ hidden: ReadonlySet<string>;
10
+ /** Assistant messages whose failure the harness continued: no error row. */
11
+ quiet: ReadonlySet<string>;
12
+ /** The last assistant message of a chain that ended in failure → retries before it. */
13
+ retries: ReadonlyMap<string, number>;
14
+ }
15
+ export declare function autoRecoveryOf(thread: SessionLogThread | null | undefined): AutoRecovery;
16
+ export declare function DefaultEmptyState(): import("react").JSX.Element;
17
+ export declare function MessageList({ session: c, emptyState, renderTool, renderers, onError, className, }: {
18
+ session: UseSessionResult;
19
+ /** Shown when the thread has no messages. Defaults to a one-line hint. */
20
+ emptyState?: ReactNode;
21
+ renderTool?: RenderTool;
22
+ renderers?: MessageRenderers;
23
+ onError?: ChatErrorHandler;
24
+ className?: string;
25
+ }): import("react").JSX.Element;
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * The scrolling transcript of one session: the session log's root thread
5
+ * (`useSessionLogThread`), the optimistic bubble while a send is in flight,
6
+ * open permission and question prompts, and the busy marker. It follows new
7
+ * content while the reader is at the bottom and stays put once they scroll up.
8
+ *
9
+ * Automatic provider-error recovery (KRTX-2597) renders as apps/web renders it:
10
+ * the harness's own `[auto-recovery]` prompt (a synthetic-only user message,
11
+ * `turn.internal`) shows no bubble, a failure the harness continued shows no
12
+ * error row, and the chain's last error row says how many retries ran.
13
+ */
14
+ import { SparkleIcon } from '@phosphor-icons/react';
15
+ import { sessionLogTurns } from '@kortix/sdk';
16
+ import { useSessionLogThread } from '@kortix/sdk/react';
17
+ import { useEffect, useMemo, useRef } from 'react';
18
+ import { Bubble, BubbleContent } from '../components/ui/bubble.js';
19
+ import Loading from '../components/ui/loading.js';
20
+ import { Marker, MarkerContent, MarkerIcon } from '../components/ui/marker.js';
21
+ import { Message } from '../components/ui/message.js';
22
+ import { TextShimmer } from '../components/ui/text-shimmer.js';
23
+ import { cn } from '../lib/utils.js';
24
+ import { useUiStrings } from '../providers/ui-provider.js';
25
+ import { MessageView } from './message-view.js';
26
+ import { PermissionPrompt } from './permission-prompt.js';
27
+ import { QuestionPrompt } from './question-prompt.js';
28
+ /** One array for a thread with no messages, so the scroll effect does not run on every render. */
29
+ const NO_MESSAGES = [];
30
+ /** Distance from the bottom, in px, that still counts as "at the bottom". */
31
+ const STICK_PX = 80;
32
+ const NO_RECOVERY = { hidden: new Set(), quiet: new Set(), retries: new Map() };
33
+ export function autoRecoveryOf(thread) {
34
+ if (!thread?.messages.length)
35
+ return NO_RECOVERY;
36
+ const hidden = new Set();
37
+ const quiet = new Set();
38
+ const retries = new Map();
39
+ for (const turn of sessionLogTurns(thread)) {
40
+ if (turn.internal)
41
+ hidden.add(turn.user.message_id);
42
+ if (!turn.autoRetry)
43
+ continue;
44
+ if (turn.autoRetry.continued)
45
+ for (const a of turn.assistant)
46
+ quiet.add(a.message_id);
47
+ const last = turn.assistant.at(-1);
48
+ if (!turn.autoRetry.continued && turn.autoRetry.retries > 0 && last)
49
+ retries.set(last.message_id, turn.autoRetry.retries);
50
+ }
51
+ return hidden.size || quiet.size || retries.size ? { hidden, quiet, retries } : NO_RECOVERY;
52
+ }
53
+ export function DefaultEmptyState() {
54
+ const t = useUiStrings().chat;
55
+ return (_jsxs("div", { className: "grid place-items-center py-16 text-center", children: [_jsx(SparkleIcon, { className: "text-muted-foreground size-6" }), _jsx("p", { className: "text-muted-foreground mt-3 text-sm", children: t.emptyState })] }));
56
+ }
57
+ export function MessageList({ session: c, emptyState, renderTool, renderers, onError, className, }) {
58
+ const scrollRef = useRef(null);
59
+ const stickRef = useRef(true);
60
+ const t = useUiStrings().chat;
61
+ const thread = useSessionLogThread(c);
62
+ const messages = thread?.messages ?? NO_MESSAGES;
63
+ const recovery = useMemo(() => autoRecoveryOf(thread), [thread]);
64
+ useEffect(() => {
65
+ const el = scrollRef.current;
66
+ if (el && stickRef.current)
67
+ el.scrollTo({ top: el.scrollHeight });
68
+ }, [messages, c.isBusy, c.hasPending, c.pending]);
69
+ return (_jsx("div", { ref: scrollRef, "data-slot": "message-list", onScroll: (e) => {
70
+ const el = e.currentTarget;
71
+ stickRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < STICK_PX;
72
+ }, className: cn('scrollbar-thin min-h-0 flex-1 overflow-y-auto', className), children: _jsxs("div", { className: "mx-auto max-w-3xl space-y-4 px-5 py-6", children: [c.isLoading && (_jsxs("div", { className: "text-muted-foreground flex items-center gap-2.5 py-10 text-sm", children: [_jsx(Loading, { className: "text-muted-foreground size-4" }), " ", t.loadingConversation] })), !c.isLoading && messages.length === 0 && !c.hasPending && !c.pending && (emptyState ?? _jsx(DefaultEmptyState, {})), messages.map((m) => recovery.hidden.has(m.message_id) ? null : (_jsx(MessageView, { message: m, renderTool: renderTool, renderers: renderers, hideError: recovery.quiet.has(m.message_id), autoRetries: recovery.retries.get(m.message_id) }, m.message_id))), c.pending && (_jsx(Message, { align: "end", "data-message-role": "pending", children: _jsx(Bubble, { align: "end", className: "opacity-70", children: _jsx(BubbleContent, { children: c.pending }) }) })), c.permissions.map((p) => (_jsx(PermissionPrompt, { request: p, onAnswer: c.answerPermission, onError: onError }, p.id))), c.questions.map((q) => (_jsx(QuestionPrompt, { request: q, onAnswer: c.answerQuestion, onCancel: c.cancel, onError: onError }, q.id))), c.isBusy && !c.hasPending && (_jsxs(Marker, { "data-slot": "busy-marker", className: "py-1", children: [_jsx(MarkerIcon, { children: _jsx(Loading, { variant: "ring", className: "text-muted-foreground" }) }), _jsx(MarkerContent, { children: _jsx(TextShimmer, { className: "text-sm", children: c.pending ? t.sending : t.agentWorking }) })] }))] }) }));
73
+ }
@@ -0,0 +1,17 @@
1
+ import { type SessionLogMessage, type ToolView } from '@kortix/sdk';
2
+ import { type PartRenderers } from '@kortix/sdk/react';
3
+ import { type ReactNode } from 'react';
4
+ /** Replaces the default card for one tool call. Return `undefined` to keep the default. */
5
+ export type RenderTool = (tool: ToolView) => ReactNode | undefined;
6
+ export type MessageRenderers = Partial<PartRenderers<ReactNode>>;
7
+ export declare function MessageView({ message, renderers, renderTool, hideError, autoRetries, }: {
8
+ message: SessionLogMessage;
9
+ /** Overrides the default renderer of any part kind. */
10
+ renderers?: MessageRenderers;
11
+ /** Overrides the tool card only; `undefined` keeps the default `ToolCall`. */
12
+ renderTool?: RenderTool;
13
+ /** Drops the error row: the harness continued this failure automatically. */
14
+ hideError?: boolean;
15
+ /** Automatic retries that ran before this failure; adds a note under the error row. */
16
+ autoRetries?: number;
17
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,86 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * One message of the session log (`kortix.session/2`). The user turn is an
5
+ * end-aligned `Bubble`; the assistant turn (and a compaction) renders full
6
+ * width as ordered content blocks.
7
+ *
8
+ * `classifySessionLogMessage` (`@kortix/sdk`) types every block as a
9
+ * `ClassifiedPart`, and `renderParts` (`@kortix/sdk/react`) requires a
10
+ * renderer for every kind at compile time: a new part type fails the build
11
+ * here instead of vanishing from the transcript. A host overrides any kind
12
+ * through `renderers`, or only the tool card through `renderTool`.
13
+ */
14
+ import { ArrowsClockwiseIcon, BrainIcon, CaretRightIcon, GitDiffIcon, PaperclipIcon, RobotIcon, ScissorsIcon, WarningCircleIcon, } from '@phosphor-icons/react';
15
+ import { classifySessionLogMessage } from '@kortix/sdk';
16
+ import { renderParts } from '@kortix/sdk/react';
17
+ import { Fragment } from 'react';
18
+ import { Bubble, BubbleContent } from '../components/ui/bubble.js';
19
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../components/ui/collapsible.js';
20
+ import { Marker, MarkerContent, MarkerIcon } from '../components/ui/marker.js';
21
+ import { Message } from '../components/ui/message.js';
22
+ import { useUiStrings } from '../providers/ui-provider.js';
23
+ import { Markdown } from './markdown.js';
24
+ import { ToolCall } from './tool-call.js';
25
+ import { userMessageParts } from './user-message-parts.js';
26
+ function Reasoning({ text }) {
27
+ const t = useUiStrings().chat;
28
+ return (_jsxs(Collapsible, { children: [_jsxs(CollapsibleTrigger, { className: "group text-muted-foreground hover:text-foreground flex items-center gap-1.5 text-xs transition-colors motion-reduce:transition-none", children: [_jsx(BrainIcon, { className: "size-3.5" }), _jsx("span", { children: t.thoughtProcess }), _jsx(CaretRightIcon, { className: "size-3 transition-transform group-data-[state=open]:rotate-90 motion-reduce:transition-none" })] }), _jsx(CollapsibleContent, { children: _jsx("p", { className: "border-border text-muted-foreground mt-1.5 border-l-2 pl-3 text-xs leading-relaxed whitespace-pre-wrap", children: text }) })] }));
29
+ }
30
+ function Note({ icon, children, tone = 'foreground' }) {
31
+ return (_jsxs(Marker, { className: tone === 'muted' ? 'w-fit' : 'text-foreground w-fit', children: [_jsx(MarkerIcon, { children: icon }), _jsx(MarkerContent, { children: children })] }));
32
+ }
33
+ /** One renderer per `ClassifiedPart['kind']`; the type requires every key. */
34
+ function defaultRenderers(t, streaming, renderTool) {
35
+ return {
36
+ text: (part) => (part.text.trim() ? _jsx(Markdown, { streaming: streaming, children: part.text }) : null),
37
+ reasoning: (part) => (part.text.trim() ? _jsx(Reasoning, { text: part.text }) : null),
38
+ tool: (part) => renderTool?.(part.tool) ?? _jsx(ToolCall, { tool: part.tool }),
39
+ file: (part) => _jsx(Note, { icon: _jsx(PaperclipIcon, {}), children: part.filename ?? part.url }),
40
+ // A sub-agent delegation; it stands alone, with no tool-state machine.
41
+ subtask: (part) => (_jsx(Note, { icon: _jsx(RobotIcon, {}), children: part.description ? `${part.description} (${part.agent})` : t.delegatedTo(part.agent) })),
42
+ // A diff-stat line. The full diff belongs in a changes panel, not the transcript.
43
+ patch: (part) => (_jsx(Note, { icon: _jsx(GitDiffIcon, {}), children: t.filesChanged(part.fileCount) })),
44
+ // An internal git checkpoint for revert: never user-facing.
45
+ snapshot: () => null,
46
+ // An inline `@agent` token: its text is already in the sibling text part.
47
+ agent: () => null,
48
+ // A model-call retry after a transient failure, so a stalled turn does not read as broken.
49
+ retry: (part) => (_jsx(Note, { tone: "muted", icon: _jsx(ArrowsClockwiseIcon, {}), children: t.retrying(part.attempt, part.message) })),
50
+ compaction: (part) => (_jsx(Note, { tone: "muted", icon: _jsx(ScissorsIcon, {}), children: part.auto ? t.contextCompactedAuto : t.contextCompacted })),
51
+ // Step bookkeeping (cost and tokens) has no chat-visible content.
52
+ step: () => null,
53
+ // A part type this build does not know yet (client older than server).
54
+ unknown: () => null,
55
+ };
56
+ }
57
+ /**
58
+ * A failed assistant turn: the runtime attaches a typed `error` and often
59
+ * zero parts. Without this the turn renders as silence.
60
+ */
61
+ function TurnError({ error, autoRetries }) {
62
+ const t = useUiStrings().chat;
63
+ return (_jsxs("div", { children: [_jsxs(Marker, { className: "text-foreground w-fit", role: "alert", children: [_jsx(MarkerIcon, { children: _jsx(WarningCircleIcon, { weight: "fill", className: "text-destructive" }) }), _jsx(MarkerContent, { className: "whitespace-normal", children: error.message || error.name })] }), autoRetries ? (_jsx("p", { className: "text-muted-foreground mt-1 text-xs", "data-auto-retry-note": true, children: t.autoRetried(autoRetries) })) : null] }));
64
+ }
65
+ export function MessageView({ message, renderers, renderTool, hideError, autoRetries, }) {
66
+ const t = useUiStrings().chat;
67
+ // A streaming message holds back half-written markdown syntax.
68
+ const streaming = message.status === 'streaming';
69
+ const all = { ...defaultRenderers(t, streaming, renderTool), ...renderers };
70
+ const { parts, error, isEmpty } = classifySessionLogMessage(message);
71
+ const keyOf = (part, i) => (part.kind === 'unknown' ? i : part.id);
72
+ if (message.role === 'user' && message.kind !== 'compaction') {
73
+ const user = userMessageParts(parts);
74
+ if (!user.text && !user.parts.length)
75
+ return null;
76
+ return (_jsx(Message, { align: "end", "data-message-role": "user", children: _jsxs(Bubble, { align: "end", children: [user.text ? _jsx(BubbleContent, { children: user.text }) : null, renderParts(user.parts, all).map((node, i) => (_jsx(Fragment, { children: node }, keyOf(user.parts[i], i))))] }) }));
77
+ }
78
+ if (isEmpty)
79
+ return null;
80
+ const shownError = hideError ? null : error;
81
+ const nodes = renderParts(parts, all);
82
+ // A continued failure with no content of its own leaves nothing to show.
83
+ if (!shownError && nodes.every((node) => node == null))
84
+ return null;
85
+ return (_jsxs("div", { "data-message-role": "assistant", className: "space-y-2.5 text-sm leading-relaxed", children: [nodes.map((node, i) => (_jsx(Fragment, { children: node }, keyOf(parts[i], i)))), shownError ? _jsx(TurnError, { error: shownError, autoRetries: autoRetries }) : null] }));
86
+ }
@@ -0,0 +1,10 @@
1
+ import type { FlatModel, ModelKey } from '@kortix/sdk/react';
2
+ /** Case-insensitive match on model and provider name; at most 60 rows. */
3
+ export declare function filterModels(models: readonly FlatModel[], query: string): FlatModel[];
4
+ export declare function ModelPicker({ models, value, onChange, providerLabel, }: {
5
+ models: readonly FlatModel[];
6
+ value: ModelKey | null;
7
+ onChange: (value: ModelKey | null) => void;
8
+ /** The provider line of a model row. Default: the server's `providerName`. */
9
+ providerLabel?: (model: FlatModel) => string;
10
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Model picker: a controlled, searchable list over `session.models`.
5
+ * `value` / `onChange` are a plain `{ providerID, modelID }` key, so the same
6
+ * picker drives a new-session form and the per-message pick. In the search
7
+ * field, ArrowUp / ArrowDown move the highlight and Enter picks it, as in the
8
+ * composer's command menu. `providerLabel` relabels a provider (a white-label
9
+ * host shows its own name for the `kortix` provider).
10
+ */
11
+ import { CaretUpDownIcon, CheckIcon, CpuIcon } from '@phosphor-icons/react';
12
+ import { useEffect, useId, useMemo, useState } from 'react';
13
+ import { Input } from '../components/ui/input.js';
14
+ import { MENU_INDICATOR, MENU_INDICATOR_ICON, menuRow } from '../components/ui/menu-recipe.js';
15
+ import { Popover, PopoverContent, PopoverTrigger } from '../components/ui/popover.js';
16
+ import { useUiStrings } from '../providers/ui-provider.js';
17
+ const TRIGGER = 'text-muted-foreground hover:text-foreground h-7 max-w-44 min-w-0 gap-1 px-2 text-xs';
18
+ /** Case-insensitive match on model and provider name; at most 60 rows. */
19
+ export function filterModels(models, query) {
20
+ const q = query.trim().toLowerCase();
21
+ const base = q ? models.filter((m) => `${m.modelName} ${m.providerName}`.toLowerCase().includes(q)) : models;
22
+ return base.slice(0, 60);
23
+ }
24
+ export function ModelPicker({ models, value, onChange, providerLabel, }) {
25
+ const t = useUiStrings().chat;
26
+ const [open, setOpen] = useState(false);
27
+ const [query, setQuery] = useState('');
28
+ const [highlight, setHighlight] = useState(0);
29
+ const listId = useId();
30
+ const filtered = useMemo(() => filterModels(models, query), [models, query]);
31
+ // Keep the keyboard highlight in view in a long list.
32
+ useEffect(() => {
33
+ if (open)
34
+ document.getElementById(`${listId}-${highlight}`)?.scrollIntoView?.({ block: 'nearest' });
35
+ }, [open, highlight, listId]);
36
+ if (models.length === 0)
37
+ return null;
38
+ const current = value && models.find((m) => m.providerID === value.providerID && m.modelID === value.modelID);
39
+ const pick = (m) => {
40
+ onChange({ providerID: m.providerID, modelID: m.modelID });
41
+ setOpen(false);
42
+ setQuery('');
43
+ };
44
+ return (_jsxs(Popover, { open: open, onOpenChange: (next) => {
45
+ setOpen(next);
46
+ if (!next)
47
+ setQuery('');
48
+ setHighlight(0);
49
+ }, children: [_jsxs(PopoverTrigger, { variant: "transparent", className: TRIGGER, "aria-label": t.model, children: [_jsx(CpuIcon, { className: "size-3.5 shrink-0" }), _jsx("span", { className: "truncate", children: current?.modelName ?? t.defaultModel }), _jsx(CaretUpDownIcon, { className: "size-3 shrink-0" })] }), _jsxs(PopoverContent, { align: "start", className: "w-72 p-0", children: [_jsx("div", { className: "border-border border-b p-2", children: _jsx(Input, { autoFocus: true, size: "xs", value: query, onChange: (e) => {
50
+ setQuery(e.target.value);
51
+ setHighlight(0);
52
+ }, onKeyDown: (e) => {
53
+ if (e.nativeEvent.isComposing || filtered.length === 0)
54
+ return;
55
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
56
+ e.preventDefault();
57
+ const step = e.key === 'ArrowDown' ? 1 : -1;
58
+ setHighlight((h) => Math.min(Math.max(h + step, 0), filtered.length - 1));
59
+ }
60
+ else if (e.key === 'Enter') {
61
+ e.preventDefault();
62
+ pick(filtered[highlight] ?? filtered[0]);
63
+ }
64
+ }, placeholder: t.searchModels, "aria-label": t.searchModels, role: "combobox", "aria-expanded": true, "aria-controls": listId, "aria-activedescendant": filtered[highlight] ? `${listId}-${highlight}` : undefined }) }), _jsxs("div", { id: listId, role: "listbox", "aria-label": t.models, className: "scrollbar-thin max-h-72 overflow-y-auto p-1", children: [filtered.map((m, i) => {
65
+ const selected = value?.providerID === m.providerID && value?.modelID === m.modelID;
66
+ return (_jsxs("button", { id: `${listId}-${i}`, type: "button", role: "option", "aria-selected": selected, "data-highlighted": i === highlight ? '' : undefined, onMouseEnter: () => setHighlight(i), onClick: () => pick(m), className: menuRow('sm', 'default', 'text-left'), children: [_jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate", children: m.modelName }), _jsx("span", { className: "text-muted-foreground block truncate text-xs", children: providerLabel?.(m) ?? m.providerName })] }), _jsx("span", { className: MENU_INDICATOR, children: selected && _jsx(CheckIcon, { className: MENU_INDICATOR_ICON }) })] }, `${m.providerID}/${m.modelID}`));
67
+ }), filtered.length === 0 && (_jsx("div", { className: "text-muted-foreground px-2 py-3 text-center text-xs", children: t.noModelsMatch }))] })] })] }));
68
+ }
@@ -0,0 +1,10 @@
1
+ import type { PermissionRequest } from '@kortix/sdk';
2
+ export type PermissionDecision = 'once' | 'always' | 'reject';
3
+ /** Reports a failed reply. Without it the prompt shows the message inline. */
4
+ export type ChatErrorHandler = (message: string, error: unknown) => void;
5
+ export declare function errorMessage(error: unknown, fallback: string): string;
6
+ export declare function PermissionPrompt({ request, onAnswer, onError, }: {
7
+ request: PermissionRequest;
8
+ onAnswer: (requestId: string, decision: PermissionDecision) => Promise<void>;
9
+ onError?: ChatErrorHandler;
10
+ }): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * A pending PERMISSION request ("run this command?") and its decision.
5
+ * `onAnswer` is `session.answerPermission`: it drops the request only once the
6
+ * server accepted the decision, and throws a typed `KortixSendError`
7
+ * otherwise, so a failed reply stays visible for a retry.
8
+ */
9
+ import { ShieldWarningIcon } from '@phosphor-icons/react';
10
+ import { useState } from 'react';
11
+ import { Button } from '../components/ui/button.js';
12
+ import { useUiStrings } from '../providers/ui-provider.js';
13
+ export function errorMessage(error, fallback) {
14
+ const message = error?.message;
15
+ return typeof message === 'string' && message ? message : fallback;
16
+ }
17
+ export function PermissionPrompt({ request, onAnswer, onError, }) {
18
+ const t = useUiStrings().chat;
19
+ const [sending, setSending] = useState(false);
20
+ const [error, setError] = useState(null);
21
+ const label = String(request.permission ?? t.thisAction).replace(/[._-]/g, ' ');
22
+ async function reply(decision) {
23
+ if (sending)
24
+ return;
25
+ setSending(true);
26
+ setError(null);
27
+ try {
28
+ await onAnswer(request.id, decision);
29
+ }
30
+ catch (err) {
31
+ const message = errorMessage(err, t.decisionFailed);
32
+ if (onError)
33
+ onError(message, err);
34
+ else
35
+ setError(message);
36
+ setSending(false);
37
+ }
38
+ }
39
+ return (_jsxs("div", { "data-slot": "permission-prompt", className: "bg-kortix-orange/15 overflow-hidden rounded-md", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2.5", children: [_jsx(ShieldWarningIcon, { weight: "fill", className: "text-kortix-orange size-4 shrink-0" }), _jsxs("span", { className: "text-foreground flex-1 text-sm", children: [t.allowPrefix, " ", _jsx("span", { className: "font-medium", children: label }), t.allowSuffix] })] }), error && (_jsx("p", { role: "alert", className: "text-foreground px-3 pb-2 text-xs", children: error })), _jsxs("div", { className: "flex items-center justify-end gap-2 px-3 pb-2.5", children: [_jsx(Button, { size: "sm", variant: "ghost", disabled: sending, onClick: () => reply('reject'), children: t.deny }), _jsx(Button, { size: "sm", variant: "outline", disabled: sending, onClick: () => reply('always'), children: t.always }), _jsx(Button, { size: "sm", disabled: sending, onClick: () => reply('once'), children: t.allowOnce })] })] }));
40
+ }
@@ -0,0 +1,8 @@
1
+ import type { QuestionRequest } from '@kortix/sdk';
2
+ import { type ChatErrorHandler } from './permission-prompt.js';
3
+ export declare function QuestionPrompt({ request, onAnswer, onCancel, onError, }: {
4
+ request: QuestionRequest;
5
+ onAnswer: (requestId: string, answers: string[][]) => Promise<void>;
6
+ onCancel: () => void;
7
+ onError?: ChatErrorHandler;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * A pending agent QUESTION (one or several) and its answer. Without it a
5
+ * session that asks a clarifying question blocks forever. `onAnswer` is
6
+ * `session.answerQuestion`: it drops the question only once the server
7
+ * accepted the reply, so a failed submit stays visible for a retry.
8
+ * `onCancel` stops the run instead of answering.
9
+ */
10
+ import { ChatCircleDotsIcon, XIcon } from '@phosphor-icons/react';
11
+ import { useState } from 'react';
12
+ import { Button } from '../components/ui/button.js';
13
+ import { Input } from '../components/ui/input.js';
14
+ import { cn } from '../lib/utils.js';
15
+ import { useUiStrings } from '../providers/ui-provider.js';
16
+ import { errorMessage } from './permission-prompt.js';
17
+ export function QuestionPrompt({ request, onAnswer, onCancel, onError, }) {
18
+ const t = useUiStrings().chat;
19
+ const questions = request.questions;
20
+ const [selected, setSelected] = useState(() => questions.map(() => []));
21
+ const [custom, setCustom] = useState(() => questions.map(() => ''));
22
+ const [sending, setSending] = useState(false);
23
+ const [error, setError] = useState(null);
24
+ const answerFor = (i) => selected[i].length ? selected[i] : custom[i].trim() ? [custom[i].trim()] : [];
25
+ const allAnswered = questions.every((_, i) => answerFor(i).length > 0);
26
+ // One single-choice question with no free text: a click on an option sends it.
27
+ const autoSingle = questions.length === 1 && !questions[0]?.multiple && !questions[0]?.custom;
28
+ function pick(qi, label, multiple) {
29
+ setSelected((prev) => {
30
+ const next = prev.map((a) => [...a]);
31
+ const has = next[qi].includes(label);
32
+ next[qi] = multiple ? (has ? next[qi].filter((l) => l !== label) : [...next[qi], label]) : [label];
33
+ return next;
34
+ });
35
+ }
36
+ async function submit(answers) {
37
+ if (sending)
38
+ return;
39
+ setSending(true);
40
+ setError(null);
41
+ try {
42
+ await onAnswer(request.id, answers);
43
+ }
44
+ catch (err) {
45
+ const message = errorMessage(err, t.answerFailed);
46
+ if (onError)
47
+ onError(message, err);
48
+ else
49
+ setError(message);
50
+ setSending(false);
51
+ }
52
+ }
53
+ return (_jsxs("div", { "data-slot": "question-prompt", className: "border-border bg-card overflow-hidden rounded-md border", children: [_jsxs("div", { className: "border-border flex items-center gap-2 border-b px-3 py-2", children: [_jsx(ChatCircleDotsIcon, { className: "text-muted-foreground size-4" }), _jsx("span", { className: "text-foreground flex-1 text-xs font-medium", children: questions.length > 1 ? t.questionsTitle(questions.length) : t.questionTitle }), _jsx(Button, { type: "button", onClick: onCancel, variant: "ghost", size: "icon-xs", className: "text-muted-foreground", "aria-label": t.stopAndCancel, children: _jsx(XIcon, { className: "size-3.5" }) })] }), _jsxs("div", { className: "space-y-4 p-3", children: [questions.map((q, qi) => {
54
+ const multiple = !!q.multiple;
55
+ return (_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-foreground text-sm", children: q.question }), _jsxs("div", { className: "space-y-1.5", role: multiple ? 'group' : 'radiogroup', children: [q.options.map((opt, oi) => {
56
+ const picked = selected[qi].includes(opt.label);
57
+ return (_jsxs(Button, { type: "button", variant: "outline", role: multiple ? 'checkbox' : 'radio', "aria-checked": picked, disabled: sending, onClick: () => (autoSingle ? submit([[opt.label]]) : pick(qi, opt.label, multiple)), className: cn('h-auto w-full items-start justify-start gap-2.5 px-3 py-2 text-left whitespace-normal', picked && 'border-foreground bg-muted'), children: [_jsx("span", { className: cn('mt-0.5 grid size-4 shrink-0 place-items-center border', multiple ? 'rounded-sm' : 'rounded-full', picked ? 'border-foreground bg-foreground text-background' : 'border-border'), children: picked && _jsx("span", { className: "size-1.5 rounded-full bg-current" }) }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "text-foreground block text-sm", children: opt.label }), opt.description && (_jsx("span", { className: "text-muted-foreground block text-xs", children: opt.description }))] })] }, oi));
58
+ }), q.custom && (_jsx(Input, { value: custom[qi], disabled: sending, placeholder: t.customAnswerPlaceholder, "aria-label": t.customAnswerLabel, onChange: (e) => setCustom((prev) => prev.map((v, i) => (i === qi ? e.target.value : v))) }))] })] }, qi));
59
+ }), error && (_jsx("p", { role: "alert", className: "text-foreground text-xs", children: error })), !autoSingle && (_jsx(Button, { size: "sm", disabled: !allAnswered || sending, onClick: () => submit(questions.map((_, i) => answerFor(i))), className: "w-full", children: sending ? t.sending : t.submitAnswer }))] })] }));
60
+ }
@@ -0,0 +1,9 @@
1
+ import type { KortixSendError } from '@kortix/sdk/react';
2
+ import { type ChatStrings } from '../providers/ui-provider.js';
3
+ /**
4
+ * A one-line title for a failed send. `useSession` surfaces a typed
5
+ * `sendError` whose `message` the SDK already formats for display; the title
6
+ * names the kind of problem, because each kind needs a different reaction.
7
+ * `t` is the chat copy (`useUiStrings().chat`); default: English.
8
+ */
9
+ export declare function sendFailureTitle(error: KortixSendError, t?: ChatStrings): string;
@@ -0,0 +1,21 @@
1
+ import { defaultChatStrings } from '../providers/ui-provider.js';
2
+ /**
3
+ * A one-line title for a failed send. `useSession` surfaces a typed
4
+ * `sendError` whose `message` the SDK already formats for display; the title
5
+ * names the kind of problem, because each kind needs a different reaction.
6
+ * `t` is the chat copy (`useUiStrings().chat`); default: English.
7
+ */
8
+ export function sendFailureTitle(error, t = defaultChatStrings) {
9
+ switch (error.kind) {
10
+ case 'billing':
11
+ // The end user cannot retry this; the operator has to act.
12
+ return t.sendFailedBilling;
13
+ case 'runtime-not-ready':
14
+ // Transient and self-healing: a retry is the right move.
15
+ return t.sendFailedRuntimeNotReady;
16
+ case 'runtime-error':
17
+ return error.gateway?.provider ? t.sendFailedModel(error.gateway.provider) : t.sendFailedRuntimeError;
18
+ default:
19
+ return t.sendFailed;
20
+ }
21
+ }
@@ -0,0 +1,28 @@
1
+ import type { FlatModel, UseSessionResult } from '@kortix/sdk/react';
2
+ import type { ReactNode } from 'react';
3
+ import type { MessageRenderers, RenderTool } from './message-view.js';
4
+ import type { ChatErrorHandler } from './permission-prompt.js';
5
+ export type SessionThreadProps = {
6
+ session: UseSessionResult;
7
+ /** Replaces the composer's control row (default: model and agent pickers). */
8
+ composerToolbar?: ReactNode;
9
+ /** Rendered under the composer card, e.g. the session's scope. */
10
+ composerFooter?: ReactNode;
11
+ /** Shown when the thread has no messages. */
12
+ emptyState?: ReactNode;
13
+ /** Replaces the card of one tool call; return `undefined` to keep the default. */
14
+ renderTool?: RenderTool;
15
+ /** Overrides the renderer of any message part kind. */
16
+ renderers?: MessageRenderers;
17
+ /** Reports a failed permission reply, question reply or slash command (for a toast). Without it the error shows inline. */
18
+ onError?: ChatErrorHandler;
19
+ /** The provider line of a model row in the default model picker (a white-label relabels `kortix`). */
20
+ providerLabel?: (model: FlatModel) => string;
21
+ className?: string;
22
+ };
23
+ /** The default control row: the session's model and agent pickers. */
24
+ export declare function SessionPickers({ session: c, providerLabel, }: {
25
+ session: UseSessionResult;
26
+ providerLabel?: (model: FlatModel) => string;
27
+ }): import("react").JSX.Element;
28
+ export declare function SessionThread({ session: c, composerToolbar, composerFooter, emptyState, renderTool, renderers, onError, providerLabel, className, }: SessionThreadProps): import("react").JSX.Element;
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * The whole chat for one session, from one `useSession` result:
5
+ *
6
+ * <SessionThread session={useSession(projectId, sessionId)} />
7
+ *
8
+ * It renders the transcript (`MessageList`), the runtime state, the typed
9
+ * send error, and the composer with slash commands and the model and agent
10
+ * pickers. Everything reads off `session`: no second chat hook, no transport.
11
+ * Slots replace one region each; the parent sets the height (the thread fills it).
12
+ */
13
+ import { ArrowsClockwiseIcon, WarningCircleIcon, WarningIcon } from '@phosphor-icons/react';
14
+ import { Button } from '../components/ui/button.js';
15
+ import { InfoBanner } from '../components/ui/info-banner.js';
16
+ import { cn } from '../lib/utils.js';
17
+ import { useUiStrings } from '../providers/ui-provider.js';
18
+ import { AgentPicker } from './agent-picker.js';
19
+ import { Composer } from './composer.js';
20
+ import { MessageList } from './message-list.js';
21
+ import { ModelPicker } from './model-picker.js';
22
+ import { sendFailureTitle } from './send-failure.js';
23
+ /** The default control row: the session's model and agent pickers. */
24
+ export function SessionPickers({ session: c, providerLabel, }) {
25
+ return (_jsxs("div", { className: "flex min-w-0 items-center gap-0.5", children: [_jsx(ModelPicker, { models: c.models, value: c.picks.model, onChange: c.picks.setModel, providerLabel: providerLabel }), _jsx(AgentPicker, { agents: c.agents, value: c.picks.agent, onChange: c.picks.setAgent, defaultName: c.defaultAgent })] }));
26
+ }
27
+ function RuntimeState({ session: c }) {
28
+ const t = useUiStrings().chat;
29
+ // "Down" = it was connected and is now unreachable: a drop, not the first boot.
30
+ if (c.switched && c.runtimePhase === 'unreachable') {
31
+ return (_jsx(InfoBanner, { tone: "warning", icon: WarningIcon, title: t.runtimeStopped, className: "mb-2", action: _jsxs(Button, { size: "xs", variant: "secondary", onClick: () => c.retry(), children: [_jsx(ArrowsClockwiseIcon, { className: "size-3.5" }), t.reconnect] }) }));
32
+ }
33
+ if (c.runtimePhase !== 'ready') {
34
+ return _jsx("p", { className: "text-muted-foreground mb-2 text-center text-xs", children: t.connectingRuntime });
35
+ }
36
+ return null;
37
+ }
38
+ export function SessionThread({ session: c, composerToolbar, composerFooter, emptyState, renderTool, renderers, onError, providerLabel, className, }) {
39
+ const strings = useUiStrings();
40
+ const t = strings.chat;
41
+ const runtimeReady = c.runtimePhase === 'ready';
42
+ // Advertise "/" only when it opens something: with no commands a "/" is sent as text.
43
+ const placeholder = runtimeReady
44
+ ? `${t.placeholder}${c.commands.length > 0 ? t.placeholderCommandsHint : ''}`
45
+ : t.placeholderWaiting;
46
+ return (_jsxs("div", { "data-slot": "session-thread", className: cn('flex h-full min-h-0 flex-col', className), children: [_jsx(MessageList, { session: c, emptyState: emptyState, renderTool: renderTool, renderers: renderers, onError: onError }), _jsx("div", { className: "shrink-0 px-5 pb-5", children: _jsxs("div", { className: "mx-auto max-w-3xl", children: [_jsx(RuntimeState, { session: c }), c.sendError ? (_jsx(InfoBanner, { tone: "destructive", icon: WarningCircleIcon, title: sendFailureTitle(c.sendError, t), className: "mb-2", role: "alert", children: c.sendError.message })) : null, _jsx(Composer, { onSend: c.send, onStop: c.cancel, busy: c.isBusy, canStop: c.canStop, disabled: !runtimeReady, placeholder: placeholder, commands: c.commands, onCommand: c.runCommand, onError: onError, toolbar: composerToolbar ?? _jsx(SessionPickers, { session: c, providerLabel: providerLabel }), footer: composerFooter })] }) })] }));
47
+ }