@xpert-ai/chatkit-ui 0.0.20 → 0.1.1

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 (611) hide show
  1. package/dist/app/assets/_baseUniq-p9H3Gzep.js +1 -0
  2. package/dist/app/assets/abap-bJX3iBqH.js +1 -0
  3. package/dist/app/assets/abnf-BoiZ35EE.js +1 -0
  4. package/dist/app/assets/actionscript-D-H9vZ8b.js +1 -0
  5. package/dist/app/assets/ada-Bne3WpOl.js +1 -0
  6. package/dist/app/assets/agda-C938cagi.js +1 -0
  7. package/dist/app/assets/al-Dcxw3Vj0.js +1 -0
  8. package/dist/app/assets/antlr4-uTm2QqyV.js +1 -0
  9. package/dist/app/assets/apacheconf-D52D513G.js +1 -0
  10. package/dist/app/assets/apex-B76H7J4g.js +1 -0
  11. package/dist/app/assets/apl-CzLk42pF.js +1 -0
  12. package/dist/app/assets/applescript-Dx8Ig-Eo.js +1 -0
  13. package/dist/app/assets/aql-wjx32tAU.js +1 -0
  14. package/dist/app/assets/arc-B32_yhh0.js +1 -0
  15. package/dist/app/assets/architectureDiagram-Q4EWVU46-Ba-C8DAI.js +36 -0
  16. package/dist/app/assets/arduino-BwKDxTSS.js +1 -0
  17. package/dist/app/assets/arff-DrkRViyY.js +1 -0
  18. package/dist/app/assets/asciidoc-BGLZq9v8.js +1 -0
  19. package/dist/app/assets/asm6502-MsEWIyJj.js +1 -0
  20. package/dist/app/assets/asmatmel-CeHxqS5T.js +1 -0
  21. package/dist/app/assets/aspnet-CmsQfR5a.js +1 -0
  22. package/dist/app/assets/autohotkey-Cusm-zTm.js +1 -0
  23. package/dist/app/assets/autoit-Da8gsEm-.js +1 -0
  24. package/dist/app/assets/avisynth-C46xLzyo.js +1 -0
  25. package/dist/app/assets/avro-idl-D2WmoYBG.js +1 -0
  26. package/dist/app/assets/{basic-B-OOkRrw.js → bash-BrsKn3za.js} +1 -1
  27. package/dist/app/assets/basic-Dt5oGQ8B.js +1 -0
  28. package/dist/app/assets/batch-DtrIlfXi.js +1 -0
  29. package/dist/app/assets/bbcode-BWYlAYoE.js +1 -0
  30. package/dist/app/assets/bicep-C4sxks0f.js +1 -0
  31. package/dist/app/assets/birb-gYyyIZ-F.js +1 -0
  32. package/dist/app/assets/bison-or-umhj6.js +1 -0
  33. package/dist/app/assets/blockDiagram-DXYQGD6D-5oqbPp8P.js +132 -0
  34. package/dist/app/assets/bnf-BQR7hfk2.js +1 -0
  35. package/dist/app/assets/brainfuck-DkQqhNHv.js +1 -0
  36. package/dist/app/assets/brightscript-rGhg0HBT.js +1 -0
  37. package/dist/app/assets/bro-CIgtBg0f.js +1 -0
  38. package/dist/app/assets/bsl-C4geIkQv.js +1 -0
  39. package/dist/app/assets/c-Cw5181Rv.js +1 -0
  40. package/dist/app/assets/c4Diagram-AHTNJAMY-BKyN5n0Y.js +10 -0
  41. package/dist/app/assets/cfscript-DHPNMvWS.js +1 -0
  42. package/dist/app/assets/chaiscript-Cd8c0hJ8.js +1 -0
  43. package/dist/app/assets/channel-Cx11sSAI.js +1 -0
  44. package/dist/app/assets/chunk-4BX2VUAB-CfLubn_X.js +1 -0
  45. package/dist/app/assets/chunk-4TB4RGXK-Bhehm3S4.js +206 -0
  46. package/dist/app/assets/chunk-55IACEB6-D0Zgi2qX.js +1 -0
  47. package/dist/app/assets/chunk-EDXVE4YY-DzMULs0l.js +1 -0
  48. package/dist/app/assets/chunk-FMBD7UC4-CEU9agAN.js +15 -0
  49. package/dist/app/assets/chunk-OYMX7WX6-C-avxOs6.js +231 -0
  50. package/dist/app/assets/chunk-QZHKN3VN-C66xsvBW.js +1 -0
  51. package/dist/app/assets/chunk-YZCP3GAM-DZlwMcoL.js +1 -0
  52. package/dist/app/assets/cil-L3oWT8Nl.js +1 -0
  53. package/dist/app/assets/classDiagram-6PBFFD2Q-BQrwJXsB.js +1 -0
  54. package/dist/app/assets/classDiagram-v2-HSJHXN6E-BQrwJXsB.js +1 -0
  55. package/dist/app/assets/clike-CHF9NJQa.js +1 -0
  56. package/dist/app/assets/clojure-YgRWUbgr.js +1 -0
  57. package/dist/app/assets/clone-DHPdZQ_6.js +1 -0
  58. package/dist/app/assets/cmake-TK-Cvlxu.js +1 -0
  59. package/dist/app/assets/cobol-XSbSVVcZ.js +1 -0
  60. package/dist/app/assets/coffeescript-HxNd9-Ob.js +1 -0
  61. package/dist/app/assets/concurnas-DK3wUjjD.js +1 -0
  62. package/dist/app/assets/coq-B9Rq7NUE.js +1 -0
  63. package/dist/app/assets/core-B1vWjEfj.js +1 -0
  64. package/dist/app/assets/cose-bilkent-S5V4N54A-4PebjqsX.js +1 -0
  65. package/dist/app/assets/cpp-DUWMh-8O.js +1 -0
  66. package/dist/app/assets/crystal-rYgGF4lS.js +1 -0
  67. package/dist/app/assets/csharp-eqTMyksU.js +1 -0
  68. package/dist/app/assets/cshtml-DSv9-mpk.js +1 -0
  69. package/dist/app/assets/csp-DyZfVzvb.js +1 -0
  70. package/dist/app/assets/css-DYXyUyJe.js +1 -0
  71. package/dist/app/assets/css-extras-FP15zHq8.js +1 -0
  72. package/dist/app/assets/csv-Bp1iUR7c.js +1 -0
  73. package/dist/app/assets/cypher-BjXgs7Y3.js +1 -0
  74. package/dist/app/assets/cytoscape.esm-DkOyvmE4.js +321 -0
  75. package/dist/app/assets/d-Bquc1S6a.js +1 -0
  76. package/dist/app/assets/dagre-KV5264BT-D9OICDLb.js +4 -0
  77. package/dist/app/assets/dart-DrKyO7TC.js +1 -0
  78. package/dist/app/assets/dataweave-BgpsWzO7.js +1 -0
  79. package/dist/app/assets/dax-BwP1SyCZ.js +1 -0
  80. package/dist/app/assets/defaultLocale-DX6XiGOO.js +1 -0
  81. package/dist/app/assets/dhall-BA5nXB8V.js +1 -0
  82. package/dist/app/assets/diagram-5BDNPKRD-BIFTIy6n.js +10 -0
  83. package/dist/app/assets/diagram-G4DWMVQ6-BCVIBrZ2.js +24 -0
  84. package/dist/app/assets/diagram-MMDJMWI5-43z4NaFN.js +43 -0
  85. package/dist/app/assets/diagram-TYMM5635-BDZjM1c_.js +24 -0
  86. package/dist/app/assets/diff-Yc6a7YOT.js +3 -0
  87. package/dist/app/assets/django-B61BBi1t.js +1 -0
  88. package/dist/app/assets/dns-zone-file-DtXhOJHq.js +1 -0
  89. package/dist/app/assets/docker-BLh9n10i.js +1 -0
  90. package/dist/app/assets/dot-BbSnn0Ap.js +1 -0
  91. package/dist/app/assets/ebnf-D_ljHBdb.js +1 -0
  92. package/dist/app/assets/editorconfig-BQXrLGC5.js +1 -0
  93. package/dist/app/assets/eiffel-Cm3FUI5X.js +1 -0
  94. package/dist/app/assets/ejs-CIp2UdDw.js +1 -0
  95. package/dist/app/assets/elixir-DXlWBe5R.js +1 -0
  96. package/dist/app/assets/elm-ECxjLCR-.js +1 -0
  97. package/dist/app/assets/erDiagram-SMLLAGMA-B9I89ndp.js +85 -0
  98. package/dist/app/assets/erb-FzgX8ydn.js +1 -0
  99. package/dist/app/assets/erlang-CzvdSvoz.js +1 -0
  100. package/dist/app/assets/etlua-C3Zsz3RA.js +1 -0
  101. package/dist/app/assets/excel-formula-Cua38PQJ.js +1 -0
  102. package/dist/app/assets/factor-CSAzXoQb.js +1 -0
  103. package/dist/app/assets/false-NSFMCUjP.js +1 -0
  104. package/dist/app/assets/firestore-security-rules-BjNYwvNe.js +1 -0
  105. package/dist/app/assets/flow-BuZaM8y6.js +1 -0
  106. package/dist/app/assets/flowDiagram-DWJPFMVM-CWmW_muY.js +162 -0
  107. package/dist/app/assets/fortran-Cc_f_mSH.js +1 -0
  108. package/dist/app/assets/fsharp-IelQ4Z-Z.js +1 -0
  109. package/dist/app/assets/ftl-Ddl9DDyG.js +1 -0
  110. package/dist/app/assets/ganttDiagram-T4ZO3ILL-CuR1J7dx.js +292 -0
  111. package/dist/app/assets/gap-D3W6p-Jp.js +1 -0
  112. package/dist/app/assets/gcode-Bn8O4UOx.js +1 -0
  113. package/dist/app/assets/gdscript-B4nck3Az.js +1 -0
  114. package/dist/app/assets/gedcom-BCTZRsxn.js +1 -0
  115. package/dist/app/assets/gherkin-CFCJQug9.js +1 -0
  116. package/dist/app/assets/git-Dd2t83_l.js +1 -0
  117. package/dist/app/assets/gitGraphDiagram-UUTBAWPF-DzscVnaS.js +106 -0
  118. package/dist/app/assets/glsl-NXGZDuA9.js +1 -0
  119. package/dist/app/assets/gml-DtS9_99j.js +1 -0
  120. package/dist/app/assets/gn-C6VmNt4U.js +1 -0
  121. package/dist/app/assets/go-module-CmBM8SA1.js +1 -0
  122. package/dist/app/assets/go-otK-v_nb.js +1 -0
  123. package/dist/app/assets/graph-BelNBDAZ.js +1 -0
  124. package/dist/app/assets/graphql-JPlPKrhh.js +1 -0
  125. package/dist/app/assets/groovy-CkMUqzIt.js +1 -0
  126. package/dist/app/assets/haml-DwaIQOGd.js +1 -0
  127. package/dist/app/assets/handlebars-Ck6RB1iw.js +1 -0
  128. package/dist/app/assets/haskell-BxYLBxBa.js +1 -0
  129. package/dist/app/assets/haxe-C4OMV9zJ.js +1 -0
  130. package/dist/app/assets/hcl-DVznmODf.js +1 -0
  131. package/dist/app/assets/hlsl-Z_ySkish.js +1 -0
  132. package/dist/app/assets/hoon-UWT3k4H8.js +1 -0
  133. package/dist/app/assets/hpkp-CXa39f7J.js +1 -0
  134. package/dist/app/assets/hsts-CJF4yNvU.js +1 -0
  135. package/dist/app/assets/http-BxOKxlr4.js +1 -0
  136. package/dist/app/assets/ichigojam-Csb66zY2.js +1 -0
  137. package/dist/app/assets/icon-DxphTQI9.js +1 -0
  138. package/dist/app/assets/icu-message-format-CSZfssuP.js +1 -0
  139. package/dist/app/assets/idris-BmXANiaa.js +1 -0
  140. package/dist/app/assets/iecst-FfznJdjL.js +1 -0
  141. package/dist/app/assets/ignore-C3IKkXMi.js +1 -0
  142. package/dist/app/assets/index-D972kqET.css +1 -0
  143. package/dist/app/assets/index-DmMWBDJR.js +747 -0
  144. package/dist/app/assets/infoDiagram-42DDH7IO-rTeQPEt4.js +2 -0
  145. package/dist/app/assets/inform7-Dk4gPo4b.js +1 -0
  146. package/dist/app/assets/ini-CClGKGMe.js +1 -0
  147. package/dist/app/assets/init-Gi6I4Gst.js +1 -0
  148. package/dist/app/assets/io-6YtqLtET.js +1 -0
  149. package/dist/app/assets/ishikawaDiagram-UXIWVN3A-BBnJ9iuN.js +70 -0
  150. package/dist/app/assets/j-DBPrIcAG.js +1 -0
  151. package/dist/app/assets/java-CopGP3Lu.js +1 -0
  152. package/dist/app/assets/javadoc-C8F3ifW2.js +1 -0
  153. package/dist/app/assets/javadoclike-BNVFpoJC.js +1 -0
  154. package/dist/app/assets/javascript-BMkkas2q.js +1 -0
  155. package/dist/app/assets/javastacktrace-DuykBujE.js +1 -0
  156. package/dist/app/assets/jexl-BSWOm8s5.js +1 -0
  157. package/dist/app/assets/jolie-CdkOmKFM.js +1 -0
  158. package/dist/app/assets/journeyDiagram-VCZTEJTY-CRDpL_1T.js +139 -0
  159. package/dist/app/assets/jq-Nr0Kxpxc.js +1 -0
  160. package/dist/app/assets/js-extras-CA8iZ_E5.js +1 -0
  161. package/dist/app/assets/js-templates-BoqcQW67.js +1 -0
  162. package/dist/app/assets/jsdoc-CeMFl6xP.js +1 -0
  163. package/dist/app/assets/json-CrSHUueM.js +1 -0
  164. package/dist/app/assets/json5-BBfX460l.js +1 -0
  165. package/dist/app/assets/jsonp-DHEqmGWL.js +1 -0
  166. package/dist/app/assets/jsstacktrace-BK3SuvsS.js +1 -0
  167. package/dist/app/assets/jsx-CjR3dp14.js +1 -0
  168. package/dist/app/assets/julia-BJJ6LUnI.js +1 -0
  169. package/dist/app/assets/kanban-definition-6JOO6SKY-Dztk4Auy.js +89 -0
  170. package/dist/app/assets/keepalived-CjGUJvsk.js +1 -0
  171. package/dist/app/assets/keyman-Bogz-7f0.js +1 -0
  172. package/dist/app/assets/kotlin-DGdetcAk.js +1 -0
  173. package/dist/app/assets/kumir-Czhml4-j.js +1 -0
  174. package/dist/app/assets/kusto-BuL9qwXk.js +1 -0
  175. package/dist/app/assets/latex-BAc_zS_4.js +1 -0
  176. package/dist/app/assets/latte-BzZFX_wH.js +1 -0
  177. package/dist/app/assets/layout-DOHRtR3x.js +1 -0
  178. package/dist/app/assets/less-DATW_Ot3.js +1 -0
  179. package/dist/app/assets/lilypond-DSmAdE7B.js +1 -0
  180. package/dist/app/assets/linear-rr7FzlEM.js +1 -0
  181. package/dist/app/assets/liquid-CF8lqz9m.js +1 -0
  182. package/dist/app/assets/lisp-BUPAsWUh.js +1 -0
  183. package/dist/app/assets/livescript-B8CIEQDH.js +1 -0
  184. package/dist/app/assets/llvm-DGaRc9w0.js +1 -0
  185. package/dist/app/assets/log-XuE3Wqn5.js +1 -0
  186. package/dist/app/assets/lolcode-Clk-p_j2.js +1 -0
  187. package/dist/app/assets/{java-CNwVyXY2.js → lua-BLczZbJa.js} +1 -1
  188. package/dist/app/assets/magma-DTO3ftgF.js +1 -0
  189. package/dist/app/assets/makefile-OSVaZHmV.js +1 -0
  190. package/dist/app/assets/markdown-InD7dXs9.js +1 -0
  191. package/dist/app/assets/markup-BN6MlRZT.js +1 -0
  192. package/dist/app/assets/markup-templating-DRXAmI1c.js +1 -0
  193. package/dist/app/assets/matlab-CV_q70_G.js +1 -0
  194. package/dist/app/assets/maxscript-Ck_8H__C.js +1 -0
  195. package/dist/app/assets/mel-D9MU0rZa.js +1 -0
  196. package/dist/app/assets/mermaid-DshECBS6.js +1 -0
  197. package/dist/app/assets/min-CfLzpwyh.js +1 -0
  198. package/dist/app/assets/mindmap-definition-QFDTVHPH-C7XGlydX.js +96 -0
  199. package/dist/app/assets/mizar-WBJ-SwIG.js +1 -0
  200. package/dist/app/assets/mongodb-CmzRTKBq.js +1 -0
  201. package/dist/app/assets/monkey-W1yB--1T.js +1 -0
  202. package/dist/app/assets/moonscript-BD5hlCXn.js +1 -0
  203. package/dist/app/assets/n1ql-CwugAEoM.js +1 -0
  204. package/dist/app/assets/n4js-tFC-Lsvd.js +1 -0
  205. package/dist/app/assets/nand2tetris-hdl-hzvfBJxH.js +1 -0
  206. package/dist/app/assets/naniscript-DUtjoUL1.js +1 -0
  207. package/dist/app/assets/nasm-Dcckq6ib.js +1 -0
  208. package/dist/app/assets/neon-DeVv09BE.js +1 -0
  209. package/dist/app/assets/nevod-CAq9Kfwt.js +1 -0
  210. package/dist/app/assets/nginx-C8GHDEqt.js +1 -0
  211. package/dist/app/assets/nim-BqdyUedD.js +1 -0
  212. package/dist/app/assets/nix-514mCcjs.js +1 -0
  213. package/dist/app/assets/nsis-CdKqXn3g.js +1 -0
  214. package/dist/app/assets/objectivec-uPp8iMUn.js +1 -0
  215. package/dist/app/assets/ocaml-D4EB6rFL.js +1 -0
  216. package/dist/app/assets/opencl-BN8tmrp-.js +1 -0
  217. package/dist/app/assets/openqasm-CZT9yVLH.js +1 -0
  218. package/dist/app/assets/ordinal-Cboi1Yqb.js +1 -0
  219. package/dist/app/assets/oz-xEnzbfGI.js +1 -0
  220. package/dist/app/assets/parigp-PN33G_ZS.js +1 -0
  221. package/dist/app/assets/parser-YigtK2Gn.js +1 -0
  222. package/dist/app/assets/pascal-BSQHqJO2.js +1 -0
  223. package/dist/app/assets/pascaligo-B3om_nlX.js +1 -0
  224. package/dist/app/assets/pcaxis-B_qwjIH4.js +1 -0
  225. package/dist/app/assets/peoplecode-G3CTxh8q.js +1 -0
  226. package/dist/app/assets/perl-CBvGMSZZ.js +1 -0
  227. package/dist/app/assets/php-DewJLtev.js +1 -0
  228. package/dist/app/assets/php-extras-BT2DdjGn.js +1 -0
  229. package/dist/app/assets/phpdoc-DiQXOd9D.js +1 -0
  230. package/dist/app/assets/pieDiagram-DEJITSTG-CYXmqIpD.js +30 -0
  231. package/dist/app/assets/plsql-BzUO3h3t.js +1 -0
  232. package/dist/app/assets/powerquery-D_713gdU.js +1 -0
  233. package/dist/app/assets/powershell-D7IGyPyT.js +1 -0
  234. package/dist/app/assets/processing-CULfTuKk.js +1 -0
  235. package/dist/app/assets/prolog-DI8sHw_1.js +1 -0
  236. package/dist/app/assets/promql-DdWPpZzX.js +1 -0
  237. package/dist/app/assets/properties-UUBptvjg.js +1 -0
  238. package/dist/app/assets/protobuf-Yh4lBroy.js +1 -0
  239. package/dist/app/assets/psl-CKuqp255.js +1 -0
  240. package/dist/app/assets/pug-Duz4hJlP.js +1 -0
  241. package/dist/app/assets/puppet-Tenfq4aE.js +1 -0
  242. package/dist/app/assets/pure-CTE3YKFb.js +1 -0
  243. package/dist/app/assets/purebasic-BzV6ZqWW.js +1 -0
  244. package/dist/app/assets/purescript-CjSCYtGb.js +1 -0
  245. package/dist/app/assets/q-BTX8RKFy.js +1 -0
  246. package/dist/app/assets/qml-CGjBjP81.js +1 -0
  247. package/dist/app/assets/qore-5Gggmt2I.js +1 -0
  248. package/dist/app/assets/qsharp-DhqE1FPx.js +1 -0
  249. package/dist/app/assets/quadrantDiagram-34T5L4WZ-BbnPMKp-.js +7 -0
  250. package/dist/app/assets/r-Dr0jr5tD.js +1 -0
  251. package/dist/app/assets/racket-NVUa01EO.js +1 -0
  252. package/dist/app/assets/reason-Bx5CI0l0.js +1 -0
  253. package/dist/app/assets/regex-12879jLK.js +1 -0
  254. package/dist/app/assets/rego-w2Fhvb_N.js +1 -0
  255. package/dist/app/assets/renpy-gPxX0z3Q.js +1 -0
  256. package/dist/app/assets/requirementDiagram-MS252O5E-BhOU7uOd.js +84 -0
  257. package/dist/app/assets/rest-C39bU2b1.js +1 -0
  258. package/dist/app/assets/rip-RLtTVF0Y.js +1 -0
  259. package/dist/app/assets/roboconf-BJckt4oD.js +1 -0
  260. package/dist/app/assets/robotframework-DCR96jiT.js +1 -0
  261. package/dist/app/assets/ruby-CRs8uxXB.js +1 -0
  262. package/dist/app/assets/rust-C0bGL254.js +1 -0
  263. package/dist/app/assets/sankeyDiagram-XADWPNL6-CFgkd6GO.js +10 -0
  264. package/dist/app/assets/sas-CkLtpL1M.js +1 -0
  265. package/dist/app/assets/sass-FNfCYuQd.js +1 -0
  266. package/dist/app/assets/scala-Dy5lip5O.js +1 -0
  267. package/dist/app/assets/scheme-pkKED5As.js +1 -0
  268. package/dist/app/assets/scss-DrZ4F_S5.js +1 -0
  269. package/dist/app/assets/sequenceDiagram-FGHM5R23-t5z2WRg9.js +157 -0
  270. package/dist/app/assets/shell-session-tfqRzQ64.js +1 -0
  271. package/dist/app/assets/smali-D9oJJF_a.js +1 -0
  272. package/dist/app/assets/smalltalk-FhicZwdZ.js +1 -0
  273. package/dist/app/assets/smarty-RTVkhvGe.js +1 -0
  274. package/dist/app/assets/sml-8jU1U62j.js +1 -0
  275. package/dist/app/assets/solidity-DLvpuywG.js +1 -0
  276. package/dist/app/assets/solution-file-BOwCbL9x.js +1 -0
  277. package/dist/app/assets/soy-Dye6FppK.js +1 -0
  278. package/dist/app/assets/sparql-BRIOTA6e.js +1 -0
  279. package/dist/app/assets/splunk-spl-xjEKSM5T.js +1 -0
  280. package/dist/app/assets/sqf-BTXRZqz9.js +1 -0
  281. package/dist/app/assets/sql-LIGcsz7H.js +1 -0
  282. package/dist/app/assets/squirrel-D1i-yP9F.js +1 -0
  283. package/dist/app/assets/stan-Bz-MTQlG.js +1 -0
  284. package/dist/app/assets/stateDiagram-FHFEXIEX-INV79XkW.js +1 -0
  285. package/dist/app/assets/stateDiagram-v2-QKLJ7IA2-DkwGLXRp.js +1 -0
  286. package/dist/app/assets/stylus-CPcHbGGR.js +1 -0
  287. package/dist/app/assets/swift-CMnIAhC_.js +1 -0
  288. package/dist/app/assets/systemd-CnQ86vtn.js +2 -0
  289. package/dist/app/assets/t4-cs-ClADD8kZ.js +1 -0
  290. package/dist/app/assets/t4-templating-BxEXIn9V.js +1 -0
  291. package/dist/app/assets/t4-vb-BuQFrDQM.js +1 -0
  292. package/dist/app/assets/tap-D-OeTv7J.js +1 -0
  293. package/dist/app/assets/tcl-D4EWmvqA.js +1 -0
  294. package/dist/app/assets/textile-vCa5WeBr.js +1 -0
  295. package/dist/app/assets/timeline-definition-GMOUNBTQ-CZVpkWZR.js +120 -0
  296. package/dist/app/assets/toml-CyQfWyMg.js +1 -0
  297. package/dist/app/assets/tremor-DTpakXR3.js +1 -0
  298. package/dist/app/assets/tt2-I3k-jzpY.js +1 -0
  299. package/dist/app/assets/turtle-BjS87MX7.js +1 -0
  300. package/dist/app/assets/twig-BYK2hDMY.js +1 -0
  301. package/dist/app/assets/typescript-DNEOvUVG.js +1 -0
  302. package/dist/app/assets/typoscript-hqzFge6d.js +1 -0
  303. package/dist/app/assets/unrealscript-_-NzaZj0.js +1 -0
  304. package/dist/app/assets/uorazor-BMR9qMW5.js +1 -0
  305. package/dist/app/assets/uri-BSGWfMxZ.js +1 -0
  306. package/dist/app/assets/v-CLtdeXIK.js +1 -0
  307. package/dist/app/assets/vala-wzCcqtKA.js +1 -0
  308. package/dist/app/assets/{turtle-D8pkqXh1.js → vbnet-DGCLmXdC.js} +1 -1
  309. package/dist/app/assets/velocity-DX_5gTOq.js +1 -0
  310. package/dist/app/assets/vennDiagram-DHZGUBPP-Dq1FXdcO.js +34 -0
  311. package/dist/app/assets/verilog-DeAFTKrK.js +1 -0
  312. package/dist/app/assets/vhdl-CgPp3m3I.js +1 -0
  313. package/dist/app/assets/vim-ZY6C4NgO.js +1 -0
  314. package/dist/app/assets/visual-basic-DmV7laqn.js +1 -0
  315. package/dist/app/assets/wardley-RL74JXVD-OqiGOeix.js +162 -0
  316. package/dist/app/assets/wardleyDiagram-NUSXRM2D-XXEOUAR6.js +20 -0
  317. package/dist/app/assets/warpscript-CST9Acbf.js +1 -0
  318. package/dist/app/assets/wasm-D44TvCcf.js +1 -0
  319. package/dist/app/assets/web-idl-CUAX3ogm.js +1 -0
  320. package/dist/app/assets/wiki-KNEqZQWK.js +1 -0
  321. package/dist/app/assets/wolfram-CZdD1bRd.js +1 -0
  322. package/dist/app/assets/wren-PITvEkQ4.js +1 -0
  323. package/dist/app/assets/xeora-BM_ABt9y.js +1 -0
  324. package/dist/app/assets/xml-doc-249eg8mF.js +1 -0
  325. package/dist/app/assets/xojo-M3SASV_b.js +1 -0
  326. package/dist/app/assets/xquery-BWv2VkcM.js +1 -0
  327. package/dist/app/assets/xychartDiagram-5P7HB3ND-CvXT15VO.js +7 -0
  328. package/dist/app/assets/yaml-B70AwQ7Y.js +1 -0
  329. package/dist/app/assets/yang-DffrsIpd.js +1 -0
  330. package/dist/app/assets/zig-C9vlYfKL.js +1 -0
  331. package/dist/app/index.html +2 -2
  332. package/dist/index.cjs +2734 -595
  333. package/dist/index.d.cts +20 -5
  334. package/dist/index.d.ts +20 -5
  335. package/dist/index.js +2768 -592
  336. package/package.json +8 -4
  337. package/dist/app/assets/abap-CabZ0vYL.js +0 -1
  338. package/dist/app/assets/abnf-CPoubvVG.js +0 -1
  339. package/dist/app/assets/actionscript-CL1BPQFv.js +0 -1
  340. package/dist/app/assets/ada-BOt55oS4.js +0 -1
  341. package/dist/app/assets/agda-DKyUkxie.js +0 -1
  342. package/dist/app/assets/al-Jnhqb7P-.js +0 -1
  343. package/dist/app/assets/antlr4-BeT3YbbK.js +0 -1
  344. package/dist/app/assets/apacheconf-Ck_DRZXY.js +0 -1
  345. package/dist/app/assets/apex-CPjbO0O4.js +0 -1
  346. package/dist/app/assets/apl-Ccs4_jOU.js +0 -1
  347. package/dist/app/assets/applescript-C6i7vo8F.js +0 -1
  348. package/dist/app/assets/aql-D3ZWY-VL.js +0 -1
  349. package/dist/app/assets/arduino-xTj3TTXg.js +0 -1
  350. package/dist/app/assets/arff-BOuVccGR.js +0 -1
  351. package/dist/app/assets/asciidoc-BmShvnn0.js +0 -1
  352. package/dist/app/assets/asm6502-6FWPK68i.js +0 -1
  353. package/dist/app/assets/asmatmel-KLAd82QV.js +0 -1
  354. package/dist/app/assets/aspnet-vZiSZd1y.js +0 -1
  355. package/dist/app/assets/autohotkey-tcBDP1b7.js +0 -1
  356. package/dist/app/assets/autoit-Bwt0tLM_.js +0 -1
  357. package/dist/app/assets/avisynth-Bzz43Lfu.js +0 -1
  358. package/dist/app/assets/avro-idl-Bt9aSyrD.js +0 -1
  359. package/dist/app/assets/bash-BloO3C-T.js +0 -1
  360. package/dist/app/assets/batch-aOUu2msA.js +0 -1
  361. package/dist/app/assets/bbcode-C4D8vm8O.js +0 -1
  362. package/dist/app/assets/bicep-BtBByAYv.js +0 -1
  363. package/dist/app/assets/birb-BKXLouTf.js +0 -1
  364. package/dist/app/assets/bison-CniuHJJN.js +0 -1
  365. package/dist/app/assets/bnf-CGcuZYv2.js +0 -1
  366. package/dist/app/assets/brainfuck-C9dlh056.js +0 -1
  367. package/dist/app/assets/brightscript-nhHFw9_4.js +0 -1
  368. package/dist/app/assets/bro-BTsReVOc.js +0 -1
  369. package/dist/app/assets/bsl-CmOTwcFR.js +0 -1
  370. package/dist/app/assets/c-Yjfq4oES.js +0 -1
  371. package/dist/app/assets/cfscript-DGhYlgJ7.js +0 -1
  372. package/dist/app/assets/chaiscript-CpP8bBSU.js +0 -1
  373. package/dist/app/assets/cil-CZ7j4pcz.js +0 -1
  374. package/dist/app/assets/clike-D581thF2.js +0 -1
  375. package/dist/app/assets/clojure-AXVmar0o.js +0 -1
  376. package/dist/app/assets/cmake-BozSSfax.js +0 -1
  377. package/dist/app/assets/cobol-OciN9vwY.js +0 -1
  378. package/dist/app/assets/coffeescript-B9yMzVL5.js +0 -1
  379. package/dist/app/assets/concurnas-DeQIM64O.js +0 -1
  380. package/dist/app/assets/coq-CicPksao.js +0 -1
  381. package/dist/app/assets/core-BIcqXTaK.js +0 -1
  382. package/dist/app/assets/cpp-DKQF7403.js +0 -1
  383. package/dist/app/assets/crystal-Bcau7QFZ.js +0 -1
  384. package/dist/app/assets/csharp-BYghYpTl.js +0 -1
  385. package/dist/app/assets/cshtml-BIxIGrsH.js +0 -1
  386. package/dist/app/assets/csp-CzDOD-m1.js +0 -1
  387. package/dist/app/assets/css-CPRwU6oY.js +0 -1
  388. package/dist/app/assets/css-extras-C28yWYxN.js +0 -1
  389. package/dist/app/assets/csv-D8IAZwKO.js +0 -1
  390. package/dist/app/assets/cypher-0hMRBt8D.js +0 -1
  391. package/dist/app/assets/d-B5PQgXXo.js +0 -1
  392. package/dist/app/assets/dart-CvCyf8me.js +0 -1
  393. package/dist/app/assets/dataweave-Izl0xtz9.js +0 -1
  394. package/dist/app/assets/dax-D-bGAkbS.js +0 -1
  395. package/dist/app/assets/dhall-DXIOSM5Q.js +0 -1
  396. package/dist/app/assets/diff-BE-xKdIi.js +0 -3
  397. package/dist/app/assets/django-DxEZdkeU.js +0 -1
  398. package/dist/app/assets/dns-zone-file-D406E4S7.js +0 -1
  399. package/dist/app/assets/docker-BZkb2U00.js +0 -1
  400. package/dist/app/assets/dot-BGJNVmx1.js +0 -1
  401. package/dist/app/assets/ebnf-_PEATas2.js +0 -1
  402. package/dist/app/assets/editorconfig-C1UuLwJC.js +0 -1
  403. package/dist/app/assets/eiffel-PzXVtlzf.js +0 -1
  404. package/dist/app/assets/ejs-707c0691.js +0 -1
  405. package/dist/app/assets/elixir-Bd3zWMjP.js +0 -1
  406. package/dist/app/assets/elm-DvEDEOdK.js +0 -1
  407. package/dist/app/assets/erb-B6lZT1P9.js +0 -1
  408. package/dist/app/assets/erlang-BwhqRmQk.js +0 -1
  409. package/dist/app/assets/etlua-Bkg93PrU.js +0 -1
  410. package/dist/app/assets/excel-formula-BD0I0dyD.js +0 -1
  411. package/dist/app/assets/factor-CiQgOsxY.js +0 -1
  412. package/dist/app/assets/false-DlJ-f_Rc.js +0 -1
  413. package/dist/app/assets/firestore-security-rules-CxrEhPSm.js +0 -1
  414. package/dist/app/assets/flow-DOjTBDi4.js +0 -1
  415. package/dist/app/assets/fortran-D6uA-pWI.js +0 -1
  416. package/dist/app/assets/fsharp-CFL1DcvT.js +0 -1
  417. package/dist/app/assets/ftl-DzWZwecM.js +0 -1
  418. package/dist/app/assets/gap-DatQeRFY.js +0 -1
  419. package/dist/app/assets/gcode-5FSxboIT.js +0 -1
  420. package/dist/app/assets/gdscript-Dz-OC8bG.js +0 -1
  421. package/dist/app/assets/gedcom-BS0539Ys.js +0 -1
  422. package/dist/app/assets/gherkin-BJKrWYAT.js +0 -1
  423. package/dist/app/assets/git-DCjIevVw.js +0 -1
  424. package/dist/app/assets/glsl-toSXKJrw.js +0 -1
  425. package/dist/app/assets/gml-DODsSWU7.js +0 -1
  426. package/dist/app/assets/gn-CzmtMWMm.js +0 -1
  427. package/dist/app/assets/go-BCQUEKVv.js +0 -1
  428. package/dist/app/assets/go-module-BbcV-9oG.js +0 -1
  429. package/dist/app/assets/graphql-C_KxCYJO.js +0 -1
  430. package/dist/app/assets/groovy-Cj97iKYK.js +0 -1
  431. package/dist/app/assets/haml-tLXJGYDb.js +0 -1
  432. package/dist/app/assets/handlebars-DIdVe3xN.js +0 -1
  433. package/dist/app/assets/haskell-DPqw5u4H.js +0 -1
  434. package/dist/app/assets/haxe-AsnHNCIR.js +0 -1
  435. package/dist/app/assets/hcl-C6aoWR34.js +0 -1
  436. package/dist/app/assets/hlsl-B2hhU30-.js +0 -1
  437. package/dist/app/assets/hoon-Bs-KhWO3.js +0 -1
  438. package/dist/app/assets/hpkp-C-J4O-Mp.js +0 -1
  439. package/dist/app/assets/hsts-BNFEkSnm.js +0 -1
  440. package/dist/app/assets/http-D7UlQANy.js +0 -1
  441. package/dist/app/assets/ichigojam-B01TJ8BA.js +0 -1
  442. package/dist/app/assets/icon-Ca_ghvQd.js +0 -1
  443. package/dist/app/assets/icu-message-format-CkcsJ0ML.js +0 -1
  444. package/dist/app/assets/idris-BApVxI9a.js +0 -1
  445. package/dist/app/assets/iecst-CXLR8sGn.js +0 -1
  446. package/dist/app/assets/ignore-7LzAeAFj.js +0 -1
  447. package/dist/app/assets/index-BUg2yVDW.js +0 -439
  448. package/dist/app/assets/index-om2E9pNd.css +0 -1
  449. package/dist/app/assets/inform7-CtnRN-Iq.js +0 -1
  450. package/dist/app/assets/ini-Cjpl6yTL.js +0 -1
  451. package/dist/app/assets/io-C6W_EboY.js +0 -1
  452. package/dist/app/assets/j-BOBDun2W.js +0 -1
  453. package/dist/app/assets/javadoc-DS6hxu7_.js +0 -1
  454. package/dist/app/assets/javadoclike-J6YT11JS.js +0 -1
  455. package/dist/app/assets/javascript-IbEfuVSB.js +0 -1
  456. package/dist/app/assets/javastacktrace-DjxwGV26.js +0 -1
  457. package/dist/app/assets/jexl-TLHmHaQ5.js +0 -1
  458. package/dist/app/assets/jolie-CLk71kur.js +0 -1
  459. package/dist/app/assets/jq-DZKnIQZM.js +0 -1
  460. package/dist/app/assets/js-extras-CJab09ti.js +0 -1
  461. package/dist/app/assets/js-templates-CQGqrHhi.js +0 -1
  462. package/dist/app/assets/jsdoc--ymvl4aq.js +0 -1
  463. package/dist/app/assets/json-D9b-V85G.js +0 -1
  464. package/dist/app/assets/json5-LgA47n7A.js +0 -1
  465. package/dist/app/assets/jsonp-Cvwp3f8M.js +0 -1
  466. package/dist/app/assets/jsstacktrace-z8t2H6h6.js +0 -1
  467. package/dist/app/assets/jsx-B71LrwNd.js +0 -1
  468. package/dist/app/assets/julia-DCATdxwO.js +0 -1
  469. package/dist/app/assets/keepalived-DVYYbgrL.js +0 -1
  470. package/dist/app/assets/keyman-DLyOXnhf.js +0 -1
  471. package/dist/app/assets/kotlin-CYoDfyDA.js +0 -1
  472. package/dist/app/assets/kumir-CPWiEvmL.js +0 -1
  473. package/dist/app/assets/kusto-BkfRYk0W.js +0 -1
  474. package/dist/app/assets/latex-BEjZ0ppC.js +0 -1
  475. package/dist/app/assets/latte-DaZOqdGV.js +0 -1
  476. package/dist/app/assets/less-BmKsj1gN.js +0 -1
  477. package/dist/app/assets/lilypond-mmng28aJ.js +0 -1
  478. package/dist/app/assets/liquid-BuuJO6_6.js +0 -1
  479. package/dist/app/assets/lisp-DnffFM5N.js +0 -1
  480. package/dist/app/assets/livescript-BSsr00Wr.js +0 -1
  481. package/dist/app/assets/llvm-37YjcHN5.js +0 -1
  482. package/dist/app/assets/log-D3l5N3To.js +0 -1
  483. package/dist/app/assets/lolcode-C0Q2M_6s.js +0 -1
  484. package/dist/app/assets/lua-DcLwN4Tg.js +0 -1
  485. package/dist/app/assets/magma-CK0Amip9.js +0 -1
  486. package/dist/app/assets/makefile-CtpS-RoO.js +0 -1
  487. package/dist/app/assets/markdown-BNK3F4ql.js +0 -1
  488. package/dist/app/assets/markup-C9GIL65H.js +0 -1
  489. package/dist/app/assets/markup-templating-Du1J3ADP.js +0 -1
  490. package/dist/app/assets/matlab-DEM6O1Ul.js +0 -1
  491. package/dist/app/assets/maxscript-DMvqa3gf.js +0 -1
  492. package/dist/app/assets/mel-C8DBIw1g.js +0 -1
  493. package/dist/app/assets/mermaid-CVko6NSq.js +0 -1
  494. package/dist/app/assets/mizar-CwYm3_It.js +0 -1
  495. package/dist/app/assets/mongodb-DRqGwjq6.js +0 -1
  496. package/dist/app/assets/monkey-BxiKe6Nr.js +0 -1
  497. package/dist/app/assets/moonscript-CJyt1xoM.js +0 -1
  498. package/dist/app/assets/n1ql-BBmjIGEU.js +0 -1
  499. package/dist/app/assets/n4js-ByKsJMJL.js +0 -1
  500. package/dist/app/assets/nand2tetris-hdl-BTSXj71h.js +0 -1
  501. package/dist/app/assets/naniscript-C4jykFVF.js +0 -1
  502. package/dist/app/assets/nasm-DPA0eXtX.js +0 -1
  503. package/dist/app/assets/neon-upN4Ak64.js +0 -1
  504. package/dist/app/assets/nevod-CdttHB8F.js +0 -1
  505. package/dist/app/assets/nginx-DI1fsQ3j.js +0 -1
  506. package/dist/app/assets/nim-D7kc_mK9.js +0 -1
  507. package/dist/app/assets/nix-BUG5ppr9.js +0 -1
  508. package/dist/app/assets/nsis-BnXhmmxO.js +0 -1
  509. package/dist/app/assets/objectivec-Bu4dOfb9.js +0 -1
  510. package/dist/app/assets/ocaml-aT7VVPiL.js +0 -1
  511. package/dist/app/assets/opencl-BzyWcYkI.js +0 -1
  512. package/dist/app/assets/openqasm-b2yFBJdq.js +0 -1
  513. package/dist/app/assets/oz-D46TtIuw.js +0 -1
  514. package/dist/app/assets/parigp-BAJyhdut.js +0 -1
  515. package/dist/app/assets/parser-B-ALvauC.js +0 -1
  516. package/dist/app/assets/pascal-B0ap4FDW.js +0 -1
  517. package/dist/app/assets/pascaligo-ChOneu9-.js +0 -1
  518. package/dist/app/assets/pcaxis-DTAmxHgs.js +0 -1
  519. package/dist/app/assets/peoplecode-dQfUy8zn.js +0 -1
  520. package/dist/app/assets/perl-CYk00e1Q.js +0 -1
  521. package/dist/app/assets/php-DvSqFnSN.js +0 -1
  522. package/dist/app/assets/php-extras-BFjUbIU6.js +0 -1
  523. package/dist/app/assets/phpdoc-Di7rKCNL.js +0 -1
  524. package/dist/app/assets/plsql-dX0-BKqD.js +0 -1
  525. package/dist/app/assets/powerquery-3xq4KaAs.js +0 -1
  526. package/dist/app/assets/powershell-BbXooszO.js +0 -1
  527. package/dist/app/assets/processing-GWbfNCzH.js +0 -1
  528. package/dist/app/assets/prolog-Tb2TbunJ.js +0 -1
  529. package/dist/app/assets/promql-QS8vHhL7.js +0 -1
  530. package/dist/app/assets/properties-BJ8AWlqX.js +0 -1
  531. package/dist/app/assets/protobuf-De-puAg3.js +0 -1
  532. package/dist/app/assets/psl-hZft3C8K.js +0 -1
  533. package/dist/app/assets/pug-BcYHdk-i.js +0 -1
  534. package/dist/app/assets/puppet-BWbqDQJD.js +0 -1
  535. package/dist/app/assets/pure-Bz2pjTxR.js +0 -1
  536. package/dist/app/assets/purebasic-BlO48lYx.js +0 -1
  537. package/dist/app/assets/purescript-BxSMm2Br.js +0 -1
  538. package/dist/app/assets/q-DDUTW9aK.js +0 -1
  539. package/dist/app/assets/qml-DisOV-LV.js +0 -1
  540. package/dist/app/assets/qore-FNRP4gBF.js +0 -1
  541. package/dist/app/assets/qsharp-DhtMV0oO.js +0 -1
  542. package/dist/app/assets/r-CyiuHjNN.js +0 -1
  543. package/dist/app/assets/racket-DFgoSckH.js +0 -1
  544. package/dist/app/assets/reason-HhYbY7K3.js +0 -1
  545. package/dist/app/assets/regex-jU5TpvM-.js +0 -1
  546. package/dist/app/assets/rego-BCjDPrQO.js +0 -1
  547. package/dist/app/assets/renpy-BTSgQi2v.js +0 -1
  548. package/dist/app/assets/rest-BLcZ4e-5.js +0 -1
  549. package/dist/app/assets/rip-SltRJnuI.js +0 -1
  550. package/dist/app/assets/roboconf-B-GZm2Oe.js +0 -1
  551. package/dist/app/assets/robotframework-BOt8S6cX.js +0 -1
  552. package/dist/app/assets/ruby-CVfYH0zM.js +0 -1
  553. package/dist/app/assets/rust-B6mEp4Sj.js +0 -1
  554. package/dist/app/assets/sas-DvEI8RJ0.js +0 -1
  555. package/dist/app/assets/sass-Cv25Jxqq.js +0 -1
  556. package/dist/app/assets/scala-CyqNr7Uv.js +0 -1
  557. package/dist/app/assets/scheme-ji0XoXLf.js +0 -1
  558. package/dist/app/assets/scss-B7_0neO_.js +0 -1
  559. package/dist/app/assets/shell-session-CqZEoMQD.js +0 -1
  560. package/dist/app/assets/smali-DKSzZYkI.js +0 -1
  561. package/dist/app/assets/smalltalk-BOA4piuq.js +0 -1
  562. package/dist/app/assets/smarty-Du99BSgN.js +0 -1
  563. package/dist/app/assets/sml-BJedIA4B.js +0 -1
  564. package/dist/app/assets/solidity-DidQwG5Z.js +0 -1
  565. package/dist/app/assets/solution-file-Bx0d9qN8.js +0 -1
  566. package/dist/app/assets/soy-BBLv3Cfa.js +0 -1
  567. package/dist/app/assets/sparql-Da5WZKbL.js +0 -1
  568. package/dist/app/assets/splunk-spl-DbJKl8So.js +0 -1
  569. package/dist/app/assets/sqf-CYrx0jxf.js +0 -1
  570. package/dist/app/assets/sql-Gv-aOlOf.js +0 -1
  571. package/dist/app/assets/squirrel-FpIGPPw4.js +0 -1
  572. package/dist/app/assets/stan-Dq001Nrk.js +0 -1
  573. package/dist/app/assets/stylus-aatfgWwe.js +0 -1
  574. package/dist/app/assets/swift-pn7VW95d.js +0 -1
  575. package/dist/app/assets/systemd-9capsVJ6.js +0 -2
  576. package/dist/app/assets/t4-cs-CKXcczci.js +0 -1
  577. package/dist/app/assets/t4-templating-1wTayb8u.js +0 -1
  578. package/dist/app/assets/t4-vb-B_O7wBow.js +0 -1
  579. package/dist/app/assets/tap-D-TV5_gQ.js +0 -1
  580. package/dist/app/assets/tcl-BaVob1Om.js +0 -1
  581. package/dist/app/assets/textile-COMk-HmI.js +0 -1
  582. package/dist/app/assets/toml-D9NJpArC.js +0 -1
  583. package/dist/app/assets/tremor-rCNHwdQL.js +0 -1
  584. package/dist/app/assets/tt2-DTDvfOgc.js +0 -1
  585. package/dist/app/assets/twig-DxSF8gqH.js +0 -1
  586. package/dist/app/assets/typescript-Caebatmk.js +0 -1
  587. package/dist/app/assets/typoscript-B3uk1kES.js +0 -1
  588. package/dist/app/assets/unrealscript-ZNoSG8ji.js +0 -1
  589. package/dist/app/assets/uorazor-LekoNNOo.js +0 -1
  590. package/dist/app/assets/uri-B8YcIzOv.js +0 -1
  591. package/dist/app/assets/v-6rOne2a0.js +0 -1
  592. package/dist/app/assets/vala-CjEJEdsP.js +0 -1
  593. package/dist/app/assets/vbnet-DBPmBm7_.js +0 -1
  594. package/dist/app/assets/velocity-DOooMwL8.js +0 -1
  595. package/dist/app/assets/verilog-Cq0ZocvP.js +0 -1
  596. package/dist/app/assets/vhdl-Dxs_xidb.js +0 -1
  597. package/dist/app/assets/vim-BqsnXwB6.js +0 -1
  598. package/dist/app/assets/visual-basic-zAzjvaqP.js +0 -1
  599. package/dist/app/assets/warpscript-D9hbfr6_.js +0 -1
  600. package/dist/app/assets/wasm-C4TU9VDY.js +0 -1
  601. package/dist/app/assets/web-idl-DD5JcddQ.js +0 -1
  602. package/dist/app/assets/wiki-Des21yVK.js +0 -1
  603. package/dist/app/assets/wolfram-B7enpov1.js +0 -1
  604. package/dist/app/assets/wren-Rr8h-Ayu.js +0 -1
  605. package/dist/app/assets/xeora-EjcLXBhx.js +0 -1
  606. package/dist/app/assets/xml-doc-uaTxx6-m.js +0 -1
  607. package/dist/app/assets/xojo-CX6G8nhh.js +0 -1
  608. package/dist/app/assets/xquery-DvPb3Uw9.js +0 -1
  609. package/dist/app/assets/yaml-D-l_Y2hx.js +0 -1
  610. package/dist/app/assets/yang-KBoIIT4_.js +0 -1
  611. package/dist/app/assets/zig-_uNXp9cY.js +0 -1
package/dist/index.cjs CHANGED
@@ -66,8 +66,8 @@ __export(index_exports, {
66
66
  module.exports = __toCommonJS(index_exports);
67
67
 
68
68
  // src/components/chat.tsx
69
- var React20 = __toESM(require("react"), 1);
70
- var import_lucide_react9 = require("lucide-react");
69
+ var React22 = __toESM(require("react"), 1);
70
+ var import_lucide_react11 = require("lucide-react");
71
71
 
72
72
  // src/lib/utils.ts
73
73
  var import_clsx = require("clsx");
@@ -88,6 +88,64 @@ function createMessageId() {
88
88
  return globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
89
89
  }
90
90
 
91
+ // src/lib/message.ts
92
+ var import_lodash_es = require("lodash-es");
93
+ var ASSISTANT_STREAM_IDLE_TO_THINKING_MS = 2e3;
94
+ function hasRenderableReasoning(reasoning) {
95
+ return Array.isArray(reasoning) && reasoning.some((item) => item.text?.trim());
96
+ }
97
+ function hasRenderableMessageContent(content) {
98
+ if (typeof content === "string") {
99
+ return content.trim().length > 0;
100
+ }
101
+ if (!Array.isArray(content) || content.length === 0) {
102
+ return false;
103
+ }
104
+ const items = content;
105
+ return items.some((item) => {
106
+ if (typeof item === "string") {
107
+ return item.trim().length > 0;
108
+ }
109
+ if (!item || typeof item !== "object") {
110
+ return false;
111
+ }
112
+ if (item.type === "text") {
113
+ return Boolean(item.text?.trim());
114
+ }
115
+ if (item.type === "reasoning") {
116
+ return Boolean(item.text?.trim());
117
+ }
118
+ return true;
119
+ });
120
+ }
121
+ function hasRenderableAssistantMessage(message) {
122
+ return hasRenderableMessageContent(message.content) || hasRenderableReasoning(message.reasoning);
123
+ }
124
+ function getAssistantStreamingStatus(message, isStreaming, options) {
125
+ if (!isStreaming) {
126
+ return null;
127
+ }
128
+ const now = options?.now ?? Date.now();
129
+ const lastStreamOutputAt = typeof message.lastStreamOutputAt === "number" ? message.lastStreamOutputAt : null;
130
+ const isIdle = lastStreamOutputAt !== null && now - lastStreamOutputAt >= ASSISTANT_STREAM_IDLE_TO_THINKING_MS;
131
+ if (message.status === "reasoning") {
132
+ return "thinking";
133
+ }
134
+ if (message.status === "answering") {
135
+ if (isIdle) {
136
+ return "thinking";
137
+ }
138
+ return "answering";
139
+ }
140
+ if (hasRenderableReasoning(message.reasoning)) {
141
+ return "thinking";
142
+ }
143
+ if (isIdle) {
144
+ return "thinking";
145
+ }
146
+ return "loading";
147
+ }
148
+
91
149
  // src/lib/scroll.ts
92
150
  var BOTTOM_FOLLOW_THRESHOLD_PX = 48;
93
151
  function getDistanceFromBottom(element) {
@@ -104,6 +162,25 @@ var import_xpert_sdk = require("@xpert-ai/xpert-sdk");
104
162
  var import_tool = require("@langchain/core/messages/tool");
105
163
  var import_chatkit_types3 = require("@xpert-ai/chatkit-types");
106
164
 
165
+ // src/lib/api-config.ts
166
+ function hasConfiguredValue(value) {
167
+ return typeof value === "string" && value.trim().length > 0;
168
+ }
169
+ function getMissingApiConfigurationKind({
170
+ apiUrl,
171
+ clientSecret
172
+ }) {
173
+ const hasApiUrl = hasConfiguredValue(apiUrl);
174
+ const hasClientSecret = hasConfiguredValue(clientSecret);
175
+ if (hasApiUrl && hasClientSecret) {
176
+ return null;
177
+ }
178
+ if (!hasApiUrl && !hasClientSecret) {
179
+ return "apiUrlAndClientSecret";
180
+ }
181
+ return hasApiUrl ? "clientSecret" : "apiUrl";
182
+ }
183
+
107
184
  // src/lib/request-options.ts
108
185
  var import_chatkit_types = require("@xpert-ai/chatkit-types");
109
186
  function isRecord(value) {
@@ -199,6 +276,302 @@ function useStreamManager() {
199
276
  };
200
277
  }
201
278
 
279
+ // src/lib/references.ts
280
+ function isObjectLike(value) {
281
+ return typeof value === "object" && value !== null && !Array.isArray(value);
282
+ }
283
+ function isNonEmptyString(value) {
284
+ return typeof value === "string" && value.trim().length > 0;
285
+ }
286
+ function isOptionalString(value) {
287
+ return value === void 0 || typeof value === "string";
288
+ }
289
+ function toOptionalString(value) {
290
+ return isNonEmptyString(value) ? value.trim() : void 0;
291
+ }
292
+ function toReferenceText(value) {
293
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
294
+ }
295
+ function toLineNumber(value) {
296
+ if (typeof value === "number" && Number.isInteger(value) && value > 0) {
297
+ return value;
298
+ }
299
+ return null;
300
+ }
301
+ function isOptionalNumber(value) {
302
+ return value === void 0 || Number.isFinite(value);
303
+ }
304
+ function toOptionalNumber(value, options) {
305
+ const allowZero = options?.allowZero ?? false;
306
+ if (!Number.isFinite(value)) {
307
+ return void 0;
308
+ }
309
+ const numberValue = value;
310
+ if (numberValue > 0 || allowZero && numberValue === 0) {
311
+ return numberValue;
312
+ }
313
+ return void 0;
314
+ }
315
+ function hasImageReferenceLocator(candidate) {
316
+ return isNonEmptyString(candidate.fileId) || isNonEmptyString(candidate.url) || isNonEmptyString(candidate.name) || isNonEmptyString(candidate.label) || isNonEmptyString(candidate.text);
317
+ }
318
+ function isCodeReferenceCandidate(value) {
319
+ if (!isObjectLike(value)) {
320
+ return false;
321
+ }
322
+ const candidate = value;
323
+ return isNonEmptyString(candidate.path) && toLineNumber(candidate.startLine) !== null && toLineNumber(candidate.endLine) !== null && toReferenceText(candidate.text) !== null && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.language) && isOptionalString(candidate.taskId);
324
+ }
325
+ function isQuoteReferenceCandidate(value) {
326
+ if (!isObjectLike(value)) {
327
+ return false;
328
+ }
329
+ const candidate = value;
330
+ return candidate.type === "quote" && toReferenceText(candidate.text) !== null && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.messageId) && isOptionalString(candidate.source);
331
+ }
332
+ function isImageReferenceCandidate(value) {
333
+ if (!isObjectLike(value)) {
334
+ return false;
335
+ }
336
+ const candidate = value;
337
+ return candidate.type === "image" && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.text) && isOptionalString(candidate.fileId) && isOptionalString(candidate.url) && isOptionalString(candidate.mimeType) && isOptionalString(candidate.name) && isOptionalNumber(candidate.size) && isOptionalNumber(candidate.width) && isOptionalNumber(candidate.height) && hasImageReferenceLocator(candidate);
338
+ }
339
+ function toCodeReference(candidate) {
340
+ return {
341
+ type: "code",
342
+ ...toOptionalString(candidate.id) ? { id: toOptionalString(candidate.id) } : {},
343
+ ...toOptionalString(candidate.label) ? { label: toOptionalString(candidate.label) } : {},
344
+ path: candidate.path.trim(),
345
+ startLine: candidate.startLine,
346
+ endLine: candidate.endLine,
347
+ text: candidate.text,
348
+ ...toOptionalString(candidate.language) ? { language: toOptionalString(candidate.language) } : {},
349
+ ...toOptionalString(candidate.taskId) ? { taskId: toOptionalString(candidate.taskId) } : {}
350
+ };
351
+ }
352
+ function toQuoteReference(candidate) {
353
+ return {
354
+ type: "quote",
355
+ ...toOptionalString(candidate.id) ? { id: toOptionalString(candidate.id) } : {},
356
+ ...toOptionalString(candidate.label) ? { label: toOptionalString(candidate.label) } : {},
357
+ text: candidate.text,
358
+ ...toOptionalString(candidate.messageId) ? { messageId: toOptionalString(candidate.messageId) } : {},
359
+ ...toOptionalString(candidate.source) ? { source: toOptionalString(candidate.source) } : {}
360
+ };
361
+ }
362
+ function toImageReference(candidate) {
363
+ const fileId = toOptionalString(candidate.fileId);
364
+ const url = toOptionalString(candidate.url);
365
+ const name = toOptionalString(candidate.name);
366
+ const label = toOptionalString(candidate.label);
367
+ const rawText = toReferenceText(candidate.text);
368
+ const text = rawText ?? name ?? label ?? "Pasted image";
369
+ return {
370
+ type: "image",
371
+ ...toOptionalString(candidate.id) ? { id: toOptionalString(candidate.id) } : {},
372
+ ...label ? { label } : {},
373
+ text,
374
+ ...fileId ? { fileId } : {},
375
+ ...url ? { url } : {},
376
+ ...toOptionalString(candidate.mimeType) ? { mimeType: toOptionalString(candidate.mimeType) } : {},
377
+ ...name ? { name } : {},
378
+ ...toOptionalNumber(candidate.size, { allowZero: true }) !== void 0 ? { size: toOptionalNumber(candidate.size, { allowZero: true }) } : {},
379
+ ...toOptionalNumber(candidate.width) !== void 0 ? { width: toOptionalNumber(candidate.width) } : {},
380
+ ...toOptionalNumber(candidate.height) !== void 0 ? { height: toOptionalNumber(candidate.height) } : {}
381
+ };
382
+ }
383
+ function isLegacyCodeReference(candidate) {
384
+ return candidate.type === void 0 && isNonEmptyString(candidate.path) && toLineNumber(candidate.startLine) !== null && toLineNumber(candidate.endLine) !== null && toReferenceText(candidate.text) !== null;
385
+ }
386
+ function normalizeReference(value) {
387
+ if (!isObjectLike(value)) {
388
+ return null;
389
+ }
390
+ const candidate = value;
391
+ const type = toOptionalString(candidate.type);
392
+ if (type === "code" && isCodeReferenceCandidate(candidate)) {
393
+ return toCodeReference(candidate);
394
+ }
395
+ if (isQuoteReferenceCandidate(candidate)) {
396
+ return toQuoteReference(candidate);
397
+ }
398
+ if (isImageReferenceCandidate(candidate)) {
399
+ return toImageReference(candidate);
400
+ }
401
+ if (type === void 0 && isLegacyCodeReference(candidate)) {
402
+ return toCodeReference(candidate);
403
+ }
404
+ return null;
405
+ }
406
+ function normalizeReferences(value) {
407
+ if (!Array.isArray(value)) {
408
+ return [];
409
+ }
410
+ return value.map((item) => normalizeReference(item)).filter((item) => item !== null);
411
+ }
412
+ function getCodeReferenceRange(reference) {
413
+ return reference.startLine === reference.endLine ? `${reference.startLine}` : `${reference.startLine}-${reference.endLine}`;
414
+ }
415
+ function getQuoteExcerpt(reference) {
416
+ const normalized = reference.text.replace(/\s+/g, " ").trim();
417
+ if (normalized.length <= 32) {
418
+ return normalized;
419
+ }
420
+ return `${normalized.slice(0, 29)}...`;
421
+ }
422
+ function getCodeReferenceLocation(reference) {
423
+ return `${reference.path}:${getCodeReferenceRange(reference)}`;
424
+ }
425
+ function formatReferenceSize(size2) {
426
+ if (size2 < 1024) {
427
+ return `${size2} B`;
428
+ }
429
+ if (size2 < 1024 * 1024) {
430
+ return `${(size2 / 1024).toFixed(size2 < 10 * 1024 ? 1 : 0)} KB`;
431
+ }
432
+ return `${(size2 / (1024 * 1024)).toFixed(size2 < 10 * 1024 * 1024 ? 1 : 0)} MB`;
433
+ }
434
+ function getImageReferenceDimensions(reference) {
435
+ if (!reference.width || !reference.height) {
436
+ return null;
437
+ }
438
+ return `${reference.width}x${reference.height}`;
439
+ }
440
+ function getImageReferenceMetaParts(reference) {
441
+ return [
442
+ reference.mimeType?.trim() || null,
443
+ getImageReferenceDimensions(reference),
444
+ typeof reference.size === "number" ? formatReferenceSize(reference.size) : null
445
+ ].filter((part) => Boolean(part));
446
+ }
447
+ function getReferenceKey(reference) {
448
+ if (reference.type === "image" && reference.fileId?.trim()) {
449
+ return `image:${reference.fileId.trim()}`;
450
+ }
451
+ if (reference.id && reference.id.trim()) {
452
+ return reference.id.trim();
453
+ }
454
+ if (reference.type === "code") {
455
+ return [
456
+ reference.type,
457
+ reference.path,
458
+ reference.startLine,
459
+ reference.endLine,
460
+ reference.text
461
+ ].join(":");
462
+ }
463
+ if (reference.type === "image") {
464
+ return [
465
+ reference.type,
466
+ reference.url ?? "",
467
+ reference.name ?? "",
468
+ reference.mimeType ?? "",
469
+ reference.size ?? "",
470
+ reference.width ?? "",
471
+ reference.height ?? "",
472
+ reference.text
473
+ ].join(":");
474
+ }
475
+ return [
476
+ reference.type,
477
+ reference.messageId ?? "",
478
+ reference.source ?? "",
479
+ reference.text
480
+ ].join(":");
481
+ }
482
+ function mergeReferences(current, incoming) {
483
+ const merged = [...current];
484
+ const seen = new Set(current.map(getReferenceKey));
485
+ incoming.forEach((reference) => {
486
+ const key = getReferenceKey(reference);
487
+ if (seen.has(key)) {
488
+ return;
489
+ }
490
+ seen.add(key);
491
+ merged.push(reference);
492
+ });
493
+ return merged;
494
+ }
495
+ function getReferenceLabel(reference) {
496
+ if (reference.label && reference.label.trim()) {
497
+ return reference.label.trim();
498
+ }
499
+ if (reference.type === "code") {
500
+ const segments = reference.path.split("/");
501
+ const fileName = segments[segments.length - 1] || reference.path;
502
+ return `${fileName} ${getCodeReferenceRange(reference)}`;
503
+ }
504
+ if (reference.type === "image") {
505
+ return reference.name?.trim() || "Pasted image";
506
+ }
507
+ if (reference.source && reference.source.trim()) {
508
+ return reference.source.trim();
509
+ }
510
+ return getQuoteExcerpt(reference);
511
+ }
512
+ function getReferenceMetaLine(reference) {
513
+ if (reference.type === "code") {
514
+ return getCodeReferenceLocation(reference);
515
+ }
516
+ if (reference.type === "image") {
517
+ const parts = getImageReferenceMetaParts(reference);
518
+ return parts.length ? parts.join(" \u2022 ") : null;
519
+ }
520
+ if (reference.source && reference.source.trim()) {
521
+ return getQuoteExcerpt(reference);
522
+ }
523
+ if (reference.messageId && reference.messageId.trim()) {
524
+ return `Message ${reference.messageId.trim()}`;
525
+ }
526
+ return null;
527
+ }
528
+ function getReferenceTitle(reference) {
529
+ if (reference.type === "code") {
530
+ return `${getCodeReferenceLocation(reference)}
531
+
532
+ ${reference.text}`;
533
+ }
534
+ if (reference.type === "image") {
535
+ const titleLines = [getReferenceLabel(reference)];
536
+ const metaLine = getReferenceMetaLine(reference);
537
+ const url = reference.url?.trim() && !reference.url.trim().startsWith("data:") ? reference.url.trim() : null;
538
+ if (metaLine) {
539
+ titleLines.push(metaLine);
540
+ }
541
+ if (url) {
542
+ titleLines.push(url);
543
+ }
544
+ if (reference.text.trim() && reference.text.trim() !== getReferenceLabel(reference)) {
545
+ titleLines.push("", reference.text.trim());
546
+ }
547
+ return titleLines.join("\n");
548
+ }
549
+ const header = reference.label?.trim() || reference.source?.trim() || "Quoted text";
550
+ return `${header}
551
+
552
+ ${reference.text}`;
553
+ }
554
+ function buildHumanMessageInputPayload(source) {
555
+ const references = normalizeReferences(source.references);
556
+ const nextReferenceComposition = source.referenceComposition ?? (references.length > 0 && typeof source.submittedInput !== "string" ? "compose" : void 0);
557
+ if (typeof source.submittedInput === "string") {
558
+ return {
559
+ input: source.submittedInput.trim(),
560
+ ...references.length > 0 ? { references } : {},
561
+ ...nextReferenceComposition ? { referenceComposition: nextReferenceComposition } : {}
562
+ };
563
+ }
564
+ const input = typeof source.content === "string" ? source.content.trim() : "";
565
+ if (!input && references.length === 0) {
566
+ return null;
567
+ }
568
+ return {
569
+ input,
570
+ ...references.length > 0 ? { references } : {},
571
+ ...nextReferenceComposition ? { referenceComposition: nextReferenceComposition } : {}
572
+ };
573
+ }
574
+
202
575
  // src/providers/ParentMessenger.tsx
203
576
  var import_jsx_runtime = require("react/jsx-runtime");
204
577
  var handledSendUserMessageNonces = /* @__PURE__ */ new Set();
@@ -227,6 +600,10 @@ function ParentMessengerProvider({
227
600
  /* @__PURE__ */ new Map()
228
601
  );
229
602
  const onSetOptionsHandlersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
603
+ const onSetComposerValueHandlersRef = (0, import_react.useRef)(
604
+ /* @__PURE__ */ new Set()
605
+ );
606
+ const onFocusComposerHandlersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
230
607
  const latestOptionsRef = (0, import_react.useRef)(null);
231
608
  const isParentAvailable = (0, import_react.useMemo)(() => {
232
609
  return typeof window !== "undefined" && window.parent !== window;
@@ -240,6 +617,24 @@ function ParentMessengerProvider({
240
617
  onSetOptionsHandlersRef.current.delete(handler);
241
618
  };
242
619
  }, []);
620
+ const registerOnSetComposerValue = (0, import_react.useCallback)(
621
+ (handler) => {
622
+ onSetComposerValueHandlersRef.current.add(handler);
623
+ return () => {
624
+ onSetComposerValueHandlersRef.current.delete(handler);
625
+ };
626
+ },
627
+ []
628
+ );
629
+ const registerOnFocusComposer = (0, import_react.useCallback)(
630
+ (handler) => {
631
+ onFocusComposerHandlersRef.current.add(handler);
632
+ return () => {
633
+ onFocusComposerHandlersRef.current.delete(handler);
634
+ };
635
+ },
636
+ []
637
+ );
243
638
  (0, import_react.useEffect)(() => {
244
639
  if (!isParentAvailable) return;
245
640
  const sendResponse = (nonce, response, error) => {
@@ -260,7 +655,7 @@ function ParentMessengerProvider({
260
655
  }
261
656
  const payload = event.data;
262
657
  if (payload.__xpaiChatKit !== true) return;
263
- if (payload.type == "command" && payload.command === "onSendUserMessage") {
658
+ if (payload.type === "command" && payload.command === "onSendUserMessage") {
264
659
  const nonce = typeof payload.nonce === "string" ? payload.nonce : null;
265
660
  if (nonce) {
266
661
  if (handledSendUserMessageNonces.has(nonce)) return;
@@ -270,34 +665,53 @@ function ParentMessengerProvider({
270
665
  handledSendUserMessageEvents.add(event);
271
666
  }
272
667
  const params = payload.data;
273
- const prompt = (params.text ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.input ?? "").trim();
668
+ const prompt = typeof params.text === "string" ? params.text.trim() : typeof params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.input === "string" ? params.state[import_chatkit_types2.STATE_VARIABLE_HUMAN].input.trim() : "";
669
+ const references = normalizeReferences(
670
+ params.references ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.references
671
+ );
672
+ const referenceComposition = params.referenceComposition ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.referenceComposition;
673
+ const humanInput = buildHumanMessageInputPayload({
674
+ content: prompt,
675
+ references,
676
+ referenceComposition
677
+ });
678
+ if (!humanInput) {
679
+ if (payload.nonce) {
680
+ sendResponse(payload.nonce, { ok: true });
681
+ }
682
+ return;
683
+ }
274
684
  const newMessage = {
275
685
  id: createMessageId(),
276
686
  type: "human",
277
- content: prompt
687
+ content: prompt,
688
+ submittedInput: humanInput.input,
689
+ ...humanInput.referenceComposition ? { referenceComposition: humanInput.referenceComposition } : {},
690
+ ...references.length > 0 ? { references } : {}
278
691
  };
692
+ const stream = streamRef2.current;
693
+ const activeFollowUpMode = stream?.isLoading ? params.followUpMode && params.followUpMode !== "default" ? params.followUpMode : stream.followUpBehavior ?? "queue" : void 0;
279
694
  const requestOptions = buildInjectedRequestOptions({
280
695
  defaults: latestOptionsRef.current?.request,
281
696
  state: params.state,
282
- humanInput: {
283
- input: prompt
284
- }
697
+ humanInput
285
698
  });
286
- streamRef2.current?.submit(
699
+ stream?.submit(
287
700
  {
288
- input: {
289
- input: prompt
290
- },
701
+ input: humanInput,
291
702
  ...requestOptions.state ? { state: requestOptions.state } : {}
292
703
  },
293
704
  {
294
705
  newThread: params.newThread,
706
+ ...activeFollowUpMode ? { followUpMode: activeFollowUpMode } : {},
295
707
  ...requestOptions.context ? { context: requestOptions.context } : {},
296
708
  ...requestOptions.config ? { config: requestOptions.config } : {},
297
- optimisticValues: (prev) => {
298
- const prevMessages = prev?.messages ?? [];
299
- return { ...prev, messages: [...prevMessages, newMessage] };
300
- }
709
+ ...!activeFollowUpMode ? {
710
+ optimisticValues: (prev) => {
711
+ const prevMessages = prev?.messages ?? [];
712
+ return { ...prev, messages: [...prevMessages, newMessage] };
713
+ }
714
+ } : {}
301
715
  }
302
716
  );
303
717
  if (payload.nonce) {
@@ -305,7 +719,28 @@ function ParentMessengerProvider({
305
719
  }
306
720
  return;
307
721
  }
308
- if (payload.type == "command" && payload.command === "onSetOptions") {
722
+ if (payload.type === "command" && payload.command === "onSetComposerValue") {
723
+ const nextPayload = payload.data ?? null;
724
+ const normalizedPayload = nextPayload && Array.isArray(nextPayload.references) ? {
725
+ ...nextPayload,
726
+ references: normalizeReferences(nextPayload.references)
727
+ } : nextPayload;
728
+ void Promise.all(
729
+ [...onSetComposerValueHandlersRef.current].map(
730
+ (handler2) => Promise.resolve(handler2(normalizedPayload))
731
+ )
732
+ ).then(() => {
733
+ if (payload.nonce) {
734
+ sendResponse(payload.nonce, { ok: true });
735
+ }
736
+ }).catch((error) => {
737
+ if (payload.nonce) {
738
+ sendResponse(payload.nonce, void 0, error);
739
+ }
740
+ });
741
+ return;
742
+ }
743
+ if (payload.type === "command" && payload.command === "onSetOptions") {
309
744
  latestOptionsRef.current = payload.data ?? null;
310
745
  if (onSetOptionsHandlersRef.current.size > 0) {
311
746
  onSetOptionsHandlersRef.current.forEach((handler2) => {
@@ -317,16 +752,41 @@ function ParentMessengerProvider({
317
752
  }
318
753
  return;
319
754
  }
320
- if (payload.type == "command" && payload.command === "onSetThreadId") {
755
+ if (payload.type === "command" && payload.command === "onFocusComposer") {
756
+ void Promise.all(
757
+ [...onFocusComposerHandlersRef.current].map(
758
+ (handler2) => Promise.resolve(handler2())
759
+ )
760
+ ).then(() => {
761
+ if (payload.nonce) {
762
+ sendResponse(payload.nonce, { ok: true });
763
+ }
764
+ }).catch((error) => {
765
+ if (payload.nonce) {
766
+ sendResponse(payload.nonce, void 0, error);
767
+ }
768
+ });
769
+ return;
770
+ }
771
+ if (payload.type === "command" && payload.command === "onSetThreadId") {
321
772
  const data = payload.data;
322
773
  const nextThreadId = data?.threadId ?? null;
323
774
  const stream = streamRef2.current;
775
+ if (stream?.threadId === nextThreadId) {
776
+ if (payload.nonce) {
777
+ sendResponse(payload.nonce, { ok: true });
778
+ }
779
+ return;
780
+ }
324
781
  stream?.reset(nextThreadId, void 0, { suppressThreadChange: true });
325
782
  if (stream && nextThreadId) {
326
783
  stream.loadThread(nextThreadId).catch((err) => {
327
784
  console.warn("Failed to load thread messages", err);
328
785
  });
329
786
  }
787
+ if (payload.nonce) {
788
+ sendResponse(payload.nonce, { ok: true });
789
+ }
330
790
  return;
331
791
  }
332
792
  if (payload.type !== "response") return;
@@ -387,25 +847,55 @@ function ParentMessengerProvider({
387
847
  isParentAvailable,
388
848
  sendCommand,
389
849
  sendEvent,
390
- registerOnSetOptions
850
+ registerOnSetOptions,
851
+ registerOnSetComposerValue,
852
+ registerOnFocusComposer
391
853
  }),
392
- [isParentAvailable, sendCommand, sendEvent, registerOnSetOptions]
854
+ [
855
+ isParentAvailable,
856
+ sendCommand,
857
+ sendEvent,
858
+ registerOnSetOptions,
859
+ registerOnSetComposerValue,
860
+ registerOnFocusComposer
861
+ ]
393
862
  );
394
863
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ParentMessengerContext.Provider, { value, children });
395
864
  }
396
865
 
397
866
  // src/hooks/useParentMessenger.tsx
398
- function useParentMessenger({ onSetOptions } = {}) {
867
+ function useParentMessenger({
868
+ onSetOptions,
869
+ onSetComposerValue,
870
+ onFocusComposer
871
+ } = {}) {
399
872
  const context = (0, import_react2.useContext)(ParentMessengerContext);
400
873
  if (!context) {
401
- throw new Error("useParentMessenger must be used within a ParentMessengerProvider");
874
+ throw new Error(
875
+ "useParentMessenger must be used within a ParentMessengerProvider"
876
+ );
402
877
  }
403
- const { registerOnSetOptions, ...messenger } = context;
878
+ const {
879
+ registerOnSetOptions,
880
+ registerOnSetComposerValue,
881
+ registerOnFocusComposer,
882
+ ...messenger
883
+ } = context;
404
884
  const onSetOptionsRef = (0, import_react2.useRef)(onSetOptions);
885
+ const onSetComposerValueRef = (0, import_react2.useRef)(onSetComposerValue);
886
+ const onFocusComposerRef = (0, import_react2.useRef)(onFocusComposer);
405
887
  (0, import_react2.useEffect)(() => {
406
888
  onSetOptionsRef.current = onSetOptions;
407
889
  }, [onSetOptions]);
890
+ (0, import_react2.useEffect)(() => {
891
+ onSetComposerValueRef.current = onSetComposerValue;
892
+ }, [onSetComposerValue]);
893
+ (0, import_react2.useEffect)(() => {
894
+ onFocusComposerRef.current = onFocusComposer;
895
+ }, [onFocusComposer]);
408
896
  const hasOnSetOptions = Boolean(onSetOptions);
897
+ const hasOnSetComposerValue = Boolean(onSetComposerValue);
898
+ const hasOnFocusComposer = Boolean(onFocusComposer);
409
899
  (0, import_react2.useEffect)(() => {
410
900
  if (!hasOnSetOptions) return;
411
901
  const handler = (options) => {
@@ -413,6 +903,20 @@ function useParentMessenger({ onSetOptions } = {}) {
413
903
  };
414
904
  return registerOnSetOptions(handler);
415
905
  }, [hasOnSetOptions, registerOnSetOptions]);
906
+ (0, import_react2.useEffect)(() => {
907
+ if (!hasOnSetComposerValue) return;
908
+ const handler = (payload) => {
909
+ onSetComposerValueRef.current?.(payload);
910
+ };
911
+ return registerOnSetComposerValue(handler);
912
+ }, [hasOnSetComposerValue, registerOnSetComposerValue]);
913
+ (0, import_react2.useEffect)(() => {
914
+ if (!hasOnFocusComposer) return;
915
+ const handler = () => {
916
+ onFocusComposerRef.current?.();
917
+ };
918
+ return registerOnFocusComposer(handler);
919
+ }, [hasOnFocusComposer, registerOnFocusComposer]);
416
920
  return messenger;
417
921
  }
418
922
 
@@ -446,6 +950,17 @@ function resolveUsedContextSize(options) {
446
950
  return normalizeContextUsageNumber(options.fallbackUsedTokens) ?? 0;
447
951
  }
448
952
 
953
+ // src/lib/follow-ups.ts
954
+ function getComposerFollowUpShortcutLabels(queueShortcutLabel) {
955
+ return {
956
+ steer: "Enter",
957
+ queue: queueShortcutLabel
958
+ };
959
+ }
960
+ function getBusyComposerShortcutFollowUpMode(useQueueShortcut) {
961
+ return useQueueShortcut ? "queue" : "steer";
962
+ }
963
+
449
964
  // src/providers/Stream.tsx
450
965
  var import_jsx_runtime2 = require("react/jsx-runtime");
451
966
  var import_meta = {};
@@ -567,12 +1082,39 @@ var en_US_default = {
567
1082
  statusOnline: "Online",
568
1083
  missingConfigShort: "Missing ChatKit configuration.",
569
1084
  missingConfigDetail: "Missing ChatKit configuration. Check `VITE_XPERTAI_API_URL`, and the `clientSecret` prop.",
1085
+ missingApiUrlShort: "Missing ChatKit API URL.",
1086
+ missingApiUrlDetail: "Missing ChatKit API URL. Check `VITE_XPERTAI_API_URL` or `options.api.apiUrl`.",
1087
+ missingClientSecretShort: "Missing ChatKit client secret.",
1088
+ missingClientSecretDetail: "Missing ChatKit client secret. Check the `clientSecret` prop or `api.getClientSecret` integration.",
1089
+ missingApiUrlAndClientSecretShort: "Missing ChatKit API URL and client secret.",
1090
+ missingApiUrlAndClientSecretDetail: "Missing ChatKit API URL and client secret. Check `VITE_XPERTAI_API_URL`, `options.api.apiUrl`, and your client secret integration.",
570
1091
  loadingThread: "Loading thread...",
571
1092
  stop: "Stop",
572
1093
  send: "Send message",
1094
+ referencedContentOnly: "Referenced content",
1095
+ youLabel: "You",
573
1096
  scrollToBottom: "Scroll to bottom",
574
1097
  retryUpload: "Retry upload",
575
1098
  poweredBy: "Powered by Xpert AI",
1099
+ followUps: {
1100
+ label: "Follow-up behavior",
1101
+ settings: "Settings",
1102
+ idleHint: "Used when you send while a run is active.",
1103
+ activeHint: "This message will use the selected busy-run behavior.",
1104
+ pending: "Pending follow-ups",
1105
+ queue: "Queue",
1106
+ steer: "Steer",
1107
+ steerAction: "Steer",
1108
+ promoteToSteer: "Steer now",
1109
+ sendNow: "Send now",
1110
+ remove: "Remove pending follow-up",
1111
+ more: "More actions",
1112
+ edit: "Edit message",
1113
+ turnOffQueueing: "Turn off queueing",
1114
+ queueHint: "Starts after the current run finishes",
1115
+ manualQueueHint: "Ready to send as a new run",
1116
+ steerHint: "Injects after the current tool call"
1117
+ },
576
1118
  errors: {
577
1119
  loadMessages: "Failed to load thread messages",
578
1120
  createThread: "Failed to create thread",
@@ -603,13 +1145,24 @@ var en_US_default = {
603
1145
  },
604
1146
  composer: {
605
1147
  openMenu: "Open menu",
606
- addAttachment: "Add attachment"
1148
+ addAttachment: "Add attachment",
1149
+ removeReference: "Remove reference",
1150
+ quoteSelection: "Quote selection"
607
1151
  },
608
1152
  sheet: {
609
1153
  close: "Close"
610
1154
  },
611
1155
  markdown: {
612
- copy: "Copy"
1156
+ copy: "Copy",
1157
+ mermaid: {
1158
+ title: "Mermaid",
1159
+ diagram: "Diagram",
1160
+ code: "Code",
1161
+ download: "Download SVG",
1162
+ fullScreen: "Open full screen",
1163
+ rendering: "Rendering diagram",
1164
+ failed: "Failed to render diagram"
1165
+ }
613
1166
  },
614
1167
  thread: {
615
1168
  errorToast: "An error occurred. Please try again.",
@@ -618,7 +1171,10 @@ var en_US_default = {
618
1171
  },
619
1172
  message: {
620
1173
  answer: "Answer",
621
- reasoning: "Reasoning"
1174
+ reasoning: "Reasoning",
1175
+ loading: "Loading",
1176
+ thinking: "Thinking",
1177
+ answering: "Answering"
622
1178
  }
623
1179
  };
624
1180
 
@@ -630,12 +1186,39 @@ var zh_CN_default = {
630
1186
  statusOnline: "\u5728\u7EBF",
631
1187
  missingConfigShort: "\u7F3A\u5C11 ChatKit \u914D\u7F6E\u3002",
632
1188
  missingConfigDetail: "\u7F3A\u5C11 ChatKit \u914D\u7F6E\u3002\u8BF7\u68C0\u67E5 `VITE_XPERTAI_API_URL` \u548C `clientSecret` \u53C2\u6570\u3002",
1189
+ missingApiUrlShort: "\u7F3A\u5C11 ChatKit API URL\u3002",
1190
+ missingApiUrlDetail: "\u7F3A\u5C11 ChatKit API URL\u3002\u8BF7\u68C0\u67E5 `VITE_XPERTAI_API_URL` \u6216 `options.api.apiUrl`\u3002",
1191
+ missingClientSecretShort: "\u7F3A\u5C11 ChatKit client secret\u3002",
1192
+ missingClientSecretDetail: "\u7F3A\u5C11 ChatKit client secret\u3002\u8BF7\u68C0\u67E5 `clientSecret` \u53C2\u6570\u6216 `api.getClientSecret` \u96C6\u6210\u3002",
1193
+ missingApiUrlAndClientSecretShort: "\u7F3A\u5C11 ChatKit API URL \u548C client secret\u3002",
1194
+ missingApiUrlAndClientSecretDetail: "\u7F3A\u5C11 ChatKit API URL \u548C client secret\u3002\u8BF7\u68C0\u67E5 `VITE_XPERTAI_API_URL`\u3001`options.api.apiUrl` \u4EE5\u53CA client secret \u96C6\u6210\u3002",
633
1195
  loadingThread: "\u6B63\u5728\u52A0\u8F7D\u7EBF\u7A0B...",
634
1196
  stop: "\u505C\u6B62",
635
1197
  send: "\u53D1\u9001\u6D88\u606F",
1198
+ referencedContentOnly: "\u5DF2\u5F15\u7528\u5185\u5BB9",
1199
+ youLabel: "\u4F60",
636
1200
  scrollToBottom: "\u56DE\u5230\u5E95\u90E8",
637
1201
  retryUpload: "\u91CD\u65B0\u4E0A\u4F20",
638
1202
  poweredBy: "\u7531 Xpert AI \u9A71\u52A8",
1203
+ followUps: {
1204
+ label: "Follow-up \u6A21\u5F0F",
1205
+ settings: "\u8BBE\u7F6E",
1206
+ idleHint: "\u4EC5\u5728\u8FD0\u884C\u4E2D\u53D1\u9001\u6D88\u606F\u65F6\u751F\u6548\u3002",
1207
+ activeHint: "\u5F53\u524D\u6D88\u606F\u4F1A\u6309\u6240\u9009\u7684\u8FD0\u884C\u4E2D\u884C\u4E3A\u5904\u7406\u3002",
1208
+ pending: "\u5F85\u5904\u7406 Follow-up",
1209
+ queue: "\u6392\u961F",
1210
+ steer: "\u5F15\u5BFC",
1211
+ steerAction: "\u5F15\u5BFC",
1212
+ promoteToSteer: "\u8F6C\u4E3A\u5F15\u5BFC",
1213
+ sendNow: "\u7ACB\u5373\u53D1\u9001",
1214
+ remove: "\u79FB\u9664\u6B64\u5F85\u5904\u7406 Follow-up",
1215
+ more: "\u66F4\u591A\u64CD\u4F5C",
1216
+ edit: "\u7F16\u8F91\u6D88\u606F",
1217
+ turnOffQueueing: "\u5173\u95ED\u6392\u961F",
1218
+ queueHint: "\u5F53\u524D\u8FD0\u884C\u7ED3\u675F\u540E\u5F00\u542F\u4E0B\u4E00\u8F6E",
1219
+ manualQueueHint: "\u4FDD\u7559\u4E3A\u5F85\u53D1\u9001\uFF0C\u53EF\u624B\u52A8\u5F00\u542F\u65B0\u4E00\u8F6E",
1220
+ steerHint: "\u5F53\u524D\u5DE5\u5177\u8C03\u7528\u5B8C\u6210\u540E\u6CE8\u5165"
1221
+ },
639
1222
  errors: {
640
1223
  loadMessages: "\u52A0\u8F7D\u7EBF\u7A0B\u6D88\u606F\u5931\u8D25",
641
1224
  createThread: "\u521B\u5EFA\u7EBF\u7A0B\u5931\u8D25",
@@ -666,13 +1249,24 @@ var zh_CN_default = {
666
1249
  },
667
1250
  composer: {
668
1251
  openMenu: "\u6253\u5F00\u83DC\u5355",
669
- addAttachment: "\u6DFB\u52A0\u9644\u4EF6"
1252
+ addAttachment: "\u6DFB\u52A0\u9644\u4EF6",
1253
+ removeReference: "\u79FB\u9664\u5F15\u7528",
1254
+ quoteSelection: "\u5F15\u7528\u9009\u4E2D\u5185\u5BB9"
670
1255
  },
671
1256
  sheet: {
672
1257
  close: "\u5173\u95ED"
673
1258
  },
674
1259
  markdown: {
675
- copy: "\u590D\u5236"
1260
+ copy: "\u590D\u5236",
1261
+ mermaid: {
1262
+ title: "Mermaid",
1263
+ diagram: "\u56FE\u8868",
1264
+ code: "\u4EE3\u7801",
1265
+ download: "\u4E0B\u8F7D SVG",
1266
+ fullScreen: "\u5168\u5C4F\u67E5\u770B",
1267
+ rendering: "\u6B63\u5728\u6E32\u67D3\u56FE\u8868",
1268
+ failed: "\u56FE\u8868\u6E32\u67D3\u5931\u8D25"
1269
+ }
676
1270
  },
677
1271
  thread: {
678
1272
  errorToast: "\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u91CD\u8BD5\u3002",
@@ -681,7 +1275,10 @@ var zh_CN_default = {
681
1275
  },
682
1276
  message: {
683
1277
  answer: "\u56DE\u7B54",
684
- reasoning: "\u63A8\u7406"
1278
+ reasoning: "\u63A8\u7406",
1279
+ loading: "\u6B63\u5728\u52A0\u8F7D",
1280
+ thinking: "\u6B63\u5728\u601D\u8003",
1281
+ answering: "\u6B63\u5728\u751F\u6210"
685
1282
  }
686
1283
  };
687
1284
 
@@ -1202,18 +1799,86 @@ function ComposerMenu({
1202
1799
 
1203
1800
  // src/components/composer/SendButton.tsx
1204
1801
  var import_lucide_react2 = require("lucide-react");
1802
+
1803
+ // src/components/ui/tooltip.tsx
1804
+ var React6 = require("react");
1805
+ var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
1205
1806
  var import_jsx_runtime7 = require("react/jsx-runtime");
1807
+ function TooltipProvider({
1808
+ delayDuration = 0,
1809
+ ...props
1810
+ }) {
1811
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1812
+ TooltipPrimitive.Provider,
1813
+ {
1814
+ "data-slot": "tooltip-provider",
1815
+ delayDuration,
1816
+ ...props
1817
+ }
1818
+ );
1819
+ }
1820
+ function Tooltip({
1821
+ ...props
1822
+ }) {
1823
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1824
+ TooltipPrimitive.Root,
1825
+ {
1826
+ "data-slot": "tooltip",
1827
+ ...props
1828
+ }
1829
+ ) });
1830
+ }
1831
+ function TooltipTrigger({
1832
+ ...props
1833
+ }) {
1834
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1835
+ TooltipPrimitive.Trigger,
1836
+ {
1837
+ "data-slot": "tooltip-trigger",
1838
+ ...props
1839
+ }
1840
+ );
1841
+ }
1842
+ function TooltipContent({
1843
+ className,
1844
+ sideOffset = 0,
1845
+ hideArrow = false,
1846
+ children,
1847
+ ...props
1848
+ }) {
1849
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1850
+ TooltipPrimitive.Content,
1851
+ {
1852
+ "data-slot": "tooltip-content",
1853
+ sideOffset,
1854
+ className: cn(
1855
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
1856
+ className
1857
+ ),
1858
+ ...props,
1859
+ children: [
1860
+ children,
1861
+ !hideArrow ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" }) : null
1862
+ ]
1863
+ }
1864
+ ) });
1865
+ }
1866
+
1867
+ // src/components/composer/SendButton.tsx
1868
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1206
1869
  function SendButton({
1207
1870
  disabled = false,
1208
1871
  isLoading = false,
1872
+ showStop = isLoading,
1209
1873
  onStop,
1210
1874
  stopLabel = "Stop",
1211
- sendLabel = "Send"
1875
+ sendLabel = "Send",
1876
+ shortcuts
1212
1877
  }) {
1213
1878
  const { theme } = useTheme();
1214
1879
  const roundedClass = getRoundedClass(theme.radius);
1215
- if (isLoading) {
1216
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1880
+ if (showStop) {
1881
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1217
1882
  "button",
1218
1883
  {
1219
1884
  type: "button",
@@ -1226,11 +1891,11 @@ function SendButton({
1226
1891
  "hover:scale-105 active:scale-95"
1227
1892
  ),
1228
1893
  "aria-label": stopLabel,
1229
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.Square, { size: 14, fill: "currentColor", stroke: "currentColor", strokeWidth: 0 })
1894
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Square, { size: 14, fill: "currentColor", stroke: "currentColor", strokeWidth: 0 })
1230
1895
  }
1231
1896
  );
1232
1897
  }
1233
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1898
+ const button = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1234
1899
  "button",
1235
1900
  {
1236
1901
  type: "submit",
@@ -1244,34 +1909,63 @@ function SendButton({
1244
1909
  "disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:scale-100"
1245
1910
  ),
1246
1911
  "aria-label": sendLabel,
1247
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.ArrowUp, { size: 18, strokeWidth: 2.5 })
1912
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.ArrowUp, { size: 18, strokeWidth: 2.5 })
1248
1913
  }
1249
1914
  );
1915
+ if (!shortcuts?.length || disabled) {
1916
+ return button;
1917
+ }
1918
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Tooltip, { children: [
1919
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipTrigger, { asChild: true, children: button }),
1920
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1921
+ TooltipContent,
1922
+ {
1923
+ side: "top",
1924
+ sideOffset: 10,
1925
+ hideArrow: true,
1926
+ className: cn(
1927
+ "min-w-36 border border-border/70 bg-background px-3 py-2 text-foreground shadow-lg",
1928
+ roundedClass
1929
+ ),
1930
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "space-y-1", children: shortcuts.map((shortcut) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1931
+ "div",
1932
+ {
1933
+ className: "flex items-center justify-between gap-4 text-sm",
1934
+ children: [
1935
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-medium", children: shortcut.label }),
1936
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("kbd", { className: "inline-flex min-w-16 items-center justify-center rounded-full bg-muted px-2.5 py-0.5 text-xs font-medium text-muted-foreground", children: shortcut.keys })
1937
+ ]
1938
+ },
1939
+ `${shortcut.label}-${shortcut.keys}`
1940
+ )) })
1941
+ }
1942
+ )
1943
+ ] });
1250
1944
  }
1251
1945
 
1252
1946
  // src/components/history/HistorySidebar.tsx
1253
- var React8 = __toESM(require("react"), 1);
1947
+ var React9 = __toESM(require("react"), 1);
1254
1948
  var import_lucide_react4 = require("lucide-react");
1255
1949
 
1256
1950
  // src/components/ui/scroll-area.tsx
1257
- var React6 = __toESM(require("react"), 1);
1951
+ var React7 = __toESM(require("react"), 1);
1258
1952
  var ScrollAreaPrimitive = __toESM(require("@radix-ui/react-scroll-area"), 1);
1259
- var import_jsx_runtime8 = require("react/jsx-runtime");
1260
- var ScrollArea = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1953
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1954
+ var ScrollArea = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1261
1955
  ScrollAreaPrimitive.Root,
1262
1956
  {
1263
1957
  ref,
1264
1958
  className: cn("relative overflow-hidden", className),
1265
1959
  ...props,
1266
1960
  children: [
1267
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
1268
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ScrollBar, {}),
1269
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ScrollAreaPrimitive.Corner, {})
1961
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
1962
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollBar, {}),
1963
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollAreaPrimitive.Corner, {})
1270
1964
  ]
1271
1965
  }
1272
1966
  ));
1273
1967
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
1274
- var ScrollBar = React6.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1968
+ var ScrollBar = React7.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1275
1969
  ScrollAreaPrimitive.ScrollAreaScrollbar,
1276
1970
  {
1277
1971
  ref,
@@ -1283,30 +1977,30 @@ var ScrollBar = React6.forwardRef(({ className, orientation = "vertical", ...pro
1283
1977
  className
1284
1978
  ),
1285
1979
  ...props,
1286
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
1980
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
1287
1981
  }
1288
1982
  ));
1289
1983
  ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
1290
1984
 
1291
1985
  // src/components/ui/sheet.tsx
1292
- var React7 = require("react");
1986
+ var React8 = require("react");
1293
1987
  var import_lucide_react3 = require("lucide-react");
1294
1988
  var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
1295
- var import_jsx_runtime9 = require("react/jsx-runtime");
1989
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1296
1990
  function Sheet({ ...props }) {
1297
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SheetPrimitive.Root, { ...props });
1991
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Root, { ...props });
1298
1992
  }
1299
1993
  function SheetTrigger({ ...props }) {
1300
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SheetPrimitive.Trigger, { ...props });
1994
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Trigger, { ...props });
1301
1995
  }
1302
1996
  function SheetPortal({ ...props }) {
1303
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SheetPrimitive.Portal, { ...props });
1997
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetPrimitive.Portal, { ...props });
1304
1998
  }
1305
1999
  function SheetOverlay({
1306
2000
  className,
1307
2001
  ...props
1308
2002
  }) {
1309
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2003
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1310
2004
  SheetPrimitive.Overlay,
1311
2005
  {
1312
2006
  className: cn(
@@ -1330,9 +2024,9 @@ function SheetContent({
1330
2024
  left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
1331
2025
  right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
1332
2026
  };
1333
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SheetPortal, { children: [
1334
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SheetOverlay, {}),
1335
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2027
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SheetPortal, { children: [
2028
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetOverlay, {}),
2029
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1336
2030
  SheetPrimitive.Content,
1337
2031
  {
1338
2032
  className: cn(
@@ -1343,9 +2037,9 @@ function SheetContent({
1343
2037
  ...props,
1344
2038
  children: [
1345
2039
  children,
1346
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SheetPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
1347
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react3.X, { size: 16 }),
1348
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "sr-only", children: t("sheet.close") })
2040
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SheetPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
2041
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.X, { size: 16 }),
2042
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "sr-only", children: t("sheet.close") })
1349
2043
  ] })
1350
2044
  ]
1351
2045
  }
@@ -1356,7 +2050,7 @@ function SheetHeader({
1356
2050
  className,
1357
2051
  ...props
1358
2052
  }) {
1359
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2053
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1360
2054
  "div",
1361
2055
  {
1362
2056
  className: cn(
@@ -1371,7 +2065,7 @@ function SheetTitle({
1371
2065
  className,
1372
2066
  ...props
1373
2067
  }) {
1374
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2068
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1375
2069
  SheetPrimitive.Title,
1376
2070
  {
1377
2071
  className: cn("text-lg font-semibold text-foreground", className),
@@ -1381,7 +2075,7 @@ function SheetTitle({
1381
2075
  }
1382
2076
 
1383
2077
  // src/components/history/HistorySidebar.tsx
1384
- var import_jsx_runtime10 = require("react/jsx-runtime");
2078
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1385
2079
  function HistorySidebar({
1386
2080
  threads = [],
1387
2081
  currentThreadId,
@@ -1392,7 +2086,7 @@ function HistorySidebar({
1392
2086
  disabled = false
1393
2087
  }) {
1394
2088
  const { t } = useChatkitTranslation();
1395
- const [open, setOpen] = React8.useState(false);
2089
+ const [open, setOpen] = React9.useState(false);
1396
2090
  const handleNewThread = () => {
1397
2091
  onNewThread?.();
1398
2092
  setOpen(false);
@@ -1401,8 +2095,8 @@ function HistorySidebar({
1401
2095
  onSelectThread?.(id);
1402
2096
  setOpen(false);
1403
2097
  };
1404
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Sheet, { open, onOpenChange: setOpen, children: [
1405
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2098
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Sheet, { open, onOpenChange: setOpen, children: [
2099
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SheetTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1406
2100
  Button,
1407
2101
  {
1408
2102
  variant: "ghost",
@@ -1410,26 +2104,26 @@ function HistorySidebar({
1410
2104
  disabled,
1411
2105
  className: "h-8 w-8 cursor-pointer",
1412
2106
  children: [
1413
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.History, { size: 16 }),
1414
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "sr-only", children: t("history.threadHistory") })
2107
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.History, { size: 16 }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "sr-only", children: t("history.threadHistory") })
1415
2109
  ]
1416
2110
  }
1417
2111
  ) }),
1418
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SheetContent, { side: "right", className: "w-80 p-0", children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetHeader, { className: "border-b p-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SheetTitle, { children: t("history.title") }) }),
1420
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-4", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2112
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(SheetContent, { side: "right", className: "w-80 p-0", children: [
2113
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SheetHeader, { className: "border-b p-4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SheetTitle, { children: t("history.title") }) }),
2114
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1421
2115
  Button,
1422
2116
  {
1423
2117
  onClick: handleNewThread,
1424
2118
  className: "w-full justify-start gap-2",
1425
2119
  variant: "secondary",
1426
2120
  children: [
1427
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.PlusCircle, { size: 16 }),
2121
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.PlusCircle, { size: 16 }),
1428
2122
  t("history.newThread")
1429
2123
  ]
1430
2124
  }
1431
2125
  ) }),
1432
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ScrollArea, { className: "h-[calc(100vh-140px)]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "px-4 pb-4", children: threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "py-8 text-center text-sm text-muted-foreground", children: t("history.empty") }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "space-y-1", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2126
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScrollArea, { className: "h-[calc(100vh-140px)]", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "px-4 pb-4", children: threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "py-8 text-center text-sm text-muted-foreground", children: t("history.empty") }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "space-y-1", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1433
2127
  "div",
1434
2128
  {
1435
2129
  className: cn(
@@ -1439,9 +2133,9 @@ function HistorySidebar({
1439
2133
  ),
1440
2134
  onClick: () => handleSelectThread(thread.id),
1441
2135
  children: [
1442
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.MessageSquare, { size: 16 }) }),
1443
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "flex-1 truncate", children: thread.title }),
1444
- showDelete && onDeleteThread && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2136
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.MessageSquare, { size: 16 }) }),
2137
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "flex-1 truncate", children: thread.title }),
2138
+ showDelete && onDeleteThread && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1445
2139
  "button",
1446
2140
  {
1447
2141
  type: "button",
@@ -1450,7 +2144,7 @@ function HistorySidebar({
1450
2144
  onDeleteThread(thread.id);
1451
2145
  },
1452
2146
  className: "opacity-0 group-hover:opacity-100 p-1 rounded hover:bg-destructive/10 hover:text-destructive transition-all",
1453
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react4.Trash2, { size: 14 })
2147
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.Trash2, { size: 14 })
1454
2148
  }
1455
2149
  )
1456
2150
  ]
@@ -1461,31 +2155,327 @@ function HistorySidebar({
1461
2155
  ] });
1462
2156
  }
1463
2157
 
1464
- // src/components/thread/messages/ai.tsx
1465
- var React13 = __toESM(require("react"), 1);
1466
- var import_lucide_react6 = require("lucide-react");
2158
+ // src/components/composer/pending-follow-ups.tsx
2159
+ var React10 = __toESM(require("react"), 1);
2160
+ var import_lucide_react5 = require("lucide-react");
2161
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2162
+ function getPendingFollowUpText(item, referencedContentFallback) {
2163
+ const text = item.request?.input?.input?.trim() ?? "";
2164
+ if (text) {
2165
+ return text;
2166
+ }
2167
+ const references = normalizeReferences(item.request?.input?.references);
2168
+ if (references.length === 0) {
2169
+ return referencedContentFallback;
2170
+ }
2171
+ const firstReferenceLabel = getReferenceLabel(references[0]);
2172
+ if (references.length === 1) {
2173
+ return firstReferenceLabel;
2174
+ }
2175
+ return `${firstReferenceLabel} +${references.length - 1}`;
2176
+ }
2177
+ function useRoundedClasses() {
2178
+ const { theme } = useTheme();
2179
+ return {
2180
+ top: theme.radius ? {
2181
+ pill: "rounded-t-full",
2182
+ round: "rounded-t-xl",
2183
+ soft: "rounded-t-lg",
2184
+ sharp: "rounded-t-none"
2185
+ }[theme.radius] : "rounded-t-lg",
2186
+ panel: getRoundedClass(theme.radius, "rounded-lg"),
2187
+ control: getRoundedClass(theme.radius, "rounded-md")
2188
+ };
2189
+ }
2190
+ function PendingFollowUps({
2191
+ items,
2192
+ isLoading,
2193
+ followUpBehavior,
2194
+ onBehaviorChange,
2195
+ onPromoteToSteer,
2196
+ canSendNow,
2197
+ onSendNow,
2198
+ onEdit,
2199
+ onRemove,
2200
+ className
2201
+ }) {
2202
+ const { t } = useChatkitTranslation();
2203
+ const rounded = useRoundedClasses();
2204
+ const referencedContentFallback = t("chat.referencedContentOnly");
2205
+ const [isSettingsOpen, setIsSettingsOpen] = React10.useState(false);
2206
+ const [openMenuId, setOpenMenuId] = React10.useState(null);
2207
+ React10.useEffect(() => {
2208
+ if (items.length === 0 && isSettingsOpen) {
2209
+ setIsSettingsOpen(false);
2210
+ }
2211
+ if (items.every((item) => item.id !== openMenuId)) {
2212
+ setOpenMenuId(null);
2213
+ }
2214
+ }, [isSettingsOpen, items, openMenuId]);
2215
+ if (items.length === 0) {
2216
+ return null;
2217
+ }
2218
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2219
+ "div",
2220
+ {
2221
+ className: cn(
2222
+ "space-y-2 mx-2 p-2 border border-border border-b-0",
2223
+ rounded.top,
2224
+ className
2225
+ ),
2226
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
2227
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
2228
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs font-medium text-foreground", children: t("chat.followUps.pending") }),
2229
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Tooltip, { children: [
2230
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2231
+ "button",
2232
+ {
2233
+ type: "button",
2234
+ onClick: () => setIsSettingsOpen((prev) => !prev),
2235
+ className: cn(
2236
+ "inline-flex h-6 w-6 items-center justify-center transition-colors",
2237
+ isSettingsOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/60 hover:text-foreground",
2238
+ rounded.control
2239
+ ),
2240
+ "aria-label": t("chat.followUps.settings"),
2241
+ "aria-expanded": isSettingsOpen,
2242
+ "aria-controls": "follow-ups-settings-panel",
2243
+ children: [
2244
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.SlidersHorizontal, { className: "h-3.5 w-3.5" }),
2245
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "sr-only", children: t("chat.followUps.settings") })
2246
+ ]
2247
+ }
2248
+ ) }),
2249
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipContent, { side: "top", children: t("chat.followUps.settings") })
2250
+ ] })
2251
+ ] }),
2252
+ isSettingsOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2253
+ "div",
2254
+ {
2255
+ id: "follow-ups-settings-panel",
2256
+ className: cn(
2257
+ "border border-border/70 bg-muted/20 px-3 py-2",
2258
+ rounded.panel
2259
+ ),
2260
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
2261
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
2262
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs font-medium text-foreground", children: t("chat.followUps.label") }),
2263
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-[11px] text-muted-foreground", children: isLoading ? t("chat.followUps.activeHint") : t("chat.followUps.idleHint") })
2264
+ ] }),
2265
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2266
+ "div",
2267
+ {
2268
+ className: cn(
2269
+ "inline-flex shrink-0 border border-border bg-background p-1",
2270
+ rounded.control
2271
+ ),
2272
+ children: ["queue", "steer"].map((behavior) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Tooltip, { children: [
2273
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2274
+ "button",
2275
+ {
2276
+ type: "button",
2277
+ onClick: () => {
2278
+ onBehaviorChange(behavior);
2279
+ setIsSettingsOpen(false);
2280
+ },
2281
+ className: cn(
2282
+ "px-3 py-1 text-xs font-medium transition-colors",
2283
+ rounded.control,
2284
+ followUpBehavior === behavior ? "bg-primary text-background" : "text-muted-foreground hover:text-foreground"
2285
+ ),
2286
+ children: behavior === "queue" ? t("chat.followUps.queue") : t("chat.followUps.steer")
2287
+ }
2288
+ ) }),
2289
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipContent, { side: "top", children: behavior === "queue" ? t("chat.followUps.queueHint") : t("chat.followUps.steerHint") })
2290
+ ] }, behavior))
2291
+ }
2292
+ )
2293
+ ] })
2294
+ }
2295
+ ),
2296
+ items.map((item) => {
2297
+ const canSendItemNow = item.mode === "queue" && canSendNow(item.id);
2298
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2299
+ "div",
2300
+ {
2301
+ className: cn(
2302
+ "border border-border/50 bg-muted/15 px-2 py-1",
2303
+ rounded.panel
2304
+ ),
2305
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start gap-2.5", children: [
2306
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.CornerDownLeft, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
2307
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0 flex-1", children: [
2308
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start gap-2", children: [
2309
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2310
+ "div",
2311
+ {
2312
+ className: "truncate text-[13px] leading-5 text-foreground",
2313
+ title: getPendingFollowUpText(
2314
+ item,
2315
+ referencedContentFallback
2316
+ ),
2317
+ children: getPendingFollowUpText(
2318
+ item,
2319
+ referencedContentFallback
2320
+ )
2321
+ }
2322
+ ) }),
2323
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
2324
+ item.mode === "queue" && isLoading && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2325
+ "button",
2326
+ {
2327
+ type: "button",
2328
+ onClick: () => void onPromoteToSteer(item.id),
2329
+ className: cn(
2330
+ "inline-flex h-6 items-center border border-primary/20 bg-primary/5 px-2 text-[11px] font-medium text-primary transition-colors hover:bg-primary/10",
2331
+ rounded.control
2332
+ ),
2333
+ "aria-label": t("chat.followUps.steerAction"),
2334
+ title: t("chat.followUps.steerAction"),
2335
+ children: t("chat.followUps.steerAction")
2336
+ }
2337
+ ),
2338
+ canSendItemNow && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2339
+ "button",
2340
+ {
2341
+ type: "button",
2342
+ onClick: () => void onSendNow(item.id),
2343
+ className: cn(
2344
+ "inline-flex h-6 items-center border border-primary/20 bg-primary/5 px-2 text-[11px] font-medium text-primary transition-colors hover:bg-primary/10",
2345
+ rounded.control
2346
+ ),
2347
+ "aria-label": t("chat.followUps.sendNow"),
2348
+ title: t("chat.followUps.sendNow"),
2349
+ children: t("chat.followUps.sendNow")
2350
+ }
2351
+ ),
2352
+ item.mode === "queue" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2353
+ "button",
2354
+ {
2355
+ type: "button",
2356
+ onClick: () => onRemove(item.id),
2357
+ className: cn(
2358
+ "inline-flex h-6 w-6 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
2359
+ rounded.control
2360
+ ),
2361
+ "aria-label": t("chat.followUps.remove"),
2362
+ title: t("chat.followUps.remove"),
2363
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Trash2, { size: 13 })
2364
+ }
2365
+ ),
2366
+ item.mode === "queue" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2367
+ Popover,
2368
+ {
2369
+ open: openMenuId === item.id,
2370
+ onOpenChange: (open) => setOpenMenuId(open ? item.id : null),
2371
+ children: [
2372
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2373
+ "button",
2374
+ {
2375
+ type: "button",
2376
+ className: cn(
2377
+ "inline-flex h-6 w-6 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
2378
+ rounded.control
2379
+ ),
2380
+ "aria-label": t("chat.followUps.more"),
2381
+ title: t("chat.followUps.more"),
2382
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Ellipsis, { size: 13 })
2383
+ }
2384
+ ) }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2386
+ PopoverContent,
2387
+ {
2388
+ align: "end",
2389
+ side: "bottom",
2390
+ className: cn(
2391
+ "w-52 border-border/70 bg-background p-1.5",
2392
+ rounded.panel
2393
+ ),
2394
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-1", children: [
2395
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2396
+ "button",
2397
+ {
2398
+ type: "button",
2399
+ onClick: () => {
2400
+ setOpenMenuId(null);
2401
+ onEdit(item.id);
2402
+ },
2403
+ className: cn(
2404
+ "flex items-center gap-2 px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-muted",
2405
+ rounded.control
2406
+ ),
2407
+ children: [
2408
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.PencilLine, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
2409
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t("chat.followUps.edit") })
2410
+ ]
2411
+ }
2412
+ ),
2413
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2414
+ "button",
2415
+ {
2416
+ type: "button",
2417
+ onClick: () => {
2418
+ setOpenMenuId(null);
2419
+ onBehaviorChange("steer");
2420
+ },
2421
+ className: cn(
2422
+ "flex items-center gap-2 px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-muted",
2423
+ rounded.control
2424
+ ),
2425
+ children: [
2426
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.CornerDownLeft, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
2427
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t("chat.followUps.turnOffQueueing") })
2428
+ ]
2429
+ }
2430
+ )
2431
+ ] })
2432
+ }
2433
+ )
2434
+ ]
2435
+ }
2436
+ )
2437
+ ] })
2438
+ ] }),
2439
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1.5 text-[10px] leading-4 text-muted-foreground", children: [
2440
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Info, { className: "h-3 w-3 shrink-0" }),
2441
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "truncate", children: item.mode === "queue" ? canSendItemNow ? t("chat.followUps.manualQueueHint") : t("chat.followUps.queueHint") : t("chat.followUps.steerHint") })
2442
+ ] })
2443
+ ] })
2444
+ ] })
2445
+ },
2446
+ item.id
2447
+ );
2448
+ })
2449
+ ] })
2450
+ }
2451
+ );
2452
+ }
2453
+
2454
+ // src/components/thread/messages/ai.tsx
2455
+ var React15 = __toESM(require("react"), 1);
2456
+ var import_lucide_react8 = require("lucide-react");
1467
2457
 
1468
2458
  // src/components/ui/badge.tsx
1469
- var React9 = __toESM(require("react"), 1);
1470
- var import_jsx_runtime11 = require("react/jsx-runtime");
2459
+ var React11 = __toESM(require("react"), 1);
2460
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1471
2461
  var base = "inline-flex items-center rounded-full border border-transparent px-2.5 py-0.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background";
1472
2462
  var variants = {
1473
2463
  default: "bg-primary text-primary-foreground",
1474
2464
  secondary: "bg-secondary text-secondary-foreground",
1475
2465
  outline: "border-input text-foreground"
1476
2466
  };
1477
- var Badge = React9.forwardRef(
2467
+ var Badge = React11.forwardRef(
1478
2468
  ({ className, variant = "default", ...props }, ref) => {
1479
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { ref, className: cn(base, variants[variant], className), ...props });
2469
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { ref, className: cn(base, variants[variant], className), ...props });
1480
2470
  }
1481
2471
  );
1482
2472
  Badge.displayName = "Badge";
1483
2473
 
1484
2474
  // src/components/ui/card.tsx
1485
- var React10 = __toESM(require("react"), 1);
1486
- var import_jsx_runtime12 = require("react/jsx-runtime");
1487
- var Card = React10.forwardRef(
1488
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2475
+ var React12 = __toESM(require("react"), 1);
2476
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2477
+ var Card = React12.forwardRef(
2478
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1489
2479
  "div",
1490
2480
  {
1491
2481
  ref,
@@ -1498,50 +2488,50 @@ var Card = React10.forwardRef(
1498
2488
  )
1499
2489
  );
1500
2490
  Card.displayName = "Card";
1501
- var CardHeader = React10.forwardRef(
1502
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref, className: cn("flex flex-col gap-1.5 px-6 pt-6", className), ...props })
2491
+ var CardHeader = React12.forwardRef(
2492
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("flex flex-col gap-1.5 px-6 pt-6", className), ...props })
1503
2493
  );
1504
2494
  CardHeader.displayName = "CardHeader";
1505
- var CardTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { ref, className: cn("text-lg font-semibold leading-tight", className), ...props }));
2495
+ var CardTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { ref, className: cn("text-lg font-semibold leading-tight", className), ...props }));
1506
2496
  CardTitle.displayName = "CardTitle";
1507
- var CardDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
2497
+ var CardDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1508
2498
  CardDescription.displayName = "CardDescription";
1509
- var CardContent = React10.forwardRef(
1510
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref, className: cn("px-6 pb-6", className), ...props })
2499
+ var CardContent = React12.forwardRef(
2500
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("px-6 pb-6", className), ...props })
1511
2501
  );
1512
2502
  CardContent.displayName = "CardContent";
1513
- var CardFooter = React10.forwardRef(
1514
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref, className: cn("flex items-center px-6 pb-6", className), ...props })
2503
+ var CardFooter = React12.forwardRef(
2504
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("flex items-center px-6 pb-6", className), ...props })
1515
2505
  );
1516
2506
  CardFooter.displayName = "CardFooter";
1517
- var CardAction = React10.forwardRef(
1518
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { ref, className: cn("ml-auto flex items-center", className), ...props })
2507
+ var CardAction = React12.forwardRef(
2508
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("ml-auto flex items-center", className), ...props })
1519
2509
  );
1520
2510
  CardAction.displayName = "CardAction";
1521
2511
 
1522
2512
  // src/components/ui/tabs.tsx
1523
- var React11 = __toESM(require("react"), 1);
1524
- var import_jsx_runtime13 = require("react/jsx-runtime");
1525
- var TabsContext = React11.createContext(null);
2513
+ var React13 = __toESM(require("react"), 1);
2514
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2515
+ var TabsContext = React13.createContext(null);
1526
2516
  function Tabs({ className, defaultValue, value, onValueChange, ...props }) {
1527
- const [internalValue, setInternalValue] = React11.useState(defaultValue ?? "");
2517
+ const [internalValue, setInternalValue] = React13.useState(defaultValue ?? "");
1528
2518
  const activeValue = value ?? internalValue;
1529
- const setValue = React11.useCallback(
2519
+ const setValue = React13.useCallback(
1530
2520
  (nextValue) => {
1531
2521
  if (value === void 0) setInternalValue(nextValue);
1532
2522
  onValueChange?.(nextValue);
1533
2523
  },
1534
2524
  [onValueChange, value]
1535
2525
  );
1536
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TabsContext.Provider, { value: { value: activeValue, setValue }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("w-full", className), ...props }) });
2526
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TabsContext.Provider, { value: { value: activeValue, setValue }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn("w-full", className), ...props }) });
1537
2527
  }
1538
- var TabsList = React11.forwardRef(
1539
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2528
+ var TabsList = React13.forwardRef(
2529
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1540
2530
  "div",
1541
2531
  {
1542
2532
  ref,
1543
2533
  className: cn(
1544
- "inline-flex h-11 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
2534
+ "inline-flex items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
1545
2535
  className
1546
2536
  ),
1547
2537
  role: "tablist",
@@ -1550,14 +2540,14 @@ var TabsList = React11.forwardRef(
1550
2540
  )
1551
2541
  );
1552
2542
  TabsList.displayName = "TabsList";
1553
- var TabsTrigger = React11.forwardRef(
2543
+ var TabsTrigger = React13.forwardRef(
1554
2544
  ({ className, value, onClick, ...props }, ref) => {
1555
- const context = React11.useContext(TabsContext);
2545
+ const context = React13.useContext(TabsContext);
1556
2546
  if (!context) {
1557
2547
  throw new Error("TabsTrigger must be used within Tabs");
1558
2548
  }
1559
2549
  const isActive = context.value === value;
1560
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2550
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1561
2551
  "button",
1562
2552
  {
1563
2553
  ref,
@@ -1566,7 +2556,7 @@ var TabsTrigger = React11.forwardRef(
1566
2556
  "aria-selected": isActive,
1567
2557
  "data-state": isActive ? "active" : "inactive",
1568
2558
  className: cn(
1569
- "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-2 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
2559
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
1570
2560
  className
1571
2561
  ),
1572
2562
  onClick: (event) => {
@@ -1579,14 +2569,14 @@ var TabsTrigger = React11.forwardRef(
1579
2569
  }
1580
2570
  );
1581
2571
  TabsTrigger.displayName = "TabsTrigger";
1582
- var TabsContent = React11.forwardRef(
2572
+ var TabsContent = React13.forwardRef(
1583
2573
  ({ className, value, ...props }, ref) => {
1584
- const context = React11.useContext(TabsContext);
2574
+ const context = React13.useContext(TabsContext);
1585
2575
  if (!context) {
1586
2576
  throw new Error("TabsContent must be used within Tabs");
1587
2577
  }
1588
2578
  if (context.value !== value) return null;
1589
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2579
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1590
2580
  "div",
1591
2581
  {
1592
2582
  ref,
@@ -1608,7 +2598,7 @@ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
1608
2598
  var import_rehype_katex = __toESM(require("rehype-katex"), 1);
1609
2599
  var import_remark_math = __toESM(require("remark-math"), 1);
1610
2600
  var import_react6 = require("react");
1611
- var import_lucide_react5 = require("lucide-react");
2601
+ var import_lucide_react7 = require("lucide-react");
1612
2602
 
1613
2603
  // src/components/thread/syntax-highlighter.tsx
1614
2604
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
@@ -1616,7 +2606,7 @@ var import_tsx = __toESM(require("react-syntax-highlighter/dist/esm/languages/pr
1616
2606
  var import_python = __toESM(require("react-syntax-highlighter/dist/esm/languages/prism/python"), 1);
1617
2607
  var import_prism = require("react-syntax-highlighter/dist/cjs/styles/prism");
1618
2608
  var import_react4 = require("react");
1619
- var import_jsx_runtime14 = require("react/jsx-runtime");
2609
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1620
2610
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("js", import_tsx.default);
1621
2611
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("jsx", import_tsx.default);
1622
2612
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("ts", import_tsx.default);
@@ -1627,7 +2617,7 @@ var SyntaxHighlighter = ({
1627
2617
  language,
1628
2618
  className
1629
2619
  }) => {
1630
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2620
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1631
2621
  import_react_syntax_highlighter.PrismAsyncLight,
1632
2622
  {
1633
2623
  language,
@@ -1644,77 +2634,18 @@ var SyntaxHighlighter = ({
1644
2634
  );
1645
2635
  };
1646
2636
 
1647
- // src/components/thread/tooltip-icon-button.tsx
1648
- var import_react5 = require("react");
1649
-
1650
- // src/components/ui/tooltip.tsx
1651
- var React12 = require("react");
1652
- var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
1653
- var import_jsx_runtime15 = require("react/jsx-runtime");
1654
- function TooltipProvider({
1655
- delayDuration = 0,
1656
- ...props
1657
- }) {
1658
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1659
- TooltipPrimitive.Provider,
1660
- {
1661
- "data-slot": "tooltip-provider",
1662
- delayDuration,
1663
- ...props
1664
- }
1665
- );
1666
- }
1667
- function Tooltip({
1668
- ...props
1669
- }) {
1670
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1671
- TooltipPrimitive.Root,
1672
- {
1673
- "data-slot": "tooltip",
1674
- ...props
1675
- }
1676
- ) });
1677
- }
1678
- function TooltipTrigger({
1679
- ...props
1680
- }) {
1681
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1682
- TooltipPrimitive.Trigger,
1683
- {
1684
- "data-slot": "tooltip-trigger",
1685
- ...props
1686
- }
1687
- );
1688
- }
1689
- function TooltipContent({
1690
- className,
1691
- sideOffset = 0,
1692
- children,
1693
- ...props
1694
- }) {
1695
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1696
- TooltipPrimitive.Content,
1697
- {
1698
- "data-slot": "tooltip-content",
1699
- sideOffset,
1700
- className: cn(
1701
- "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit rounded-md px-3 py-1.5 text-xs text-balance",
1702
- className
1703
- ),
1704
- ...props,
1705
- children: [
1706
- children,
1707
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
1708
- ]
1709
- }
1710
- ) });
1711
- }
2637
+ // src/components/thread/mermaid-block.tsx
2638
+ var Dialog = __toESM(require("@radix-ui/react-dialog"), 1);
2639
+ var import_mermaid = __toESM(require("mermaid"), 1);
2640
+ var import_lucide_react6 = require("lucide-react");
2641
+ var React14 = __toESM(require("react"), 1);
1712
2642
 
1713
2643
  // src/components/thread/tooltip-icon-button.tsx
1714
- var import_jsx_runtime16 = require("react/jsx-runtime");
2644
+ var import_react5 = require("react");
2645
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1715
2646
  var TooltipIconButton = (0, import_react5.forwardRef)(({ children, tooltip, side = "bottom", className, ...rest }, ref) => {
1716
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Tooltip, { children: [
1717
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2647
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
2648
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1718
2649
  Button,
1719
2650
  {
1720
2651
  variant: "ghost",
@@ -1724,24 +2655,515 @@ var TooltipIconButton = (0, import_react5.forwardRef)(({ children, tooltip, side
1724
2655
  ref,
1725
2656
  children: [
1726
2657
  children,
1727
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "sr-only", children: tooltip })
2658
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "sr-only", children: tooltip })
1728
2659
  ]
1729
2660
  }
1730
2661
  ) }),
1731
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipContent, { side, children: tooltip })
2662
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { side, children: tooltip })
1732
2663
  ] }) });
1733
2664
  });
1734
2665
  TooltipIconButton.displayName = "TooltipIconButton";
1735
2666
 
2667
+ // src/components/thread/mermaid-block.tsx
2668
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2669
+ var HEX_COLOR_PATTERN = /^#([\da-f]{3,8})$/i;
2670
+ var MERMAID_DIRECTIVE_PATTERN = /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi;
2671
+ var MERMAID_FRONTMATTER_PATTERN = /^-{3}\s*[\n\r](.*?)[\n\r]-{3}\s*[\n\r]+/s;
2672
+ var OKLCH_COLOR_PATTERN = /^oklch\((.+)\)$/i;
2673
+ var RGB_COLOR_PATTERN = /^rgba?\((.+)\)$/i;
2674
+ var MERMAID_SECURE_KEYS = [
2675
+ "fontFamily",
2676
+ "maxEdges",
2677
+ "maxTextSize",
2678
+ "securityLevel",
2679
+ "secure",
2680
+ "startOnLoad",
2681
+ "suppressErrorRendering",
2682
+ "theme",
2683
+ "themeVariables"
2684
+ ];
2685
+ function clamp(value, min, max) {
2686
+ return Math.min(max, Math.max(min, value));
2687
+ }
2688
+ function normalizeMermaidCode(code) {
2689
+ return code.replace(MERMAID_FRONTMATTER_PATTERN, "").replace(MERMAID_DIRECTIVE_PATTERN, "").trim();
2690
+ }
2691
+ function parseAlpha(value) {
2692
+ if (!value) return 1;
2693
+ const normalized = value.trim();
2694
+ if (!normalized) return 1;
2695
+ if (normalized.endsWith("%")) {
2696
+ return clamp(Number.parseFloat(normalized) / 100, 0, 1);
2697
+ }
2698
+ return clamp(Number.parseFloat(normalized), 0, 1);
2699
+ }
2700
+ function parseHexColor(value) {
2701
+ const match = value.trim().match(HEX_COLOR_PATTERN);
2702
+ if (!match) return null;
2703
+ const hex = match[1];
2704
+ if (hex.length === 3 || hex.length === 4) {
2705
+ const [r, g, b, a = "f"] = hex.split("");
2706
+ return {
2707
+ r: Number.parseInt(r + r, 16),
2708
+ g: Number.parseInt(g + g, 16),
2709
+ b: Number.parseInt(b + b, 16),
2710
+ a: Number.parseInt(a + a, 16) / 255
2711
+ };
2712
+ }
2713
+ if (hex.length === 6 || hex.length === 8) {
2714
+ const alphaHex = hex.length === 8 ? hex.slice(6, 8) : "ff";
2715
+ return {
2716
+ r: Number.parseInt(hex.slice(0, 2), 16),
2717
+ g: Number.parseInt(hex.slice(2, 4), 16),
2718
+ b: Number.parseInt(hex.slice(4, 6), 16),
2719
+ a: Number.parseInt(alphaHex, 16) / 255
2720
+ };
2721
+ }
2722
+ return null;
2723
+ }
2724
+ function parseRgbChannel(value) {
2725
+ const normalized = value.trim();
2726
+ if (normalized.endsWith("%")) {
2727
+ return clamp(Math.round(Number.parseFloat(normalized) / 100 * 255), 0, 255);
2728
+ }
2729
+ return clamp(Math.round(Number.parseFloat(normalized)), 0, 255);
2730
+ }
2731
+ function parseRgbColor(value) {
2732
+ const match = value.trim().match(RGB_COLOR_PATTERN);
2733
+ if (!match) return null;
2734
+ const parts = match[1].split(/[,\s/]+/).map((part) => part.trim()).filter(Boolean);
2735
+ if (parts.length < 3) return null;
2736
+ return {
2737
+ r: parseRgbChannel(parts[0]),
2738
+ g: parseRgbChannel(parts[1]),
2739
+ b: parseRgbChannel(parts[2]),
2740
+ a: parseAlpha(parts[3])
2741
+ };
2742
+ }
2743
+ function parseOklchLightness(value) {
2744
+ const normalized = value.trim();
2745
+ if (normalized.endsWith("%")) {
2746
+ return clamp(Number.parseFloat(normalized) / 100, 0, 1);
2747
+ }
2748
+ return clamp(Number.parseFloat(normalized), 0, 1);
2749
+ }
2750
+ function parseHue(value) {
2751
+ const normalized = value.trim().toLowerCase();
2752
+ const numeric = Number.parseFloat(normalized);
2753
+ if (Number.isNaN(numeric)) return 0;
2754
+ if (normalized.endsWith("turn")) return numeric * 360;
2755
+ if (normalized.endsWith("rad")) return numeric * (180 / Math.PI);
2756
+ if (normalized.endsWith("grad")) return numeric * 0.9;
2757
+ return numeric;
2758
+ }
2759
+ function linearToSrgb(linear) {
2760
+ if (linear <= 31308e-7) {
2761
+ return 12.92 * linear;
2762
+ }
2763
+ return 1.055 * Math.pow(linear, 1 / 2.4) - 0.055;
2764
+ }
2765
+ function parseOklchColor(value) {
2766
+ const match = value.trim().match(OKLCH_COLOR_PATTERN);
2767
+ if (!match) return null;
2768
+ const [base2, alphaSegment] = match[1].split("/");
2769
+ const parts = base2.trim().split(/\s+/).map((part) => part.trim()).filter(Boolean);
2770
+ if (parts.length < 3) return null;
2771
+ const lightness = parseOklchLightness(parts[0]);
2772
+ const chroma = Number.parseFloat(parts[1]);
2773
+ const hueRadians = parseHue(parts[2]) * Math.PI / 180;
2774
+ const alpha = parseAlpha(alphaSegment);
2775
+ const a = chroma * Math.cos(hueRadians);
2776
+ const b = chroma * Math.sin(hueRadians);
2777
+ const l_ = lightness + 0.3963377774 * a + 0.2158037573 * b;
2778
+ const m_ = lightness - 0.1055613458 * a - 0.0638541728 * b;
2779
+ const s_ = lightness - 0.0894841775 * a - 1.291485548 * b;
2780
+ const l = l_ * l_ * l_;
2781
+ const m = m_ * m_ * m_;
2782
+ const s = s_ * s_ * s_;
2783
+ const linearR = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
2784
+ const linearG = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
2785
+ const linearB = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;
2786
+ return {
2787
+ r: clamp(Math.round(linearToSrgb(linearR) * 255), 0, 255),
2788
+ g: clamp(Math.round(linearToSrgb(linearG) * 255), 0, 255),
2789
+ b: clamp(Math.round(linearToSrgb(linearB) * 255), 0, 255),
2790
+ a: alpha
2791
+ };
2792
+ }
2793
+ function parseCssColor(value) {
2794
+ const normalized = value.trim();
2795
+ if (!normalized) return null;
2796
+ return parseHexColor(normalized) ?? parseRgbColor(normalized) ?? parseOklchColor(normalized);
2797
+ }
2798
+ function compositeColor(foreground, background) {
2799
+ const alpha = foreground.a + background.a * (1 - foreground.a);
2800
+ if (alpha <= 0) {
2801
+ return { r: 0, g: 0, b: 0, a: 0 };
2802
+ }
2803
+ const r = (foreground.r * foreground.a + background.r * background.a * (1 - foreground.a)) / alpha;
2804
+ const g = (foreground.g * foreground.a + background.g * background.a * (1 - foreground.a)) / alpha;
2805
+ const b = (foreground.b * foreground.a + background.b * background.a * (1 - foreground.a)) / alpha;
2806
+ return {
2807
+ r: clamp(Math.round(r), 0, 255),
2808
+ g: clamp(Math.round(g), 0, 255),
2809
+ b: clamp(Math.round(b), 0, 255),
2810
+ a: clamp(alpha, 0, 1)
2811
+ };
2812
+ }
2813
+ function toHexChannel(value) {
2814
+ return value.toString(16).padStart(2, "0");
2815
+ }
2816
+ function rgbaToHex(value) {
2817
+ return `#${toHexChannel(value.r)}${toHexChannel(value.g)}${toHexChannel(value.b)}`;
2818
+ }
2819
+ function getFallbackPalette(isDarkMode) {
2820
+ if (isDarkMode) {
2821
+ return {
2822
+ background: "#171717",
2823
+ border: "#52525b",
2824
+ fontFamily: "Inter Variable, sans-serif",
2825
+ line: "#a1a1aa",
2826
+ surface: "#262626",
2827
+ surfaceAlt: "#3f3f46",
2828
+ text: "#fafafa"
2829
+ };
2830
+ }
2831
+ return {
2832
+ background: "#ffffff",
2833
+ border: "#e4e4e7",
2834
+ fontFamily: "Inter Variable, sans-serif",
2835
+ line: "#71717a",
2836
+ surface: "#ffffff",
2837
+ surfaceAlt: "#f4f4f5",
2838
+ text: "#18181b"
2839
+ };
2840
+ }
2841
+ function resolveColor(styles, property, fallback, background) {
2842
+ const parsed = parseCssColor(styles.getPropertyValue(property));
2843
+ if (!parsed) return fallback;
2844
+ if (parsed.a < 1 && background) {
2845
+ return rgbaToHex(compositeColor(parsed, background));
2846
+ }
2847
+ return rgbaToHex(parsed);
2848
+ }
2849
+ function resolvePalette(element, isDarkMode) {
2850
+ const fallback = getFallbackPalette(isDarkMode);
2851
+ const styles = window.getComputedStyle(element);
2852
+ const backgroundColor = parseCssColor(styles.getPropertyValue("--card")) ?? parseCssColor(styles.getPropertyValue("--background")) ?? parseCssColor(fallback.surface);
2853
+ return {
2854
+ background: resolveColor(styles, "--background", fallback.background, backgroundColor),
2855
+ border: resolveColor(styles, "--border", fallback.border, backgroundColor),
2856
+ fontFamily: styles.getPropertyValue("font-family").trim() || fallback.fontFamily,
2857
+ line: resolveColor(styles, "--muted-foreground", fallback.line, backgroundColor),
2858
+ surface: resolveColor(styles, "--card", fallback.surface, backgroundColor),
2859
+ surfaceAlt: resolveColor(styles, "--muted", fallback.surfaceAlt, backgroundColor),
2860
+ text: resolveColor(styles, "--foreground", fallback.text, backgroundColor)
2861
+ };
2862
+ }
2863
+ function buildThemeVariables(palette) {
2864
+ return {
2865
+ background: palette.background,
2866
+ clusterBkg: palette.surfaceAlt,
2867
+ clusterBorder: palette.border,
2868
+ edgeLabelBackground: palette.surface,
2869
+ fontFamily: palette.fontFamily,
2870
+ lineColor: palette.line,
2871
+ mainBkg: palette.surface,
2872
+ nodeBorder: palette.border,
2873
+ nodeTextColor: palette.text,
2874
+ primaryBorderColor: palette.border,
2875
+ primaryColor: palette.surfaceAlt,
2876
+ primaryTextColor: palette.text,
2877
+ secondaryBorderColor: palette.border,
2878
+ secondaryColor: palette.surface,
2879
+ secondaryTextColor: palette.text,
2880
+ tertiaryBorderColor: palette.border,
2881
+ tertiaryColor: palette.surface,
2882
+ tertiaryTextColor: palette.text,
2883
+ textColor: palette.text
2884
+ };
2885
+ }
2886
+ async function renderMermaidDiagram({
2887
+ code,
2888
+ host,
2889
+ id,
2890
+ palette
2891
+ }) {
2892
+ host.innerHTML = "";
2893
+ import_mermaid.default.initialize({
2894
+ flowchart: {
2895
+ htmlLabels: false,
2896
+ useMaxWidth: true
2897
+ },
2898
+ fontFamily: palette.fontFamily,
2899
+ secure: [...MERMAID_SECURE_KEYS],
2900
+ securityLevel: "strict",
2901
+ startOnLoad: false,
2902
+ theme: "base",
2903
+ themeVariables: buildThemeVariables(palette)
2904
+ });
2905
+ const { svg } = await import_mermaid.default.render(id, code, host);
2906
+ host.innerHTML = "";
2907
+ return svg;
2908
+ }
2909
+ function MermaidPreviewDialog({
2910
+ closeLabel,
2911
+ onOpenChange,
2912
+ open,
2913
+ svgMarkup,
2914
+ title
2915
+ }) {
2916
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Dialog.Root, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Dialog.Portal, { children: [
2917
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }),
2918
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Dialog.Content, { className: "fixed inset-[5vh] z-50 flex flex-col overflow-hidden rounded-3xl border border-border bg-background shadow-2xl outline-none data-[state=closed]:animate-out data-[state=open]:animate-in data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", children: [
2919
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center justify-between gap-4 border-b border-border px-5 py-4", children: [
2920
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Dialog.Title, { className: "text-base font-semibold text-foreground", children: title }),
2921
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Dialog.Close, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2922
+ "button",
2923
+ {
2924
+ type: "button",
2925
+ className: "inline-flex size-10 items-center justify-center rounded-full border border-border bg-card text-muted-foreground transition-colors hover:text-foreground",
2926
+ children: [
2927
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.X, { className: "size-4" }),
2928
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "sr-only", children: closeLabel })
2929
+ ]
2930
+ }
2931
+ ) })
2932
+ ] }),
2933
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex-1 overflow-auto bg-card p-6", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2934
+ "div",
2935
+ {
2936
+ "data-slot": "mermaid-preview",
2937
+ className: "min-h-full rounded-[calc(var(--radius)+0.5rem)] border border-border bg-background p-6 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-none",
2938
+ dangerouslySetInnerHTML: { __html: svgMarkup }
2939
+ }
2940
+ ) })
2941
+ ] })
2942
+ ] }) });
2943
+ }
2944
+ function MermaidBlock({ code }) {
2945
+ const { t } = useChatkitTranslation();
2946
+ const { theme, isDarkMode } = useTheme();
2947
+ const containerRef = React14.useRef(null);
2948
+ const renderHostRef = React14.useRef(null);
2949
+ const renderSequenceRef = React14.useRef(0);
2950
+ const copyResetTimeoutRef = React14.useRef(null);
2951
+ const diagramId = React14.useId().replace(/:/g, "");
2952
+ const [activeTab, setActiveTab] = React14.useState("diagram");
2953
+ const [isCopied, setIsCopied] = React14.useState(false);
2954
+ const [isPreviewOpen, setIsPreviewOpen] = React14.useState(false);
2955
+ const [isRendering, setIsRendering] = React14.useState(true);
2956
+ const [renderError, setRenderError] = React14.useState(null);
2957
+ const [svgMarkup, setSvgMarkup] = React14.useState(null);
2958
+ const normalizedCode = React14.useMemo(() => normalizeMermaidCode(code), [code]);
2959
+ const clearCopyResetTimeout = React14.useCallback(() => {
2960
+ if (copyResetTimeoutRef.current === null) return;
2961
+ window.clearTimeout(copyResetTimeoutRef.current);
2962
+ copyResetTimeoutRef.current = null;
2963
+ }, []);
2964
+ React14.useEffect(() => {
2965
+ let isActive = true;
2966
+ async function runRender() {
2967
+ const container = containerRef.current;
2968
+ const renderHost = renderHostRef.current;
2969
+ if (!container || !renderHost) return;
2970
+ setIsRendering(true);
2971
+ setRenderError(null);
2972
+ try {
2973
+ renderSequenceRef.current += 1;
2974
+ const svg = await renderMermaidDiagram({
2975
+ code: normalizedCode,
2976
+ host: renderHost,
2977
+ id: `mermaid-${diagramId}-${renderSequenceRef.current}`,
2978
+ palette: resolvePalette(container, isDarkMode)
2979
+ });
2980
+ if (!isActive) return;
2981
+ setSvgMarkup(svg);
2982
+ } catch (error) {
2983
+ if (!isActive) return;
2984
+ setSvgMarkup(null);
2985
+ setRenderError(error instanceof Error ? error.message : "render_failed");
2986
+ setActiveTab((currentTab) => currentTab === "diagram" ? "code" : currentTab);
2987
+ } finally {
2988
+ if (isActive) {
2989
+ setIsRendering(false);
2990
+ renderHost.innerHTML = "";
2991
+ }
2992
+ }
2993
+ }
2994
+ void runRender();
2995
+ return () => {
2996
+ isActive = false;
2997
+ if (renderHostRef.current) {
2998
+ renderHostRef.current.innerHTML = "";
2999
+ }
3000
+ };
3001
+ }, [diagramId, isDarkMode, normalizedCode, theme]);
3002
+ React14.useEffect(() => {
3003
+ clearCopyResetTimeout();
3004
+ setIsCopied(false);
3005
+ }, [activeTab, clearCopyResetTimeout, code]);
3006
+ React14.useEffect(
3007
+ () => () => {
3008
+ clearCopyResetTimeout();
3009
+ },
3010
+ [clearCopyResetTimeout]
3011
+ );
3012
+ const handleDownload = React14.useCallback(() => {
3013
+ if (!svgMarkup) return;
3014
+ const blob = new Blob([svgMarkup], {
3015
+ type: "image/svg+xml;charset=utf-8"
3016
+ });
3017
+ const url = window.URL.createObjectURL(blob);
3018
+ const anchor = document.createElement("a");
3019
+ anchor.href = url;
3020
+ anchor.download = `mermaid-diagram-${diagramId}.svg`;
3021
+ document.body.append(anchor);
3022
+ anchor.click();
3023
+ anchor.remove();
3024
+ window.URL.revokeObjectURL(url);
3025
+ }, [diagramId, svgMarkup]);
3026
+ const handleCopyCode = React14.useCallback(() => {
3027
+ if (!code || isCopied) return;
3028
+ navigator.clipboard.writeText(code).then(() => {
3029
+ setIsCopied(true);
3030
+ clearCopyResetTimeout();
3031
+ copyResetTimeoutRef.current = window.setTimeout(() => {
3032
+ setIsCopied(false);
3033
+ copyResetTimeoutRef.current = null;
3034
+ }, 3e3);
3035
+ }).catch(() => {
3036
+ });
3037
+ }, [clearCopyResetTimeout, code, isCopied]);
3038
+ const hasRenderedDiagram = svgMarkup !== null && !renderError;
3039
+ const statusMessage = isRendering ? t("markdown.mermaid.rendering") : t("markdown.mermaid.failed");
3040
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
3041
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3042
+ Tabs,
3043
+ {
3044
+ className: "w-full",
3045
+ onValueChange: (value) => setActiveTab(value),
3046
+ value: activeTab,
3047
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3048
+ "div",
3049
+ {
3050
+ ref: containerRef,
3051
+ "data-slot": "mermaid-block",
3052
+ className: "relative overflow-hidden text-card-foreground",
3053
+ children: [
3054
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3055
+ "div",
3056
+ {
3057
+ ref: renderHostRef,
3058
+ "aria-hidden": "true",
3059
+ className: "pointer-events-none absolute inset-0 -z-10 overflow-hidden opacity-0",
3060
+ "data-slot": "mermaid-render-host"
3061
+ }
3062
+ ),
3063
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 px-4 py-3", children: [
3064
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex min-w-0 items-center gap-3", children: [
3065
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.Code2Icon, { className: "size-4" }) }),
3066
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate text-base font-semibold text-foreground", children: t("markdown.mermaid.title") })
3067
+ ] }),
3068
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
3069
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1", children: [
3070
+ activeTab === "diagram" && hasRenderedDiagram ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3071
+ TooltipIconButton,
3072
+ {
3073
+ onClick: handleDownload,
3074
+ tooltip: t("markdown.mermaid.download"),
3075
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.DownloadIcon, { className: "size-4" })
3076
+ }
3077
+ ) : null,
3078
+ activeTab === "diagram" && hasRenderedDiagram ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3079
+ TooltipIconButton,
3080
+ {
3081
+ onClick: () => setIsPreviewOpen(true),
3082
+ tooltip: t("markdown.mermaid.fullScreen"),
3083
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.ExpandIcon, { className: "size-4" })
3084
+ }
3085
+ ) : null,
3086
+ activeTab === "code" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3087
+ TooltipIconButton,
3088
+ {
3089
+ onClick: handleCopyCode,
3090
+ tooltip: t("markdown.copy"),
3091
+ children: isCopied ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.CheckIcon, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.CopyIcon, { className: "size-4" })
3092
+ }
3093
+ ) : null
3094
+ ] }),
3095
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(TabsList, { children: [
3096
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TabsTrigger, { value: "diagram", children: t("markdown.mermaid.diagram") }),
3097
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TabsTrigger, { value: "code", children: t("markdown.mermaid.code") })
3098
+ ] })
3099
+ ] })
3100
+ ] }),
3101
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "border-t border-border pt-4", children: [
3102
+ renderError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "alert", className: "mb-4 text-sm font-medium text-destructive", children: t("markdown.mermaid.failed") }) : null,
3103
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TabsContent, { value: "diagram", className: "mt-0 space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3104
+ "div",
3105
+ {
3106
+ className: cn(
3107
+ "relative overflow-auto rounded-[calc(var(--radius)+0.5rem)] border border-border bg-background p-4",
3108
+ hasRenderedDiagram ? "[&_svg]:mx-auto [&_svg]:h-auto [&_svg]:w-full [&_svg]:max-w-none" : "min-h-[14rem]"
3109
+ ),
3110
+ children: hasRenderedDiagram ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3111
+ "div",
3112
+ {
3113
+ "data-slot": "mermaid-diagram",
3114
+ dangerouslySetInnerHTML: { __html: svgMarkup }
3115
+ }
3116
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex min-h-[12rem] flex-col items-center justify-center gap-3 text-center text-muted-foreground", children: [
3117
+ isRendering ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.Loader2, { className: "size-5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.TriangleAlert, { className: "size-5 text-destructive" }),
3118
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3119
+ "p",
3120
+ {
3121
+ className: cn("text-sm font-medium", !isRendering && "text-destructive"),
3122
+ role: renderError ? "alert" : void 0,
3123
+ children: statusMessage
3124
+ }
3125
+ )
3126
+ ] })
3127
+ }
3128
+ ) }),
3129
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TabsContent, { value: "code", className: "mt-0", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3130
+ "pre",
3131
+ {
3132
+ "data-slot": "mermaid-code",
3133
+ className: "overflow-x-auto rounded-[calc(var(--radius)+0.5rem)] border border-border bg-zinc-950 px-4 py-4 text-sm text-zinc-50",
3134
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("code", { className: "block whitespace-pre font-mono", children: code })
3135
+ }
3136
+ ) })
3137
+ ] })
3138
+ ]
3139
+ }
3140
+ )
3141
+ }
3142
+ ),
3143
+ svgMarkup ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3144
+ MermaidPreviewDialog,
3145
+ {
3146
+ closeLabel: t("sheet.close"),
3147
+ onOpenChange: setIsPreviewOpen,
3148
+ open: isPreviewOpen,
3149
+ svgMarkup,
3150
+ title: t("markdown.mermaid.title")
3151
+ }
3152
+ ) : null
3153
+ ] });
3154
+ }
3155
+
1736
3156
  // src/components/thread/markdown-text.tsx
1737
3157
  var import_katex_min = require("katex/dist/katex.min.css");
1738
- var import_jsx_runtime17 = require("react/jsx-runtime");
3158
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1739
3159
  var getTextContent = (children) => import_react6.Children.toArray(children).map((child) => {
1740
3160
  if (typeof child === "string" || typeof child === "number") {
1741
3161
  return String(child);
1742
3162
  }
1743
3163
  return "";
1744
3164
  }).join("");
3165
+ var isMermaidBlockChild = (child) => (0, import_react6.isValidElement)(child) && child.type === MermaidBlock;
3166
+ var isMermaidCodeElement = (child) => (0, import_react6.isValidElement)(child) && typeof child.props.className === "string" && child.props.className.includes("language-mermaid");
1745
3167
  var useCopyToClipboard = ({
1746
3168
  copiedDuration = 3e3
1747
3169
  } = {}) => {
@@ -1762,23 +3184,23 @@ var CodeHeader = ({ language, code }) => {
1762
3184
  if (!code || isCopied) return;
1763
3185
  copyToClipboard(code);
1764
3186
  };
1765
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white", children: [
1766
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "lowercase [&>span]:text-xs", children: language }),
1767
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
3187
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center justify-between gap-4 rounded-t-lg bg-zinc-900 px-4 py-2 text-sm font-semibold text-white", children: [
3188
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "lowercase [&>span]:text-xs", children: language }),
3189
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1768
3190
  TooltipIconButton,
1769
3191
  {
1770
3192
  tooltip: t("markdown.copy"),
1771
3193
  onClick: onCopy,
1772
3194
  children: [
1773
- !isCopied && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.CopyIcon, {}),
1774
- isCopied && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.CheckIcon, {})
3195
+ !isCopied && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react7.CopyIcon, {}),
3196
+ isCopied && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react7.CheckIcon, {})
1775
3197
  ]
1776
3198
  }
1777
3199
  )
1778
3200
  ] });
1779
3201
  };
1780
3202
  var defaultComponents = {
1781
- h1: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3203
+ h1: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1782
3204
  "h1",
1783
3205
  {
1784
3206
  className: cn(
@@ -1788,7 +3210,7 @@ var defaultComponents = {
1788
3210
  ...props
1789
3211
  }
1790
3212
  ),
1791
- h2: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3213
+ h2: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1792
3214
  "h2",
1793
3215
  {
1794
3216
  className: cn(
@@ -1798,7 +3220,7 @@ var defaultComponents = {
1798
3220
  ...props
1799
3221
  }
1800
3222
  ),
1801
- h3: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3223
+ h3: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1802
3224
  "h3",
1803
3225
  {
1804
3226
  className: cn(
@@ -1808,7 +3230,7 @@ var defaultComponents = {
1808
3230
  ...props
1809
3231
  }
1810
3232
  ),
1811
- h4: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3233
+ h4: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1812
3234
  "h4",
1813
3235
  {
1814
3236
  className: cn(
@@ -1818,7 +3240,7 @@ var defaultComponents = {
1818
3240
  ...props
1819
3241
  }
1820
3242
  ),
1821
- h5: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3243
+ h5: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1822
3244
  "h5",
1823
3245
  {
1824
3246
  className: cn(
@@ -1828,21 +3250,21 @@ var defaultComponents = {
1828
3250
  ...props
1829
3251
  }
1830
3252
  ),
1831
- h6: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3253
+ h6: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1832
3254
  "h6",
1833
3255
  {
1834
3256
  className: cn("my-4 font-semibold first:mt-0 last:mb-0", className),
1835
3257
  ...props
1836
3258
  }
1837
3259
  ),
1838
- p: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3260
+ p: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1839
3261
  "p",
1840
3262
  {
1841
3263
  className: cn("mt-5 mb-5 leading-7 first:mt-0 last:mb-0", className),
1842
3264
  ...props
1843
3265
  }
1844
3266
  ),
1845
- a: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3267
+ a: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1846
3268
  "a",
1847
3269
  {
1848
3270
  className: cn(
@@ -1858,7 +3280,7 @@ var defaultComponents = {
1858
3280
  className,
1859
3281
  node: _node,
1860
3282
  ...props
1861
- }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3283
+ }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1862
3284
  "blockquote",
1863
3285
  {
1864
3286
  className: cn(
@@ -1868,21 +3290,21 @@ var defaultComponents = {
1868
3290
  ...props
1869
3291
  }
1870
3292
  ),
1871
- ul: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3293
+ ul: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1872
3294
  "ul",
1873
3295
  {
1874
3296
  className: cn("my-5 list-outside list-disc pl-6 [&>li]:mt-2", className),
1875
3297
  ...props
1876
3298
  }
1877
3299
  ),
1878
- ol: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3300
+ ol: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1879
3301
  "ol",
1880
3302
  {
1881
3303
  className: cn("my-5 list-outside list-decimal pl-8 [&>li]:mt-2", className),
1882
3304
  ...props
1883
3305
  }
1884
3306
  ),
1885
- hr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3307
+ hr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1886
3308
  "hr",
1887
3309
  {
1888
3310
  className: cn("my-5 border-b", className),
@@ -1893,7 +3315,7 @@ var defaultComponents = {
1893
3315
  className,
1894
3316
  node: _node,
1895
3317
  ...props
1896
- }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3318
+ }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1897
3319
  "table",
1898
3320
  {
1899
3321
  className: cn(
@@ -1903,7 +3325,7 @@ var defaultComponents = {
1903
3325
  ...props
1904
3326
  }
1905
3327
  ),
1906
- th: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3328
+ th: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1907
3329
  "th",
1908
3330
  {
1909
3331
  className: cn(
@@ -1913,7 +3335,7 @@ var defaultComponents = {
1913
3335
  ...props
1914
3336
  }
1915
3337
  ),
1916
- td: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3338
+ td: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1917
3339
  "td",
1918
3340
  {
1919
3341
  className: cn(
@@ -1923,7 +3345,7 @@ var defaultComponents = {
1923
3345
  ...props
1924
3346
  }
1925
3347
  ),
1926
- tr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3348
+ tr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1927
3349
  "tr",
1928
3350
  {
1929
3351
  className: cn(
@@ -1933,21 +3355,21 @@ var defaultComponents = {
1933
3355
  ...props
1934
3356
  }
1935
3357
  ),
1936
- sup: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3358
+ sup: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1937
3359
  "sup",
1938
3360
  {
1939
3361
  className: cn("[&>a]:text-xs [&>a]:no-underline", className),
1940
3362
  ...props
1941
3363
  }
1942
3364
  ),
1943
- pre: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3365
+ pre: ({ className, children, node: _node }) => import_react6.Children.toArray(children).length === 1 && (isMermaidBlockChild(import_react6.Children.toArray(children)[0]) || isMermaidCodeElement(import_react6.Children.toArray(children)[0])) ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1944
3366
  "div",
1945
3367
  {
1946
3368
  className: cn(
1947
3369
  "max-w-4xl overflow-x-auto rounded-lg text-sm bg-black text-white dark:bg-zinc-800",
1948
3370
  className
1949
3371
  ),
1950
- ...props
3372
+ children
1951
3373
  }
1952
3374
  ),
1953
3375
  code: ({
@@ -1956,21 +3378,24 @@ var defaultComponents = {
1956
3378
  node: _node,
1957
3379
  ...props
1958
3380
  }) => {
1959
- const match = /language-(\w+)/.exec(className || "");
3381
+ const match = /language-([\w-]+)/.exec(className || "");
1960
3382
  const code = getTextContent(children);
1961
3383
  const isBlockCode = code.includes("\n");
1962
3384
  if (match) {
1963
3385
  const language = match[1];
1964
3386
  const normalizedCode = code.replace(/\n$/, "");
1965
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
1966
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3387
+ if (language === "mermaid") {
3388
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MermaidBlock, { code: normalizedCode });
3389
+ }
3390
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3391
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1967
3392
  CodeHeader,
1968
3393
  {
1969
3394
  language,
1970
3395
  code: normalizedCode
1971
3396
  }
1972
3397
  ),
1973
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3398
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1974
3399
  SyntaxHighlighter,
1975
3400
  {
1976
3401
  language,
@@ -1981,7 +3406,7 @@ var defaultComponents = {
1981
3406
  ] });
1982
3407
  }
1983
3408
  if (isBlockCode) {
1984
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3409
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1985
3410
  "code",
1986
3411
  {
1987
3412
  className: cn(
@@ -1993,7 +3418,7 @@ var defaultComponents = {
1993
3418
  }
1994
3419
  );
1995
3420
  }
1996
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3421
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1997
3422
  "code",
1998
3423
  {
1999
3424
  className: cn(
@@ -2007,7 +3432,7 @@ var defaultComponents = {
2007
3432
  }
2008
3433
  };
2009
3434
  var MarkdownTextImpl = ({ children }) => {
2010
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "markdown-content", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3435
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "markdown-content", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2011
3436
  import_react_markdown.default,
2012
3437
  {
2013
3438
  remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
@@ -2021,18 +3446,18 @@ var MarkdownText = (0, import_react6.memo)(MarkdownTextImpl);
2021
3446
 
2022
3447
  // src/components/thread/messages/widget.tsx
2023
3448
  var import_a2ui_react = require("@xpert-ai/a2ui-react");
2024
- var import_jsx_runtime18 = require("react/jsx-runtime");
3449
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2025
3450
  function WidgetMessage({ messageId, data }) {
2026
3451
  const widgets = Array.isArray(data.widgets) ? data.widgets : [];
2027
3452
  if (widgets.length === 0) return null;
2028
3453
  const baseSurfaceId = `widget-${messageId}`;
2029
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "space-y-3", children: widgets.map((widget, index) => {
3454
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "space-y-3", children: widgets.map((widget, index) => {
2030
3455
  const config = widget?.config;
2031
3456
  if (!config || typeof config !== "object") {
2032
3457
  return null;
2033
3458
  }
2034
3459
  const surfaceId = widgets.length > 1 ? `${baseSurfaceId}-${index}` : baseSurfaceId;
2035
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3460
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2036
3461
  import_a2ui_react.SurfaceRenderer,
2037
3462
  {
2038
3463
  surfaceId,
@@ -2044,7 +3469,7 @@ function WidgetMessage({ messageId, data }) {
2044
3469
  }
2045
3470
 
2046
3471
  // src/components/thread/messages/ai.tsx
2047
- var import_jsx_runtime19 = require("react/jsx-runtime");
3472
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2048
3473
  function isTextContent(content) {
2049
3474
  return content.type === "text";
2050
3475
  }
@@ -2060,15 +3485,15 @@ function isComponentContent(content) {
2060
3485
  var statusConfig = {
2061
3486
  success: {
2062
3487
  iconClass: "border-green-500 text-green-700",
2063
- icon: import_lucide_react6.CheckCircle2
3488
+ icon: import_lucide_react8.CheckCircle2
2064
3489
  },
2065
3490
  fail: {
2066
3491
  iconClass: "border-red-500 text-red-700",
2067
- icon: import_lucide_react6.XCircle
3492
+ icon: import_lucide_react8.XCircle
2068
3493
  },
2069
3494
  running: {
2070
3495
  iconClass: "border-blue-500 text-blue-700",
2071
- icon: import_lucide_react6.Loader2
3496
+ icon: import_lucide_react8.Loader2
2072
3497
  }
2073
3498
  };
2074
3499
  function isWidgetComponent(content) {
@@ -2085,14 +3510,17 @@ function safeJson(value) {
2085
3510
  return String(value);
2086
3511
  }
2087
3512
  }
3513
+ function formatDisplayValue(value) {
3514
+ return typeof value === "string" ? value : safeJson(value);
3515
+ }
2088
3516
  function ReasoningBlock({ reasoning }) {
2089
3517
  const blocks = reasoning.filter((item) => item.text?.trim());
2090
3518
  if (blocks.length === 0) return null;
2091
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-2", children: blocks.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3519
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-2", children: blocks.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2092
3520
  "div",
2093
3521
  {
2094
3522
  className: "rounded-lg border bg-muted/40 p-3 text-xs text-muted-foreground",
2095
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "whitespace-pre-wrap wrap-break-word leading-relaxed", children: item.text })
3523
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "whitespace-pre-wrap wrap-break-word leading-relaxed", children: item.text })
2096
3524
  },
2097
3525
  item.id ?? `reasoning-${index}`
2098
3526
  )) });
@@ -2100,27 +3528,27 @@ function ReasoningBlock({ reasoning }) {
2100
3528
  function ImageBlock({ content }) {
2101
3529
  const imageUrl = typeof content.image_url === "string" ? content.image_url : typeof content.image_url?.url === "string" ? content.image_url.url : null;
2102
3530
  if (!imageUrl) {
2103
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Card, { children: [
2104
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardHeader, { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardTitle, { className: "text-sm", children: "Image" }) }),
2105
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: safeJson(content) })
3531
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Card, { children: [
3532
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardHeader, { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardTitle, { className: "text-sm", children: "Image" }) }),
3533
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: safeJson(content) })
2106
3534
  ] });
2107
3535
  }
2108
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("figure", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("img", { src: imageUrl, alt: "Assistant output", className: "h-auto w-full object-cover" }) });
3536
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("figure", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: imageUrl, alt: "Assistant output", className: "h-auto w-full object-cover" }) });
2109
3537
  }
2110
3538
  function MemoryBlock({ content }) {
2111
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Card, { children: [
2112
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
2113
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardTitle, { className: "text-sm", children: "Memory" }),
2114
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Badge, { variant: "secondary", children: "Memory" })
3539
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Card, { children: [
3540
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
3541
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardTitle, { className: "text-sm", children: "Memory" }),
3542
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: "Memory" })
2115
3543
  ] }),
2116
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: safeJson(content.data ?? []) }) })
3544
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: safeJson(content.data ?? []) }) })
2117
3545
  ] });
2118
3546
  }
2119
3547
  function ComponentBlock({ content }) {
2120
- const [isExpanded, setIsExpanded] = React13.useState(false);
2121
- const contentRef = React13.useRef(null);
2122
- const shouldAutoScrollRef = React13.useRef(true);
2123
- const previousScrollTopRef = React13.useRef(0);
3548
+ const [isExpanded, setIsExpanded] = React15.useState(false);
3549
+ const contentRef = React15.useRef(null);
3550
+ const shouldAutoScrollRef = React15.useRef(true);
3551
+ const previousScrollTopRef = React15.useRef(0);
2124
3552
  const data = content.data ?? {};
2125
3553
  const category = data.category ?? "Component";
2126
3554
  const title = data.tool && category === "Tool" ? data.tool : data.title ?? data.type ?? "Component";
@@ -2128,12 +3556,12 @@ function ComponentBlock({ content }) {
2128
3556
  const message = data.message ?? null;
2129
3557
  const output = data.output ?? null;
2130
3558
  const error = data.error ?? null;
2131
- const fallback = message ?? output ?? safeJson(data.data ?? data);
3559
+ const fallback = message ?? output ?? data.data ?? data;
2132
3560
  const hasOutput = message !== null || output !== null;
2133
- React13.useEffect(() => {
3561
+ React15.useEffect(() => {
2134
3562
  if (status === "running" && output !== null) setIsExpanded(true);
2135
3563
  }, [status, output]);
2136
- React13.useEffect(() => {
3564
+ React15.useEffect(() => {
2137
3565
  const element = contentRef.current;
2138
3566
  if (!element) return;
2139
3567
  previousScrollTopRef.current = element.scrollTop;
@@ -2153,7 +3581,7 @@ function ComponentBlock({ content }) {
2153
3581
  element.removeEventListener("scroll", updateAutoScrollState);
2154
3582
  };
2155
3583
  }, [isExpanded]);
2156
- React13.useEffect(() => {
3584
+ React15.useEffect(() => {
2157
3585
  if (status !== "running") {
2158
3586
  shouldAutoScrollRef.current = true;
2159
3587
  return;
@@ -2166,21 +3594,21 @@ function ComponentBlock({ content }) {
2166
3594
  }, [isExpanded, output, status]);
2167
3595
  const config = status ? statusConfig[status] : null;
2168
3596
  const StatusIcon = config?.icon;
2169
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Card, { children: [
2170
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2 px-2 py-1 cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
2171
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center space-x-1 flex-1 min-w-0", children: [
2172
- status && StatusIcon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StatusIcon, { className: cn("h-4 w-4", config?.iconClass, status === "running" && "animate-spin") }),
2173
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardTitle, { className: "text-sm truncate", children: title })
3597
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Card, { children: [
3598
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2 px-2 py-1 cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
3599
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center space-x-1 flex-1 min-w-0", children: [
3600
+ status && StatusIcon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusIcon, { className: cn("h-4 w-4", config?.iconClass, status === "running" && "animate-spin") }),
3601
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardTitle, { className: "text-sm truncate", children: title })
2174
3602
  ] }),
2175
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-wrap items-center gap-2 shrink-0", children: [
2176
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Badge, { variant: "secondary", className: "rounded-lg px-1.5", children: category }),
2177
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3603
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2 shrink-0", children: [
3604
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", className: "rounded-lg px-1.5", children: category }),
3605
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2178
3606
  "button",
2179
3607
  {
2180
3608
  className: "text-muted-foreground hover:text-foreground transition-colors",
2181
3609
  "aria-label": isExpanded ? "Collapse" : "Expand",
2182
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2183
- import_lucide_react6.ChevronDown,
3610
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3611
+ import_lucide_react8.ChevronDown,
2184
3612
  {
2185
3613
  className: cn("h-4 w-4 transition-transform", isExpanded && "rotate-180")
2186
3614
  }
@@ -2189,89 +3617,128 @@ function ComponentBlock({ content }) {
2189
3617
  )
2190
3618
  ] })
2191
3619
  ] }),
2192
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(CardContent, { ref: contentRef, className: "text-xs text-muted-foreground max-h-60 overflow-auto", children: [
2193
- data.input && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: JSON.stringify(data.input, null, 2) }),
2194
- error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word text-destructive", children: typeof error === "string" ? error : safeJson(error) }) : hasOutput && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: fallback })
3620
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardContent, { ref: contentRef, className: "text-xs text-muted-foreground max-h-60 overflow-auto", children: [
3621
+ data.input && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: formatDisplayValue(data.input) }),
3622
+ error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word text-destructive", children: formatDisplayValue(error) }) : hasOutput && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: formatDisplayValue(fallback) })
2195
3623
  ] })
2196
3624
  ] });
2197
3625
  }
2198
3626
  function UnknownBlock({ content }) {
2199
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Card, { children: [
2200
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
2201
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardTitle, { className: "text-sm", children: "Assistant Content" }),
2202
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Badge, { variant: "outline", children: content.type ?? "unknown" })
3627
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Card, { children: [
3628
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
3629
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardTitle, { className: "text-sm", children: "Assistant Content" }),
3630
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: content.type ?? "unknown" })
2203
3631
  ] }),
2204
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "whitespace-pre-wrap break-words", children: safeJson(content) }) })
3632
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "whitespace-pre-wrap break-words", children: safeJson(content) }) })
2205
3633
  ] });
2206
3634
  }
2207
3635
  function renderContentItem(content, index, messageId) {
2208
3636
  if (typeof content === "string") {
2209
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
2210
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MarkdownText, { children: content }),
3637
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3638
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MarkdownText, { children: content }),
2211
3639
  ";"
2212
3640
  ] }, `text-${index}`);
2213
3641
  }
2214
3642
  if (isTextContent(content)) {
2215
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MarkdownText, { children: content.text }) }, content.id ?? `text-${index}`);
3643
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MarkdownText, { children: content.text }) }, content.id ?? `text-${index}`);
2216
3644
  }
2217
3645
  if (isReasoningContent(content)) {
2218
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReasoningBlock, { reasoning: [content] }) }, content.id ?? `reasoning-${index}`);
3646
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReasoningBlock, { reasoning: [content] }) }, content.id ?? `reasoning-${index}`);
2219
3647
  }
2220
3648
  if (isImageContent(content)) {
2221
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ImageBlock, { content }) }, content.id ?? `image-${index}`);
3649
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ImageBlock, { content }) }, content.id ?? `image-${index}`);
2222
3650
  }
2223
3651
  if (isComponentContent(content)) {
2224
3652
  if (isWidgetComponent(content)) {
2225
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(WidgetMessage, { messageId, data: content.data }) }, content.id ?? `widget-${index}`);
3653
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(WidgetMessage, { messageId, data: content.data }) }, content.id ?? `widget-${index}`);
2226
3654
  }
2227
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ComponentBlock, { content }) }, content.id ?? `component-${index}`);
3655
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ComponentBlock, { content }) }, content.id ?? `component-${index}`);
2228
3656
  }
2229
3657
  if (isMemoryContent(content)) {
2230
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MemoryBlock, { content }) }, content.id ?? `memory-${index}`);
3658
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MemoryBlock, { content }) }, content.id ?? `memory-${index}`);
2231
3659
  }
2232
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(UnknownBlock, { content }) }, content.id ?? `unknown-${index}`);
3660
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(UnknownBlock, { content }) }, content.id ?? `unknown-${index}`);
2233
3661
  }
2234
3662
  function renderContent(content, messageId) {
2235
3663
  if (typeof content === "string") {
2236
3664
  if (!content.trim()) return null;
2237
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MarkdownText, { children: content });
3665
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MarkdownText, { children: content });
2238
3666
  }
2239
3667
  if (!Array.isArray(content) || content.length === 0) return null;
2240
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-3", children: content.map((item, index) => renderContentItem(item, index, messageId)) });
3668
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-3", children: content.map((item, index) => renderContentItem(item, index, messageId)) });
2241
3669
  }
2242
- function AssistantMessage({ message, className, isStreaming = false }) {
3670
+ function AssistantStreamingIndicator({
3671
+ status,
3672
+ className
3673
+ }) {
2243
3674
  const { t } = useChatkitTranslation();
2244
- const content = message.content;
2245
- const hasContent = content != null && !(typeof content === "string" && content.trim() === "" || Array.isArray(message.content) && message.content.length === 0);
2246
- const hasReasoning = Array.isArray(message.reasoning) && message.reasoning.some((item) => item.text?.trim());
3675
+ const labelMap = {
3676
+ loading: t("message.loading"),
3677
+ thinking: t("message.thinking"),
3678
+ answering: t("message.answering")
3679
+ };
3680
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("flex items-center gap-2 text-xs text-muted-foreground", className), children: [
3681
+ status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
3682
+ status === "thinking" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-1", "aria-hidden": "true", children: [
3683
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce [animation-delay:-0.3s]" }),
3684
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce [animation-delay:-0.15s]" }),
3685
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce" })
3686
+ ] }),
3687
+ status === "answering" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-1", "aria-hidden": "true", children: [
3688
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-2 w-0.5 rounded-full bg-current animate-pulse [animation-delay:-0.25s]" }),
3689
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-3 w-0.5 rounded-full bg-current animate-pulse [animation-delay:-0.1s]" }),
3690
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "h-2.5 w-0.5 rounded-full bg-current animate-pulse" })
3691
+ ] }),
3692
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: labelMap[status] })
3693
+ ] });
3694
+ }
3695
+ function AssistantMessage({
3696
+ message,
3697
+ className,
3698
+ isStreaming = false,
3699
+ streamingStatus
3700
+ }) {
3701
+ const { t } = useChatkitTranslation();
3702
+ const hasContent = hasRenderableMessageContent(message.content);
3703
+ const hasReasoning = hasRenderableReasoning(message.reasoning);
3704
+ const resolvedStreamingStatus = streamingStatus ?? getAssistantStreamingStatus(message, isStreaming);
2247
3705
  const answerNode = renderContent(message.content, message.id);
2248
- const reasoningNode = hasReasoning ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ReasoningBlock, { reasoning: message.reasoning ?? [] }) : null;
2249
- if (!hasContent && !hasReasoning) return null;
3706
+ const reasoningNode = hasReasoning ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ReasoningBlock, { reasoning: message.reasoning ?? [] }) : null;
3707
+ if (!hasRenderableAssistantMessage(message) && !resolvedStreamingStatus) return null;
2250
3708
  const streamingClass = isStreaming ? "streaming-active" : "";
3709
+ if (!hasRenderableAssistantMessage(message) && resolvedStreamingStatus) {
3710
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn("space-y-3", streamingClass, className), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) });
3711
+ }
2251
3712
  if (hasContent && hasReasoning) {
2252
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("space-y-3", streamingClass, className), children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
2253
- Tabs,
2254
- {
2255
- defaultValue: message.status === "reasoning" ? "reasoning" : "answer",
2256
- className: "w-full",
2257
- children: [
2258
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(TabsList, { className: "h-9", children: [
2259
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TabsTrigger, { value: "answer", children: t("message.answer") }),
2260
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TabsTrigger, { value: "reasoning", children: t("message.reasoning") })
2261
- ] }),
2262
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TabsContent, { value: "answer", className: "space-y-3", children: answerNode }),
2263
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TabsContent, { value: "reasoning", className: "space-y-3", children: reasoningNode })
2264
- ]
2265
- }
2266
- ) });
3713
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("space-y-3", streamingClass, className), children: [
3714
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3715
+ Tabs,
3716
+ {
3717
+ defaultValue: message.status === "reasoning" ? "reasoning" : "answer",
3718
+ className: "w-full",
3719
+ children: [
3720
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(TabsList, { className: "", children: [
3721
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TabsTrigger, { value: "answer", children: t("message.answer") }),
3722
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TabsTrigger, { value: "reasoning", children: t("message.reasoning") })
3723
+ ] }),
3724
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TabsContent, { value: "answer", className: "space-y-3", children: answerNode }),
3725
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TabsContent, { value: "reasoning", className: "space-y-3", children: reasoningNode })
3726
+ ]
3727
+ }
3728
+ ),
3729
+ resolvedStreamingStatus ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) : null
3730
+ ] });
2267
3731
  }
2268
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("space-y-3", streamingClass, className), children: hasReasoning ? reasoningNode : answerNode });
3732
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("space-y-3", streamingClass, className), children: [
3733
+ hasReasoning ? reasoningNode : answerNode,
3734
+ resolvedStreamingStatus ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) : null
3735
+ ] });
2269
3736
  }
2270
3737
 
2271
3738
  // src/components/thread/MessageActions.tsx
2272
- var React14 = __toESM(require("react"), 1);
2273
- var import_lucide_react7 = require("lucide-react");
2274
- var import_jsx_runtime20 = require("react/jsx-runtime");
3739
+ var React16 = __toESM(require("react"), 1);
3740
+ var import_lucide_react9 = require("lucide-react");
3741
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2275
3742
  function MessageActions({
2276
3743
  content,
2277
3744
  isAssistant = false,
@@ -2280,7 +3747,7 @@ function MessageActions({
2280
3747
  className
2281
3748
  }) {
2282
3749
  const { t } = useChatkitTranslation();
2283
- const [copied, setCopied] = React14.useState(false);
3750
+ const [copied, setCopied] = React16.useState(false);
2284
3751
  const handleCopy = async () => {
2285
3752
  try {
2286
3753
  await navigator.clipboard.writeText(content);
@@ -2293,7 +3760,7 @@ function MessageActions({
2293
3760
  if (isStreaming) {
2294
3761
  return null;
2295
3762
  }
2296
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
3763
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2297
3764
  "div",
2298
3765
  {
2299
3766
  className: cn(
@@ -2301,7 +3768,7 @@ function MessageActions({
2301
3768
  className
2302
3769
  ),
2303
3770
  children: [
2304
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3771
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2305
3772
  "button",
2306
3773
  {
2307
3774
  type: "button",
@@ -2311,17 +3778,17 @@ function MessageActions({
2311
3778
  copied && "text-green-500"
2312
3779
  ),
2313
3780
  title: copied ? t("messageActions.copied") : t("messageActions.copy"),
2314
- children: copied ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.Check, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.Copy, { size: 14 })
3781
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Check, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Copy, { size: 14 })
2315
3782
  }
2316
3783
  ),
2317
- isAssistant && onRetry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3784
+ isAssistant && onRetry && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2318
3785
  "button",
2319
3786
  {
2320
3787
  type: "button",
2321
3788
  onClick: onRetry,
2322
3789
  className: "p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
2323
3790
  title: t("messageActions.regenerate"),
2324
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.RefreshCw, { size: 14 })
3791
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.RefreshCw, { size: 14 })
2325
3792
  }
2326
3793
  )
2327
3794
  ]
@@ -2330,20 +3797,20 @@ function MessageActions({
2330
3797
  }
2331
3798
 
2332
3799
  // src/components/thread/StartScreen.tsx
2333
- var React15 = require("react");
2334
- var import_lucide_react8 = require("lucide-react");
2335
- var import_jsx_runtime21 = require("react/jsx-runtime");
3800
+ var React17 = require("react");
3801
+ var import_lucide_react10 = require("lucide-react");
3802
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2336
3803
  function getIconComponent2(icon) {
2337
3804
  const iconMap = {
2338
- "circle-question": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.HelpCircle, { size: 20 }),
2339
- "lightbulb": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Lightbulb, { size: 20 }),
2340
- "sparkle": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Sparkles, { size: 20 }),
2341
- "write": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Pencil, { size: 20 }),
2342
- "search": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Search, { size: 20 }),
2343
- "globe": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Globe, { size: 20 }),
2344
- "book-open": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.BookOpen, { size: 20 }),
2345
- "compass": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Compass, { size: 20 }),
2346
- "bolt": /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Zap, { size: 20 })
3805
+ "circle-question": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.HelpCircle, { size: 20 }),
3806
+ "lightbulb": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Lightbulb, { size: 20 }),
3807
+ "sparkle": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Sparkles, { size: 20 }),
3808
+ "write": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Pencil, { size: 20 }),
3809
+ "search": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Search, { size: 20 }),
3810
+ "globe": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Globe, { size: 20 }),
3811
+ "book-open": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.BookOpen, { size: 20 }),
3812
+ "compass": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Compass, { size: 20 }),
3813
+ "bolt": /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react10.Zap, { size: 20 })
2347
3814
  };
2348
3815
  return icon ? iconMap[icon] || iconMap["sparkle"] : iconMap["sparkle"];
2349
3816
  }
@@ -2351,9 +3818,9 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2351
3818
  const { t } = useChatkitTranslation();
2352
3819
  const greeting = startScreen?.greeting ?? t("startScreen.greeting");
2353
3820
  const prompts = startScreen?.prompts ?? [];
2354
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn("flex flex-col items-center justify-center py-12 px-4", className), children: [
2355
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mb-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-2", children: greeting }) }),
2356
- prompts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: prompts.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
3821
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("flex flex-col items-center justify-center py-12 px-4", className), children: [
3822
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "mb-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-2", children: greeting }) }),
3823
+ prompts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: prompts.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2357
3824
  "button",
2358
3825
  {
2359
3826
  type: "button",
@@ -2364,8 +3831,8 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2364
3831
  "focus:outline-none focus:ring-2 focus:ring-primary/20"
2365
3832
  ),
2366
3833
  children: [
2367
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: getIconComponent2(item.icon) }),
2368
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm font-medium text-foreground", children: item.label })
3834
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: getIconComponent2(item.icon) }),
3835
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm font-medium text-foreground", children: item.label })
2369
3836
  ]
2370
3837
  },
2371
3838
  `prompt-${index}`
@@ -2374,13 +3841,13 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2374
3841
  }
2375
3842
 
2376
3843
  // src/components/ui/chatkit-avatar.tsx
2377
- var React17 = require("react");
3844
+ var React19 = require("react");
2378
3845
 
2379
3846
  // src/components/ui/avatar.tsx
2380
- var React16 = __toESM(require("react"), 1);
3847
+ var React18 = __toESM(require("react"), 1);
2381
3848
  var AvatarPrimitive = __toESM(require("@radix-ui/react-avatar"), 1);
2382
- var import_jsx_runtime22 = require("react/jsx-runtime");
2383
- var Avatar = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3849
+ var import_jsx_runtime24 = require("react/jsx-runtime");
3850
+ var Avatar = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2384
3851
  AvatarPrimitive.Root,
2385
3852
  {
2386
3853
  ref,
@@ -2392,7 +3859,7 @@ var Avatar = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
2392
3859
  }
2393
3860
  ));
2394
3861
  Avatar.displayName = AvatarPrimitive.Root.displayName;
2395
- var AvatarImage = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3862
+ var AvatarImage = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2396
3863
  AvatarPrimitive.Image,
2397
3864
  {
2398
3865
  ref,
@@ -2401,7 +3868,7 @@ var AvatarImage = React16.forwardRef(({ className, ...props }, ref) => /* @__PUR
2401
3868
  }
2402
3869
  ));
2403
3870
  AvatarImage.displayName = AvatarPrimitive.Image.displayName;
2404
- var AvatarFallback = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3871
+ var AvatarFallback = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2405
3872
  AvatarPrimitive.Fallback,
2406
3873
  {
2407
3874
  ref,
@@ -2415,7 +3882,7 @@ var AvatarFallback = React16.forwardRef(({ className, ...props }, ref) => /* @__
2415
3882
  AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
2416
3883
 
2417
3884
  // src/components/ui/chatkit-avatar.tsx
2418
- var import_jsx_runtime23 = require("react/jsx-runtime");
3885
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2419
3886
  function asRecord(value) {
2420
3887
  return value && typeof value === "object" ? value : null;
2421
3888
  }
@@ -2488,21 +3955,21 @@ function ChatkitAvatar({
2488
3955
  const fallbackStyle = {
2489
3956
  ...avatar?.background ? { background: avatar.background } : {}
2490
3957
  };
2491
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Avatar, { className: cn(roundedClass, className), style, ...props, children: [
2492
- avatar?.url ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AvatarImage, { className: imageClassName, src: avatar.url, alt: label }) : null,
2493
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3958
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Avatar, { className: cn(roundedClass, className), style, ...props, children: [
3959
+ avatar?.url ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AvatarImage, { className: imageClassName, src: avatar.url, alt: label }) : null,
3960
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2494
3961
  AvatarFallback,
2495
3962
  {
2496
3963
  className: cn(roundedClass, "text-sm font-medium text-foreground", fallbackClassName),
2497
3964
  style: fallbackStyle,
2498
- children: emojiCharacter ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[1.1em] leading-none", style: emojiStyle, children: emojiCharacter }) : fallbackText
3965
+ children: emojiCharacter ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-[1.1em] leading-none", style: emojiStyle, children: emojiCharacter }) : fallbackText
2499
3966
  }
2500
3967
  )
2501
3968
  ] });
2502
3969
  }
2503
3970
 
2504
3971
  // src/hooks/useThreads.ts
2505
- var React18 = __toESM(require("react"), 1);
3972
+ var React20 = __toESM(require("react"), 1);
2506
3973
  var DEFAULT_LIMIT = 50;
2507
3974
  var getThreadTitle = (threadRecord) => {
2508
3975
  const title = threadRecord.title?.trim();
@@ -2540,16 +4007,16 @@ function useThreads(limit = DEFAULT_LIMIT) {
2540
4007
  isReady,
2541
4008
  isLoading: isStreamLoading
2542
4009
  } = useStreamContext();
2543
- const [threadRecords, setThreadRecords] = React18.useState([]);
2544
- const [isLoading, setIsLoading] = React18.useState(false);
2545
- const [error, setError] = React18.useState(null);
2546
- const upsertThreadRecord = React18.useCallback((threadRecord) => {
4010
+ const [threadRecords, setThreadRecords] = React20.useState([]);
4011
+ const [isLoading, setIsLoading] = React20.useState(false);
4012
+ const [error, setError] = React20.useState(null);
4013
+ const upsertThreadRecord = React20.useCallback((threadRecord) => {
2547
4014
  setThreadRecords((prev) => {
2548
4015
  const next = prev.filter((item) => item.id !== threadRecord.id);
2549
4016
  return sortThreadRecords([threadRecord, ...next]);
2550
4017
  });
2551
4018
  }, []);
2552
- const refreshThreads = React18.useCallback(async () => {
4019
+ const refreshThreads = React20.useCallback(async () => {
2553
4020
  setIsLoading(true);
2554
4021
  setError(null);
2555
4022
  try {
@@ -2565,7 +4032,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2565
4032
  setIsLoading(false);
2566
4033
  }
2567
4034
  }, [client, limit, assistantId]);
2568
- const createThread = React18.useCallback(
4035
+ const createThread = React20.useCallback(
2569
4036
  async (input) => {
2570
4037
  setError(null);
2571
4038
  const payload = {};
@@ -2579,7 +4046,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2579
4046
  },
2580
4047
  [client, upsertThreadRecord]
2581
4048
  );
2582
- const updateThread = React18.useCallback(
4049
+ const updateThread = React20.useCallback(
2583
4050
  async (recordId, payload) => {
2584
4051
  setError(null);
2585
4052
  const updated = await client.conversations.update(recordId, payload);
@@ -2588,7 +4055,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2588
4055
  },
2589
4056
  [client, upsertThreadRecord]
2590
4057
  );
2591
- const deleteThread = React18.useCallback(
4058
+ const deleteThread = React20.useCallback(
2592
4059
  async (recordId) => {
2593
4060
  setError(null);
2594
4061
  await client.conversations.delete(recordId);
@@ -2596,23 +4063,24 @@ function useThreads(limit = DEFAULT_LIMIT) {
2596
4063
  },
2597
4064
  [client]
2598
4065
  );
2599
- React18.useEffect(() => {
4066
+ React20.useEffect(() => {
2600
4067
  if (!isReady) return;
2601
4068
  void refreshThreads();
2602
4069
  }, [refreshThreads, isReady]);
2603
- React18.useEffect(() => {
4070
+ React20.useEffect(() => {
2604
4071
  if (!threadId || !isStreamLoading) return;
2605
4072
  const now = (/* @__PURE__ */ new Date()).toISOString();
4073
+ const busyStatus = "busy";
2606
4074
  setThreadRecords((prev) => {
2607
4075
  let changed = false;
2608
4076
  const next = prev.map((item) => {
2609
4077
  const isCurrentThread = item.threadId === threadId || item.id === threadId;
2610
4078
  if (!isCurrentThread) return item;
2611
- if (item.status === "busy" && !item.error) return item;
4079
+ if (item.status === busyStatus && !item.error) return item;
2612
4080
  changed = true;
2613
4081
  return {
2614
4082
  ...item,
2615
- status: "busy",
4083
+ status: busyStatus,
2616
4084
  error: void 0,
2617
4085
  updatedAt: now
2618
4086
  };
@@ -2620,7 +4088,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2620
4088
  return changed ? sortThreadRecords(next) : prev;
2621
4089
  });
2622
4090
  }, [threadId, isStreamLoading]);
2623
- React18.useEffect(() => {
4091
+ React20.useEffect(() => {
2624
4092
  if (!isReady || !threadId || isStreamLoading) return;
2625
4093
  let cancelled = false;
2626
4094
  void client.conversations.search({ where: { threadId }, limit: 1 }).then((result) => {
@@ -2634,7 +4102,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2634
4102
  cancelled = true;
2635
4103
  };
2636
4104
  }, [client, threadId, upsertThreadRecord, isReady, isStreamLoading]);
2637
- const threads = React18.useMemo(
4105
+ const threads = React20.useMemo(
2638
4106
  () => threadRecords.map((threadRecord) => toThreadItem(threadRecord)),
2639
4107
  [threadRecords]
2640
4108
  );
@@ -2651,22 +4119,22 @@ function useThreads(limit = DEFAULT_LIMIT) {
2651
4119
  }
2652
4120
 
2653
4121
  // src/components/thread/context-usage-indicator.tsx
2654
- var React19 = __toESM(require("react"), 1);
4122
+ var React21 = __toESM(require("react"), 1);
2655
4123
 
2656
4124
  // src/components/ui/progress-circle.tsx
2657
- var import_jsx_runtime24 = (
4125
+ var import_jsx_runtime26 = (
2658
4126
  // biome-ignore lint/a11y/useFocusableInteractive: false positive (progress + progressbar are not focusable interactives)
2659
4127
  // biome-ignore lint/nursery/useAriaPropsSupportedByRole: biome rule at odds with mdn docs (presumed nursary bug with rule)
2660
4128
  require("react/jsx-runtime")
2661
4129
  );
2662
- function clamp(input, a, b) {
4130
+ function clamp2(input, a, b) {
2663
4131
  return Math.max(Math.min(input, Math.max(a, b)), Math.min(a, b));
2664
4132
  }
2665
4133
  var size = 24;
2666
4134
  var strokeWidth = 4;
2667
4135
  var total = 100;
2668
4136
  var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2669
- const normalizedValue = clamp(value, 0, total);
4137
+ const normalizedValue = clamp2(value, 0, total);
2670
4138
  const radius = (size - strokeWidth) / 2;
2671
4139
  const circumference = 2 * Math.PI * radius;
2672
4140
  const progress = normalizedValue / total * circumference;
@@ -2678,7 +4146,7 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2678
4146
  fill: "none",
2679
4147
  strokeWidth
2680
4148
  };
2681
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4149
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
2682
4150
  "svg",
2683
4151
  {
2684
4152
  role: "progressbar",
@@ -2689,8 +4157,8 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2689
4157
  "aria-valuemax": 100,
2690
4158
  ...restSvgProps,
2691
4159
  children: [
2692
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { ...commonParams, className: "stroke-current/25" }),
2693
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4160
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("circle", { ...commonParams, className: "stroke-current/25" }),
4161
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2694
4162
  "circle",
2695
4163
  {
2696
4164
  ...commonParams,
@@ -2708,7 +4176,7 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2708
4176
  };
2709
4177
 
2710
4178
  // src/components/thread/context-usage-indicator.tsx
2711
- var import_jsx_runtime25 = require("react/jsx-runtime");
4179
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2712
4180
  var kNumberFormatter = new Intl.NumberFormat("en-US", {
2713
4181
  minimumFractionDigits: 0,
2714
4182
  maximumFractionDigits: 1
@@ -2741,20 +4209,20 @@ function ContextUsageIndicator({
2741
4209
  }) {
2742
4210
  const { t } = useChatkitTranslation();
2743
4211
  const stream = useStreamContext();
2744
- const [maxContextSize, setMaxContextSize] = React19.useState(null);
2745
- const [usedContextSize, setUsedContextSize] = React19.useState(null);
2746
- const [assistantAgentKey, setAssistantAgentKey] = React19.useState(null);
2747
- const latestRealtimeUsageRef = React19.useRef({
4212
+ const [maxContextSize, setMaxContextSize] = React21.useState(null);
4213
+ const [usedContextSize, setUsedContextSize] = React21.useState(null);
4214
+ const [assistantAgentKey, setAssistantAgentKey] = React21.useState(null);
4215
+ const latestRealtimeUsageRef = React21.useRef({
2748
4216
  threadId: null,
2749
4217
  agentKey: null,
2750
4218
  usedTokens: null
2751
4219
  });
2752
- const realtimeUsage = React19.useMemo(
4220
+ const realtimeUsage = React21.useMemo(
2753
4221
  () => getThreadContextUsage(stream.contextUsageByAgentKey, assistantAgentKey),
2754
4222
  [assistantAgentKey, stream.contextUsageByAgentKey]
2755
4223
  );
2756
4224
  const realtimeUsedContextSize = getThreadContextUsageTotalTokens(realtimeUsage);
2757
- React19.useEffect(() => {
4225
+ React21.useEffect(() => {
2758
4226
  if (!stream.client || !stream.assistantId) {
2759
4227
  setMaxContextSize(null);
2760
4228
  setAssistantAgentKey(null);
@@ -2774,18 +4242,18 @@ function ContextUsageIndicator({
2774
4242
  cancelled = true;
2775
4243
  };
2776
4244
  }, [stream.client, stream.assistantId]);
2777
- React19.useEffect(() => {
4245
+ React21.useEffect(() => {
2778
4246
  latestRealtimeUsageRef.current = {
2779
4247
  threadId: stream.threadId ?? null,
2780
4248
  agentKey: assistantAgentKey,
2781
4249
  usedTokens: realtimeUsedContextSize
2782
4250
  };
2783
4251
  }, [assistantAgentKey, realtimeUsedContextSize, stream.threadId]);
2784
- React19.useEffect(() => {
4252
+ React21.useEffect(() => {
2785
4253
  if (realtimeUsedContextSize == null) return;
2786
4254
  setUsedContextSize(realtimeUsedContextSize);
2787
4255
  }, [realtimeUsedContextSize]);
2788
- React19.useEffect(() => {
4256
+ React21.useEffect(() => {
2789
4257
  if (!stream.client) {
2790
4258
  setUsedContextSize(null);
2791
4259
  return;
@@ -2850,8 +4318,8 @@ function ContextUsageIndicator({
2850
4318
  });
2851
4319
  const usageLabelWithSuffix = usageLabel.endsWith(":") ? usageLabel : `${usageLabel}:`;
2852
4320
  const progressClassName = percent >= 90 ? "text-destructive" : percent >= 75 ? "text-amber-500" : "text-primary dark:text-zinc-300";
2853
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
2854
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4321
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Tooltip, { children: [
4322
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2855
4323
  "button",
2856
4324
  {
2857
4325
  type: "button",
@@ -2860,21 +4328,74 @@ function ContextUsageIndicator({
2860
4328
  className
2861
4329
  ),
2862
4330
  "aria-label": `${usageLabelWithSuffix} ${usageFullLabel}. ${usageTokensLabel}`,
2863
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProgressCircle, { value: percent, className: cn("size-3.5", progressClassName) })
4331
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ProgressCircle, { value: percent, className: cn("size-3.5", progressClassName) })
2864
4332
  }
2865
4333
  ) }),
2866
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(TooltipContent, { side: "top", sideOffset: 6, className: "space-y-0.5 px-3 py-2 text-center", children: [
2867
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-primary-foreground/70", children: usageLabelWithSuffix }),
2868
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "font-medium text-primary-foreground/80", children: usageFullLabel }),
2869
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-sm font-semibold", children: usageTokensLabel })
4334
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(TooltipContent, { side: "top", sideOffset: 6, className: "space-y-0.5 px-3 py-2 text-center", children: [
4335
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-primary-foreground/70", children: usageLabelWithSuffix }),
4336
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "font-medium text-primary-foreground/80", children: usageFullLabel }),
4337
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "text-sm font-semibold", children: usageTokensLabel })
2870
4338
  ] })
2871
4339
  ] });
2872
4340
  }
2873
4341
 
2874
4342
  // src/components/chat.tsx
2875
- var import_jsx_runtime26 = require("react/jsx-runtime");
4343
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2876
4344
  var import_meta2 = {};
2877
4345
  var defaultApiUrl2 = import_meta2.env.VITE_XPERTAI_API_URL;
4346
+ var COMPOSER_INPUT_MAX_HEIGHT = 128;
4347
+ var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
4348
+ async function readImageDimensions(file) {
4349
+ if (typeof window === "undefined" || typeof URL === "undefined") {
4350
+ return {};
4351
+ }
4352
+ return new Promise((resolve) => {
4353
+ const objectUrl = URL.createObjectURL(file);
4354
+ const image = new window.Image();
4355
+ const cleanup = () => {
4356
+ URL.revokeObjectURL(objectUrl);
4357
+ };
4358
+ image.onload = () => {
4359
+ resolve({
4360
+ width: image.naturalWidth || void 0,
4361
+ height: image.naturalHeight || void 0
4362
+ });
4363
+ cleanup();
4364
+ };
4365
+ image.onerror = () => {
4366
+ resolve({});
4367
+ cleanup();
4368
+ };
4369
+ image.src = objectUrl;
4370
+ });
4371
+ }
4372
+ function getStorageFileUrl(file) {
4373
+ return file.url ?? file.fileUrl ?? file.thumbUrl;
4374
+ }
4375
+ function buildPastedImageReference(file, storageFile, dimensions) {
4376
+ const name = storageFile.originalName?.trim() || file.name.trim() || "Pasted image";
4377
+ const mimeType = storageFile.mimetype?.trim() || file.type.trim() || "image/*";
4378
+ const size2 = storageFile.size ?? file.size;
4379
+ const width = dimensions?.width;
4380
+ const height = dimensions?.height;
4381
+ const metaParts = [
4382
+ mimeType,
4383
+ width && height ? `${width}x${height}` : null,
4384
+ typeof size2 === "number" ? `${size2} bytes` : null
4385
+ ].filter((part) => Boolean(part));
4386
+ return {
4387
+ type: "image",
4388
+ id: storageFile.id,
4389
+ fileId: storageFile.id,
4390
+ url: getStorageFileUrl(storageFile),
4391
+ mimeType,
4392
+ name,
4393
+ ...typeof size2 === "number" ? { size: size2 } : {},
4394
+ ...width ? { width } : {},
4395
+ ...height ? { height } : {},
4396
+ text: `Pasted image${metaParts.length ? ` (${metaParts.join(", ")})` : ""}: ${name}`
4397
+ };
4398
+ }
2878
4399
  function formatMessageContent(content) {
2879
4400
  if (typeof content === "string") {
2880
4401
  return content;
@@ -2896,6 +4417,81 @@ function formatMessageContent(content) {
2896
4417
  }
2897
4418
  return "";
2898
4419
  }
4420
+ function getClosestQuoteContainer(node) {
4421
+ if (!node) {
4422
+ return null;
4423
+ }
4424
+ const element = node instanceof HTMLElement ? node : node instanceof Text ? node.parentElement : null;
4425
+ return element?.closest("[data-quote-message-id]") ?? null;
4426
+ }
4427
+ function ReferenceChip({
4428
+ reference,
4429
+ variant,
4430
+ onRemove,
4431
+ removeLabel
4432
+ }) {
4433
+ const metaLine = getReferenceMetaLine(reference);
4434
+ const isComposer = variant === "composer";
4435
+ const Icon = reference.type === "quote" ? import_lucide_react11.Quote : reference.type === "image" ? import_lucide_react11.ImageIcon : import_lucide_react11.FileText;
4436
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4437
+ "div",
4438
+ {
4439
+ className: cn(
4440
+ "flex items-start gap-2 rounded-md px-2 py-1",
4441
+ isComposer ? "bg-muted text-foreground" : "bg-primary-foreground/20"
4442
+ ),
4443
+ title: getReferenceTitle(reference),
4444
+ children: [
4445
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4446
+ Icon,
4447
+ {
4448
+ size: isComposer ? 14 : 12,
4449
+ className: cn(
4450
+ "mt-0.5 shrink-0",
4451
+ isComposer ? "text-muted-foreground" : "text-primary-foreground/80"
4452
+ )
4453
+ }
4454
+ ),
4455
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0 flex-1", children: [
4456
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4457
+ "div",
4458
+ {
4459
+ className: cn(
4460
+ "truncate whitespace-pre-wrap",
4461
+ isComposer ? "text-sm" : "text-xs font-medium"
4462
+ ),
4463
+ children: getReferenceLabel(reference)
4464
+ }
4465
+ ),
4466
+ metaLine && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4467
+ "div",
4468
+ {
4469
+ className: cn(
4470
+ "truncate whitespace-pre-wrap",
4471
+ isComposer ? "text-xs text-muted-foreground" : "text-[10px] text-primary-foreground/75"
4472
+ ),
4473
+ children: metaLine
4474
+ }
4475
+ )
4476
+ ] }),
4477
+ onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4478
+ "button",
4479
+ {
4480
+ type: "button",
4481
+ onClick: onRemove,
4482
+ className: cn(
4483
+ "ml-1 rounded-full p-0.5",
4484
+ isComposer ? "hover:bg-muted-foreground/20" : "hover:bg-primary-foreground/20"
4485
+ ),
4486
+ title: removeLabel,
4487
+ "aria-label": removeLabel,
4488
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.X, { size: 12 })
4489
+ }
4490
+ )
4491
+ ]
4492
+ }
4493
+ );
4494
+ }
2899
4495
  function Chat({
2900
4496
  className,
2901
4497
  options,
@@ -2912,17 +4508,21 @@ function Chat({
2912
4508
  const apiUrl = options?.api?.apiUrl || defaultApiUrl2;
2913
4509
  const { setStream } = useStreamManager();
2914
4510
  const stream = useStreamContext();
2915
- const [isHistoryLoading, setIsHistoryLoading] = React20.useState(false);
2916
- const [historyError, setHistoryError] = React20.useState(null);
2917
- const [assistantName, setAssistantName] = React20.useState(null);
2918
- const [assistantAvatar, setAssistantAvatar] = React20.useState(null);
4511
+ const { theme } = useTheme();
4512
+ const [isHistoryLoading, setIsHistoryLoading] = React22.useState(false);
4513
+ const [historyError, setHistoryError] = React22.useState(null);
4514
+ const [assistantName, setAssistantName] = React22.useState(null);
4515
+ const [assistantAvatar, setAssistantAvatar] = React22.useState(null);
2919
4516
  const LOADING_DOTS_MIN_DURATION = 800;
2920
- const [showLoadingDots, setShowLoadingDots] = React20.useState(false);
2921
- const loadingStartTimeRef = React20.useRef(null);
2922
- React20.useEffect(() => {
4517
+ const STREAMING_STATUS_REFRESH_MS = 250;
4518
+ const [showLoadingDots, setShowLoadingDots] = React22.useState(false);
4519
+ const [streamingNow, setStreamingNow] = React22.useState(() => Date.now());
4520
+ const loadingStartTimeRef = React22.useRef(null);
4521
+ const lastStreamOutputAtRef = React22.useRef(null);
4522
+ React22.useEffect(() => {
2923
4523
  setStream(stream);
2924
4524
  }, [setStream, stream]);
2925
- React20.useEffect(() => {
4525
+ React22.useEffect(() => {
2926
4526
  if (stream.isLoading) {
2927
4527
  if (!loadingStartTimeRef.current) {
2928
4528
  loadingStartTimeRef.current = Date.now();
@@ -2945,67 +4545,181 @@ function Chat({
2945
4545
  }
2946
4546
  }
2947
4547
  }, [stream.isLoading]);
2948
- const [draft, setDraft] = React20.useState("");
2949
- const [selectedTool, setSelectedTool] = React20.useState(null);
2950
- const [attachments, setAttachments] = React20.useState([]);
2951
- const [isAtBottom, setIsAtBottom] = React20.useState(true);
2952
- const [hasUpdatesBelow, setHasUpdatesBelow] = React20.useState(false);
4548
+ React22.useEffect(() => {
4549
+ if (!stream.isLoading) {
4550
+ lastStreamOutputAtRef.current = null;
4551
+ setStreamingNow(Date.now());
4552
+ return;
4553
+ }
4554
+ const now = Date.now();
4555
+ lastStreamOutputAtRef.current = now;
4556
+ setStreamingNow(now);
4557
+ }, [stream.messages, stream.isLoading]);
4558
+ React22.useEffect(() => {
4559
+ if (!stream.isLoading) {
4560
+ return;
4561
+ }
4562
+ const timer = window.setInterval(() => {
4563
+ setStreamingNow(Date.now());
4564
+ }, STREAMING_STATUS_REFRESH_MS);
4565
+ return () => window.clearInterval(timer);
4566
+ }, [stream.isLoading]);
4567
+ const [draft, setDraft] = React22.useState("");
4568
+ const [selectedTool, setSelectedTool] = React22.useState(
4569
+ null
4570
+ );
4571
+ const [attachments, setAttachments] = React22.useState([]);
4572
+ const [references, setReferences] = React22.useState([]);
4573
+ const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React22.useState(false);
4574
+ const [quoteSelection, setQuoteSelection] = React22.useState(null);
4575
+ const [isAtBottom, setIsAtBottom] = React22.useState(true);
4576
+ const [hasUpdatesBelow, setHasUpdatesBelow] = React22.useState(false);
2953
4577
  const {
2954
4578
  threads,
2955
4579
  deleteThread,
2956
4580
  refreshThreads,
2957
4581
  isLoading: isThreadsLoading
2958
4582
  } = useThreads();
2959
- const viewportRef = React20.useRef(null);
2960
- const fileInputRef = React20.useRef(null);
2961
- const shouldAutoScrollRef = React20.useRef(true);
2962
- const forceFollowRef = React20.useRef(false);
2963
- const previousMessageCountRef = React20.useRef(0);
2964
- const previousScrollTopRef = React20.useRef(0);
2965
- const autoScrollFrameRef = React20.useRef(null);
2966
- const isPointerDownRef = React20.useRef(false);
2967
- const lastTouchYRef = React20.useRef(null);
4583
+ const viewportRef = React22.useRef(null);
4584
+ const fileInputRef = React22.useRef(null);
4585
+ const composerInputRef = React22.useRef(null);
4586
+ const shouldAutoScrollRef = React22.useRef(true);
4587
+ const forceFollowRef = React22.useRef(false);
4588
+ const previousMessageCountRef = React22.useRef(0);
4589
+ const previousScrollTopRef = React22.useRef(0);
4590
+ const autoScrollFrameRef = React22.useRef(null);
4591
+ const isPointerDownRef = React22.useRef(false);
4592
+ const lastTouchYRef = React22.useRef(null);
2968
4593
  const resolvedTitle = title ?? t("chat.title");
2969
4594
  const resolvedPlaceholder = placeholder ?? t("chat.placeholder");
2970
4595
  const inputPlaceholder = selectedTool?.placeholderOverride ?? composer?.placeholder ?? resolvedPlaceholder;
2971
- const messages = React20.useMemo(() => stream.messages ?? [], [stream.messages]);
4596
+ const messages = React22.useMemo(
4597
+ () => stream.messages ?? [],
4598
+ [stream.messages]
4599
+ );
2972
4600
  const trimmedDraft = draft.trim();
2973
- const cancelPendingAutoScroll = React20.useCallback(() => {
4601
+ const hasReferences = references.length > 0;
4602
+ const pendingFollowUps = React22.useMemo(
4603
+ () => [...stream.pendingFollowUps ?? []].sort(
4604
+ (a, b) => a.createdAt - b.createdAt
4605
+ ),
4606
+ [stream.pendingFollowUps]
4607
+ );
4608
+ const clearQuoteSelection = React22.useCallback(() => {
4609
+ setQuoteSelection(null);
4610
+ }, []);
4611
+ useParentMessenger({
4612
+ onSetComposerValue: React22.useCallback(
4613
+ (payload) => {
4614
+ if (!payload) {
4615
+ return;
4616
+ }
4617
+ if (typeof payload.text === "string") {
4618
+ setDraft(payload.text);
4619
+ }
4620
+ if (Array.isArray(payload.references)) {
4621
+ const nextReferences = normalizeReferences(payload.references);
4622
+ setReferences(
4623
+ (previous) => payload.appendReferences ? mergeReferences(previous, nextReferences) : nextReferences
4624
+ );
4625
+ }
4626
+ if (payload.selectedToolId !== void 0) {
4627
+ const nextTool = payload.selectedToolId === null ? null : (composer?.tools ?? []).find(
4628
+ (tool) => tool.id === payload.selectedToolId
4629
+ ) ?? null;
4630
+ setSelectedTool(nextTool);
4631
+ }
4632
+ },
4633
+ [composer?.tools]
4634
+ ),
4635
+ onFocusComposer: React22.useCallback(() => {
4636
+ composerInputRef.current?.focus();
4637
+ }, [])
4638
+ });
4639
+ const syncQuoteSelection = React22.useCallback(() => {
4640
+ if (typeof window === "undefined") {
4641
+ clearQuoteSelection();
4642
+ return;
4643
+ }
4644
+ const selection = window.getSelection();
4645
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
4646
+ clearQuoteSelection();
4647
+ return;
4648
+ }
4649
+ const text = selection.toString().trim();
4650
+ if (!text) {
4651
+ clearQuoteSelection();
4652
+ return;
4653
+ }
4654
+ const anchorContainer = getClosestQuoteContainer(selection.anchorNode);
4655
+ const focusContainer = getClosestQuoteContainer(selection.focusNode);
4656
+ if (!anchorContainer || !focusContainer || anchorContainer !== focusContainer || !viewportRef.current?.contains(anchorContainer)) {
4657
+ clearQuoteSelection();
4658
+ return;
4659
+ }
4660
+ const range = selection.getRangeAt(0);
4661
+ const rect = range.getBoundingClientRect();
4662
+ if (rect.width === 0 && rect.height === 0) {
4663
+ clearQuoteSelection();
4664
+ return;
4665
+ }
4666
+ const top = rect.bottom + 8 > window.innerHeight - 48 ? Math.max(12, rect.top - 44) : rect.bottom + 8;
4667
+ const left = Math.min(
4668
+ Math.max(24, rect.left + rect.width / 2),
4669
+ window.innerWidth - 24
4670
+ );
4671
+ const source = anchorContainer.dataset.quoteSource?.trim() || void 0;
4672
+ const messageId = anchorContainer.dataset.quoteMessageId?.trim() || void 0;
4673
+ setQuoteSelection({
4674
+ reference: {
4675
+ type: "quote",
4676
+ text,
4677
+ ...messageId ? { messageId } : {},
4678
+ ...source ? { source, label: source } : {}
4679
+ },
4680
+ top,
4681
+ left
4682
+ });
4683
+ }, [clearQuoteSelection]);
4684
+ const cancelPendingAutoScroll = React22.useCallback(() => {
2974
4685
  if (autoScrollFrameRef.current !== null) {
2975
4686
  cancelAnimationFrame(autoScrollFrameRef.current);
2976
4687
  autoScrollFrameRef.current = null;
2977
4688
  }
2978
4689
  }, []);
2979
- const disableAutoFollow = React20.useCallback(() => {
4690
+ const disableAutoFollow = React22.useCallback(() => {
2980
4691
  forceFollowRef.current = false;
2981
4692
  shouldAutoScrollRef.current = false;
2982
4693
  cancelPendingAutoScroll();
2983
4694
  }, [cancelPendingAutoScroll]);
2984
- const enableAutoFollow = React20.useCallback(() => {
4695
+ const enableAutoFollow = React22.useCallback(() => {
2985
4696
  forceFollowRef.current = true;
2986
4697
  shouldAutoScrollRef.current = true;
2987
4698
  setHasUpdatesBelow(false);
2988
4699
  }, []);
2989
- const scrollToBottom = React20.useCallback((smooth = false, force = false) => {
2990
- if (force) {
2991
- enableAutoFollow();
2992
- }
2993
- cancelPendingAutoScroll();
2994
- autoScrollFrameRef.current = requestAnimationFrame(() => {
2995
- autoScrollFrameRef.current = null;
2996
- const viewport = viewportRef.current;
2997
- if (viewport) {
2998
- if (!force && !shouldAutoScrollRef.current) {
2999
- return;
3000
- }
3001
- viewport.scrollTo({
3002
- top: viewport.scrollHeight,
3003
- behavior: smooth ? "smooth" : "instant"
3004
- });
4700
+ const scrollToBottom = React22.useCallback(
4701
+ (smooth = false, force = false) => {
4702
+ if (force) {
4703
+ enableAutoFollow();
3005
4704
  }
3006
- });
3007
- }, [cancelPendingAutoScroll, enableAutoFollow]);
3008
- React20.useEffect(() => {
4705
+ cancelPendingAutoScroll();
4706
+ autoScrollFrameRef.current = requestAnimationFrame(() => {
4707
+ autoScrollFrameRef.current = null;
4708
+ const viewport = viewportRef.current;
4709
+ if (viewport) {
4710
+ if (!force && !shouldAutoScrollRef.current) {
4711
+ return;
4712
+ }
4713
+ viewport.scrollTo({
4714
+ top: viewport.scrollHeight,
4715
+ behavior: smooth ? "smooth" : "instant"
4716
+ });
4717
+ }
4718
+ });
4719
+ },
4720
+ [cancelPendingAutoScroll, enableAutoFollow]
4721
+ );
4722
+ React22.useEffect(() => {
3009
4723
  const viewport = viewportRef.current;
3010
4724
  if (!viewport) return;
3011
4725
  previousScrollTopRef.current = viewport.scrollTop;
@@ -3057,13 +4771,23 @@ function Chat({
3057
4771
  };
3058
4772
  updateAutoScrollState();
3059
4773
  viewport.addEventListener("wheel", handleWheel, { passive: true });
3060
- viewport.addEventListener("pointerdown", handlePointerDown, { passive: true });
3061
- viewport.addEventListener("scroll", updateAutoScrollState, { passive: true });
3062
- viewport.addEventListener("touchstart", handleTouchStart, { passive: true });
4774
+ viewport.addEventListener("pointerdown", handlePointerDown, {
4775
+ passive: true
4776
+ });
4777
+ viewport.addEventListener("scroll", updateAutoScrollState, {
4778
+ passive: true
4779
+ });
4780
+ viewport.addEventListener("touchstart", handleTouchStart, {
4781
+ passive: true
4782
+ });
3063
4783
  viewport.addEventListener("touchmove", handleTouchMove, { passive: true });
3064
4784
  viewport.addEventListener("touchend", handleTouchEnd, { passive: true });
3065
- window.addEventListener("pointerup", stopPointerTracking, { passive: true });
3066
- window.addEventListener("pointercancel", stopPointerTracking, { passive: true });
4785
+ window.addEventListener("pointerup", stopPointerTracking, {
4786
+ passive: true
4787
+ });
4788
+ window.addEventListener("pointercancel", stopPointerTracking, {
4789
+ passive: true
4790
+ });
3067
4791
  return () => {
3068
4792
  cancelPendingAutoScroll();
3069
4793
  viewport.removeEventListener("wheel", handleWheel);
@@ -3076,14 +4800,14 @@ function Chat({
3076
4800
  window.removeEventListener("pointercancel", stopPointerTracking);
3077
4801
  };
3078
4802
  }, [cancelPendingAutoScroll, disableAutoFollow]);
3079
- React20.useEffect(() => {
4803
+ React22.useEffect(() => {
3080
4804
  shouldAutoScrollRef.current = true;
3081
4805
  forceFollowRef.current = false;
3082
4806
  previousScrollTopRef.current = 0;
3083
4807
  setIsAtBottom(true);
3084
4808
  setHasUpdatesBelow(false);
3085
4809
  }, [stream.threadId]);
3086
- React20.useEffect(() => {
4810
+ React22.useEffect(() => {
3087
4811
  const messageCountChanged = messages.length !== previousMessageCountRef.current;
3088
4812
  previousMessageCountRef.current = messages.length;
3089
4813
  if (!shouldAutoScrollRef.current) {
@@ -3097,16 +4821,85 @@ function Chat({
3097
4821
  }
3098
4822
  }, [stream.isLoading, messages, scrollToBottom]);
3099
4823
  const effectiveClientSecret = stream.apiKey?.trim() ? stream.apiKey : clientSecret;
3100
- const hasApiKey = Boolean(effectiveClientSecret.trim());
3101
- const missingConfig = !apiUrl || !hasApiKey;
4824
+ const missingConfigKind = getMissingApiConfigurationKind({
4825
+ apiUrl,
4826
+ clientSecret: effectiveClientSecret
4827
+ });
4828
+ const missingConfig = Boolean(missingConfigKind);
4829
+ const missingConfigShortMessage = React22.useMemo(() => {
4830
+ switch (missingConfigKind) {
4831
+ case "apiUrl":
4832
+ return t("chat.missingApiUrlShort");
4833
+ case "clientSecret":
4834
+ return t("chat.missingClientSecretShort");
4835
+ case "apiUrlAndClientSecret":
4836
+ return t("chat.missingApiUrlAndClientSecretShort");
4837
+ default:
4838
+ return t("chat.missingConfigShort");
4839
+ }
4840
+ }, [missingConfigKind, t]);
4841
+ const missingConfigDetailMessage = React22.useMemo(() => {
4842
+ switch (missingConfigKind) {
4843
+ case "apiUrl":
4844
+ return t("chat.missingApiUrlDetail");
4845
+ case "clientSecret":
4846
+ return t("chat.missingClientSecretDetail");
4847
+ case "apiUrlAndClientSecret":
4848
+ return t("chat.missingApiUrlAndClientSecretDetail");
4849
+ default:
4850
+ return t("chat.missingConfigDetail");
4851
+ }
4852
+ }, [missingConfigKind, t]);
3102
4853
  const showMissingConfig = !isClientSecretInitializing && missingConfig;
3103
4854
  const hasUploadingFiles = attachments.some((a) => a.status === "uploading");
3104
- const isSendDisabled = !trimmedDraft || stream.isLoading || missingConfig || isHistoryLoading || hasUploadingFiles;
3105
- React20.useEffect(() => {
4855
+ const isSendDisabled = !trimmedDraft && !hasReferences || missingConfig || isHistoryLoading || hasUploadingFiles || isUploadingReferenceImages;
4856
+ const resizeComposerInput = React22.useCallback(() => {
4857
+ const textarea = composerInputRef.current;
4858
+ if (!textarea) {
4859
+ return;
4860
+ }
4861
+ textarea.style.height = "auto";
4862
+ const nextHeight = Math.min(
4863
+ textarea.scrollHeight,
4864
+ COMPOSER_INPUT_MAX_HEIGHT
4865
+ );
4866
+ textarea.style.height = `${nextHeight}px`;
4867
+ textarea.style.overflowY = textarea.scrollHeight > COMPOSER_INPUT_MAX_HEIGHT ? "auto" : "hidden";
4868
+ }, []);
4869
+ React22.useEffect(() => {
4870
+ resizeComposerInput();
4871
+ }, [draft, resizeComposerInput]);
4872
+ React22.useEffect(() => {
4873
+ document.addEventListener("selectionchange", syncQuoteSelection);
4874
+ return () => {
4875
+ document.removeEventListener("selectionchange", syncQuoteSelection);
4876
+ };
4877
+ }, [syncQuoteSelection]);
4878
+ React22.useEffect(() => {
4879
+ const viewport = viewportRef.current;
4880
+ if (!viewport) {
4881
+ return;
4882
+ }
4883
+ const handleViewportScroll = () => {
4884
+ clearQuoteSelection();
4885
+ };
4886
+ viewport.addEventListener("scroll", handleViewportScroll, {
4887
+ passive: true
4888
+ });
4889
+ window.addEventListener("resize", handleViewportScroll, { passive: true });
4890
+ return () => {
4891
+ viewport.removeEventListener("scroll", handleViewportScroll);
4892
+ window.removeEventListener("resize", handleViewportScroll);
4893
+ };
4894
+ }, [clearQuoteSelection]);
4895
+ React22.useEffect(() => {
4896
+ clearQuoteSelection();
4897
+ }, [messages.length, stream.threadId, clearQuoteSelection]);
4898
+ React22.useEffect(() => {
3106
4899
  if (missingConfig) return;
3107
4900
  void refreshThreads();
3108
4901
  }, [missingConfig, refreshThreads]);
3109
- React20.useEffect(() => {
4902
+ React22.useEffect(() => {
3110
4903
  if (missingConfig || !stream.client || !stream.assistantId) {
3111
4904
  setAssistantName(null);
3112
4905
  setAssistantAvatar(null);
@@ -3137,80 +4930,275 @@ function Chat({
3137
4930
  mimetype: a.storageFile?.mimetype ?? a.file.type,
3138
4931
  size: a.storageFile?.size ?? a.file.size
3139
4932
  }));
4933
+ const submitDraft = React22.useCallback(
4934
+ (followUpOverride) => {
4935
+ if (isSendDisabled) return;
4936
+ const filesToSend = uploadedFiles.length > 0 ? [...uploadedFiles] : void 0;
4937
+ const referencesToSend = references.length > 0 ? [...references] : void 0;
4938
+ const nextFollowUpMode = stream.isLoading ? followUpOverride ?? stream.followUpBehavior : void 0;
4939
+ const humanInput = buildHumanMessageInputPayload({
4940
+ content: trimmedDraft,
4941
+ references: referencesToSend
4942
+ });
4943
+ if (!humanInput) {
4944
+ return;
4945
+ }
4946
+ const displayContent = trimmedDraft || (referencesToSend ? t("chat.referencedContentOnly") : "");
4947
+ const newMessage = {
4948
+ id: createMessageId(),
4949
+ type: "human",
4950
+ content: displayContent,
4951
+ submittedInput: humanInput.input,
4952
+ ...humanInput.referenceComposition ? { referenceComposition: humanInput.referenceComposition } : {},
4953
+ ...filesToSend ? { attachments: filesToSend } : {},
4954
+ ...referencesToSend ? { references: referencesToSend } : {}
4955
+ };
4956
+ setDraft("");
4957
+ const inputPayload = {
4958
+ ...humanInput
4959
+ };
4960
+ if (filesToSend) {
4961
+ inputPayload.files = filesToSend;
4962
+ }
4963
+ const requestOptions = buildInjectedRequestOptions({
4964
+ defaults: options?.request,
4965
+ humanInput: inputPayload
4966
+ });
4967
+ stream.submit(
4968
+ {
4969
+ input: inputPayload,
4970
+ ...requestOptions.state ? { state: requestOptions.state } : {}
4971
+ },
4972
+ {
4973
+ ...nextFollowUpMode ? { followUpMode: nextFollowUpMode } : {},
4974
+ ...requestOptions.context ? { context: requestOptions.context } : {},
4975
+ ...requestOptions.config ? { config: requestOptions.config } : {},
4976
+ ...!nextFollowUpMode ? {
4977
+ optimisticValues: (prev) => {
4978
+ const prevMessages = prev?.messages ?? [];
4979
+ return { ...prev, messages: [...prevMessages, newMessage] };
4980
+ }
4981
+ } : {}
4982
+ }
4983
+ );
4984
+ scrollToBottom(true, true);
4985
+ if (selectedTool && !selectedTool.pinned) {
4986
+ setSelectedTool(null);
4987
+ }
4988
+ setAttachments([]);
4989
+ setReferences([]);
4990
+ },
4991
+ [
4992
+ isSendDisabled,
4993
+ options?.request,
4994
+ references,
4995
+ scrollToBottom,
4996
+ selectedTool,
4997
+ stream,
4998
+ trimmedDraft,
4999
+ uploadedFiles,
5000
+ t
5001
+ ]
5002
+ );
3140
5003
  const handleSubmit = (event) => {
3141
5004
  event.preventDefault();
3142
- if (isSendDisabled) return;
3143
- const filesToSend = uploadedFiles.length > 0 ? [...uploadedFiles] : void 0;
3144
- const newMessage = {
3145
- id: createMessageId(),
3146
- type: "human",
3147
- content: trimmedDraft,
3148
- ...filesToSend ? { attachments: filesToSend } : {}
3149
- };
3150
- setDraft("");
3151
- const inputPayload = {
3152
- input: trimmedDraft
3153
- };
3154
- if (filesToSend) {
3155
- inputPayload.files = filesToSend;
3156
- }
3157
- const requestOptions = buildInjectedRequestOptions({
3158
- defaults: options?.request,
3159
- humanInput: inputPayload
3160
- });
3161
- stream.submit(
3162
- {
3163
- input: inputPayload,
3164
- ...requestOptions.state ? { state: requestOptions.state } : {}
3165
- },
3166
- {
3167
- ...requestOptions.context ? { context: requestOptions.context } : {},
3168
- ...requestOptions.config ? { config: requestOptions.config } : {},
3169
- optimisticValues: (prev) => {
3170
- const prevMessages = prev?.messages ?? [];
3171
- return { ...prev, messages: [...prevMessages, newMessage] };
3172
- }
5005
+ submitDraft();
5006
+ };
5007
+ const handleEditPendingFollowUp = React22.useCallback(
5008
+ (id) => {
5009
+ const item = pendingFollowUps.find(
5010
+ (entry) => entry.id === id && entry.mode === "queue"
5011
+ );
5012
+ if (!item) {
5013
+ return;
3173
5014
  }
5015
+ const text = item.request?.input?.input?.trim() ?? "";
5016
+ const nextReferences = normalizeReferences(
5017
+ item.request?.input?.references
5018
+ );
5019
+ stream.removePendingFollowUp(id);
5020
+ setDraft(text);
5021
+ setReferences(nextReferences);
5022
+ requestAnimationFrame(() => {
5023
+ const input = composerInputRef.current;
5024
+ if (!input) {
5025
+ return;
5026
+ }
5027
+ input.focus();
5028
+ const position = text.length;
5029
+ input.setSelectionRange(position, position);
5030
+ });
5031
+ },
5032
+ [pendingFollowUps, stream]
5033
+ );
5034
+ const handleQuoteSelection = React22.useCallback(() => {
5035
+ if (!quoteSelection) {
5036
+ return;
5037
+ }
5038
+ setReferences(
5039
+ (previous) => mergeReferences(previous, [quoteSelection.reference])
3174
5040
  );
3175
- scrollToBottom(true, true);
3176
- if (selectedTool && !selectedTool.pinned) {
3177
- setSelectedTool(null);
5041
+ clearQuoteSelection();
5042
+ if (typeof window !== "undefined") {
5043
+ window.getSelection()?.removeAllRanges();
3178
5044
  }
3179
- setAttachments([]);
3180
- };
5045
+ composerInputRef.current?.focus();
5046
+ }, [clearQuoteSelection, quoteSelection]);
3181
5047
  const handleAttachmentClick = () => {
3182
5048
  fileInputRef.current?.click();
3183
5049
  };
3184
- const uploadFile = React20.useCallback(async (localId, file) => {
3185
- try {
3186
- const result = await stream.client.contexts.uploadFile(file);
3187
- setAttachments(
3188
- (prev) => prev.map(
3189
- (item) => item.localId === localId ? { ...item, status: "success", storageFile: result } : item
3190
- )
5050
+ const uploadContextFile = React22.useCallback(
5051
+ (file) => stream.client.contexts.uploadFile(file),
5052
+ [stream.client]
5053
+ );
5054
+ const handleComposerKeyDown = (event) => {
5055
+ if (event.key !== "Enter") {
5056
+ return;
5057
+ }
5058
+ if (event.shiftKey) {
5059
+ return;
5060
+ }
5061
+ if (event.nativeEvent.isComposing) {
5062
+ return;
5063
+ }
5064
+ event.preventDefault();
5065
+ if (isSendDisabled) {
5066
+ return;
5067
+ }
5068
+ if (stream.isLoading) {
5069
+ submitDraft(
5070
+ getBusyComposerShortcutFollowUpMode(event.metaKey || event.ctrlKey)
5071
+ );
5072
+ return;
5073
+ }
5074
+ submitDraft();
5075
+ };
5076
+ const handleComposerPaste = React22.useCallback(
5077
+ (event) => {
5078
+ const clipboardData = event.clipboardData;
5079
+ if (!clipboardData) {
5080
+ return;
5081
+ }
5082
+ const imageFiles = Array.from(clipboardData.items).filter(
5083
+ (item) => item.kind === "file" && item.type.startsWith("image/")
5084
+ ).map((item) => item.getAsFile()).filter((item) => Boolean(item));
5085
+ if (imageFiles.length > 0) {
5086
+ event.preventDefault();
5087
+ const maxCount = composer?.attachments?.maxCount ?? 10;
5088
+ const maxSize = composer?.attachments?.maxSize ?? 100 * 1024 * 1024;
5089
+ const currentImageReferenceCount = references.filter(
5090
+ (reference) => reference.type === "image"
5091
+ ).length;
5092
+ const availableSlots = Math.max(
5093
+ 0,
5094
+ maxCount - currentImageReferenceCount
5095
+ );
5096
+ const nextFiles = imageFiles.filter((file) => file.size <= maxSize).slice(0, availableSlots);
5097
+ if (nextFiles.length === 0) {
5098
+ return;
5099
+ }
5100
+ setIsUploadingReferenceImages(true);
5101
+ void Promise.allSettled(
5102
+ nextFiles.map(async (file) => {
5103
+ const [dimensions, storageFile] = await Promise.all([
5104
+ readImageDimensions(file),
5105
+ uploadContextFile(file)
5106
+ ]);
5107
+ return buildPastedImageReference(file, storageFile, dimensions);
5108
+ })
5109
+ ).then((results) => {
5110
+ const nextReferences = results.filter(
5111
+ (result) => result.status === "fulfilled"
5112
+ ).map((result) => result.value);
5113
+ if (nextReferences.length > 0) {
5114
+ setReferences(
5115
+ (previous) => mergeReferences(previous, nextReferences)
5116
+ );
5117
+ composerInputRef.current?.focus();
5118
+ }
5119
+ results.filter(
5120
+ (result) => result.status === "rejected"
5121
+ ).forEach((result) => {
5122
+ console.warn(
5123
+ "[Chat] Failed to upload pasted image reference:",
5124
+ result.reason
5125
+ );
5126
+ });
5127
+ }).finally(() => {
5128
+ setIsUploadingReferenceImages(false);
5129
+ });
5130
+ return;
5131
+ }
5132
+ const pastedText = clipboardData.getData("text/plain");
5133
+ if (pastedText.trim().length <= LONG_TEXT_REFERENCE_THRESHOLD) {
5134
+ return;
5135
+ }
5136
+ event.preventDefault();
5137
+ setReferences(
5138
+ (previous) => mergeReferences(previous, [
5139
+ {
5140
+ type: "quote",
5141
+ source: "Pasted text",
5142
+ text: pastedText
5143
+ }
5144
+ ])
3191
5145
  );
3192
- } catch (error) {
5146
+ composerInputRef.current?.focus();
5147
+ },
5148
+ [
5149
+ composer?.attachments?.maxCount,
5150
+ composer?.attachments?.maxSize,
5151
+ references,
5152
+ uploadContextFile
5153
+ ]
5154
+ );
5155
+ const alternateFollowUpShortcutLabel = React22.useMemo(() => {
5156
+ if (typeof navigator === "undefined") {
5157
+ return "\u2318Enter";
5158
+ }
5159
+ const platform = navigator.platform || navigator.userAgent;
5160
+ return /Mac|iPhone|iPad|iPod/i.test(platform) ? "\u2318Enter" : "Ctrl+Enter";
5161
+ }, []);
5162
+ const followUpShortcutLabels = React22.useMemo(
5163
+ () => getComposerFollowUpShortcutLabels(alternateFollowUpShortcutLabel),
5164
+ [alternateFollowUpShortcutLabel]
5165
+ );
5166
+ const uploadFile = React22.useCallback(
5167
+ async (localId, file) => {
5168
+ try {
5169
+ const result = await uploadContextFile(file);
5170
+ setAttachments(
5171
+ (prev) => prev.map(
5172
+ (item) => item.localId === localId ? { ...item, status: "success", storageFile: result } : item
5173
+ )
5174
+ );
5175
+ } catch (error) {
5176
+ setAttachments(
5177
+ (prev) => prev.map(
5178
+ (item) => item.localId === localId ? {
5179
+ ...item,
5180
+ status: "error",
5181
+ error: error instanceof Error ? error.message : "Upload failed"
5182
+ } : item
5183
+ )
5184
+ );
5185
+ }
5186
+ },
5187
+ [uploadContextFile]
5188
+ );
5189
+ const handleRetryUpload = React22.useCallback(
5190
+ (localId) => {
5191
+ const attachment = attachments.find((a) => a.localId === localId);
5192
+ if (!attachment || attachment.status !== "error") return;
3193
5193
  setAttachments(
3194
5194
  (prev) => prev.map(
3195
- (item) => item.localId === localId ? {
3196
- ...item,
3197
- status: "error",
3198
- error: error instanceof Error ? error.message : "Upload failed"
3199
- } : item
5195
+ (item) => item.localId === localId ? { ...item, status: "uploading", error: void 0 } : item
3200
5196
  )
3201
5197
  );
3202
- }
3203
- }, [stream.client]);
3204
- const handleRetryUpload = React20.useCallback((localId) => {
3205
- const attachment = attachments.find((a) => a.localId === localId);
3206
- if (!attachment || attachment.status !== "error") return;
3207
- setAttachments(
3208
- (prev) => prev.map(
3209
- (item) => item.localId === localId ? { ...item, status: "uploading", error: void 0 } : item
3210
- )
3211
- );
3212
- void uploadFile(localId, attachment.file);
3213
- }, [attachments, uploadFile]);
5198
+ void uploadFile(localId, attachment.file);
5199
+ },
5200
+ [attachments, uploadFile]
5201
+ );
3214
5202
  const handleFileChange = (event) => {
3215
5203
  const files = event.target.files;
3216
5204
  if (!files || files.length === 0) return;
@@ -3244,12 +5232,15 @@ function Chat({
3244
5232
  if (!attachment) return;
3245
5233
  if (attachment.status === "success" && attachment.storageFile?.id) {
3246
5234
  try {
3247
- await fetch(`${stream.apiUrl}/contexts/file/${attachment.storageFile.id}`, {
3248
- method: "DELETE",
3249
- headers: {
3250
- "Authorization": `Bearer ${effectiveClientSecret}`
5235
+ await fetch(
5236
+ `${stream.apiUrl}/contexts/file/${attachment.storageFile.id}`,
5237
+ {
5238
+ method: "DELETE",
5239
+ headers: {
5240
+ Authorization: `Bearer ${effectiveClientSecret}`
5241
+ }
3251
5242
  }
3252
- });
5243
+ );
3253
5244
  } catch {
3254
5245
  }
3255
5246
  }
@@ -3259,27 +5250,31 @@ function Chat({
3259
5250
  setSelectedTool((prev) => prev?.id === tool.id ? null : tool);
3260
5251
  };
3261
5252
  const handlePromptClick = (prompt) => {
3262
- if (missingConfig || stream.isLoading || isHistoryLoading) return;
5253
+ if (missingConfig || isHistoryLoading) return;
3263
5254
  const newMessage = {
3264
5255
  id: createMessageId(),
3265
5256
  type: "human",
3266
5257
  content: prompt
3267
5258
  };
5259
+ const nextFollowUpMode = stream.isLoading ? stream.followUpBehavior : void 0;
3268
5260
  stream.submit(
3269
5261
  { input: { input: prompt } },
3270
5262
  {
3271
- optimisticValues: (prev) => {
3272
- const prevMessages = prev?.messages ?? [];
3273
- return { ...prev, messages: [...prevMessages, newMessage] };
3274
- }
5263
+ ...nextFollowUpMode ? { followUpMode: nextFollowUpMode } : {},
5264
+ ...!nextFollowUpMode ? {
5265
+ optimisticValues: (prev) => {
5266
+ const prevMessages = prev?.messages ?? [];
5267
+ return { ...prev, messages: [...prevMessages, newMessage] };
5268
+ }
5269
+ } : {}
3275
5270
  }
3276
5271
  );
3277
5272
  scrollToBottom(true, true);
3278
5273
  };
3279
- const loadConversationMessages = React20.useCallback(
5274
+ const loadConversationMessages = React22.useCallback(
3280
5275
  async (recordId) => {
3281
5276
  if (missingConfig) {
3282
- setHistoryError(t("chat.missingConfigShort"));
5277
+ setHistoryError(missingConfigShortMessage);
3283
5278
  return;
3284
5279
  }
3285
5280
  setHistoryError(null);
@@ -3295,7 +5290,7 @@ function Chat({
3295
5290
  setIsHistoryLoading(false);
3296
5291
  }
3297
5292
  },
3298
- [missingConfig, stream, t]
5293
+ [missingConfig, missingConfigShortMessage, stream, t]
3299
5294
  );
3300
5295
  const handleNewThread = async () => {
3301
5296
  if (missingConfig || isHistoryLoading) return;
@@ -3338,12 +5333,16 @@ function Chat({
3338
5333
  };
3339
5334
  const handleRetry = (messageIndex) => {
3340
5335
  const messagesUpToIndex = messages.slice(0, messageIndex);
3341
- const lastHumanMessage = [...messagesUpToIndex].reverse().find(
3342
- (m) => String(m.type) === "human"
3343
- );
3344
- if (lastHumanMessage && typeof lastHumanMessage.content === "string") {
5336
+ const lastHumanMessage = [...messagesUpToIndex].reverse().find((m) => String(m.type) === "human");
5337
+ const humanInput = buildHumanMessageInputPayload({
5338
+ content: lastHumanMessage && typeof lastHumanMessage.content === "string" ? lastHumanMessage.content : "",
5339
+ submittedInput: lastHumanMessage?.submittedInput,
5340
+ references: lastHumanMessage?.references,
5341
+ referenceComposition: lastHumanMessage?.referenceComposition
5342
+ });
5343
+ if (humanInput) {
3345
5344
  stream.submit(
3346
- { input: { input: lastHumanMessage.content } },
5345
+ { input: humanInput },
3347
5346
  {
3348
5347
  optimisticValues: (prev) => {
3349
5348
  const prevMessages = prev?.messages ?? [];
@@ -3358,18 +5357,18 @@ function Chat({
3358
5357
  }
3359
5358
  };
3360
5359
  const acceptMimes = composer?.attachments?.accept ? Object.entries(composer.attachments.accept).map(([mime, exts]) => [mime, ...exts.map((e) => `.${e}`)].join(",")).join(",") : void 0;
3361
- const currentThread = React20.useMemo(
5360
+ const currentThread = React22.useMemo(
3362
5361
  () => threads.find((item) => item.id === stream.threadId),
3363
5362
  [threads, stream.threadId]
3364
5363
  );
3365
5364
  const errorMessage = stream.error instanceof Error ? stream.error.message : void 0;
3366
- const threadErrorMessage = React20.useMemo(() => {
5365
+ const threadErrorMessage = React22.useMemo(() => {
3367
5366
  if (currentThread?.status !== "error") return void 0;
3368
5367
  const message = currentThread.error?.trim();
3369
5368
  return message || t("thread.errorToast");
3370
5369
  }, [currentThread, t]);
3371
5370
  const assistantTitle = assistantName || resolvedTitle;
3372
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5371
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3373
5372
  "div",
3374
5373
  {
3375
5374
  ref: viewportRef,
@@ -3378,10 +5377,10 @@ function Chat({
3378
5377
  className
3379
5378
  ),
3380
5379
  children: [
3381
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between border-b p-2 sticky top-0 z-10 bg-background", children: [
3382
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-3 overflow-hidden", children: [
3383
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "relative shrink-0", children: [
3384
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5380
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between border-b p-2 sticky top-0 z-10 bg-background", children: [
5381
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center gap-3 overflow-hidden", children: [
5382
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative shrink-0", children: [
5383
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3385
5384
  ChatkitAvatar,
3386
5385
  {
3387
5386
  avatar: assistantAvatar,
@@ -3389,15 +5388,22 @@ function Chat({
3389
5388
  label: assistantTitle
3390
5389
  }
3391
5390
  ),
3392
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
5391
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
3393
5392
  ] }),
3394
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "truncate", children: [
3395
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { className: "text-lg font-semibold truncate", title: assistantTitle, children: assistantTitle }),
3396
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-xs text-muted-foreground", children: t("chat.statusOnline") })
5393
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "truncate", children: [
5394
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5395
+ "h2",
5396
+ {
5397
+ className: "text-lg font-semibold truncate",
5398
+ title: assistantTitle,
5399
+ children: assistantTitle
5400
+ }
5401
+ ),
5402
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-xs text-muted-foreground", children: t("chat.statusOnline") })
3397
5403
  ] })
3398
5404
  ] }),
3399
- history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1", children: [
3400
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5405
+ history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center gap-1", children: [
5406
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3401
5407
  "button",
3402
5408
  {
3403
5409
  type: "button",
@@ -3410,10 +5416,10 @@ function Chat({
3410
5416
  "disabled:opacity-50 disabled:cursor-not-allowed"
3411
5417
  ),
3412
5418
  title: t("history.newThread"),
3413
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.Pencil, { size: 16 })
5419
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.Pencil, { size: 16 })
3414
5420
  }
3415
5421
  ),
3416
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5422
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3417
5423
  HistorySidebar,
3418
5424
  {
3419
5425
  threads,
@@ -3427,23 +5433,45 @@ function Chat({
3427
5433
  )
3428
5434
  ] })
3429
5435
  ] }),
3430
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex-1 p-4", children: [
3431
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
3432
- historyError && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: historyError }),
3433
- showMissingConfig && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: t("chat.missingConfigDetail") }),
3434
- isHistoryLoading && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
3435
- messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5436
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex-1 p-4", children: [
5437
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
5438
+ historyError && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: historyError }),
5439
+ showMissingConfig && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: missingConfigDetailMessage }),
5440
+ isHistoryLoading && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
5441
+ messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3436
5442
  StartScreen,
3437
5443
  {
3438
5444
  startScreen,
3439
5445
  onPromptClick: handlePromptClick
3440
5446
  }
3441
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
5447
+ ) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "space-y-4", children: [
3442
5448
  messages.map((message, index) => {
3443
5449
  const messageType = String(message.type);
3444
5450
  const isAssistantMessage = messageType === "assistant" || messageType === "ai";
5451
+ const isStreamingMessage = stream.isLoading && index === messages.length - 1;
5452
+ const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
5453
+ {
5454
+ ...message,
5455
+ lastStreamOutputAt: lastStreamOutputAtRef.current
5456
+ },
5457
+ isStreamingMessage,
5458
+ { now: streamingNow }
5459
+ ) : null;
5460
+ if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
5461
+ return null;
5462
+ }
3445
5463
  const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
3446
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5464
+ const hasPlainRenderableContent = messageContent.trim().length > 0;
5465
+ const humanMessage = message;
5466
+ const humanReferences = humanMessage.references ?? [];
5467
+ const humanAttachments = humanMessage.attachments ?? [];
5468
+ const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
5469
+ const canQuoteMessage = message.type === "human" || isAssistantMessage;
5470
+ const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
5471
+ if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanReferences.length === 0) {
5472
+ return null;
5473
+ }
5474
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3447
5475
  "div",
3448
5476
  {
3449
5477
  className: cn(
@@ -3451,53 +5479,66 @@ function Chat({
3451
5479
  message.type === "human" ? "justify-end" : "justify-start -ml-1"
3452
5480
  // AI messages: slightly closer to left
3453
5481
  ),
3454
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col px-3 overflow-hidden", children: [
3455
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5482
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col px-3 overflow-hidden", children: [
5483
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3456
5484
  "div",
3457
5485
  {
5486
+ ...canQuoteMessage ? {
5487
+ "data-quote-message-id": message.id,
5488
+ "data-quote-source": quoteSource
5489
+ } : {},
3458
5490
  className: cn(
3459
5491
  "max-w-full rounded-2xl",
3460
5492
  message.type === "human" ? "bg-primary text-primary-foreground px-4 py-2.5" : message.type === "system" ? "bg-muted text-muted-foreground text-xs px-4 py-2.5" : "py-1 text-chat-foreground"
3461
5493
  // AI messages: use chat-specific foreground color
3462
5494
  ),
3463
- children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5495
+ children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3464
5496
  AssistantMessage,
3465
5497
  {
3466
5498
  message: {
3467
5499
  ...message,
3468
5500
  type: "assistant"
3469
5501
  },
3470
- isStreaming: stream.isLoading && index === messages.length - 1
5502
+ isStreaming: isStreamingMessage,
5503
+ streamingStatus
3471
5504
  }
3472
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
3473
- message.type === "human" && message.attachments?.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2", children: message.attachments.map((file, fileIndex) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5505
+ ) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5506
+ message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5507
+ ReferenceChip,
5508
+ {
5509
+ reference,
5510
+ variant: "message"
5511
+ },
5512
+ getReferenceKey(reference)
5513
+ )) }),
5514
+ message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3474
5515
  "div",
3475
5516
  {
3476
5517
  className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
3477
5518
  children: [
3478
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.FileText, { size: 12 }),
3479
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName })
5519
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.FileText, { size: 12 }),
5520
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName })
3480
5521
  ]
3481
5522
  },
3482
5523
  fileIndex
3483
5524
  )) }),
3484
- Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5525
+ Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3485
5526
  "p",
3486
5527
  {
3487
5528
  className: "wrap-break-word text-sm leading-relaxed",
3488
5529
  children: formatMessageContent(part)
3489
5530
  },
3490
5531
  `${part.type}-${partIndex}`
3491
- )) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
5532
+ )) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
3492
5533
  ] })
3493
5534
  }
3494
5535
  ),
3495
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5536
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3496
5537
  MessageActions,
3497
5538
  {
3498
5539
  content: messageContent,
3499
5540
  isAssistant: isAssistantMessage,
3500
- isStreaming: stream.isLoading && index === messages.length - 1,
5541
+ isStreaming: isStreamingMessage,
3501
5542
  onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
3502
5543
  }
3503
5544
  )
@@ -3510,18 +5551,34 @@ function Chat({
3510
5551
  const lastMessage = messages[messages.length - 1];
3511
5552
  const lastMessageType = lastMessage ? String(lastMessage.type) : "";
3512
5553
  const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
3513
- const lastMsgContent = lastMessage?.content;
3514
- const hasSubstantialContent = isLastMessageFromAI && (typeof lastMsgContent === "string" && lastMsgContent.length > 10 || Array.isArray(lastMsgContent) && lastMsgContent.length > 0);
3515
- if (hasSubstantialContent) return null;
3516
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1.5", children: [
3517
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:-0.3s]" }),
3518
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:-0.15s]" }),
3519
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-muted-foreground/60" })
3520
- ] }) }) });
5554
+ const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
5555
+ {
5556
+ ...lastMessage,
5557
+ lastStreamOutputAt: lastStreamOutputAtRef.current
5558
+ },
5559
+ stream.isLoading,
5560
+ { now: streamingNow }
5561
+ ) : null;
5562
+ if (lastAssistantStatus) return null;
5563
+ const fallbackStreamingStatus = getAssistantStreamingStatus(
5564
+ {
5565
+ status: void 0,
5566
+ reasoning: void 0,
5567
+ lastStreamOutputAt: lastStreamOutputAtRef.current
5568
+ },
5569
+ stream.isLoading,
5570
+ { now: streamingNow }
5571
+ );
5572
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5573
+ AssistantStreamingIndicator,
5574
+ {
5575
+ status: fallbackStreamingStatus ?? "loading"
5576
+ }
5577
+ ) }) });
3521
5578
  })()
3522
5579
  ] })
3523
5580
  ] }),
3524
- !isAtBottom && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5581
+ !isAtBottom && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3525
5582
  Button,
3526
5583
  {
3527
5584
  type: "button",
@@ -3534,12 +5591,40 @@ function Chat({
3534
5591
  onClick: () => scrollToBottom(true, true),
3535
5592
  "aria-label": t("chat.scrollToBottom"),
3536
5593
  title: t("chat.scrollToBottom"),
3537
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.ArrowDown, { size: 16 })
5594
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.ArrowDown, { size: 16 })
3538
5595
  }
3539
5596
  ) }),
3540
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "p-2 sticky bottom-0 z-10 bg-background", children: [
3541
- threadErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-3 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: threadErrorMessage }),
3542
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5597
+ quoteSelection && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5598
+ "div",
5599
+ {
5600
+ className: "pointer-events-none fixed z-50",
5601
+ style: {
5602
+ top: `${quoteSelection.top}px`,
5603
+ left: `${quoteSelection.left}px`,
5604
+ transform: "translateX(-50%)"
5605
+ },
5606
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5607
+ Button,
5608
+ {
5609
+ type: "button",
5610
+ size: "sm",
5611
+ variant: "secondary",
5612
+ className: "pointer-events-auto shadow-lg",
5613
+ onMouseDown: (event) => event.preventDefault(),
5614
+ onClick: handleQuoteSelection,
5615
+ "aria-label": t("composer.quoteSelection"),
5616
+ title: t("composer.quoteSelection"),
5617
+ children: [
5618
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.Quote, { size: 14 }),
5619
+ t("composer.quoteSelection")
5620
+ ]
5621
+ }
5622
+ )
5623
+ }
5624
+ ),
5625
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "p-2 sticky bottom-0 z-10 bg-background", children: [
5626
+ threadErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-3 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive overflow-auto", children: threadErrorMessage }),
5627
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3543
5628
  "input",
3544
5629
  {
3545
5630
  ref: fileInputRef,
@@ -3550,7 +5635,7 @@ function Chat({
3550
5635
  className: "hidden"
3551
5636
  }
3552
5637
  ),
3553
- attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: attachments.map((item) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5638
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: attachments.map((item) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3554
5639
  "div",
3555
5640
  {
3556
5641
  className: cn(
@@ -3558,24 +5643,36 @@ function Chat({
3558
5643
  item.status === "error" ? "bg-destructive/10 border border-destructive/30" : "bg-muted"
3559
5644
  ),
3560
5645
  children: [
3561
- item.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.Loader2, { size: 14, className: "animate-spin text-muted-foreground" }),
3562
- item.status === "success" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.FileText, { size: 14, className: "text-muted-foreground" }),
3563
- item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.FileText, { size: 14, className: "text-destructive" }),
3564
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: cn(
3565
- "max-w-30 truncate",
3566
- item.status === "error" && "text-destructive"
3567
- ), children: item.file.name }),
3568
- item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5646
+ item.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5647
+ import_lucide_react11.Loader2,
5648
+ {
5649
+ size: 14,
5650
+ className: "animate-spin text-muted-foreground"
5651
+ }
5652
+ ),
5653
+ item.status === "success" && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.FileText, { size: 14, className: "text-muted-foreground" }),
5654
+ item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.FileText, { size: 14, className: "text-destructive" }),
5655
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5656
+ "span",
5657
+ {
5658
+ className: cn(
5659
+ "max-w-30 truncate",
5660
+ item.status === "error" && "text-destructive"
5661
+ ),
5662
+ children: item.file.name
5663
+ }
5664
+ ),
5665
+ item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3569
5666
  "button",
3570
5667
  {
3571
5668
  type: "button",
3572
5669
  onClick: () => handleRetryUpload(item.localId),
3573
5670
  className: "ml-1 rounded-full p-0.5 text-destructive hover:bg-destructive/20",
3574
5671
  title: t("chat.retryUpload"),
3575
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.RefreshCw, { size: 12 })
5672
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.RefreshCw, { size: 12 })
3576
5673
  }
3577
5674
  ),
3578
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5675
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3579
5676
  "button",
3580
5677
  {
3581
5678
  type: "button",
@@ -3584,76 +5681,118 @@ function Chat({
3584
5681
  "ml-1 rounded-full p-0.5",
3585
5682
  item.status === "error" ? "text-destructive hover:bg-destructive/20" : "hover:bg-muted-foreground/20"
3586
5683
  ),
3587
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.X, { size: 12 })
5684
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.X, { size: 12 })
3588
5685
  }
3589
5686
  )
3590
5687
  ]
3591
5688
  },
3592
5689
  item.localId
3593
5690
  )) }),
3594
- selectedTool && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mb-2 flex items-center gap-2", children: [
3595
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary", children: selectedTool.shortLabel ?? selectedTool.label }),
3596
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5691
+ references.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5692
+ ReferenceChip,
5693
+ {
5694
+ reference,
5695
+ variant: "composer",
5696
+ onRemove: () => setReferences(
5697
+ (previous) => previous.filter(
5698
+ (item) => getReferenceKey(item) !== getReferenceKey(reference)
5699
+ )
5700
+ ),
5701
+ removeLabel: t("composer.removeReference")
5702
+ },
5703
+ getReferenceKey(reference)
5704
+ )) }),
5705
+ selectedTool && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "mb-2 flex items-center gap-2", children: [
5706
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary", children: selectedTool.shortLabel ?? selectedTool.label }),
5707
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3597
5708
  "button",
3598
5709
  {
3599
5710
  type: "button",
3600
5711
  onClick: () => setSelectedTool(null),
3601
5712
  className: "rounded-full p-0.5 text-muted-foreground hover:bg-muted",
3602
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.X, { size: 12 })
5713
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react11.X, { size: 12 })
3603
5714
  }
3604
5715
  )
3605
5716
  ] }),
3606
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("form", { className: "flex items-center", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5717
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5718
+ PendingFollowUps,
5719
+ {
5720
+ items: pendingFollowUps,
5721
+ isLoading: stream.isLoading,
5722
+ followUpBehavior: stream.followUpBehavior,
5723
+ onBehaviorChange: stream.setFollowUpBehavior,
5724
+ onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
5725
+ canSendNow: stream.canSendPendingFollowUpNow,
5726
+ onSendNow: (id) => stream.sendPendingFollowUpNow(id),
5727
+ onEdit: handleEditPendingFollowUp,
5728
+ onRemove: stream.removePendingFollowUp
5729
+ }
5730
+ ),
5731
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3607
5732
  "div",
3608
5733
  {
3609
5734
  className: cn(
3610
- "flex flex-1 items-center gap-1 rounded-xl",
5735
+ "flex flex-1 items-end gap-1 rounded-xl",
3611
5736
  "bg-background border border-border shadow-sm",
3612
5737
  "pl-1.5 pr-1.5 py-1",
3613
5738
  "focus-within:border-muted-foreground/30 focus-within:shadow-md",
3614
- "transition-shadow duration-200"
5739
+ "transition-shadow duration-200",
5740
+ getRoundedClass(theme.radius)
3615
5741
  ),
3616
5742
  children: [
3617
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5743
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3618
5744
  ComposerMenu,
3619
5745
  {
3620
5746
  composer,
3621
5747
  onAttachmentClick: handleAttachmentClick,
3622
5748
  onToolSelect: handleToolSelect,
3623
5749
  selectedTool,
3624
- disabled: stream.isLoading || missingConfig || isHistoryLoading
5750
+ disabled: missingConfig || isHistoryLoading
3625
5751
  }
3626
5752
  ),
3627
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3628
- "input",
5753
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5754
+ "textarea",
3629
5755
  {
3630
- type: "text",
5756
+ ref: composerInputRef,
3631
5757
  value: draft,
3632
5758
  onChange: (event) => setDraft(event.target.value),
5759
+ onPaste: handleComposerPaste,
5760
+ onKeyDown: handleComposerKeyDown,
5761
+ rows: 1,
3633
5762
  placeholder: inputPlaceholder,
3634
- disabled: stream.isLoading || missingConfig || isHistoryLoading,
5763
+ disabled: missingConfig || isHistoryLoading,
3635
5764
  className: cn(
3636
- "flex-1 bg-transparent text-sm text-foreground outline-none pr-2",
5765
+ "min-h-8 max-h-32 flex-1 resize-none bg-transparent py-1 pr-2 text-sm leading-5 text-foreground outline-none",
3637
5766
  "placeholder:text-muted-foreground",
3638
5767
  "disabled:cursor-not-allowed disabled:opacity-50"
3639
- ),
3640
- autoComplete: "off"
5768
+ )
3641
5769
  }
3642
5770
  ),
3643
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5771
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3644
5772
  SendButton,
3645
5773
  {
3646
5774
  disabled: isSendDisabled,
3647
5775
  isLoading: stream.isLoading,
5776
+ showStop: stream.isLoading && !trimmedDraft,
3648
5777
  onStop: () => stream.stop(),
3649
5778
  stopLabel: t("chat.stop"),
3650
- sendLabel: t("chat.send")
5779
+ sendLabel: t("chat.send"),
5780
+ shortcuts: stream.isLoading && trimmedDraft ? [
5781
+ {
5782
+ label: t("chat.followUps.steer"),
5783
+ keys: followUpShortcutLabels.steer
5784
+ },
5785
+ {
5786
+ label: t("chat.followUps.queue"),
5787
+ keys: followUpShortcutLabels.queue
5788
+ }
5789
+ ] : void 0
3651
5790
  }
3652
5791
  )
3653
5792
  ]
3654
5793
  }
3655
5794
  ) }),
3656
- disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5795
+ disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3657
5796
  "p",
3658
5797
  {
3659
5798
  className: cn(
@@ -3663,9 +5802,9 @@ function Chat({
3663
5802
  children: disclaimer.text
3664
5803
  }
3665
5804
  ),
3666
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
3667
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: t("chat.poweredBy") }),
3668
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
5805
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
5806
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: t("chat.poweredBy") }),
5807
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
3669
5808
  ] })
3670
5809
  ] })
3671
5810
  ]
@@ -3674,11 +5813,11 @@ function Chat({
3674
5813
  }
3675
5814
 
3676
5815
  // src/components/ui/input.tsx
3677
- var React21 = __toESM(require("react"), 1);
3678
- var import_jsx_runtime27 = require("react/jsx-runtime");
3679
- var Input = React21.forwardRef(
5816
+ var React23 = __toESM(require("react"), 1);
5817
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5818
+ var Input = React23.forwardRef(
3680
5819
  ({ className, type, ...props }, ref) => {
3681
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5820
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3682
5821
  "input",
3683
5822
  {
3684
5823
  ref,
@@ -3695,10 +5834,10 @@ var Input = React21.forwardRef(
3695
5834
  Input.displayName = "Input";
3696
5835
 
3697
5836
  // src/components/ui/separator.tsx
3698
- var React22 = __toESM(require("react"), 1);
3699
- var import_jsx_runtime28 = require("react/jsx-runtime");
3700
- var Separator = React22.forwardRef(
3701
- ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5837
+ var React24 = __toESM(require("react"), 1);
5838
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5839
+ var Separator = React24.forwardRef(
5840
+ ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
3702
5841
  "div",
3703
5842
  {
3704
5843
  ref,