@xpert-ai/chatkit-ui 0.0.20 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/dist/app/assets/{abap-CabZ0vYL.js → abap-DMqO-Um8.js} +1 -1
  2. package/dist/app/assets/{abnf-CPoubvVG.js → abnf-CBYpoE1H.js} +1 -1
  3. package/dist/app/assets/{actionscript-CL1BPQFv.js → actionscript-ieE-wJMz.js} +1 -1
  4. package/dist/app/assets/{ada-BOt55oS4.js → ada-0-3Dx7g-.js} +1 -1
  5. package/dist/app/assets/{agda-DKyUkxie.js → agda-uvq9b4Kv.js} +1 -1
  6. package/dist/app/assets/{al-Jnhqb7P-.js → al-BmajJCAx.js} +1 -1
  7. package/dist/app/assets/{antlr4-BeT3YbbK.js → antlr4-DnRRgAfR.js} +1 -1
  8. package/dist/app/assets/{apacheconf-Ck_DRZXY.js → apacheconf-BWoRK3Q3.js} +1 -1
  9. package/dist/app/assets/{apex-CPjbO0O4.js → apex-u3cbevj3.js} +1 -1
  10. package/dist/app/assets/{apl-Ccs4_jOU.js → apl-Cifc7IZj.js} +1 -1
  11. package/dist/app/assets/{applescript-C6i7vo8F.js → applescript-CpHbiQqz.js} +1 -1
  12. package/dist/app/assets/{aql-D3ZWY-VL.js → aql-C_VCCvUl.js} +1 -1
  13. package/dist/app/assets/{arduino-xTj3TTXg.js → arduino-CSAc4iDr.js} +1 -1
  14. package/dist/app/assets/{arff-BOuVccGR.js → arff-B8hSQDyJ.js} +1 -1
  15. package/dist/app/assets/{asciidoc-BmShvnn0.js → asciidoc-Guc1Uqnw.js} +1 -1
  16. package/dist/app/assets/{asm6502-6FWPK68i.js → asm6502-CxPqNdV6.js} +1 -1
  17. package/dist/app/assets/{asmatmel-KLAd82QV.js → asmatmel-C76CHB5e.js} +1 -1
  18. package/dist/app/assets/{aspnet-vZiSZd1y.js → aspnet-BQFc33QF.js} +1 -1
  19. package/dist/app/assets/{autohotkey-tcBDP1b7.js → autohotkey-uQeN2mix.js} +1 -1
  20. package/dist/app/assets/{autoit-Bwt0tLM_.js → autoit-Bmy0PsAQ.js} +1 -1
  21. package/dist/app/assets/{avisynth-Bzz43Lfu.js → avisynth-BvuIlb62.js} +1 -1
  22. package/dist/app/assets/{avro-idl-Bt9aSyrD.js → avro-idl-DWeVWQR3.js} +1 -1
  23. package/dist/app/assets/{bash-BloO3C-T.js → bash-HypWaeXO.js} +1 -1
  24. package/dist/app/assets/{basic-B-OOkRrw.js → basic-B4YxRCle.js} +1 -1
  25. package/dist/app/assets/{batch-aOUu2msA.js → batch-B1yKhArW.js} +1 -1
  26. package/dist/app/assets/{bbcode-C4D8vm8O.js → bbcode-BIDNxh7c.js} +1 -1
  27. package/dist/app/assets/{bicep-BtBByAYv.js → bicep-DkupOIs7.js} +1 -1
  28. package/dist/app/assets/{birb-BKXLouTf.js → birb-Jo6NYQYX.js} +1 -1
  29. package/dist/app/assets/{bison-CniuHJJN.js → bison-BjPiLxuX.js} +1 -1
  30. package/dist/app/assets/{bnf-CGcuZYv2.js → bnf-BjygHCSE.js} +1 -1
  31. package/dist/app/assets/{brainfuck-C9dlh056.js → brainfuck-CsnLnGPx.js} +1 -1
  32. package/dist/app/assets/{brightscript-nhHFw9_4.js → brightscript-CwmmyoHc.js} +1 -1
  33. package/dist/app/assets/{bro-BTsReVOc.js → bro-BNKXu22N.js} +1 -1
  34. package/dist/app/assets/{bsl-CmOTwcFR.js → bsl-DOwsbsXU.js} +1 -1
  35. package/dist/app/assets/{c-Yjfq4oES.js → c-DyedRTs7.js} +1 -1
  36. package/dist/app/assets/{cfscript-DGhYlgJ7.js → cfscript-DCpmh-J_.js} +1 -1
  37. package/dist/app/assets/{chaiscript-CpP8bBSU.js → chaiscript-DRaisf-4.js} +1 -1
  38. package/dist/app/assets/{cil-CZ7j4pcz.js → cil-C5bobqND.js} +1 -1
  39. package/dist/app/assets/{clike-D581thF2.js → clike-CvmXR497.js} +1 -1
  40. package/dist/app/assets/{clojure-AXVmar0o.js → clojure-BH_u6xTK.js} +1 -1
  41. package/dist/app/assets/{cmake-BozSSfax.js → cmake-CZruZSdT.js} +1 -1
  42. package/dist/app/assets/{cobol-OciN9vwY.js → cobol-qc5xAkcg.js} +1 -1
  43. package/dist/app/assets/{coffeescript-B9yMzVL5.js → coffeescript-DGM4CLoq.js} +1 -1
  44. package/dist/app/assets/{concurnas-DeQIM64O.js → concurnas-DFyZRxPp.js} +1 -1
  45. package/dist/app/assets/{coq-CicPksao.js → coq-DbZe2f_H.js} +1 -1
  46. package/dist/app/assets/{core-BIcqXTaK.js → core-BWUnDrKt.js} +1 -1
  47. package/dist/app/assets/{cpp-DKQF7403.js → cpp-CidpRyAJ.js} +1 -1
  48. package/dist/app/assets/{crystal-Bcau7QFZ.js → crystal-DZE9-h5D.js} +1 -1
  49. package/dist/app/assets/{csharp-BYghYpTl.js → csharp-Cf2K5CJJ.js} +1 -1
  50. package/dist/app/assets/{cshtml-BIxIGrsH.js → cshtml-DRjf7C5F.js} +1 -1
  51. package/dist/app/assets/{csp-CzDOD-m1.js → csp-dEoRcP0N.js} +1 -1
  52. package/dist/app/assets/{css-CPRwU6oY.js → css-BWUfAyau.js} +1 -1
  53. package/dist/app/assets/{css-extras-C28yWYxN.js → css-extras-pPY_Crez.js} +1 -1
  54. package/dist/app/assets/{csv-D8IAZwKO.js → csv-DdkqZn4I.js} +1 -1
  55. package/dist/app/assets/{cypher-0hMRBt8D.js → cypher-BXQbix41.js} +1 -1
  56. package/dist/app/assets/{d-B5PQgXXo.js → d-BctgRQp0.js} +1 -1
  57. package/dist/app/assets/{dart-CvCyf8me.js → dart-DuiikcDB.js} +1 -1
  58. package/dist/app/assets/{dataweave-Izl0xtz9.js → dataweave-ClZ_D-Ju.js} +1 -1
  59. package/dist/app/assets/{dax-D-bGAkbS.js → dax-DXNfCTH9.js} +1 -1
  60. package/dist/app/assets/{dhall-DXIOSM5Q.js → dhall-Cbz5hfMr.js} +1 -1
  61. package/dist/app/assets/{diff-BE-xKdIi.js → diff-bify6WLh.js} +1 -1
  62. package/dist/app/assets/{django-DxEZdkeU.js → django-5DdvW3LZ.js} +1 -1
  63. package/dist/app/assets/{dns-zone-file-D406E4S7.js → dns-zone-file-DIIW7lsW.js} +1 -1
  64. package/dist/app/assets/{docker-BZkb2U00.js → docker-BxIMVoJD.js} +1 -1
  65. package/dist/app/assets/{dot-BGJNVmx1.js → dot-DLEHPnum.js} +1 -1
  66. package/dist/app/assets/{ebnf-_PEATas2.js → ebnf-DHWaG3pk.js} +1 -1
  67. package/dist/app/assets/{editorconfig-C1UuLwJC.js → editorconfig-D2gTUSqU.js} +1 -1
  68. package/dist/app/assets/{eiffel-PzXVtlzf.js → eiffel-C3dcM2dq.js} +1 -1
  69. package/dist/app/assets/{ejs-707c0691.js → ejs-0qd3jtKi.js} +1 -1
  70. package/dist/app/assets/{elixir-Bd3zWMjP.js → elixir-BbBaHIGe.js} +1 -1
  71. package/dist/app/assets/{elm-DvEDEOdK.js → elm-KJmeOU7e.js} +1 -1
  72. package/dist/app/assets/{erb-B6lZT1P9.js → erb-BncgAY0M.js} +1 -1
  73. package/dist/app/assets/{erlang-BwhqRmQk.js → erlang-DS2SHYdK.js} +1 -1
  74. package/dist/app/assets/{etlua-Bkg93PrU.js → etlua-CvdrPEPO.js} +1 -1
  75. package/dist/app/assets/{excel-formula-BD0I0dyD.js → excel-formula-BSj1zROW.js} +1 -1
  76. package/dist/app/assets/{factor-CiQgOsxY.js → factor-DAbcpTN7.js} +1 -1
  77. package/dist/app/assets/{false-DlJ-f_Rc.js → false-CI895JmG.js} +1 -1
  78. package/dist/app/assets/{firestore-security-rules-CxrEhPSm.js → firestore-security-rules-CJ33YIQv.js} +1 -1
  79. package/dist/app/assets/{flow-DOjTBDi4.js → flow-a2eNz08o.js} +1 -1
  80. package/dist/app/assets/{fortran-D6uA-pWI.js → fortran-Bt9e6qJa.js} +1 -1
  81. package/dist/app/assets/{fsharp-CFL1DcvT.js → fsharp-Y0Qf2U16.js} +1 -1
  82. package/dist/app/assets/{ftl-DzWZwecM.js → ftl-D-TrqPet.js} +1 -1
  83. package/dist/app/assets/{gap-DatQeRFY.js → gap-CP5bMoJx.js} +1 -1
  84. package/dist/app/assets/{gcode-5FSxboIT.js → gcode-DQNcGCou.js} +1 -1
  85. package/dist/app/assets/{gdscript-Dz-OC8bG.js → gdscript-Bxt6W-z5.js} +1 -1
  86. package/dist/app/assets/{gedcom-BS0539Ys.js → gedcom-Cqgp4wkt.js} +1 -1
  87. package/dist/app/assets/{gherkin-BJKrWYAT.js → gherkin-D7pNUe8Z.js} +1 -1
  88. package/dist/app/assets/{git-DCjIevVw.js → git-C4ec-8cM.js} +1 -1
  89. package/dist/app/assets/{glsl-toSXKJrw.js → glsl-8sVKxech.js} +1 -1
  90. package/dist/app/assets/{gml-DODsSWU7.js → gml-TuwFoFK6.js} +1 -1
  91. package/dist/app/assets/{gn-CzmtMWMm.js → gn-BwHrmBhU.js} +1 -1
  92. package/dist/app/assets/{go-module-BbcV-9oG.js → go-module-cqolzX_W.js} +1 -1
  93. package/dist/app/assets/{go-BCQUEKVv.js → go-vGJJNlGP.js} +1 -1
  94. package/dist/app/assets/{graphql-C_KxCYJO.js → graphql-Do6Lisgl.js} +1 -1
  95. package/dist/app/assets/{groovy-Cj97iKYK.js → groovy--87wZh42.js} +1 -1
  96. package/dist/app/assets/{haml-tLXJGYDb.js → haml-vhodueeI.js} +1 -1
  97. package/dist/app/assets/{handlebars-DIdVe3xN.js → handlebars-CNLRaZ5R.js} +1 -1
  98. package/dist/app/assets/{haskell-DPqw5u4H.js → haskell-BWTsCqP4.js} +1 -1
  99. package/dist/app/assets/{haxe-AsnHNCIR.js → haxe-CSb0SWYW.js} +1 -1
  100. package/dist/app/assets/{hcl-C6aoWR34.js → hcl-ftOASTH-.js} +1 -1
  101. package/dist/app/assets/{hlsl-B2hhU30-.js → hlsl-BnaGHwDi.js} +1 -1
  102. package/dist/app/assets/{hoon-Bs-KhWO3.js → hoon-wyj1oNzn.js} +1 -1
  103. package/dist/app/assets/{hpkp-C-J4O-Mp.js → hpkp-Broim0YQ.js} +1 -1
  104. package/dist/app/assets/{hsts-BNFEkSnm.js → hsts-BSMt-Rhs.js} +1 -1
  105. package/dist/app/assets/{http-D7UlQANy.js → http-yK1zPe9M.js} +1 -1
  106. package/dist/app/assets/{ichigojam-B01TJ8BA.js → ichigojam-Bpzuxs1S.js} +1 -1
  107. package/dist/app/assets/{icon-Ca_ghvQd.js → icon-DjPW0ImK.js} +1 -1
  108. package/dist/app/assets/{icu-message-format-CkcsJ0ML.js → icu-message-format-CTS86FWW.js} +1 -1
  109. package/dist/app/assets/{idris-BApVxI9a.js → idris-DkPie8bu.js} +1 -1
  110. package/dist/app/assets/{iecst-CXLR8sGn.js → iecst-CG1KmB8U.js} +1 -1
  111. package/dist/app/assets/{ignore-7LzAeAFj.js → ignore-D9eho3CQ.js} +1 -1
  112. package/dist/app/assets/{index-BUg2yVDW.js → index-4J46qBCc.js} +105 -99
  113. package/dist/app/assets/{index-om2E9pNd.css → index-DTn9OjqV.css} +1 -1
  114. package/dist/app/assets/{inform7-CtnRN-Iq.js → inform7-DD1mc6Wh.js} +1 -1
  115. package/dist/app/assets/{ini-Cjpl6yTL.js → ini-Db6U4nBT.js} +1 -1
  116. package/dist/app/assets/{io-C6W_EboY.js → io-BRkH6hzB.js} +1 -1
  117. package/dist/app/assets/{j-BOBDun2W.js → j-CD22iLrA.js} +1 -1
  118. package/dist/app/assets/{java-CNwVyXY2.js → java-DvhwWZfy.js} +1 -1
  119. package/dist/app/assets/{javadoc-DS6hxu7_.js → javadoc-Ecoxhe_9.js} +1 -1
  120. package/dist/app/assets/{javadoclike-J6YT11JS.js → javadoclike-Realhpv4.js} +1 -1
  121. package/dist/app/assets/{javascript-IbEfuVSB.js → javascript-BBd1k8wl.js} +1 -1
  122. package/dist/app/assets/{javastacktrace-DjxwGV26.js → javastacktrace-C8QW0vuU.js} +1 -1
  123. package/dist/app/assets/{jexl-TLHmHaQ5.js → jexl-CT2UXrnH.js} +1 -1
  124. package/dist/app/assets/{jolie-CLk71kur.js → jolie-qtyDXXST.js} +1 -1
  125. package/dist/app/assets/{jq-DZKnIQZM.js → jq-CNJQULTZ.js} +1 -1
  126. package/dist/app/assets/{js-extras-CJab09ti.js → js-extras-DwIZLd4T.js} +1 -1
  127. package/dist/app/assets/{js-templates-CQGqrHhi.js → js-templates-glA_Un9b.js} +1 -1
  128. package/dist/app/assets/{jsdoc--ymvl4aq.js → jsdoc-BsXlBBjy.js} +1 -1
  129. package/dist/app/assets/{json-D9b-V85G.js → json-BC3xmMOU.js} +1 -1
  130. package/dist/app/assets/{json5-LgA47n7A.js → json5-CiePGcB9.js} +1 -1
  131. package/dist/app/assets/{jsonp-Cvwp3f8M.js → jsonp-B9HJmhak.js} +1 -1
  132. package/dist/app/assets/{jsstacktrace-z8t2H6h6.js → jsstacktrace-3xS0eyZd.js} +1 -1
  133. package/dist/app/assets/{jsx-B71LrwNd.js → jsx-B5kMqxBm.js} +1 -1
  134. package/dist/app/assets/{julia-DCATdxwO.js → julia-B5Udq0EY.js} +1 -1
  135. package/dist/app/assets/{keepalived-DVYYbgrL.js → keepalived-CI0hMS1b.js} +1 -1
  136. package/dist/app/assets/{keyman-DLyOXnhf.js → keyman-BCtXwe5i.js} +1 -1
  137. package/dist/app/assets/{kotlin-CYoDfyDA.js → kotlin-B3l0V1Fn.js} +1 -1
  138. package/dist/app/assets/{kumir-CPWiEvmL.js → kumir-BmC_PBOp.js} +1 -1
  139. package/dist/app/assets/{kusto-BkfRYk0W.js → kusto-B0p1ppsT.js} +1 -1
  140. package/dist/app/assets/{latex-BEjZ0ppC.js → latex-CHwNDYz_.js} +1 -1
  141. package/dist/app/assets/{latte-DaZOqdGV.js → latte-DihAtCCl.js} +1 -1
  142. package/dist/app/assets/{less-BmKsj1gN.js → less-BLGkFSp1.js} +1 -1
  143. package/dist/app/assets/{lilypond-mmng28aJ.js → lilypond-CCsAc8Nl.js} +1 -1
  144. package/dist/app/assets/{liquid-BuuJO6_6.js → liquid-jBSQx5I5.js} +1 -1
  145. package/dist/app/assets/{lisp-DnffFM5N.js → lisp-CgzQXnYE.js} +1 -1
  146. package/dist/app/assets/{livescript-BSsr00Wr.js → livescript-u96H-zdx.js} +1 -1
  147. package/dist/app/assets/{llvm-37YjcHN5.js → llvm-WmVcvcNM.js} +1 -1
  148. package/dist/app/assets/{log-D3l5N3To.js → log-990P-Rch.js} +1 -1
  149. package/dist/app/assets/{lolcode-C0Q2M_6s.js → lolcode-DdFIjfxs.js} +1 -1
  150. package/dist/app/assets/{lua-DcLwN4Tg.js → lua-GkhnMu0T.js} +1 -1
  151. package/dist/app/assets/{magma-CK0Amip9.js → magma-wajb6K9F.js} +1 -1
  152. package/dist/app/assets/{makefile-CtpS-RoO.js → makefile-CGHjuGaS.js} +1 -1
  153. package/dist/app/assets/{markdown-BNK3F4ql.js → markdown-BFWQ31vs.js} +1 -1
  154. package/dist/app/assets/{markup-C9GIL65H.js → markup-1ihI0X17.js} +1 -1
  155. package/dist/app/assets/{markup-templating-Du1J3ADP.js → markup-templating-DblqKZLi.js} +1 -1
  156. package/dist/app/assets/{matlab-DEM6O1Ul.js → matlab-CPqo7ZUC.js} +1 -1
  157. package/dist/app/assets/{maxscript-DMvqa3gf.js → maxscript-CTgVjA7o.js} +1 -1
  158. package/dist/app/assets/{mel-C8DBIw1g.js → mel-Cxah6vYr.js} +1 -1
  159. package/dist/app/assets/{mermaid-CVko6NSq.js → mermaid-BAgJSsZ7.js} +1 -1
  160. package/dist/app/assets/{mizar-CwYm3_It.js → mizar-BL3spn8_.js} +1 -1
  161. package/dist/app/assets/{mongodb-DRqGwjq6.js → mongodb-DXzP7tR0.js} +1 -1
  162. package/dist/app/assets/{monkey-BxiKe6Nr.js → monkey-anPtBsfj.js} +1 -1
  163. package/dist/app/assets/{moonscript-CJyt1xoM.js → moonscript-Y_tcmLfW.js} +1 -1
  164. package/dist/app/assets/{n1ql-BBmjIGEU.js → n1ql-B7NGFYRY.js} +1 -1
  165. package/dist/app/assets/{n4js-ByKsJMJL.js → n4js-zh8URwWB.js} +1 -1
  166. package/dist/app/assets/{nand2tetris-hdl-BTSXj71h.js → nand2tetris-hdl-CDUtzUHw.js} +1 -1
  167. package/dist/app/assets/{naniscript-C4jykFVF.js → naniscript-CjJGU6C6.js} +1 -1
  168. package/dist/app/assets/{nasm-DPA0eXtX.js → nasm-D6biC9Vr.js} +1 -1
  169. package/dist/app/assets/{neon-upN4Ak64.js → neon-C3Z0pCuH.js} +1 -1
  170. package/dist/app/assets/{nevod-CdttHB8F.js → nevod-BT4Ivkzb.js} +1 -1
  171. package/dist/app/assets/{nginx-DI1fsQ3j.js → nginx-vHHTRs1B.js} +1 -1
  172. package/dist/app/assets/{nim-D7kc_mK9.js → nim-Jk1NOWk0.js} +1 -1
  173. package/dist/app/assets/{nix-BUG5ppr9.js → nix-CEkA_w3B.js} +1 -1
  174. package/dist/app/assets/{nsis-BnXhmmxO.js → nsis-Du9w_Qb8.js} +1 -1
  175. package/dist/app/assets/{objectivec-Bu4dOfb9.js → objectivec-BciYUGRR.js} +1 -1
  176. package/dist/app/assets/{ocaml-aT7VVPiL.js → ocaml-CpZ_M4DP.js} +1 -1
  177. package/dist/app/assets/{opencl-BzyWcYkI.js → opencl-C-4M-Mvx.js} +1 -1
  178. package/dist/app/assets/{openqasm-b2yFBJdq.js → openqasm-CilZXlSe.js} +1 -1
  179. package/dist/app/assets/{oz-D46TtIuw.js → oz-DluYJ10T.js} +1 -1
  180. package/dist/app/assets/{parigp-BAJyhdut.js → parigp-BlIaVN51.js} +1 -1
  181. package/dist/app/assets/{parser-B-ALvauC.js → parser-BZVTYRp4.js} +1 -1
  182. package/dist/app/assets/{pascal-B0ap4FDW.js → pascal-CMz_wkC0.js} +1 -1
  183. package/dist/app/assets/{pascaligo-ChOneu9-.js → pascaligo-DLQY1QwY.js} +1 -1
  184. package/dist/app/assets/{pcaxis-DTAmxHgs.js → pcaxis-C-5nzMDp.js} +1 -1
  185. package/dist/app/assets/{peoplecode-dQfUy8zn.js → peoplecode-BhTicHl8.js} +1 -1
  186. package/dist/app/assets/{perl-CYk00e1Q.js → perl-BArlZZ8M.js} +1 -1
  187. package/dist/app/assets/{php-DvSqFnSN.js → php-C6zNUOf5.js} +1 -1
  188. package/dist/app/assets/{php-extras-BFjUbIU6.js → php-extras-DD5Glhrz.js} +1 -1
  189. package/dist/app/assets/{phpdoc-Di7rKCNL.js → phpdoc-Buj0qa-9.js} +1 -1
  190. package/dist/app/assets/{plsql-dX0-BKqD.js → plsql-o2-C-Ezr.js} +1 -1
  191. package/dist/app/assets/{powerquery-3xq4KaAs.js → powerquery-Cl0Dbp57.js} +1 -1
  192. package/dist/app/assets/{powershell-BbXooszO.js → powershell-BVFtl1FS.js} +1 -1
  193. package/dist/app/assets/{processing-GWbfNCzH.js → processing-BHJTqgxZ.js} +1 -1
  194. package/dist/app/assets/{prolog-Tb2TbunJ.js → prolog-C9gykhtA.js} +1 -1
  195. package/dist/app/assets/{promql-QS8vHhL7.js → promql-TzYBDR1F.js} +1 -1
  196. package/dist/app/assets/{properties-BJ8AWlqX.js → properties-Bi8GxxCM.js} +1 -1
  197. package/dist/app/assets/{protobuf-De-puAg3.js → protobuf-s08U24Jk.js} +1 -1
  198. package/dist/app/assets/{psl-hZft3C8K.js → psl-By228u9L.js} +1 -1
  199. package/dist/app/assets/{pug-BcYHdk-i.js → pug-CahxgaMR.js} +1 -1
  200. package/dist/app/assets/{puppet-BWbqDQJD.js → puppet-BAY6TBQY.js} +1 -1
  201. package/dist/app/assets/{pure-Bz2pjTxR.js → pure-IA8ihD9R.js} +1 -1
  202. package/dist/app/assets/{purebasic-BlO48lYx.js → purebasic-B6joY-ZH.js} +1 -1
  203. package/dist/app/assets/{purescript-BxSMm2Br.js → purescript-DczXEj8E.js} +1 -1
  204. package/dist/app/assets/{q-DDUTW9aK.js → q-CEXq_tpX.js} +1 -1
  205. package/dist/app/assets/{qml-DisOV-LV.js → qml-ND31CBLa.js} +1 -1
  206. package/dist/app/assets/{qore-FNRP4gBF.js → qore-DAjVLL2F.js} +1 -1
  207. package/dist/app/assets/{qsharp-DhtMV0oO.js → qsharp-jccBvH6Y.js} +1 -1
  208. package/dist/app/assets/{r-CyiuHjNN.js → r-pv5Xhvsd.js} +1 -1
  209. package/dist/app/assets/{racket-DFgoSckH.js → racket-xRigDwdL.js} +1 -1
  210. package/dist/app/assets/{reason-HhYbY7K3.js → reason-DnAP7dec.js} +1 -1
  211. package/dist/app/assets/{regex-jU5TpvM-.js → regex-Dwkma1bN.js} +1 -1
  212. package/dist/app/assets/{rego-BCjDPrQO.js → rego-3dHPz-ut.js} +1 -1
  213. package/dist/app/assets/{renpy-BTSgQi2v.js → renpy-Czxc7hu0.js} +1 -1
  214. package/dist/app/assets/{rest-BLcZ4e-5.js → rest-BP_JQ_AG.js} +1 -1
  215. package/dist/app/assets/{rip-SltRJnuI.js → rip-Nredd5kD.js} +1 -1
  216. package/dist/app/assets/{roboconf-B-GZm2Oe.js → roboconf-CkR4ACer.js} +1 -1
  217. package/dist/app/assets/{robotframework-BOt8S6cX.js → robotframework-CYYV7JaP.js} +1 -1
  218. package/dist/app/assets/{ruby-CVfYH0zM.js → ruby-EA_sSyU6.js} +1 -1
  219. package/dist/app/assets/{rust-B6mEp4Sj.js → rust-BM2hEYJt.js} +1 -1
  220. package/dist/app/assets/{sas-DvEI8RJ0.js → sas-jaxOWx-0.js} +1 -1
  221. package/dist/app/assets/{sass-Cv25Jxqq.js → sass-pkiTdYnF.js} +1 -1
  222. package/dist/app/assets/{scala-CyqNr7Uv.js → scala-lTsQiijh.js} +1 -1
  223. package/dist/app/assets/{scheme-ji0XoXLf.js → scheme-DkPZYA1o.js} +1 -1
  224. package/dist/app/assets/{scss-B7_0neO_.js → scss-DZjxUgqE.js} +1 -1
  225. package/dist/app/assets/{shell-session-CqZEoMQD.js → shell-session-CKXJ0a90.js} +1 -1
  226. package/dist/app/assets/{smali-DKSzZYkI.js → smali-DVWpHHAX.js} +1 -1
  227. package/dist/app/assets/{smalltalk-BOA4piuq.js → smalltalk-ChiRh9QF.js} +1 -1
  228. package/dist/app/assets/{smarty-Du99BSgN.js → smarty-C4i7AVoC.js} +1 -1
  229. package/dist/app/assets/{sml-BJedIA4B.js → sml-v9dKzil3.js} +1 -1
  230. package/dist/app/assets/{solidity-DidQwG5Z.js → solidity-DaxM8K8t.js} +1 -1
  231. package/dist/app/assets/{solution-file-Bx0d9qN8.js → solution-file-Ch7ajMI6.js} +1 -1
  232. package/dist/app/assets/{soy-BBLv3Cfa.js → soy-CHeWJZPl.js} +1 -1
  233. package/dist/app/assets/{sparql-Da5WZKbL.js → sparql-f56EhPSR.js} +1 -1
  234. package/dist/app/assets/{splunk-spl-DbJKl8So.js → splunk-spl-CNX2IshN.js} +1 -1
  235. package/dist/app/assets/{sqf-CYrx0jxf.js → sqf-B9Z5kTgF.js} +1 -1
  236. package/dist/app/assets/{sql-Gv-aOlOf.js → sql-PZTLdUd4.js} +1 -1
  237. package/dist/app/assets/{squirrel-FpIGPPw4.js → squirrel-_QTHEJtD.js} +1 -1
  238. package/dist/app/assets/{stan-Dq001Nrk.js → stan-y02QaMQQ.js} +1 -1
  239. package/dist/app/assets/{stylus-aatfgWwe.js → stylus-CGYq1GKp.js} +1 -1
  240. package/dist/app/assets/{swift-pn7VW95d.js → swift-BBMLpv3H.js} +1 -1
  241. package/dist/app/assets/{systemd-9capsVJ6.js → systemd-CD7Dfv8Y.js} +1 -1
  242. package/dist/app/assets/{t4-cs-CKXcczci.js → t4-cs-BtxQixNP.js} +1 -1
  243. package/dist/app/assets/{t4-templating-1wTayb8u.js → t4-templating-BX2jWZwS.js} +1 -1
  244. package/dist/app/assets/{t4-vb-B_O7wBow.js → t4-vb-CX3AQUVf.js} +1 -1
  245. package/dist/app/assets/{tap-D-TV5_gQ.js → tap-BRBB20R0.js} +1 -1
  246. package/dist/app/assets/{tcl-BaVob1Om.js → tcl-CWrqc_vL.js} +1 -1
  247. package/dist/app/assets/{textile-COMk-HmI.js → textile-EJMS8IJv.js} +1 -1
  248. package/dist/app/assets/{toml-D9NJpArC.js → toml-DLWr0_Sd.js} +1 -1
  249. package/dist/app/assets/{tremor-rCNHwdQL.js → tremor-D0DGH64h.js} +1 -1
  250. package/dist/app/assets/{tt2-DTDvfOgc.js → tt2-CaSD1IpZ.js} +1 -1
  251. package/dist/app/assets/{turtle-D8pkqXh1.js → turtle-BtZWKoZ_.js} +1 -1
  252. package/dist/app/assets/{twig-DxSF8gqH.js → twig-BQ0AWwu3.js} +1 -1
  253. package/dist/app/assets/{typescript-Caebatmk.js → typescript-sByRs_H7.js} +1 -1
  254. package/dist/app/assets/{typoscript-B3uk1kES.js → typoscript-Bs3x5DVu.js} +1 -1
  255. package/dist/app/assets/{unrealscript-ZNoSG8ji.js → unrealscript-BPk-JGuX.js} +1 -1
  256. package/dist/app/assets/{uorazor-LekoNNOo.js → uorazor-Dxr1B729.js} +1 -1
  257. package/dist/app/assets/{uri-B8YcIzOv.js → uri-B18d7fGy.js} +1 -1
  258. package/dist/app/assets/{v-6rOne2a0.js → v-B-4se_c_.js} +1 -1
  259. package/dist/app/assets/{vala-CjEJEdsP.js → vala-CZJMpckw.js} +1 -1
  260. package/dist/app/assets/{vbnet-DBPmBm7_.js → vbnet-Bon1nLZm.js} +1 -1
  261. package/dist/app/assets/{velocity-DOooMwL8.js → velocity-Ck8gHF4B.js} +1 -1
  262. package/dist/app/assets/{verilog-Cq0ZocvP.js → verilog-zADKtd-6.js} +1 -1
  263. package/dist/app/assets/{vhdl-Dxs_xidb.js → vhdl-Ce3jhJNh.js} +1 -1
  264. package/dist/app/assets/{vim-BqsnXwB6.js → vim-CwgyIdo-.js} +1 -1
  265. package/dist/app/assets/{visual-basic-zAzjvaqP.js → visual-basic-BWQC7pBF.js} +1 -1
  266. package/dist/app/assets/{warpscript-D9hbfr6_.js → warpscript-CVp7w3zz.js} +1 -1
  267. package/dist/app/assets/{wasm-C4TU9VDY.js → wasm-yPowz3sM.js} +1 -1
  268. package/dist/app/assets/{web-idl-DD5JcddQ.js → web-idl-BkghLEob.js} +1 -1
  269. package/dist/app/assets/{wiki-Des21yVK.js → wiki-TBH4TnLK.js} +1 -1
  270. package/dist/app/assets/{wolfram-B7enpov1.js → wolfram-BmgF1AlB.js} +1 -1
  271. package/dist/app/assets/{wren-Rr8h-Ayu.js → wren-CJ8nrMy_.js} +1 -1
  272. package/dist/app/assets/{xeora-EjcLXBhx.js → xeora-N6_5XQpC.js} +1 -1
  273. package/dist/app/assets/{xml-doc-uaTxx6-m.js → xml-doc-GBGxTNFc.js} +1 -1
  274. package/dist/app/assets/{xojo-CX6G8nhh.js → xojo-CmpAfzYO.js} +1 -1
  275. package/dist/app/assets/{xquery-DvPb3Uw9.js → xquery-BA22D3yp.js} +1 -1
  276. package/dist/app/assets/{yaml-D-l_Y2hx.js → yaml-CDGmAMpu.js} +1 -1
  277. package/dist/app/assets/{yang-KBoIIT4_.js → yang-rFKIXOjI.js} +1 -1
  278. package/dist/app/assets/{zig-_uNXp9cY.js → zig-rH4Tzjve.js} +1 -1
  279. package/dist/app/index.html +2 -2
  280. package/dist/index.cjs +1891 -582
  281. package/dist/index.d.cts +17 -3
  282. package/dist/index.d.ts +17 -3
  283. package/dist/index.js +1926 -591
  284. package/package.json +4 -4
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 React21 = __toESM(require("react"), 1);
70
+ var import_lucide_react10 = 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,189 @@ 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 toOptionalString(value) {
287
+ return isNonEmptyString(value) ? value.trim() : void 0;
288
+ }
289
+ function toReferenceText(value) {
290
+ return typeof value === "string" && value.trim().length > 0 ? value : null;
291
+ }
292
+ function toLineNumber(value) {
293
+ if (typeof value === "number" && Number.isInteger(value) && value > 0) {
294
+ return value;
295
+ }
296
+ return null;
297
+ }
298
+ function normalizeCodeReference(candidate) {
299
+ const path = toOptionalString(candidate.path);
300
+ const text = toReferenceText(candidate.text);
301
+ const startLine = toLineNumber(candidate.startLine);
302
+ const endLine = toLineNumber(candidate.endLine);
303
+ if (!path || !text || startLine === null || endLine === null) {
304
+ return null;
305
+ }
306
+ return {
307
+ type: "code",
308
+ ...toOptionalString(candidate.id) ? { id: toOptionalString(candidate.id) } : {},
309
+ ...toOptionalString(candidate.label) ? { label: toOptionalString(candidate.label) } : {},
310
+ path,
311
+ startLine,
312
+ endLine,
313
+ text,
314
+ ...toOptionalString(candidate.language) ? { language: toOptionalString(candidate.language) } : {},
315
+ ...toOptionalString(candidate.taskId) ? { taskId: toOptionalString(candidate.taskId) } : {}
316
+ };
317
+ }
318
+ function normalizeQuoteReference(candidate) {
319
+ const text = toReferenceText(candidate.text);
320
+ if (!text) {
321
+ return null;
322
+ }
323
+ return {
324
+ type: "quote",
325
+ ...toOptionalString(candidate.id) ? { id: toOptionalString(candidate.id) } : {},
326
+ ...toOptionalString(candidate.label) ? { label: toOptionalString(candidate.label) } : {},
327
+ text,
328
+ ...toOptionalString(candidate.messageId) ? { messageId: toOptionalString(candidate.messageId) } : {},
329
+ ...toOptionalString(candidate.source) ? { source: toOptionalString(candidate.source) } : {}
330
+ };
331
+ }
332
+ function isLegacyCodeReference(candidate) {
333
+ return isNonEmptyString(candidate.path) && toLineNumber(candidate.startLine) !== null && toLineNumber(candidate.endLine) !== null && toReferenceText(candidate.text) !== null;
334
+ }
335
+ function normalizeReference(value) {
336
+ if (!isObjectLike(value)) {
337
+ return null;
338
+ }
339
+ const candidate = value;
340
+ const type = toOptionalString(candidate.type);
341
+ if (type === "code") {
342
+ return normalizeCodeReference(candidate);
343
+ }
344
+ if (type === "quote") {
345
+ return normalizeQuoteReference(candidate);
346
+ }
347
+ if (type === void 0 && isLegacyCodeReference(candidate)) {
348
+ return normalizeCodeReference(candidate);
349
+ }
350
+ return null;
351
+ }
352
+ function normalizeReferences(value) {
353
+ if (!Array.isArray(value)) {
354
+ return [];
355
+ }
356
+ return value.map((item) => normalizeReference(item)).filter((item) => item !== null);
357
+ }
358
+ function getCodeReferenceRange(reference) {
359
+ return reference.startLine === reference.endLine ? `${reference.startLine}` : `${reference.startLine}-${reference.endLine}`;
360
+ }
361
+ function getQuoteExcerpt(reference) {
362
+ const normalized = reference.text.replace(/\s+/g, " ").trim();
363
+ if (normalized.length <= 32) {
364
+ return normalized;
365
+ }
366
+ return `${normalized.slice(0, 29)}...`;
367
+ }
368
+ function getCodeReferenceLocation(reference) {
369
+ return `${reference.path}:${getCodeReferenceRange(reference)}`;
370
+ }
371
+ function getReferenceKey(reference) {
372
+ if (reference.id && reference.id.trim()) {
373
+ return reference.id.trim();
374
+ }
375
+ if (reference.type === "code") {
376
+ return [
377
+ reference.type,
378
+ reference.path,
379
+ reference.startLine,
380
+ reference.endLine,
381
+ reference.text
382
+ ].join(":");
383
+ }
384
+ return [
385
+ reference.type,
386
+ reference.messageId ?? "",
387
+ reference.source ?? "",
388
+ reference.text
389
+ ].join(":");
390
+ }
391
+ function mergeReferences(current, incoming) {
392
+ const merged = [...current];
393
+ const seen = new Set(current.map(getReferenceKey));
394
+ incoming.forEach((reference) => {
395
+ const key = getReferenceKey(reference);
396
+ if (seen.has(key)) {
397
+ return;
398
+ }
399
+ seen.add(key);
400
+ merged.push(reference);
401
+ });
402
+ return merged;
403
+ }
404
+ function getReferenceLabel(reference) {
405
+ if (reference.label && reference.label.trim()) {
406
+ return reference.label.trim();
407
+ }
408
+ if (reference.type === "code") {
409
+ const segments = reference.path.split("/");
410
+ const fileName = segments[segments.length - 1] || reference.path;
411
+ return `${fileName} ${getCodeReferenceRange(reference)}`;
412
+ }
413
+ if (reference.source && reference.source.trim()) {
414
+ return reference.source.trim();
415
+ }
416
+ return getQuoteExcerpt(reference);
417
+ }
418
+ function getReferenceMetaLine(reference) {
419
+ if (reference.type === "code") {
420
+ return getCodeReferenceLocation(reference);
421
+ }
422
+ if (reference.source && reference.source.trim()) {
423
+ return getQuoteExcerpt(reference);
424
+ }
425
+ if (reference.messageId && reference.messageId.trim()) {
426
+ return `Message ${reference.messageId.trim()}`;
427
+ }
428
+ return null;
429
+ }
430
+ function getReferenceTitle(reference) {
431
+ if (reference.type === "code") {
432
+ return `${getCodeReferenceLocation(reference)}
433
+
434
+ ${reference.text}`;
435
+ }
436
+ const header = reference.label?.trim() || reference.source?.trim() || "Quoted text";
437
+ return `${header}
438
+
439
+ ${reference.text}`;
440
+ }
441
+ function buildHumanMessageInputPayload(source) {
442
+ const references = normalizeReferences(source.references);
443
+ const nextReferenceComposition = source.referenceComposition ?? (references.length > 0 && typeof source.submittedInput !== "string" ? "compose" : void 0);
444
+ if (typeof source.submittedInput === "string") {
445
+ return {
446
+ input: source.submittedInput.trim(),
447
+ ...references.length > 0 ? { references } : {},
448
+ ...nextReferenceComposition ? { referenceComposition: nextReferenceComposition } : {}
449
+ };
450
+ }
451
+ const input = typeof source.content === "string" ? source.content.trim() : "";
452
+ if (!input && references.length === 0) {
453
+ return null;
454
+ }
455
+ return {
456
+ input,
457
+ ...references.length > 0 ? { references } : {},
458
+ ...nextReferenceComposition ? { referenceComposition: nextReferenceComposition } : {}
459
+ };
460
+ }
461
+
202
462
  // src/providers/ParentMessenger.tsx
203
463
  var import_jsx_runtime = require("react/jsx-runtime");
204
464
  var handledSendUserMessageNonces = /* @__PURE__ */ new Set();
@@ -227,6 +487,10 @@ function ParentMessengerProvider({
227
487
  /* @__PURE__ */ new Map()
228
488
  );
229
489
  const onSetOptionsHandlersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
490
+ const onSetComposerValueHandlersRef = (0, import_react.useRef)(
491
+ /* @__PURE__ */ new Set()
492
+ );
493
+ const onFocusComposerHandlersRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
230
494
  const latestOptionsRef = (0, import_react.useRef)(null);
231
495
  const isParentAvailable = (0, import_react.useMemo)(() => {
232
496
  return typeof window !== "undefined" && window.parent !== window;
@@ -240,6 +504,24 @@ function ParentMessengerProvider({
240
504
  onSetOptionsHandlersRef.current.delete(handler);
241
505
  };
242
506
  }, []);
507
+ const registerOnSetComposerValue = (0, import_react.useCallback)(
508
+ (handler) => {
509
+ onSetComposerValueHandlersRef.current.add(handler);
510
+ return () => {
511
+ onSetComposerValueHandlersRef.current.delete(handler);
512
+ };
513
+ },
514
+ []
515
+ );
516
+ const registerOnFocusComposer = (0, import_react.useCallback)(
517
+ (handler) => {
518
+ onFocusComposerHandlersRef.current.add(handler);
519
+ return () => {
520
+ onFocusComposerHandlersRef.current.delete(handler);
521
+ };
522
+ },
523
+ []
524
+ );
243
525
  (0, import_react.useEffect)(() => {
244
526
  if (!isParentAvailable) return;
245
527
  const sendResponse = (nonce, response, error) => {
@@ -260,7 +542,7 @@ function ParentMessengerProvider({
260
542
  }
261
543
  const payload = event.data;
262
544
  if (payload.__xpaiChatKit !== true) return;
263
- if (payload.type == "command" && payload.command === "onSendUserMessage") {
545
+ if (payload.type === "command" && payload.command === "onSendUserMessage") {
264
546
  const nonce = typeof payload.nonce === "string" ? payload.nonce : null;
265
547
  if (nonce) {
266
548
  if (handledSendUserMessageNonces.has(nonce)) return;
@@ -270,34 +552,53 @@ function ParentMessengerProvider({
270
552
  handledSendUserMessageEvents.add(event);
271
553
  }
272
554
  const params = payload.data;
273
- const prompt = (params.text ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.input ?? "").trim();
555
+ 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() : "";
556
+ const references = normalizeReferences(
557
+ params.references ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.references
558
+ );
559
+ const referenceComposition = params.referenceComposition ?? params.state?.[import_chatkit_types2.STATE_VARIABLE_HUMAN]?.referenceComposition;
560
+ const humanInput = buildHumanMessageInputPayload({
561
+ content: prompt,
562
+ references,
563
+ referenceComposition
564
+ });
565
+ if (!humanInput) {
566
+ if (payload.nonce) {
567
+ sendResponse(payload.nonce, { ok: true });
568
+ }
569
+ return;
570
+ }
274
571
  const newMessage = {
275
572
  id: createMessageId(),
276
573
  type: "human",
277
- content: prompt
574
+ content: prompt,
575
+ submittedInput: humanInput.input,
576
+ ...humanInput.referenceComposition ? { referenceComposition: humanInput.referenceComposition } : {},
577
+ ...references.length > 0 ? { references } : {}
278
578
  };
579
+ const stream = streamRef2.current;
580
+ const activeFollowUpMode = stream?.isLoading ? params.followUpMode && params.followUpMode !== "default" ? params.followUpMode : stream.followUpBehavior ?? "queue" : void 0;
279
581
  const requestOptions = buildInjectedRequestOptions({
280
582
  defaults: latestOptionsRef.current?.request,
281
583
  state: params.state,
282
- humanInput: {
283
- input: prompt
284
- }
584
+ humanInput
285
585
  });
286
- streamRef2.current?.submit(
586
+ stream?.submit(
287
587
  {
288
- input: {
289
- input: prompt
290
- },
588
+ input: humanInput,
291
589
  ...requestOptions.state ? { state: requestOptions.state } : {}
292
590
  },
293
591
  {
294
592
  newThread: params.newThread,
593
+ ...activeFollowUpMode ? { followUpMode: activeFollowUpMode } : {},
295
594
  ...requestOptions.context ? { context: requestOptions.context } : {},
296
595
  ...requestOptions.config ? { config: requestOptions.config } : {},
297
- optimisticValues: (prev) => {
298
- const prevMessages = prev?.messages ?? [];
299
- return { ...prev, messages: [...prevMessages, newMessage] };
300
- }
596
+ ...!activeFollowUpMode ? {
597
+ optimisticValues: (prev) => {
598
+ const prevMessages = prev?.messages ?? [];
599
+ return { ...prev, messages: [...prevMessages, newMessage] };
600
+ }
601
+ } : {}
301
602
  }
302
603
  );
303
604
  if (payload.nonce) {
@@ -305,7 +606,28 @@ function ParentMessengerProvider({
305
606
  }
306
607
  return;
307
608
  }
308
- if (payload.type == "command" && payload.command === "onSetOptions") {
609
+ if (payload.type === "command" && payload.command === "onSetComposerValue") {
610
+ const nextPayload = payload.data ?? null;
611
+ const normalizedPayload = nextPayload && Array.isArray(nextPayload.references) ? {
612
+ ...nextPayload,
613
+ references: normalizeReferences(nextPayload.references)
614
+ } : nextPayload;
615
+ void Promise.all(
616
+ [...onSetComposerValueHandlersRef.current].map(
617
+ (handler2) => Promise.resolve(handler2(normalizedPayload))
618
+ )
619
+ ).then(() => {
620
+ if (payload.nonce) {
621
+ sendResponse(payload.nonce, { ok: true });
622
+ }
623
+ }).catch((error) => {
624
+ if (payload.nonce) {
625
+ sendResponse(payload.nonce, void 0, error);
626
+ }
627
+ });
628
+ return;
629
+ }
630
+ if (payload.type === "command" && payload.command === "onSetOptions") {
309
631
  latestOptionsRef.current = payload.data ?? null;
310
632
  if (onSetOptionsHandlersRef.current.size > 0) {
311
633
  onSetOptionsHandlersRef.current.forEach((handler2) => {
@@ -317,16 +639,41 @@ function ParentMessengerProvider({
317
639
  }
318
640
  return;
319
641
  }
320
- if (payload.type == "command" && payload.command === "onSetThreadId") {
642
+ if (payload.type === "command" && payload.command === "onFocusComposer") {
643
+ void Promise.all(
644
+ [...onFocusComposerHandlersRef.current].map(
645
+ (handler2) => Promise.resolve(handler2())
646
+ )
647
+ ).then(() => {
648
+ if (payload.nonce) {
649
+ sendResponse(payload.nonce, { ok: true });
650
+ }
651
+ }).catch((error) => {
652
+ if (payload.nonce) {
653
+ sendResponse(payload.nonce, void 0, error);
654
+ }
655
+ });
656
+ return;
657
+ }
658
+ if (payload.type === "command" && payload.command === "onSetThreadId") {
321
659
  const data = payload.data;
322
660
  const nextThreadId = data?.threadId ?? null;
323
661
  const stream = streamRef2.current;
662
+ if (stream?.threadId === nextThreadId) {
663
+ if (payload.nonce) {
664
+ sendResponse(payload.nonce, { ok: true });
665
+ }
666
+ return;
667
+ }
324
668
  stream?.reset(nextThreadId, void 0, { suppressThreadChange: true });
325
669
  if (stream && nextThreadId) {
326
670
  stream.loadThread(nextThreadId).catch((err) => {
327
671
  console.warn("Failed to load thread messages", err);
328
672
  });
329
673
  }
674
+ if (payload.nonce) {
675
+ sendResponse(payload.nonce, { ok: true });
676
+ }
330
677
  return;
331
678
  }
332
679
  if (payload.type !== "response") return;
@@ -387,25 +734,55 @@ function ParentMessengerProvider({
387
734
  isParentAvailable,
388
735
  sendCommand,
389
736
  sendEvent,
390
- registerOnSetOptions
737
+ registerOnSetOptions,
738
+ registerOnSetComposerValue,
739
+ registerOnFocusComposer
391
740
  }),
392
- [isParentAvailable, sendCommand, sendEvent, registerOnSetOptions]
741
+ [
742
+ isParentAvailable,
743
+ sendCommand,
744
+ sendEvent,
745
+ registerOnSetOptions,
746
+ registerOnSetComposerValue,
747
+ registerOnFocusComposer
748
+ ]
393
749
  );
394
750
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ParentMessengerContext.Provider, { value, children });
395
751
  }
396
752
 
397
753
  // src/hooks/useParentMessenger.tsx
398
- function useParentMessenger({ onSetOptions } = {}) {
754
+ function useParentMessenger({
755
+ onSetOptions,
756
+ onSetComposerValue,
757
+ onFocusComposer
758
+ } = {}) {
399
759
  const context = (0, import_react2.useContext)(ParentMessengerContext);
400
760
  if (!context) {
401
- throw new Error("useParentMessenger must be used within a ParentMessengerProvider");
761
+ throw new Error(
762
+ "useParentMessenger must be used within a ParentMessengerProvider"
763
+ );
402
764
  }
403
- const { registerOnSetOptions, ...messenger } = context;
765
+ const {
766
+ registerOnSetOptions,
767
+ registerOnSetComposerValue,
768
+ registerOnFocusComposer,
769
+ ...messenger
770
+ } = context;
404
771
  const onSetOptionsRef = (0, import_react2.useRef)(onSetOptions);
772
+ const onSetComposerValueRef = (0, import_react2.useRef)(onSetComposerValue);
773
+ const onFocusComposerRef = (0, import_react2.useRef)(onFocusComposer);
405
774
  (0, import_react2.useEffect)(() => {
406
775
  onSetOptionsRef.current = onSetOptions;
407
776
  }, [onSetOptions]);
777
+ (0, import_react2.useEffect)(() => {
778
+ onSetComposerValueRef.current = onSetComposerValue;
779
+ }, [onSetComposerValue]);
780
+ (0, import_react2.useEffect)(() => {
781
+ onFocusComposerRef.current = onFocusComposer;
782
+ }, [onFocusComposer]);
408
783
  const hasOnSetOptions = Boolean(onSetOptions);
784
+ const hasOnSetComposerValue = Boolean(onSetComposerValue);
785
+ const hasOnFocusComposer = Boolean(onFocusComposer);
409
786
  (0, import_react2.useEffect)(() => {
410
787
  if (!hasOnSetOptions) return;
411
788
  const handler = (options) => {
@@ -413,6 +790,20 @@ function useParentMessenger({ onSetOptions } = {}) {
413
790
  };
414
791
  return registerOnSetOptions(handler);
415
792
  }, [hasOnSetOptions, registerOnSetOptions]);
793
+ (0, import_react2.useEffect)(() => {
794
+ if (!hasOnSetComposerValue) return;
795
+ const handler = (payload) => {
796
+ onSetComposerValueRef.current?.(payload);
797
+ };
798
+ return registerOnSetComposerValue(handler);
799
+ }, [hasOnSetComposerValue, registerOnSetComposerValue]);
800
+ (0, import_react2.useEffect)(() => {
801
+ if (!hasOnFocusComposer) return;
802
+ const handler = () => {
803
+ onFocusComposerRef.current?.();
804
+ };
805
+ return registerOnFocusComposer(handler);
806
+ }, [hasOnFocusComposer, registerOnFocusComposer]);
416
807
  return messenger;
417
808
  }
418
809
 
@@ -567,12 +958,39 @@ var en_US_default = {
567
958
  statusOnline: "Online",
568
959
  missingConfigShort: "Missing ChatKit configuration.",
569
960
  missingConfigDetail: "Missing ChatKit configuration. Check `VITE_XPERTAI_API_URL`, and the `clientSecret` prop.",
961
+ missingApiUrlShort: "Missing ChatKit API URL.",
962
+ missingApiUrlDetail: "Missing ChatKit API URL. Check `VITE_XPERTAI_API_URL` or `options.api.apiUrl`.",
963
+ missingClientSecretShort: "Missing ChatKit client secret.",
964
+ missingClientSecretDetail: "Missing ChatKit client secret. Check the `clientSecret` prop or `api.getClientSecret` integration.",
965
+ missingApiUrlAndClientSecretShort: "Missing ChatKit API URL and client secret.",
966
+ missingApiUrlAndClientSecretDetail: "Missing ChatKit API URL and client secret. Check `VITE_XPERTAI_API_URL`, `options.api.apiUrl`, and your client secret integration.",
570
967
  loadingThread: "Loading thread...",
571
968
  stop: "Stop",
572
969
  send: "Send message",
970
+ referencedContentOnly: "Referenced content",
971
+ youLabel: "You",
573
972
  scrollToBottom: "Scroll to bottom",
574
973
  retryUpload: "Retry upload",
575
974
  poweredBy: "Powered by Xpert AI",
975
+ followUps: {
976
+ label: "Follow-up behavior",
977
+ settings: "Settings",
978
+ idleHint: "Used when you send while a run is active.",
979
+ activeHint: "This message will use the selected busy-run behavior.",
980
+ pending: "Pending follow-ups",
981
+ queue: "Queue",
982
+ steer: "Steer",
983
+ steerAction: "Steer",
984
+ promoteToSteer: "Steer now",
985
+ sendNow: "Send now",
986
+ remove: "Remove pending follow-up",
987
+ more: "More actions",
988
+ edit: "Edit message",
989
+ turnOffQueueing: "Turn off queueing",
990
+ queueHint: "Starts after the current run finishes",
991
+ manualQueueHint: "Ready to send as a new run",
992
+ steerHint: "Injects after the current tool call"
993
+ },
576
994
  errors: {
577
995
  loadMessages: "Failed to load thread messages",
578
996
  createThread: "Failed to create thread",
@@ -603,7 +1021,9 @@ var en_US_default = {
603
1021
  },
604
1022
  composer: {
605
1023
  openMenu: "Open menu",
606
- addAttachment: "Add attachment"
1024
+ addAttachment: "Add attachment",
1025
+ removeReference: "Remove reference",
1026
+ quoteSelection: "Quote selection"
607
1027
  },
608
1028
  sheet: {
609
1029
  close: "Close"
@@ -618,7 +1038,10 @@ var en_US_default = {
618
1038
  },
619
1039
  message: {
620
1040
  answer: "Answer",
621
- reasoning: "Reasoning"
1041
+ reasoning: "Reasoning",
1042
+ loading: "Loading",
1043
+ thinking: "Thinking",
1044
+ answering: "Answering"
622
1045
  }
623
1046
  };
624
1047
 
@@ -630,12 +1053,39 @@ var zh_CN_default = {
630
1053
  statusOnline: "\u5728\u7EBF",
631
1054
  missingConfigShort: "\u7F3A\u5C11 ChatKit \u914D\u7F6E\u3002",
632
1055
  missingConfigDetail: "\u7F3A\u5C11 ChatKit \u914D\u7F6E\u3002\u8BF7\u68C0\u67E5 `VITE_XPERTAI_API_URL` \u548C `clientSecret` \u53C2\u6570\u3002",
1056
+ missingApiUrlShort: "\u7F3A\u5C11 ChatKit API URL\u3002",
1057
+ missingApiUrlDetail: "\u7F3A\u5C11 ChatKit API URL\u3002\u8BF7\u68C0\u67E5 `VITE_XPERTAI_API_URL` \u6216 `options.api.apiUrl`\u3002",
1058
+ missingClientSecretShort: "\u7F3A\u5C11 ChatKit client secret\u3002",
1059
+ missingClientSecretDetail: "\u7F3A\u5C11 ChatKit client secret\u3002\u8BF7\u68C0\u67E5 `clientSecret` \u53C2\u6570\u6216 `api.getClientSecret` \u96C6\u6210\u3002",
1060
+ missingApiUrlAndClientSecretShort: "\u7F3A\u5C11 ChatKit API URL \u548C client secret\u3002",
1061
+ 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
1062
  loadingThread: "\u6B63\u5728\u52A0\u8F7D\u7EBF\u7A0B...",
634
1063
  stop: "\u505C\u6B62",
635
1064
  send: "\u53D1\u9001\u6D88\u606F",
1065
+ referencedContentOnly: "\u5DF2\u5F15\u7528\u5185\u5BB9",
1066
+ youLabel: "\u4F60",
636
1067
  scrollToBottom: "\u56DE\u5230\u5E95\u90E8",
637
1068
  retryUpload: "\u91CD\u65B0\u4E0A\u4F20",
638
1069
  poweredBy: "\u7531 Xpert AI \u9A71\u52A8",
1070
+ followUps: {
1071
+ label: "Follow-up \u6A21\u5F0F",
1072
+ settings: "\u8BBE\u7F6E",
1073
+ idleHint: "\u4EC5\u5728\u8FD0\u884C\u4E2D\u53D1\u9001\u6D88\u606F\u65F6\u751F\u6548\u3002",
1074
+ activeHint: "\u5F53\u524D\u6D88\u606F\u4F1A\u6309\u6240\u9009\u7684\u8FD0\u884C\u4E2D\u884C\u4E3A\u5904\u7406\u3002",
1075
+ pending: "\u5F85\u5904\u7406 Follow-up",
1076
+ queue: "\u6392\u961F",
1077
+ steer: "\u5F15\u5BFC",
1078
+ steerAction: "Steer",
1079
+ promoteToSteer: "\u8F6C\u4E3A\u5F15\u5BFC",
1080
+ sendNow: "\u7ACB\u5373\u53D1\u9001",
1081
+ remove: "\u79FB\u9664\u6B64\u5F85\u5904\u7406 Follow-up",
1082
+ more: "\u66F4\u591A\u64CD\u4F5C",
1083
+ edit: "\u7F16\u8F91\u6D88\u606F",
1084
+ turnOffQueueing: "\u5173\u95ED\u6392\u961F",
1085
+ queueHint: "\u5F53\u524D\u8FD0\u884C\u7ED3\u675F\u540E\u5F00\u542F\u4E0B\u4E00\u8F6E",
1086
+ manualQueueHint: "\u4FDD\u7559\u4E3A\u5F85\u53D1\u9001\uFF0C\u53EF\u624B\u52A8\u5F00\u542F\u65B0\u4E00\u8F6E",
1087
+ steerHint: "\u5F53\u524D\u5DE5\u5177\u8C03\u7528\u5B8C\u6210\u540E\u6CE8\u5165"
1088
+ },
639
1089
  errors: {
640
1090
  loadMessages: "\u52A0\u8F7D\u7EBF\u7A0B\u6D88\u606F\u5931\u8D25",
641
1091
  createThread: "\u521B\u5EFA\u7EBF\u7A0B\u5931\u8D25",
@@ -666,7 +1116,9 @@ var zh_CN_default = {
666
1116
  },
667
1117
  composer: {
668
1118
  openMenu: "\u6253\u5F00\u83DC\u5355",
669
- addAttachment: "\u6DFB\u52A0\u9644\u4EF6"
1119
+ addAttachment: "\u6DFB\u52A0\u9644\u4EF6",
1120
+ removeReference: "\u79FB\u9664\u5F15\u7528",
1121
+ quoteSelection: "\u5F15\u7528\u9009\u4E2D\u5185\u5BB9"
670
1122
  },
671
1123
  sheet: {
672
1124
  close: "\u5173\u95ED"
@@ -681,7 +1133,10 @@ var zh_CN_default = {
681
1133
  },
682
1134
  message: {
683
1135
  answer: "\u56DE\u7B54",
684
- reasoning: "\u63A8\u7406"
1136
+ reasoning: "\u63A8\u7406",
1137
+ loading: "\u6B63\u5728\u52A0\u8F7D",
1138
+ thinking: "\u6B63\u5728\u601D\u8003",
1139
+ answering: "\u6B63\u5728\u751F\u6210"
685
1140
  }
686
1141
  };
687
1142
 
@@ -1206,13 +1661,14 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
1206
1661
  function SendButton({
1207
1662
  disabled = false,
1208
1663
  isLoading = false,
1664
+ showStop = isLoading,
1209
1665
  onStop,
1210
1666
  stopLabel = "Stop",
1211
1667
  sendLabel = "Send"
1212
1668
  }) {
1213
1669
  const { theme } = useTheme();
1214
1670
  const roundedClass = getRoundedClass(theme.radius);
1215
- if (isLoading) {
1671
+ if (showStop) {
1216
1672
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1217
1673
  "button",
1218
1674
  {
@@ -1461,103 +1917,464 @@ function HistorySidebar({
1461
1917
  ] });
1462
1918
  }
1463
1919
 
1464
- // src/components/thread/messages/ai.tsx
1465
- var React13 = __toESM(require("react"), 1);
1466
- var import_lucide_react6 = require("lucide-react");
1920
+ // src/components/composer/pending-follow-ups.tsx
1921
+ var React10 = __toESM(require("react"), 1);
1922
+ var import_lucide_react5 = require("lucide-react");
1467
1923
 
1468
- // src/components/ui/badge.tsx
1469
- var React9 = __toESM(require("react"), 1);
1924
+ // src/components/ui/tooltip.tsx
1925
+ var React9 = require("react");
1926
+ var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
1470
1927
  var import_jsx_runtime11 = require("react/jsx-runtime");
1471
- 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
- var variants = {
1473
- default: "bg-primary text-primary-foreground",
1474
- secondary: "bg-secondary text-secondary-foreground",
1475
- outline: "border-input text-foreground"
1476
- };
1477
- var Badge = React9.forwardRef(
1478
- ({ className, variant = "default", ...props }, ref) => {
1479
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { ref, className: cn(base, variants[variant], className), ...props });
1480
- }
1481
- );
1482
- Badge.displayName = "Badge";
1483
-
1484
- // 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)(
1489
- "div",
1928
+ function TooltipProvider({
1929
+ delayDuration = 0,
1930
+ ...props
1931
+ }) {
1932
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1933
+ TooltipPrimitive.Provider,
1490
1934
  {
1491
- ref,
1935
+ "data-slot": "tooltip-provider",
1936
+ delayDuration,
1937
+ ...props
1938
+ }
1939
+ );
1940
+ }
1941
+ function Tooltip({
1942
+ ...props
1943
+ }) {
1944
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1945
+ TooltipPrimitive.Root,
1946
+ {
1947
+ "data-slot": "tooltip",
1948
+ ...props
1949
+ }
1950
+ ) });
1951
+ }
1952
+ function TooltipTrigger({
1953
+ ...props
1954
+ }) {
1955
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1956
+ TooltipPrimitive.Trigger,
1957
+ {
1958
+ "data-slot": "tooltip-trigger",
1959
+ ...props
1960
+ }
1961
+ );
1962
+ }
1963
+ function TooltipContent({
1964
+ className,
1965
+ sideOffset = 0,
1966
+ children,
1967
+ ...props
1968
+ }) {
1969
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1970
+ TooltipPrimitive.Content,
1971
+ {
1972
+ "data-slot": "tooltip-content",
1973
+ sideOffset,
1492
1974
  className: cn(
1493
- "rounded-xl border bg-background/80 text-foreground shadow-[0_14px_40px_-30px_rgba(15,23,42,0.5)] backdrop-blur",
1975
+ "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",
1494
1976
  className
1495
1977
  ),
1496
- ...props
1978
+ ...props,
1979
+ children: [
1980
+ children,
1981
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
1982
+ ]
1497
1983
  }
1498
- )
1499
- );
1500
- 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 })
1503
- );
1504
- 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 }));
1506
- 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 }));
1508
- 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 })
1511
- );
1512
- 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 })
1515
- );
1516
- 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 })
1519
- );
1520
- CardAction.displayName = "CardAction";
1984
+ ) });
1985
+ }
1521
1986
 
1522
- // 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);
1526
- function Tabs({ className, defaultValue, value, onValueChange, ...props }) {
1527
- const [internalValue, setInternalValue] = React11.useState(defaultValue ?? "");
1528
- const activeValue = value ?? internalValue;
1529
- const setValue = React11.useCallback(
1530
- (nextValue) => {
1531
- if (value === void 0) setInternalValue(nextValue);
1532
- onValueChange?.(nextValue);
1533
- },
1534
- [onValueChange, value]
1535
- );
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 }) });
1987
+ // src/components/composer/pending-follow-ups.tsx
1988
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1989
+ function getPendingFollowUpText(item, referencedContentFallback) {
1990
+ const text = item.request?.input?.input?.trim() ?? "";
1991
+ if (text) {
1992
+ return text;
1993
+ }
1994
+ const references = normalizeReferences(item.request?.input?.references);
1995
+ if (references.length === 0) {
1996
+ return referencedContentFallback;
1997
+ }
1998
+ const firstReferenceLabel = getReferenceLabel(references[0]);
1999
+ if (references.length === 1) {
2000
+ return firstReferenceLabel;
2001
+ }
2002
+ return `${firstReferenceLabel} +${references.length - 1}`;
2003
+ }
2004
+ function useRoundedClasses() {
2005
+ const { theme } = useTheme();
2006
+ return {
2007
+ top: theme.radius ? {
2008
+ pill: "rounded-t-full",
2009
+ round: "rounded-t-xl",
2010
+ soft: "rounded-t-lg",
2011
+ sharp: "rounded-t-none"
2012
+ }[theme.radius] : "rounded-t-lg",
2013
+ panel: getRoundedClass(theme.radius, "rounded-lg"),
2014
+ control: getRoundedClass(theme.radius, "rounded-md")
2015
+ };
1537
2016
  }
1538
- var TabsList = React11.forwardRef(
1539
- ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2017
+ function PendingFollowUps({
2018
+ items,
2019
+ isLoading,
2020
+ followUpBehavior,
2021
+ onBehaviorChange,
2022
+ onPromoteToSteer,
2023
+ canSendNow,
2024
+ onSendNow,
2025
+ onEdit,
2026
+ onRemove,
2027
+ className
2028
+ }) {
2029
+ const { t } = useChatkitTranslation();
2030
+ const rounded = useRoundedClasses();
2031
+ const referencedContentFallback = t("chat.referencedContentOnly");
2032
+ const [isSettingsOpen, setIsSettingsOpen] = React10.useState(false);
2033
+ const [openMenuId, setOpenMenuId] = React10.useState(null);
2034
+ React10.useEffect(() => {
2035
+ if (items.length === 0 && isSettingsOpen) {
2036
+ setIsSettingsOpen(false);
2037
+ }
2038
+ if (items.every((item) => item.id !== openMenuId)) {
2039
+ setOpenMenuId(null);
2040
+ }
2041
+ }, [isSettingsOpen, items, openMenuId]);
2042
+ if (items.length === 0) {
2043
+ return null;
2044
+ }
2045
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1540
2046
  "div",
1541
2047
  {
1542
- ref,
1543
2048
  className: cn(
1544
- "inline-flex h-11 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
2049
+ "space-y-2 mx-2 p-2 border border-border border-b-0",
2050
+ rounded.top,
2051
+ className
2052
+ ),
2053
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
2054
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
2055
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs font-medium text-foreground", children: t("chat.followUps.pending") }),
2056
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Tooltip, { children: [
2057
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2058
+ "button",
2059
+ {
2060
+ type: "button",
2061
+ onClick: () => setIsSettingsOpen((prev) => !prev),
2062
+ className: cn(
2063
+ "inline-flex h-6 w-6 items-center justify-center transition-colors",
2064
+ isSettingsOpen ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted/60 hover:text-foreground",
2065
+ rounded.control
2066
+ ),
2067
+ "aria-label": t("chat.followUps.settings"),
2068
+ "aria-expanded": isSettingsOpen,
2069
+ "aria-controls": "follow-ups-settings-panel",
2070
+ children: [
2071
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.SlidersHorizontal, { className: "h-3.5 w-3.5" }),
2072
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "sr-only", children: t("chat.followUps.settings") })
2073
+ ]
2074
+ }
2075
+ ) }),
2076
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipContent, { side: "top", children: t("chat.followUps.settings") })
2077
+ ] })
2078
+ ] }),
2079
+ isSettingsOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2080
+ "div",
2081
+ {
2082
+ id: "follow-ups-settings-panel",
2083
+ className: cn(
2084
+ "border border-border/70 bg-muted/20 px-3 py-2",
2085
+ rounded.panel
2086
+ ),
2087
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
2088
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
2089
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-xs font-medium text-foreground", children: t("chat.followUps.label") }),
2090
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-[11px] text-muted-foreground", children: isLoading ? t("chat.followUps.activeHint") : t("chat.followUps.idleHint") })
2091
+ ] }),
2092
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2093
+ "div",
2094
+ {
2095
+ className: cn(
2096
+ "inline-flex shrink-0 border border-border bg-background p-1",
2097
+ rounded.control
2098
+ ),
2099
+ children: ["queue", "steer"].map((behavior) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Tooltip, { children: [
2100
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2101
+ "button",
2102
+ {
2103
+ type: "button",
2104
+ onClick: () => {
2105
+ onBehaviorChange(behavior);
2106
+ setIsSettingsOpen(false);
2107
+ },
2108
+ className: cn(
2109
+ "px-3 py-1 text-xs font-medium transition-colors",
2110
+ rounded.control,
2111
+ followUpBehavior === behavior ? "bg-primary text-background" : "text-muted-foreground hover:text-foreground"
2112
+ ),
2113
+ children: behavior === "queue" ? t("chat.followUps.queue") : t("chat.followUps.steer")
2114
+ }
2115
+ ) }),
2116
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipContent, { side: "top", children: behavior === "queue" ? t("chat.followUps.queueHint") : t("chat.followUps.steerHint") })
2117
+ ] }, behavior))
2118
+ }
2119
+ )
2120
+ ] })
2121
+ }
2122
+ ),
2123
+ items.map((item) => {
2124
+ const canSendItemNow = item.mode === "queue" && canSendNow(item.id);
2125
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2126
+ "div",
2127
+ {
2128
+ className: cn(
2129
+ "border border-border/50 bg-muted/15 px-2 py-1",
2130
+ rounded.panel
2131
+ ),
2132
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start gap-2.5", children: [
2133
+ /* @__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" }),
2134
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0 flex-1", children: [
2135
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start gap-2", children: [
2136
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2137
+ "div",
2138
+ {
2139
+ className: "truncate text-[13px] leading-5 text-foreground",
2140
+ title: getPendingFollowUpText(
2141
+ item,
2142
+ referencedContentFallback
2143
+ ),
2144
+ children: getPendingFollowUpText(
2145
+ item,
2146
+ referencedContentFallback
2147
+ )
2148
+ }
2149
+ ) }),
2150
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
2151
+ item.mode === "queue" && isLoading && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2152
+ "button",
2153
+ {
2154
+ type: "button",
2155
+ onClick: () => void onPromoteToSteer(item.id),
2156
+ className: cn(
2157
+ "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",
2158
+ rounded.control
2159
+ ),
2160
+ "aria-label": t("chat.followUps.steerAction"),
2161
+ title: t("chat.followUps.steerAction"),
2162
+ children: t("chat.followUps.steerAction")
2163
+ }
2164
+ ),
2165
+ canSendItemNow && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2166
+ "button",
2167
+ {
2168
+ type: "button",
2169
+ onClick: () => void onSendNow(item.id),
2170
+ className: cn(
2171
+ "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",
2172
+ rounded.control
2173
+ ),
2174
+ "aria-label": t("chat.followUps.sendNow"),
2175
+ title: t("chat.followUps.sendNow"),
2176
+ children: t("chat.followUps.sendNow")
2177
+ }
2178
+ ),
2179
+ item.mode === "queue" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2180
+ "button",
2181
+ {
2182
+ type: "button",
2183
+ onClick: () => onRemove(item.id),
2184
+ className: cn(
2185
+ "inline-flex h-6 w-6 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
2186
+ rounded.control
2187
+ ),
2188
+ "aria-label": t("chat.followUps.remove"),
2189
+ title: t("chat.followUps.remove"),
2190
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Trash2, { size: 13 })
2191
+ }
2192
+ ),
2193
+ item.mode === "queue" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2194
+ Popover,
2195
+ {
2196
+ open: openMenuId === item.id,
2197
+ onOpenChange: (open) => setOpenMenuId(open ? item.id : null),
2198
+ children: [
2199
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2200
+ "button",
2201
+ {
2202
+ type: "button",
2203
+ className: cn(
2204
+ "inline-flex h-6 w-6 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
2205
+ rounded.control
2206
+ ),
2207
+ "aria-label": t("chat.followUps.more"),
2208
+ title: t("chat.followUps.more"),
2209
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Ellipsis, { size: 13 })
2210
+ }
2211
+ ) }),
2212
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2213
+ PopoverContent,
2214
+ {
2215
+ align: "end",
2216
+ side: "bottom",
2217
+ className: cn(
2218
+ "w-52 border-border/70 bg-background p-1.5",
2219
+ rounded.panel
2220
+ ),
2221
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-1", children: [
2222
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2223
+ "button",
2224
+ {
2225
+ type: "button",
2226
+ onClick: () => {
2227
+ setOpenMenuId(null);
2228
+ onEdit(item.id);
2229
+ },
2230
+ className: cn(
2231
+ "flex items-center gap-2 px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-muted",
2232
+ rounded.control
2233
+ ),
2234
+ children: [
2235
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.PencilLine, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
2236
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t("chat.followUps.edit") })
2237
+ ]
2238
+ }
2239
+ ),
2240
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2241
+ "button",
2242
+ {
2243
+ type: "button",
2244
+ onClick: () => {
2245
+ setOpenMenuId(null);
2246
+ onBehaviorChange("steer");
2247
+ },
2248
+ className: cn(
2249
+ "flex items-center gap-2 px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-muted",
2250
+ rounded.control
2251
+ ),
2252
+ children: [
2253
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.CornerDownLeft, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
2254
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: t("chat.followUps.turnOffQueueing") })
2255
+ ]
2256
+ }
2257
+ )
2258
+ ] })
2259
+ }
2260
+ )
2261
+ ]
2262
+ }
2263
+ )
2264
+ ] })
2265
+ ] }),
2266
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1.5 text-[10px] leading-4 text-muted-foreground", children: [
2267
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Info, { className: "h-3 w-3 shrink-0" }),
2268
+ /* @__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") })
2269
+ ] })
2270
+ ] })
2271
+ ] })
2272
+ },
2273
+ item.id
2274
+ );
2275
+ })
2276
+ ] })
2277
+ }
2278
+ );
2279
+ }
2280
+
2281
+ // src/components/thread/messages/ai.tsx
2282
+ var React14 = __toESM(require("react"), 1);
2283
+ var import_lucide_react7 = require("lucide-react");
2284
+
2285
+ // src/components/ui/badge.tsx
2286
+ var React11 = __toESM(require("react"), 1);
2287
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2288
+ 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";
2289
+ var variants = {
2290
+ default: "bg-primary text-primary-foreground",
2291
+ secondary: "bg-secondary text-secondary-foreground",
2292
+ outline: "border-input text-foreground"
2293
+ };
2294
+ var Badge = React11.forwardRef(
2295
+ ({ className, variant = "default", ...props }, ref) => {
2296
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { ref, className: cn(base, variants[variant], className), ...props });
2297
+ }
2298
+ );
2299
+ Badge.displayName = "Badge";
2300
+
2301
+ // src/components/ui/card.tsx
2302
+ var React12 = __toESM(require("react"), 1);
2303
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2304
+ var Card = React12.forwardRef(
2305
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2306
+ "div",
2307
+ {
2308
+ ref,
2309
+ className: cn(
2310
+ "rounded-xl border bg-background/80 text-foreground shadow-[0_14px_40px_-30px_rgba(15,23,42,0.5)] backdrop-blur",
1545
2311
  className
1546
2312
  ),
1547
- role: "tablist",
2313
+ ...props
2314
+ }
2315
+ )
2316
+ );
2317
+ Card.displayName = "Card";
2318
+ var CardHeader = React12.forwardRef(
2319
+ ({ 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 })
2320
+ );
2321
+ CardHeader.displayName = "CardHeader";
2322
+ 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 }));
2323
+ CardTitle.displayName = "CardTitle";
2324
+ var CardDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
2325
+ CardDescription.displayName = "CardDescription";
2326
+ var CardContent = React12.forwardRef(
2327
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("px-6 pb-6", className), ...props })
2328
+ );
2329
+ CardContent.displayName = "CardContent";
2330
+ var CardFooter = React12.forwardRef(
2331
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("flex items-center px-6 pb-6", className), ...props })
2332
+ );
2333
+ CardFooter.displayName = "CardFooter";
2334
+ var CardAction = React12.forwardRef(
2335
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { ref, className: cn("ml-auto flex items-center", className), ...props })
2336
+ );
2337
+ CardAction.displayName = "CardAction";
2338
+
2339
+ // src/components/ui/tabs.tsx
2340
+ var React13 = __toESM(require("react"), 1);
2341
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2342
+ var TabsContext = React13.createContext(null);
2343
+ function Tabs({ className, defaultValue, value, onValueChange, ...props }) {
2344
+ const [internalValue, setInternalValue] = React13.useState(defaultValue ?? "");
2345
+ const activeValue = value ?? internalValue;
2346
+ const setValue = React13.useCallback(
2347
+ (nextValue) => {
2348
+ if (value === void 0) setInternalValue(nextValue);
2349
+ onValueChange?.(nextValue);
2350
+ },
2351
+ [onValueChange, value]
2352
+ );
2353
+ 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 }) });
2354
+ }
2355
+ var TabsList = React13.forwardRef(
2356
+ ({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2357
+ "div",
2358
+ {
2359
+ ref,
2360
+ className: cn(
2361
+ "inline-flex h-11 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
2362
+ className
2363
+ ),
2364
+ role: "tablist",
1548
2365
  ...props
1549
2366
  }
1550
2367
  )
1551
2368
  );
1552
2369
  TabsList.displayName = "TabsList";
1553
- var TabsTrigger = React11.forwardRef(
2370
+ var TabsTrigger = React13.forwardRef(
1554
2371
  ({ className, value, onClick, ...props }, ref) => {
1555
- const context = React11.useContext(TabsContext);
2372
+ const context = React13.useContext(TabsContext);
1556
2373
  if (!context) {
1557
2374
  throw new Error("TabsTrigger must be used within Tabs");
1558
2375
  }
1559
2376
  const isActive = context.value === value;
1560
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2377
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1561
2378
  "button",
1562
2379
  {
1563
2380
  ref,
@@ -1579,14 +2396,14 @@ var TabsTrigger = React11.forwardRef(
1579
2396
  }
1580
2397
  );
1581
2398
  TabsTrigger.displayName = "TabsTrigger";
1582
- var TabsContent = React11.forwardRef(
2399
+ var TabsContent = React13.forwardRef(
1583
2400
  ({ className, value, ...props }, ref) => {
1584
- const context = React11.useContext(TabsContext);
2401
+ const context = React13.useContext(TabsContext);
1585
2402
  if (!context) {
1586
2403
  throw new Error("TabsContent must be used within Tabs");
1587
2404
  }
1588
2405
  if (context.value !== value) return null;
1589
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2406
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1590
2407
  "div",
1591
2408
  {
1592
2409
  ref,
@@ -1608,7 +2425,7 @@ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
1608
2425
  var import_rehype_katex = __toESM(require("rehype-katex"), 1);
1609
2426
  var import_remark_math = __toESM(require("remark-math"), 1);
1610
2427
  var import_react6 = require("react");
1611
- var import_lucide_react5 = require("lucide-react");
2428
+ var import_lucide_react6 = require("lucide-react");
1612
2429
 
1613
2430
  // src/components/thread/syntax-highlighter.tsx
1614
2431
  var import_react_syntax_highlighter = require("react-syntax-highlighter");
@@ -1616,7 +2433,7 @@ var import_tsx = __toESM(require("react-syntax-highlighter/dist/esm/languages/pr
1616
2433
  var import_python = __toESM(require("react-syntax-highlighter/dist/esm/languages/prism/python"), 1);
1617
2434
  var import_prism = require("react-syntax-highlighter/dist/cjs/styles/prism");
1618
2435
  var import_react4 = require("react");
1619
- var import_jsx_runtime14 = require("react/jsx-runtime");
2436
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1620
2437
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("js", import_tsx.default);
1621
2438
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("jsx", import_tsx.default);
1622
2439
  import_react_syntax_highlighter.PrismAsyncLight.registerLanguage("ts", import_tsx.default);
@@ -1627,7 +2444,7 @@ var SyntaxHighlighter = ({
1627
2444
  language,
1628
2445
  className
1629
2446
  }) => {
1630
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2447
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1631
2448
  import_react_syntax_highlighter.PrismAsyncLight,
1632
2449
  {
1633
2450
  language,
@@ -1646,75 +2463,10 @@ var SyntaxHighlighter = ({
1646
2463
 
1647
2464
  // src/components/thread/tooltip-icon-button.tsx
1648
2465
  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
- }
1712
-
1713
- // src/components/thread/tooltip-icon-button.tsx
1714
- var import_jsx_runtime16 = require("react/jsx-runtime");
2466
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1715
2467
  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)(
2468
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Tooltip, { children: [
2469
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1718
2470
  Button,
1719
2471
  {
1720
2472
  variant: "ghost",
@@ -1724,18 +2476,18 @@ var TooltipIconButton = (0, import_react5.forwardRef)(({ children, tooltip, side
1724
2476
  ref,
1725
2477
  children: [
1726
2478
  children,
1727
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "sr-only", children: tooltip })
2479
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "sr-only", children: tooltip })
1728
2480
  ]
1729
2481
  }
1730
2482
  ) }),
1731
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TooltipContent, { side, children: tooltip })
2483
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(TooltipContent, { side, children: tooltip })
1732
2484
  ] }) });
1733
2485
  });
1734
2486
  TooltipIconButton.displayName = "TooltipIconButton";
1735
2487
 
1736
2488
  // src/components/thread/markdown-text.tsx
1737
2489
  var import_katex_min = require("katex/dist/katex.min.css");
1738
- var import_jsx_runtime17 = require("react/jsx-runtime");
2490
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1739
2491
  var getTextContent = (children) => import_react6.Children.toArray(children).map((child) => {
1740
2492
  if (typeof child === "string" || typeof child === "number") {
1741
2493
  return String(child);
@@ -1762,23 +2514,23 @@ var CodeHeader = ({ language, code }) => {
1762
2514
  if (!code || isCopied) return;
1763
2515
  copyToClipboard(code);
1764
2516
  };
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)(
2517
+ return /* @__PURE__ */ (0, import_jsx_runtime18.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: [
2518
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "lowercase [&>span]:text-xs", children: language }),
2519
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1768
2520
  TooltipIconButton,
1769
2521
  {
1770
2522
  tooltip: t("markdown.copy"),
1771
2523
  onClick: onCopy,
1772
2524
  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, {})
2525
+ !isCopied && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.CopyIcon, {}),
2526
+ isCopied && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react6.CheckIcon, {})
1775
2527
  ]
1776
2528
  }
1777
2529
  )
1778
2530
  ] });
1779
2531
  };
1780
2532
  var defaultComponents = {
1781
- h1: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2533
+ h1: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1782
2534
  "h1",
1783
2535
  {
1784
2536
  className: cn(
@@ -1788,7 +2540,7 @@ var defaultComponents = {
1788
2540
  ...props
1789
2541
  }
1790
2542
  ),
1791
- h2: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2543
+ h2: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1792
2544
  "h2",
1793
2545
  {
1794
2546
  className: cn(
@@ -1798,7 +2550,7 @@ var defaultComponents = {
1798
2550
  ...props
1799
2551
  }
1800
2552
  ),
1801
- h3: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2553
+ h3: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1802
2554
  "h3",
1803
2555
  {
1804
2556
  className: cn(
@@ -1808,7 +2560,7 @@ var defaultComponents = {
1808
2560
  ...props
1809
2561
  }
1810
2562
  ),
1811
- h4: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2563
+ h4: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1812
2564
  "h4",
1813
2565
  {
1814
2566
  className: cn(
@@ -1818,7 +2570,7 @@ var defaultComponents = {
1818
2570
  ...props
1819
2571
  }
1820
2572
  ),
1821
- h5: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2573
+ h5: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1822
2574
  "h5",
1823
2575
  {
1824
2576
  className: cn(
@@ -1828,21 +2580,21 @@ var defaultComponents = {
1828
2580
  ...props
1829
2581
  }
1830
2582
  ),
1831
- h6: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2583
+ h6: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1832
2584
  "h6",
1833
2585
  {
1834
2586
  className: cn("my-4 font-semibold first:mt-0 last:mb-0", className),
1835
2587
  ...props
1836
2588
  }
1837
2589
  ),
1838
- p: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2590
+ p: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1839
2591
  "p",
1840
2592
  {
1841
2593
  className: cn("mt-5 mb-5 leading-7 first:mt-0 last:mb-0", className),
1842
2594
  ...props
1843
2595
  }
1844
2596
  ),
1845
- a: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2597
+ a: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1846
2598
  "a",
1847
2599
  {
1848
2600
  className: cn(
@@ -1858,7 +2610,7 @@ var defaultComponents = {
1858
2610
  className,
1859
2611
  node: _node,
1860
2612
  ...props
1861
- }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2613
+ }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1862
2614
  "blockquote",
1863
2615
  {
1864
2616
  className: cn(
@@ -1868,21 +2620,21 @@ var defaultComponents = {
1868
2620
  ...props
1869
2621
  }
1870
2622
  ),
1871
- ul: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2623
+ ul: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1872
2624
  "ul",
1873
2625
  {
1874
2626
  className: cn("my-5 list-outside list-disc pl-6 [&>li]:mt-2", className),
1875
2627
  ...props
1876
2628
  }
1877
2629
  ),
1878
- ol: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2630
+ ol: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1879
2631
  "ol",
1880
2632
  {
1881
2633
  className: cn("my-5 list-outside list-decimal pl-8 [&>li]:mt-2", className),
1882
2634
  ...props
1883
2635
  }
1884
2636
  ),
1885
- hr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2637
+ hr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1886
2638
  "hr",
1887
2639
  {
1888
2640
  className: cn("my-5 border-b", className),
@@ -1893,7 +2645,7 @@ var defaultComponents = {
1893
2645
  className,
1894
2646
  node: _node,
1895
2647
  ...props
1896
- }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2648
+ }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1897
2649
  "table",
1898
2650
  {
1899
2651
  className: cn(
@@ -1903,7 +2655,7 @@ var defaultComponents = {
1903
2655
  ...props
1904
2656
  }
1905
2657
  ),
1906
- th: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2658
+ th: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1907
2659
  "th",
1908
2660
  {
1909
2661
  className: cn(
@@ -1913,7 +2665,7 @@ var defaultComponents = {
1913
2665
  ...props
1914
2666
  }
1915
2667
  ),
1916
- td: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2668
+ td: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1917
2669
  "td",
1918
2670
  {
1919
2671
  className: cn(
@@ -1923,7 +2675,7 @@ var defaultComponents = {
1923
2675
  ...props
1924
2676
  }
1925
2677
  ),
1926
- tr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2678
+ tr: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1927
2679
  "tr",
1928
2680
  {
1929
2681
  className: cn(
@@ -1933,14 +2685,14 @@ var defaultComponents = {
1933
2685
  ...props
1934
2686
  }
1935
2687
  ),
1936
- sup: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2688
+ sup: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1937
2689
  "sup",
1938
2690
  {
1939
2691
  className: cn("[&>a]:text-xs [&>a]:no-underline", className),
1940
2692
  ...props
1941
2693
  }
1942
2694
  ),
1943
- pre: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2695
+ pre: ({ className, node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1944
2696
  "div",
1945
2697
  {
1946
2698
  className: cn(
@@ -1962,15 +2714,15 @@ var defaultComponents = {
1962
2714
  if (match) {
1963
2715
  const language = match[1];
1964
2716
  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)(
2717
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
2718
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1967
2719
  CodeHeader,
1968
2720
  {
1969
2721
  language,
1970
2722
  code: normalizedCode
1971
2723
  }
1972
2724
  ),
1973
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2725
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1974
2726
  SyntaxHighlighter,
1975
2727
  {
1976
2728
  language,
@@ -1981,7 +2733,7 @@ var defaultComponents = {
1981
2733
  ] });
1982
2734
  }
1983
2735
  if (isBlockCode) {
1984
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2736
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1985
2737
  "code",
1986
2738
  {
1987
2739
  className: cn(
@@ -1993,7 +2745,7 @@ var defaultComponents = {
1993
2745
  }
1994
2746
  );
1995
2747
  }
1996
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2748
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1997
2749
  "code",
1998
2750
  {
1999
2751
  className: cn(
@@ -2007,7 +2759,7 @@ var defaultComponents = {
2007
2759
  }
2008
2760
  };
2009
2761
  var MarkdownTextImpl = ({ children }) => {
2010
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "markdown-content", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2762
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "markdown-content", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2011
2763
  import_react_markdown.default,
2012
2764
  {
2013
2765
  remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
@@ -2021,18 +2773,18 @@ var MarkdownText = (0, import_react6.memo)(MarkdownTextImpl);
2021
2773
 
2022
2774
  // src/components/thread/messages/widget.tsx
2023
2775
  var import_a2ui_react = require("@xpert-ai/a2ui-react");
2024
- var import_jsx_runtime18 = require("react/jsx-runtime");
2776
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2025
2777
  function WidgetMessage({ messageId, data }) {
2026
2778
  const widgets = Array.isArray(data.widgets) ? data.widgets : [];
2027
2779
  if (widgets.length === 0) return null;
2028
2780
  const baseSurfaceId = `widget-${messageId}`;
2029
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "space-y-3", children: widgets.map((widget, index) => {
2781
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-3", children: widgets.map((widget, index) => {
2030
2782
  const config = widget?.config;
2031
2783
  if (!config || typeof config !== "object") {
2032
2784
  return null;
2033
2785
  }
2034
2786
  const surfaceId = widgets.length > 1 ? `${baseSurfaceId}-${index}` : baseSurfaceId;
2035
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2787
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2036
2788
  import_a2ui_react.SurfaceRenderer,
2037
2789
  {
2038
2790
  surfaceId,
@@ -2044,7 +2796,7 @@ function WidgetMessage({ messageId, data }) {
2044
2796
  }
2045
2797
 
2046
2798
  // src/components/thread/messages/ai.tsx
2047
- var import_jsx_runtime19 = require("react/jsx-runtime");
2799
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2048
2800
  function isTextContent(content) {
2049
2801
  return content.type === "text";
2050
2802
  }
@@ -2060,15 +2812,15 @@ function isComponentContent(content) {
2060
2812
  var statusConfig = {
2061
2813
  success: {
2062
2814
  iconClass: "border-green-500 text-green-700",
2063
- icon: import_lucide_react6.CheckCircle2
2815
+ icon: import_lucide_react7.CheckCircle2
2064
2816
  },
2065
2817
  fail: {
2066
2818
  iconClass: "border-red-500 text-red-700",
2067
- icon: import_lucide_react6.XCircle
2819
+ icon: import_lucide_react7.XCircle
2068
2820
  },
2069
2821
  running: {
2070
2822
  iconClass: "border-blue-500 text-blue-700",
2071
- icon: import_lucide_react6.Loader2
2823
+ icon: import_lucide_react7.Loader2
2072
2824
  }
2073
2825
  };
2074
2826
  function isWidgetComponent(content) {
@@ -2088,11 +2840,11 @@ function safeJson(value) {
2088
2840
  function ReasoningBlock({ reasoning }) {
2089
2841
  const blocks = reasoning.filter((item) => item.text?.trim());
2090
2842
  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)(
2843
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "space-y-2", children: blocks.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2092
2844
  "div",
2093
2845
  {
2094
2846
  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 })
2847
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "whitespace-pre-wrap wrap-break-word leading-relaxed", children: item.text })
2096
2848
  },
2097
2849
  item.id ?? `reasoning-${index}`
2098
2850
  )) });
@@ -2100,27 +2852,27 @@ function ReasoningBlock({ reasoning }) {
2100
2852
  function ImageBlock({ content }) {
2101
2853
  const imageUrl = typeof content.image_url === "string" ? content.image_url : typeof content.image_url?.url === "string" ? content.image_url.url : null;
2102
2854
  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) })
2855
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Card, { children: [
2856
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardHeader, { className: "space-y-1", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardTitle, { className: "text-sm", children: "Image" }) }),
2857
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: safeJson(content) })
2106
2858
  ] });
2107
2859
  }
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" }) });
2860
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figure", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("img", { src: imageUrl, alt: "Assistant output", className: "h-auto w-full object-cover" }) });
2109
2861
  }
2110
2862
  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" })
2863
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Card, { children: [
2864
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
2865
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardTitle, { className: "text-sm", children: "Memory" }),
2866
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Badge, { variant: "secondary", children: "Memory" })
2115
2867
  ] }),
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 ?? []) }) })
2868
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: safeJson(content.data ?? []) }) })
2117
2869
  ] });
2118
2870
  }
2119
2871
  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);
2872
+ const [isExpanded, setIsExpanded] = React14.useState(false);
2873
+ const contentRef = React14.useRef(null);
2874
+ const shouldAutoScrollRef = React14.useRef(true);
2875
+ const previousScrollTopRef = React14.useRef(0);
2124
2876
  const data = content.data ?? {};
2125
2877
  const category = data.category ?? "Component";
2126
2878
  const title = data.tool && category === "Tool" ? data.tool : data.title ?? data.type ?? "Component";
@@ -2130,10 +2882,10 @@ function ComponentBlock({ content }) {
2130
2882
  const error = data.error ?? null;
2131
2883
  const fallback = message ?? output ?? safeJson(data.data ?? data);
2132
2884
  const hasOutput = message !== null || output !== null;
2133
- React13.useEffect(() => {
2885
+ React14.useEffect(() => {
2134
2886
  if (status === "running" && output !== null) setIsExpanded(true);
2135
2887
  }, [status, output]);
2136
- React13.useEffect(() => {
2888
+ React14.useEffect(() => {
2137
2889
  const element = contentRef.current;
2138
2890
  if (!element) return;
2139
2891
  previousScrollTopRef.current = element.scrollTop;
@@ -2153,7 +2905,7 @@ function ComponentBlock({ content }) {
2153
2905
  element.removeEventListener("scroll", updateAutoScrollState);
2154
2906
  };
2155
2907
  }, [isExpanded]);
2156
- React13.useEffect(() => {
2908
+ React14.useEffect(() => {
2157
2909
  if (status !== "running") {
2158
2910
  shouldAutoScrollRef.current = true;
2159
2911
  return;
@@ -2166,21 +2918,21 @@ function ComponentBlock({ content }) {
2166
2918
  }, [isExpanded, output, status]);
2167
2919
  const config = status ? statusConfig[status] : null;
2168
2920
  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 })
2921
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Card, { children: [
2922
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2 px-2 py-1 cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
2923
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center space-x-1 flex-1 min-w-0", children: [
2924
+ status && StatusIcon && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StatusIcon, { className: cn("h-4 w-4", config?.iconClass, status === "running" && "animate-spin") }),
2925
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardTitle, { className: "text-sm truncate", children: title })
2174
2926
  ] }),
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)(
2927
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-wrap items-center gap-2 shrink-0", children: [
2928
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Badge, { variant: "secondary", className: "rounded-lg px-1.5", children: category }),
2929
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2178
2930
  "button",
2179
2931
  {
2180
2932
  className: "text-muted-foreground hover:text-foreground transition-colors",
2181
2933
  "aria-label": isExpanded ? "Collapse" : "Expand",
2182
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2183
- import_lucide_react6.ChevronDown,
2934
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2935
+ import_lucide_react7.ChevronDown,
2184
2936
  {
2185
2937
  className: cn("h-4 w-4 transition-transform", isExpanded && "rotate-180")
2186
2938
  }
@@ -2189,89 +2941,128 @@ function ComponentBlock({ content }) {
2189
2941
  )
2190
2942
  ] })
2191
2943
  ] }),
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 })
2944
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(CardContent, { ref: contentRef, className: "text-xs text-muted-foreground max-h-60 overflow-auto", children: [
2945
+ data.input && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: JSON.stringify(data.input, null, 2) }),
2946
+ error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word text-destructive", children: typeof error === "string" ? error : safeJson(error) }) : hasOutput && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { className: "whitespace-pre-wrap wrap-break-word", children: fallback })
2195
2947
  ] })
2196
2948
  ] });
2197
2949
  }
2198
2950
  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" })
2951
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Card, { children: [
2952
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [
2953
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardTitle, { className: "text-sm", children: "Assistant Content" }),
2954
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Badge, { variant: "outline", children: content.type ?? "unknown" })
2203
2955
  ] }),
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) }) })
2956
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardContent, { className: "text-xs text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("pre", { className: "whitespace-pre-wrap break-words", children: safeJson(content) }) })
2205
2957
  ] });
2206
2958
  }
2207
2959
  function renderContentItem(content, index, messageId) {
2208
2960
  if (typeof content === "string") {
2209
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
2210
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MarkdownText, { children: content }),
2961
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
2962
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MarkdownText, { children: content }),
2211
2963
  ";"
2212
2964
  ] }, `text-${index}`);
2213
2965
  }
2214
2966
  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}`);
2967
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MarkdownText, { children: content.text }) }, content.id ?? `text-${index}`);
2216
2968
  }
2217
2969
  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}`);
2970
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ReasoningBlock, { reasoning: [content] }) }, content.id ?? `reasoning-${index}`);
2219
2971
  }
2220
2972
  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}`);
2973
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ImageBlock, { content }) }, content.id ?? `image-${index}`);
2222
2974
  }
2223
2975
  if (isComponentContent(content)) {
2224
2976
  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}`);
2977
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(WidgetMessage, { messageId, data: content.data }) }, content.id ?? `widget-${index}`);
2226
2978
  }
2227
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ComponentBlock, { content }) }, content.id ?? `component-${index}`);
2979
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ComponentBlock, { content }) }, content.id ?? `component-${index}`);
2228
2980
  }
2229
2981
  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}`);
2982
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MemoryBlock, { content }) }, content.id ?? `memory-${index}`);
2231
2983
  }
2232
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(UnknownBlock, { content }) }, content.id ?? `unknown-${index}`);
2984
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(UnknownBlock, { content }) }, content.id ?? `unknown-${index}`);
2233
2985
  }
2234
2986
  function renderContent(content, messageId) {
2235
2987
  if (typeof content === "string") {
2236
2988
  if (!content.trim()) return null;
2237
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(MarkdownText, { children: content });
2989
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MarkdownText, { children: content });
2238
2990
  }
2239
2991
  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)) });
2992
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "space-y-3", children: content.map((item, index) => renderContentItem(item, index, messageId)) });
2241
2993
  }
2242
- function AssistantMessage({ message, className, isStreaming = false }) {
2994
+ function AssistantStreamingIndicator({
2995
+ status,
2996
+ className
2997
+ }) {
2243
2998
  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());
2999
+ const labelMap = {
3000
+ loading: t("message.loading"),
3001
+ thinking: t("message.thinking"),
3002
+ answering: t("message.answering")
3003
+ };
3004
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("flex items-center gap-2 text-xs text-muted-foreground", className), children: [
3005
+ status === "loading" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.Loader2, { className: "h-3.5 w-3.5 animate-spin" }),
3006
+ status === "thinking" && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-end gap-1", "aria-hidden": "true", children: [
3007
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce [animation-delay:-0.3s]" }),
3008
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce [animation-delay:-0.15s]" }),
3009
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-current animate-bounce" })
3010
+ ] }),
3011
+ status === "answering" && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-end gap-1", "aria-hidden": "true", children: [
3012
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-2 w-0.5 rounded-full bg-current animate-pulse [animation-delay:-0.25s]" }),
3013
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-3 w-0.5 rounded-full bg-current animate-pulse [animation-delay:-0.1s]" }),
3014
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "h-2.5 w-0.5 rounded-full bg-current animate-pulse" })
3015
+ ] }),
3016
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: labelMap[status] })
3017
+ ] });
3018
+ }
3019
+ function AssistantMessage({
3020
+ message,
3021
+ className,
3022
+ isStreaming = false,
3023
+ streamingStatus
3024
+ }) {
3025
+ const { t } = useChatkitTranslation();
3026
+ const hasContent = hasRenderableMessageContent(message.content);
3027
+ const hasReasoning = hasRenderableReasoning(message.reasoning);
3028
+ const resolvedStreamingStatus = streamingStatus ?? getAssistantStreamingStatus(message, isStreaming);
2247
3029
  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;
3030
+ const reasoningNode = hasReasoning ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ReasoningBlock, { reasoning: message.reasoning ?? [] }) : null;
3031
+ if (!hasRenderableAssistantMessage(message) && !resolvedStreamingStatus) return null;
2250
3032
  const streamingClass = isStreaming ? "streaming-active" : "";
3033
+ if (!hasRenderableAssistantMessage(message) && resolvedStreamingStatus) {
3034
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("space-y-3", streamingClass, className), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) });
3035
+ }
2251
3036
  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
- ) });
3037
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("space-y-3", streamingClass, className), children: [
3038
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
3039
+ Tabs,
3040
+ {
3041
+ defaultValue: message.status === "reasoning" ? "reasoning" : "answer",
3042
+ className: "w-full",
3043
+ children: [
3044
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(TabsList, { className: "h-9", children: [
3045
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TabsTrigger, { value: "answer", children: t("message.answer") }),
3046
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TabsTrigger, { value: "reasoning", children: t("message.reasoning") })
3047
+ ] }),
3048
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TabsContent, { value: "answer", className: "space-y-3", children: answerNode }),
3049
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TabsContent, { value: "reasoning", className: "space-y-3", children: reasoningNode })
3050
+ ]
3051
+ }
3052
+ ),
3053
+ resolvedStreamingStatus ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) : null
3054
+ ] });
2267
3055
  }
2268
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("space-y-3", streamingClass, className), children: hasReasoning ? reasoningNode : answerNode });
3056
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn("space-y-3", streamingClass, className), children: [
3057
+ hasReasoning ? reasoningNode : answerNode,
3058
+ resolvedStreamingStatus ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantStreamingIndicator, { status: resolvedStreamingStatus }) : null
3059
+ ] });
2269
3060
  }
2270
3061
 
2271
3062
  // 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");
3063
+ var React15 = __toESM(require("react"), 1);
3064
+ var import_lucide_react8 = require("lucide-react");
3065
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2275
3066
  function MessageActions({
2276
3067
  content,
2277
3068
  isAssistant = false,
@@ -2280,7 +3071,7 @@ function MessageActions({
2280
3071
  className
2281
3072
  }) {
2282
3073
  const { t } = useChatkitTranslation();
2283
- const [copied, setCopied] = React14.useState(false);
3074
+ const [copied, setCopied] = React15.useState(false);
2284
3075
  const handleCopy = async () => {
2285
3076
  try {
2286
3077
  await navigator.clipboard.writeText(content);
@@ -2293,7 +3084,7 @@ function MessageActions({
2293
3084
  if (isStreaming) {
2294
3085
  return null;
2295
3086
  }
2296
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
3087
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2297
3088
  "div",
2298
3089
  {
2299
3090
  className: cn(
@@ -2301,7 +3092,7 @@ function MessageActions({
2301
3092
  className
2302
3093
  ),
2303
3094
  children: [
2304
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3095
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2305
3096
  "button",
2306
3097
  {
2307
3098
  type: "button",
@@ -2311,17 +3102,17 @@ function MessageActions({
2311
3102
  copied && "text-green-500"
2312
3103
  ),
2313
3104
  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 })
3105
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Check, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.Copy, { size: 14 })
2315
3106
  }
2316
3107
  ),
2317
- isAssistant && onRetry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3108
+ isAssistant && onRetry && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2318
3109
  "button",
2319
3110
  {
2320
3111
  type: "button",
2321
3112
  onClick: onRetry,
2322
3113
  className: "p-1.5 rounded-md text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
2323
3114
  title: t("messageActions.regenerate"),
2324
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.RefreshCw, { size: 14 })
3115
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react8.RefreshCw, { size: 14 })
2325
3116
  }
2326
3117
  )
2327
3118
  ]
@@ -2330,20 +3121,20 @@ function MessageActions({
2330
3121
  }
2331
3122
 
2332
3123
  // 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");
3124
+ var React16 = require("react");
3125
+ var import_lucide_react9 = require("lucide-react");
3126
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2336
3127
  function getIconComponent2(icon) {
2337
3128
  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 })
3129
+ "circle-question": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.HelpCircle, { size: 20 }),
3130
+ "lightbulb": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Lightbulb, { size: 20 }),
3131
+ "sparkle": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Sparkles, { size: 20 }),
3132
+ "write": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Pencil, { size: 20 }),
3133
+ "search": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Search, { size: 20 }),
3134
+ "globe": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Globe, { size: 20 }),
3135
+ "book-open": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.BookOpen, { size: 20 }),
3136
+ "compass": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Compass, { size: 20 }),
3137
+ "bolt": /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react9.Zap, { size: 20 })
2347
3138
  };
2348
3139
  return icon ? iconMap[icon] || iconMap["sparkle"] : iconMap["sparkle"];
2349
3140
  }
@@ -2351,9 +3142,9 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2351
3142
  const { t } = useChatkitTranslation();
2352
3143
  const greeting = startScreen?.greeting ?? t("startScreen.greeting");
2353
3144
  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)(
3145
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: cn("flex flex-col items-center justify-center py-12 px-4", className), children: [
3146
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "mb-8 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { className: "text-2xl font-semibold text-foreground mb-2", children: greeting }) }),
3147
+ prompts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: prompts.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2357
3148
  "button",
2358
3149
  {
2359
3150
  type: "button",
@@ -2364,8 +3155,8 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2364
3155
  "focus:outline-none focus:ring-2 focus:ring-primary/20"
2365
3156
  ),
2366
3157
  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 })
3158
+ /* @__PURE__ */ (0, import_jsx_runtime22.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) }),
3159
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-sm font-medium text-foreground", children: item.label })
2369
3160
  ]
2370
3161
  },
2371
3162
  `prompt-${index}`
@@ -2374,13 +3165,13 @@ function StartScreen({ startScreen, onPromptClick, className }) {
2374
3165
  }
2375
3166
 
2376
3167
  // src/components/ui/chatkit-avatar.tsx
2377
- var React17 = require("react");
3168
+ var React18 = require("react");
2378
3169
 
2379
3170
  // src/components/ui/avatar.tsx
2380
- var React16 = __toESM(require("react"), 1);
3171
+ var React17 = __toESM(require("react"), 1);
2381
3172
  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)(
3173
+ var import_jsx_runtime23 = require("react/jsx-runtime");
3174
+ var Avatar = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2384
3175
  AvatarPrimitive.Root,
2385
3176
  {
2386
3177
  ref,
@@ -2392,7 +3183,7 @@ var Avatar = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
2392
3183
  }
2393
3184
  ));
2394
3185
  Avatar.displayName = AvatarPrimitive.Root.displayName;
2395
- var AvatarImage = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3186
+ var AvatarImage = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2396
3187
  AvatarPrimitive.Image,
2397
3188
  {
2398
3189
  ref,
@@ -2401,7 +3192,7 @@ var AvatarImage = React16.forwardRef(({ className, ...props }, ref) => /* @__PUR
2401
3192
  }
2402
3193
  ));
2403
3194
  AvatarImage.displayName = AvatarPrimitive.Image.displayName;
2404
- var AvatarFallback = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3195
+ var AvatarFallback = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2405
3196
  AvatarPrimitive.Fallback,
2406
3197
  {
2407
3198
  ref,
@@ -2415,7 +3206,7 @@ var AvatarFallback = React16.forwardRef(({ className, ...props }, ref) => /* @__
2415
3206
  AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
2416
3207
 
2417
3208
  // src/components/ui/chatkit-avatar.tsx
2418
- var import_jsx_runtime23 = require("react/jsx-runtime");
3209
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2419
3210
  function asRecord(value) {
2420
3211
  return value && typeof value === "object" ? value : null;
2421
3212
  }
@@ -2488,21 +3279,21 @@ function ChatkitAvatar({
2488
3279
  const fallbackStyle = {
2489
3280
  ...avatar?.background ? { background: avatar.background } : {}
2490
3281
  };
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)(
3282
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Avatar, { className: cn(roundedClass, className), style, ...props, children: [
3283
+ avatar?.url ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AvatarImage, { className: imageClassName, src: avatar.url, alt: label }) : null,
3284
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2494
3285
  AvatarFallback,
2495
3286
  {
2496
3287
  className: cn(roundedClass, "text-sm font-medium text-foreground", fallbackClassName),
2497
3288
  style: fallbackStyle,
2498
- children: emojiCharacter ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[1.1em] leading-none", style: emojiStyle, children: emojiCharacter }) : fallbackText
3289
+ children: emojiCharacter ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-[1.1em] leading-none", style: emojiStyle, children: emojiCharacter }) : fallbackText
2499
3290
  }
2500
3291
  )
2501
3292
  ] });
2502
3293
  }
2503
3294
 
2504
3295
  // src/hooks/useThreads.ts
2505
- var React18 = __toESM(require("react"), 1);
3296
+ var React19 = __toESM(require("react"), 1);
2506
3297
  var DEFAULT_LIMIT = 50;
2507
3298
  var getThreadTitle = (threadRecord) => {
2508
3299
  const title = threadRecord.title?.trim();
@@ -2540,16 +3331,16 @@ function useThreads(limit = DEFAULT_LIMIT) {
2540
3331
  isReady,
2541
3332
  isLoading: isStreamLoading
2542
3333
  } = 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) => {
3334
+ const [threadRecords, setThreadRecords] = React19.useState([]);
3335
+ const [isLoading, setIsLoading] = React19.useState(false);
3336
+ const [error, setError] = React19.useState(null);
3337
+ const upsertThreadRecord = React19.useCallback((threadRecord) => {
2547
3338
  setThreadRecords((prev) => {
2548
3339
  const next = prev.filter((item) => item.id !== threadRecord.id);
2549
3340
  return sortThreadRecords([threadRecord, ...next]);
2550
3341
  });
2551
3342
  }, []);
2552
- const refreshThreads = React18.useCallback(async () => {
3343
+ const refreshThreads = React19.useCallback(async () => {
2553
3344
  setIsLoading(true);
2554
3345
  setError(null);
2555
3346
  try {
@@ -2565,7 +3356,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2565
3356
  setIsLoading(false);
2566
3357
  }
2567
3358
  }, [client, limit, assistantId]);
2568
- const createThread = React18.useCallback(
3359
+ const createThread = React19.useCallback(
2569
3360
  async (input) => {
2570
3361
  setError(null);
2571
3362
  const payload = {};
@@ -2579,7 +3370,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2579
3370
  },
2580
3371
  [client, upsertThreadRecord]
2581
3372
  );
2582
- const updateThread = React18.useCallback(
3373
+ const updateThread = React19.useCallback(
2583
3374
  async (recordId, payload) => {
2584
3375
  setError(null);
2585
3376
  const updated = await client.conversations.update(recordId, payload);
@@ -2588,7 +3379,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2588
3379
  },
2589
3380
  [client, upsertThreadRecord]
2590
3381
  );
2591
- const deleteThread = React18.useCallback(
3382
+ const deleteThread = React19.useCallback(
2592
3383
  async (recordId) => {
2593
3384
  setError(null);
2594
3385
  await client.conversations.delete(recordId);
@@ -2596,11 +3387,11 @@ function useThreads(limit = DEFAULT_LIMIT) {
2596
3387
  },
2597
3388
  [client]
2598
3389
  );
2599
- React18.useEffect(() => {
3390
+ React19.useEffect(() => {
2600
3391
  if (!isReady) return;
2601
3392
  void refreshThreads();
2602
3393
  }, [refreshThreads, isReady]);
2603
- React18.useEffect(() => {
3394
+ React19.useEffect(() => {
2604
3395
  if (!threadId || !isStreamLoading) return;
2605
3396
  const now = (/* @__PURE__ */ new Date()).toISOString();
2606
3397
  setThreadRecords((prev) => {
@@ -2620,7 +3411,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2620
3411
  return changed ? sortThreadRecords(next) : prev;
2621
3412
  });
2622
3413
  }, [threadId, isStreamLoading]);
2623
- React18.useEffect(() => {
3414
+ React19.useEffect(() => {
2624
3415
  if (!isReady || !threadId || isStreamLoading) return;
2625
3416
  let cancelled = false;
2626
3417
  void client.conversations.search({ where: { threadId }, limit: 1 }).then((result) => {
@@ -2634,7 +3425,7 @@ function useThreads(limit = DEFAULT_LIMIT) {
2634
3425
  cancelled = true;
2635
3426
  };
2636
3427
  }, [client, threadId, upsertThreadRecord, isReady, isStreamLoading]);
2637
- const threads = React18.useMemo(
3428
+ const threads = React19.useMemo(
2638
3429
  () => threadRecords.map((threadRecord) => toThreadItem(threadRecord)),
2639
3430
  [threadRecords]
2640
3431
  );
@@ -2651,10 +3442,10 @@ function useThreads(limit = DEFAULT_LIMIT) {
2651
3442
  }
2652
3443
 
2653
3444
  // src/components/thread/context-usage-indicator.tsx
2654
- var React19 = __toESM(require("react"), 1);
3445
+ var React20 = __toESM(require("react"), 1);
2655
3446
 
2656
3447
  // src/components/ui/progress-circle.tsx
2657
- var import_jsx_runtime24 = (
3448
+ var import_jsx_runtime25 = (
2658
3449
  // biome-ignore lint/a11y/useFocusableInteractive: false positive (progress + progressbar are not focusable interactives)
2659
3450
  // biome-ignore lint/nursery/useAriaPropsSupportedByRole: biome rule at odds with mdn docs (presumed nursary bug with rule)
2660
3451
  require("react/jsx-runtime")
@@ -2678,7 +3469,7 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2678
3469
  fill: "none",
2679
3470
  strokeWidth
2680
3471
  };
2681
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
3472
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
2682
3473
  "svg",
2683
3474
  {
2684
3475
  role: "progressbar",
@@ -2689,8 +3480,8 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2689
3480
  "aria-valuemax": 100,
2690
3481
  ...restSvgProps,
2691
3482
  children: [
2692
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { ...commonParams, className: "stroke-current/25" }),
2693
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3483
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("circle", { ...commonParams, className: "stroke-current/25" }),
3484
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2694
3485
  "circle",
2695
3486
  {
2696
3487
  ...commonParams,
@@ -2708,7 +3499,7 @@ var ProgressCircle = ({ value, className, ...restSvgProps }) => {
2708
3499
  };
2709
3500
 
2710
3501
  // src/components/thread/context-usage-indicator.tsx
2711
- var import_jsx_runtime25 = require("react/jsx-runtime");
3502
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2712
3503
  var kNumberFormatter = new Intl.NumberFormat("en-US", {
2713
3504
  minimumFractionDigits: 0,
2714
3505
  maximumFractionDigits: 1
@@ -2741,20 +3532,20 @@ function ContextUsageIndicator({
2741
3532
  }) {
2742
3533
  const { t } = useChatkitTranslation();
2743
3534
  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({
3535
+ const [maxContextSize, setMaxContextSize] = React20.useState(null);
3536
+ const [usedContextSize, setUsedContextSize] = React20.useState(null);
3537
+ const [assistantAgentKey, setAssistantAgentKey] = React20.useState(null);
3538
+ const latestRealtimeUsageRef = React20.useRef({
2748
3539
  threadId: null,
2749
3540
  agentKey: null,
2750
3541
  usedTokens: null
2751
3542
  });
2752
- const realtimeUsage = React19.useMemo(
3543
+ const realtimeUsage = React20.useMemo(
2753
3544
  () => getThreadContextUsage(stream.contextUsageByAgentKey, assistantAgentKey),
2754
3545
  [assistantAgentKey, stream.contextUsageByAgentKey]
2755
3546
  );
2756
3547
  const realtimeUsedContextSize = getThreadContextUsageTotalTokens(realtimeUsage);
2757
- React19.useEffect(() => {
3548
+ React20.useEffect(() => {
2758
3549
  if (!stream.client || !stream.assistantId) {
2759
3550
  setMaxContextSize(null);
2760
3551
  setAssistantAgentKey(null);
@@ -2774,18 +3565,18 @@ function ContextUsageIndicator({
2774
3565
  cancelled = true;
2775
3566
  };
2776
3567
  }, [stream.client, stream.assistantId]);
2777
- React19.useEffect(() => {
3568
+ React20.useEffect(() => {
2778
3569
  latestRealtimeUsageRef.current = {
2779
3570
  threadId: stream.threadId ?? null,
2780
3571
  agentKey: assistantAgentKey,
2781
3572
  usedTokens: realtimeUsedContextSize
2782
3573
  };
2783
3574
  }, [assistantAgentKey, realtimeUsedContextSize, stream.threadId]);
2784
- React19.useEffect(() => {
3575
+ React20.useEffect(() => {
2785
3576
  if (realtimeUsedContextSize == null) return;
2786
3577
  setUsedContextSize(realtimeUsedContextSize);
2787
3578
  }, [realtimeUsedContextSize]);
2788
- React19.useEffect(() => {
3579
+ React20.useEffect(() => {
2789
3580
  if (!stream.client) {
2790
3581
  setUsedContextSize(null);
2791
3582
  return;
@@ -2850,8 +3641,8 @@ function ContextUsageIndicator({
2850
3641
  });
2851
3642
  const usageLabelWithSuffix = usageLabel.endsWith(":") ? usageLabel : `${usageLabel}:`;
2852
3643
  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)(
3644
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Tooltip, { children: [
3645
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2855
3646
  "button",
2856
3647
  {
2857
3648
  type: "button",
@@ -2860,21 +3651,22 @@ function ContextUsageIndicator({
2860
3651
  className
2861
3652
  ),
2862
3653
  "aria-label": `${usageLabelWithSuffix} ${usageFullLabel}. ${usageTokensLabel}`,
2863
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ProgressCircle, { value: percent, className: cn("size-3.5", progressClassName) })
3654
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ProgressCircle, { value: percent, className: cn("size-3.5", progressClassName) })
2864
3655
  }
2865
3656
  ) }),
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 })
3657
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(TooltipContent, { side: "top", sideOffset: 6, className: "space-y-0.5 px-3 py-2 text-center", children: [
3658
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-primary-foreground/70", children: usageLabelWithSuffix }),
3659
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "font-medium text-primary-foreground/80", children: usageFullLabel }),
3660
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-sm font-semibold", children: usageTokensLabel })
2870
3661
  ] })
2871
3662
  ] });
2872
3663
  }
2873
3664
 
2874
3665
  // src/components/chat.tsx
2875
- var import_jsx_runtime26 = require("react/jsx-runtime");
3666
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2876
3667
  var import_meta2 = {};
2877
3668
  var defaultApiUrl2 = import_meta2.env.VITE_XPERTAI_API_URL;
3669
+ var COMPOSER_INPUT_MAX_HEIGHT = 128;
2878
3670
  function formatMessageContent(content) {
2879
3671
  if (typeof content === "string") {
2880
3672
  return content;
@@ -2896,6 +3688,81 @@ function formatMessageContent(content) {
2896
3688
  }
2897
3689
  return "";
2898
3690
  }
3691
+ function getClosestQuoteContainer(node) {
3692
+ if (!node) {
3693
+ return null;
3694
+ }
3695
+ const element = node instanceof HTMLElement ? node : node instanceof Text ? node.parentElement : null;
3696
+ return element?.closest("[data-quote-message-id]") ?? null;
3697
+ }
3698
+ function ReferenceChip({
3699
+ reference,
3700
+ variant,
3701
+ onRemove,
3702
+ removeLabel
3703
+ }) {
3704
+ const metaLine = getReferenceMetaLine(reference);
3705
+ const isComposer = variant === "composer";
3706
+ const Icon = reference.type === "quote" ? import_lucide_react10.Quote : import_lucide_react10.FileText;
3707
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3708
+ "div",
3709
+ {
3710
+ className: cn(
3711
+ "flex items-start gap-2 rounded-md px-2 py-1",
3712
+ isComposer ? "bg-muted text-foreground" : "bg-primary-foreground/20"
3713
+ ),
3714
+ title: getReferenceTitle(reference),
3715
+ children: [
3716
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3717
+ Icon,
3718
+ {
3719
+ size: isComposer ? 14 : 12,
3720
+ className: cn(
3721
+ "mt-0.5 shrink-0",
3722
+ isComposer ? "text-muted-foreground" : "text-primary-foreground/80"
3723
+ )
3724
+ }
3725
+ ),
3726
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "min-w-0 flex-1", children: [
3727
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3728
+ "div",
3729
+ {
3730
+ className: cn(
3731
+ "truncate",
3732
+ isComposer ? "text-sm" : "text-xs font-medium"
3733
+ ),
3734
+ children: getReferenceLabel(reference)
3735
+ }
3736
+ ),
3737
+ metaLine && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3738
+ "div",
3739
+ {
3740
+ className: cn(
3741
+ "truncate",
3742
+ isComposer ? "text-xs text-muted-foreground" : "text-[10px] text-primary-foreground/75"
3743
+ ),
3744
+ children: metaLine
3745
+ }
3746
+ )
3747
+ ] }),
3748
+ onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3749
+ "button",
3750
+ {
3751
+ type: "button",
3752
+ onClick: onRemove,
3753
+ className: cn(
3754
+ "ml-1 rounded-full p-0.5",
3755
+ isComposer ? "hover:bg-muted-foreground/20" : "hover:bg-primary-foreground/20"
3756
+ ),
3757
+ title: removeLabel,
3758
+ "aria-label": removeLabel,
3759
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.X, { size: 12 })
3760
+ }
3761
+ )
3762
+ ]
3763
+ }
3764
+ );
3765
+ }
2899
3766
  function Chat({
2900
3767
  className,
2901
3768
  options,
@@ -2912,17 +3779,21 @@ function Chat({
2912
3779
  const apiUrl = options?.api?.apiUrl || defaultApiUrl2;
2913
3780
  const { setStream } = useStreamManager();
2914
3781
  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);
3782
+ const { theme } = useTheme();
3783
+ const [isHistoryLoading, setIsHistoryLoading] = React21.useState(false);
3784
+ const [historyError, setHistoryError] = React21.useState(null);
3785
+ const [assistantName, setAssistantName] = React21.useState(null);
3786
+ const [assistantAvatar, setAssistantAvatar] = React21.useState(null);
2919
3787
  const LOADING_DOTS_MIN_DURATION = 800;
2920
- const [showLoadingDots, setShowLoadingDots] = React20.useState(false);
2921
- const loadingStartTimeRef = React20.useRef(null);
2922
- React20.useEffect(() => {
3788
+ const STREAMING_STATUS_REFRESH_MS = 250;
3789
+ const [showLoadingDots, setShowLoadingDots] = React21.useState(false);
3790
+ const [streamingNow, setStreamingNow] = React21.useState(() => Date.now());
3791
+ const loadingStartTimeRef = React21.useRef(null);
3792
+ const lastStreamOutputAtRef = React21.useRef(null);
3793
+ React21.useEffect(() => {
2923
3794
  setStream(stream);
2924
3795
  }, [setStream, stream]);
2925
- React20.useEffect(() => {
3796
+ React21.useEffect(() => {
2926
3797
  if (stream.isLoading) {
2927
3798
  if (!loadingStartTimeRef.current) {
2928
3799
  loadingStartTimeRef.current = Date.now();
@@ -2945,67 +3816,180 @@ function Chat({
2945
3816
  }
2946
3817
  }
2947
3818
  }, [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);
3819
+ React21.useEffect(() => {
3820
+ if (!stream.isLoading) {
3821
+ lastStreamOutputAtRef.current = null;
3822
+ setStreamingNow(Date.now());
3823
+ return;
3824
+ }
3825
+ const now = Date.now();
3826
+ lastStreamOutputAtRef.current = now;
3827
+ setStreamingNow(now);
3828
+ }, [stream.messages, stream.isLoading]);
3829
+ React21.useEffect(() => {
3830
+ if (!stream.isLoading) {
3831
+ return;
3832
+ }
3833
+ const timer = window.setInterval(() => {
3834
+ setStreamingNow(Date.now());
3835
+ }, STREAMING_STATUS_REFRESH_MS);
3836
+ return () => window.clearInterval(timer);
3837
+ }, [stream.isLoading]);
3838
+ const [draft, setDraft] = React21.useState("");
3839
+ const [selectedTool, setSelectedTool] = React21.useState(
3840
+ null
3841
+ );
3842
+ const [attachments, setAttachments] = React21.useState([]);
3843
+ const [references, setReferences] = React21.useState([]);
3844
+ const [quoteSelection, setQuoteSelection] = React21.useState(null);
3845
+ const [isAtBottom, setIsAtBottom] = React21.useState(true);
3846
+ const [hasUpdatesBelow, setHasUpdatesBelow] = React21.useState(false);
2953
3847
  const {
2954
3848
  threads,
2955
3849
  deleteThread,
2956
3850
  refreshThreads,
2957
3851
  isLoading: isThreadsLoading
2958
3852
  } = 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);
3853
+ const viewportRef = React21.useRef(null);
3854
+ const fileInputRef = React21.useRef(null);
3855
+ const composerInputRef = React21.useRef(null);
3856
+ const shouldAutoScrollRef = React21.useRef(true);
3857
+ const forceFollowRef = React21.useRef(false);
3858
+ const previousMessageCountRef = React21.useRef(0);
3859
+ const previousScrollTopRef = React21.useRef(0);
3860
+ const autoScrollFrameRef = React21.useRef(null);
3861
+ const isPointerDownRef = React21.useRef(false);
3862
+ const lastTouchYRef = React21.useRef(null);
2968
3863
  const resolvedTitle = title ?? t("chat.title");
2969
3864
  const resolvedPlaceholder = placeholder ?? t("chat.placeholder");
2970
3865
  const inputPlaceholder = selectedTool?.placeholderOverride ?? composer?.placeholder ?? resolvedPlaceholder;
2971
- const messages = React20.useMemo(() => stream.messages ?? [], [stream.messages]);
3866
+ const messages = React21.useMemo(
3867
+ () => stream.messages ?? [],
3868
+ [stream.messages]
3869
+ );
2972
3870
  const trimmedDraft = draft.trim();
2973
- const cancelPendingAutoScroll = React20.useCallback(() => {
3871
+ const hasReferences = references.length > 0;
3872
+ const pendingFollowUps = React21.useMemo(
3873
+ () => [...stream.pendingFollowUps ?? []].sort(
3874
+ (a, b) => a.createdAt - b.createdAt
3875
+ ),
3876
+ [stream.pendingFollowUps]
3877
+ );
3878
+ const clearQuoteSelection = React21.useCallback(() => {
3879
+ setQuoteSelection(null);
3880
+ }, []);
3881
+ useParentMessenger({
3882
+ onSetComposerValue: React21.useCallback(
3883
+ (payload) => {
3884
+ if (!payload) {
3885
+ return;
3886
+ }
3887
+ if (typeof payload.text === "string") {
3888
+ setDraft(payload.text);
3889
+ }
3890
+ if (Array.isArray(payload.references)) {
3891
+ const nextReferences = normalizeReferences(payload.references);
3892
+ setReferences(
3893
+ (previous) => payload.appendReferences ? mergeReferences(previous, nextReferences) : nextReferences
3894
+ );
3895
+ }
3896
+ if (payload.selectedToolId !== void 0) {
3897
+ const nextTool = payload.selectedToolId === null ? null : (composer?.tools ?? []).find(
3898
+ (tool) => tool.id === payload.selectedToolId
3899
+ ) ?? null;
3900
+ setSelectedTool(nextTool);
3901
+ }
3902
+ },
3903
+ [composer?.tools]
3904
+ ),
3905
+ onFocusComposer: React21.useCallback(() => {
3906
+ composerInputRef.current?.focus();
3907
+ }, [])
3908
+ });
3909
+ const syncQuoteSelection = React21.useCallback(() => {
3910
+ if (typeof window === "undefined") {
3911
+ clearQuoteSelection();
3912
+ return;
3913
+ }
3914
+ const selection = window.getSelection();
3915
+ if (!selection || selection.isCollapsed || selection.rangeCount === 0) {
3916
+ clearQuoteSelection();
3917
+ return;
3918
+ }
3919
+ const text = selection.toString().trim();
3920
+ if (!text) {
3921
+ clearQuoteSelection();
3922
+ return;
3923
+ }
3924
+ const anchorContainer = getClosestQuoteContainer(selection.anchorNode);
3925
+ const focusContainer = getClosestQuoteContainer(selection.focusNode);
3926
+ if (!anchorContainer || !focusContainer || anchorContainer !== focusContainer || !viewportRef.current?.contains(anchorContainer)) {
3927
+ clearQuoteSelection();
3928
+ return;
3929
+ }
3930
+ const range = selection.getRangeAt(0);
3931
+ const rect = range.getBoundingClientRect();
3932
+ if (rect.width === 0 && rect.height === 0) {
3933
+ clearQuoteSelection();
3934
+ return;
3935
+ }
3936
+ const top = rect.bottom + 8 > window.innerHeight - 48 ? Math.max(12, rect.top - 44) : rect.bottom + 8;
3937
+ const left = Math.min(
3938
+ Math.max(24, rect.left + rect.width / 2),
3939
+ window.innerWidth - 24
3940
+ );
3941
+ const source = anchorContainer.dataset.quoteSource?.trim() || void 0;
3942
+ const messageId = anchorContainer.dataset.quoteMessageId?.trim() || void 0;
3943
+ setQuoteSelection({
3944
+ reference: {
3945
+ type: "quote",
3946
+ text,
3947
+ ...messageId ? { messageId } : {},
3948
+ ...source ? { source, label: source } : {}
3949
+ },
3950
+ top,
3951
+ left
3952
+ });
3953
+ }, [clearQuoteSelection]);
3954
+ const cancelPendingAutoScroll = React21.useCallback(() => {
2974
3955
  if (autoScrollFrameRef.current !== null) {
2975
3956
  cancelAnimationFrame(autoScrollFrameRef.current);
2976
3957
  autoScrollFrameRef.current = null;
2977
3958
  }
2978
3959
  }, []);
2979
- const disableAutoFollow = React20.useCallback(() => {
3960
+ const disableAutoFollow = React21.useCallback(() => {
2980
3961
  forceFollowRef.current = false;
2981
3962
  shouldAutoScrollRef.current = false;
2982
3963
  cancelPendingAutoScroll();
2983
3964
  }, [cancelPendingAutoScroll]);
2984
- const enableAutoFollow = React20.useCallback(() => {
3965
+ const enableAutoFollow = React21.useCallback(() => {
2985
3966
  forceFollowRef.current = true;
2986
3967
  shouldAutoScrollRef.current = true;
2987
3968
  setHasUpdatesBelow(false);
2988
3969
  }, []);
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
- });
3970
+ const scrollToBottom = React21.useCallback(
3971
+ (smooth = false, force = false) => {
3972
+ if (force) {
3973
+ enableAutoFollow();
3005
3974
  }
3006
- });
3007
- }, [cancelPendingAutoScroll, enableAutoFollow]);
3008
- React20.useEffect(() => {
3975
+ cancelPendingAutoScroll();
3976
+ autoScrollFrameRef.current = requestAnimationFrame(() => {
3977
+ autoScrollFrameRef.current = null;
3978
+ const viewport = viewportRef.current;
3979
+ if (viewport) {
3980
+ if (!force && !shouldAutoScrollRef.current) {
3981
+ return;
3982
+ }
3983
+ viewport.scrollTo({
3984
+ top: viewport.scrollHeight,
3985
+ behavior: smooth ? "smooth" : "instant"
3986
+ });
3987
+ }
3988
+ });
3989
+ },
3990
+ [cancelPendingAutoScroll, enableAutoFollow]
3991
+ );
3992
+ React21.useEffect(() => {
3009
3993
  const viewport = viewportRef.current;
3010
3994
  if (!viewport) return;
3011
3995
  previousScrollTopRef.current = viewport.scrollTop;
@@ -3057,13 +4041,23 @@ function Chat({
3057
4041
  };
3058
4042
  updateAutoScrollState();
3059
4043
  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 });
4044
+ viewport.addEventListener("pointerdown", handlePointerDown, {
4045
+ passive: true
4046
+ });
4047
+ viewport.addEventListener("scroll", updateAutoScrollState, {
4048
+ passive: true
4049
+ });
4050
+ viewport.addEventListener("touchstart", handleTouchStart, {
4051
+ passive: true
4052
+ });
3063
4053
  viewport.addEventListener("touchmove", handleTouchMove, { passive: true });
3064
4054
  viewport.addEventListener("touchend", handleTouchEnd, { passive: true });
3065
- window.addEventListener("pointerup", stopPointerTracking, { passive: true });
3066
- window.addEventListener("pointercancel", stopPointerTracking, { passive: true });
4055
+ window.addEventListener("pointerup", stopPointerTracking, {
4056
+ passive: true
4057
+ });
4058
+ window.addEventListener("pointercancel", stopPointerTracking, {
4059
+ passive: true
4060
+ });
3067
4061
  return () => {
3068
4062
  cancelPendingAutoScroll();
3069
4063
  viewport.removeEventListener("wheel", handleWheel);
@@ -3076,14 +4070,14 @@ function Chat({
3076
4070
  window.removeEventListener("pointercancel", stopPointerTracking);
3077
4071
  };
3078
4072
  }, [cancelPendingAutoScroll, disableAutoFollow]);
3079
- React20.useEffect(() => {
4073
+ React21.useEffect(() => {
3080
4074
  shouldAutoScrollRef.current = true;
3081
4075
  forceFollowRef.current = false;
3082
4076
  previousScrollTopRef.current = 0;
3083
4077
  setIsAtBottom(true);
3084
4078
  setHasUpdatesBelow(false);
3085
4079
  }, [stream.threadId]);
3086
- React20.useEffect(() => {
4080
+ React21.useEffect(() => {
3087
4081
  const messageCountChanged = messages.length !== previousMessageCountRef.current;
3088
4082
  previousMessageCountRef.current = messages.length;
3089
4083
  if (!shouldAutoScrollRef.current) {
@@ -3097,16 +4091,85 @@ function Chat({
3097
4091
  }
3098
4092
  }, [stream.isLoading, messages, scrollToBottom]);
3099
4093
  const effectiveClientSecret = stream.apiKey?.trim() ? stream.apiKey : clientSecret;
3100
- const hasApiKey = Boolean(effectiveClientSecret.trim());
3101
- const missingConfig = !apiUrl || !hasApiKey;
4094
+ const missingConfigKind = getMissingApiConfigurationKind({
4095
+ apiUrl,
4096
+ clientSecret: effectiveClientSecret
4097
+ });
4098
+ const missingConfig = Boolean(missingConfigKind);
4099
+ const missingConfigShortMessage = React21.useMemo(() => {
4100
+ switch (missingConfigKind) {
4101
+ case "apiUrl":
4102
+ return t("chat.missingApiUrlShort");
4103
+ case "clientSecret":
4104
+ return t("chat.missingClientSecretShort");
4105
+ case "apiUrlAndClientSecret":
4106
+ return t("chat.missingApiUrlAndClientSecretShort");
4107
+ default:
4108
+ return t("chat.missingConfigShort");
4109
+ }
4110
+ }, [missingConfigKind, t]);
4111
+ const missingConfigDetailMessage = React21.useMemo(() => {
4112
+ switch (missingConfigKind) {
4113
+ case "apiUrl":
4114
+ return t("chat.missingApiUrlDetail");
4115
+ case "clientSecret":
4116
+ return t("chat.missingClientSecretDetail");
4117
+ case "apiUrlAndClientSecret":
4118
+ return t("chat.missingApiUrlAndClientSecretDetail");
4119
+ default:
4120
+ return t("chat.missingConfigDetail");
4121
+ }
4122
+ }, [missingConfigKind, t]);
3102
4123
  const showMissingConfig = !isClientSecretInitializing && missingConfig;
3103
4124
  const hasUploadingFiles = attachments.some((a) => a.status === "uploading");
3104
- const isSendDisabled = !trimmedDraft || stream.isLoading || missingConfig || isHistoryLoading || hasUploadingFiles;
3105
- React20.useEffect(() => {
4125
+ const isSendDisabled = !trimmedDraft && !hasReferences || missingConfig || isHistoryLoading || hasUploadingFiles;
4126
+ const resizeComposerInput = React21.useCallback(() => {
4127
+ const textarea = composerInputRef.current;
4128
+ if (!textarea) {
4129
+ return;
4130
+ }
4131
+ textarea.style.height = "auto";
4132
+ const nextHeight = Math.min(
4133
+ textarea.scrollHeight,
4134
+ COMPOSER_INPUT_MAX_HEIGHT
4135
+ );
4136
+ textarea.style.height = `${nextHeight}px`;
4137
+ textarea.style.overflowY = textarea.scrollHeight > COMPOSER_INPUT_MAX_HEIGHT ? "auto" : "hidden";
4138
+ }, []);
4139
+ React21.useEffect(() => {
4140
+ resizeComposerInput();
4141
+ }, [draft, resizeComposerInput]);
4142
+ React21.useEffect(() => {
4143
+ document.addEventListener("selectionchange", syncQuoteSelection);
4144
+ return () => {
4145
+ document.removeEventListener("selectionchange", syncQuoteSelection);
4146
+ };
4147
+ }, [syncQuoteSelection]);
4148
+ React21.useEffect(() => {
4149
+ const viewport = viewportRef.current;
4150
+ if (!viewport) {
4151
+ return;
4152
+ }
4153
+ const handleViewportScroll = () => {
4154
+ clearQuoteSelection();
4155
+ };
4156
+ viewport.addEventListener("scroll", handleViewportScroll, {
4157
+ passive: true
4158
+ });
4159
+ window.addEventListener("resize", handleViewportScroll, { passive: true });
4160
+ return () => {
4161
+ viewport.removeEventListener("scroll", handleViewportScroll);
4162
+ window.removeEventListener("resize", handleViewportScroll);
4163
+ };
4164
+ }, [clearQuoteSelection]);
4165
+ React21.useEffect(() => {
4166
+ clearQuoteSelection();
4167
+ }, [messages.length, stream.threadId, clearQuoteSelection]);
4168
+ React21.useEffect(() => {
3106
4169
  if (missingConfig) return;
3107
4170
  void refreshThreads();
3108
4171
  }, [missingConfig, refreshThreads]);
3109
- React20.useEffect(() => {
4172
+ React21.useEffect(() => {
3110
4173
  if (missingConfig || !stream.client || !stream.assistantId) {
3111
4174
  setAssistantName(null);
3112
4175
  setAssistantAvatar(null);
@@ -3137,80 +4200,186 @@ function Chat({
3137
4200
  mimetype: a.storageFile?.mimetype ?? a.file.type,
3138
4201
  size: a.storageFile?.size ?? a.file.size
3139
4202
  }));
4203
+ const submitDraft = React21.useCallback(
4204
+ (followUpOverride) => {
4205
+ if (isSendDisabled) return;
4206
+ const filesToSend = uploadedFiles.length > 0 ? [...uploadedFiles] : void 0;
4207
+ const referencesToSend = references.length > 0 ? [...references] : void 0;
4208
+ const nextFollowUpMode = stream.isLoading ? followUpOverride ?? stream.followUpBehavior : void 0;
4209
+ const humanInput = buildHumanMessageInputPayload({
4210
+ content: trimmedDraft,
4211
+ references: referencesToSend
4212
+ });
4213
+ if (!humanInput) {
4214
+ return;
4215
+ }
4216
+ const displayContent = trimmedDraft || (referencesToSend ? t("chat.referencedContentOnly") : "");
4217
+ const newMessage = {
4218
+ id: createMessageId(),
4219
+ type: "human",
4220
+ content: displayContent,
4221
+ submittedInput: humanInput.input,
4222
+ ...humanInput.referenceComposition ? { referenceComposition: humanInput.referenceComposition } : {},
4223
+ ...filesToSend ? { attachments: filesToSend } : {},
4224
+ ...referencesToSend ? { references: referencesToSend } : {}
4225
+ };
4226
+ setDraft("");
4227
+ const inputPayload = {
4228
+ ...humanInput
4229
+ };
4230
+ if (filesToSend) {
4231
+ inputPayload.files = filesToSend;
4232
+ }
4233
+ const requestOptions = buildInjectedRequestOptions({
4234
+ defaults: options?.request,
4235
+ humanInput: inputPayload
4236
+ });
4237
+ stream.submit(
4238
+ {
4239
+ input: inputPayload,
4240
+ ...requestOptions.state ? { state: requestOptions.state } : {}
4241
+ },
4242
+ {
4243
+ ...nextFollowUpMode ? { followUpMode: nextFollowUpMode } : {},
4244
+ ...requestOptions.context ? { context: requestOptions.context } : {},
4245
+ ...requestOptions.config ? { config: requestOptions.config } : {},
4246
+ ...!nextFollowUpMode ? {
4247
+ optimisticValues: (prev) => {
4248
+ const prevMessages = prev?.messages ?? [];
4249
+ return { ...prev, messages: [...prevMessages, newMessage] };
4250
+ }
4251
+ } : {}
4252
+ }
4253
+ );
4254
+ scrollToBottom(true, true);
4255
+ if (selectedTool && !selectedTool.pinned) {
4256
+ setSelectedTool(null);
4257
+ }
4258
+ setAttachments([]);
4259
+ setReferences([]);
4260
+ },
4261
+ [
4262
+ isSendDisabled,
4263
+ options?.request,
4264
+ references,
4265
+ scrollToBottom,
4266
+ selectedTool,
4267
+ stream,
4268
+ trimmedDraft,
4269
+ uploadedFiles,
4270
+ t
4271
+ ]
4272
+ );
3140
4273
  const handleSubmit = (event) => {
3141
4274
  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
- }
4275
+ submitDraft();
4276
+ };
4277
+ const handleEditPendingFollowUp = React21.useCallback(
4278
+ (id) => {
4279
+ const item = pendingFollowUps.find(
4280
+ (entry) => entry.id === id && entry.mode === "queue"
4281
+ );
4282
+ if (!item) {
4283
+ return;
3173
4284
  }
4285
+ const text = item.request?.input?.input?.trim() ?? "";
4286
+ const nextReferences = normalizeReferences(
4287
+ item.request?.input?.references
4288
+ );
4289
+ stream.removePendingFollowUp(id);
4290
+ setDraft(text);
4291
+ setReferences(nextReferences);
4292
+ requestAnimationFrame(() => {
4293
+ const input = composerInputRef.current;
4294
+ if (!input) {
4295
+ return;
4296
+ }
4297
+ input.focus();
4298
+ const position = text.length;
4299
+ input.setSelectionRange(position, position);
4300
+ });
4301
+ },
4302
+ [pendingFollowUps, stream]
4303
+ );
4304
+ const handleQuoteSelection = React21.useCallback(() => {
4305
+ if (!quoteSelection) {
4306
+ return;
4307
+ }
4308
+ setReferences(
4309
+ (previous) => mergeReferences(previous, [quoteSelection.reference])
3174
4310
  );
3175
- scrollToBottom(true, true);
3176
- if (selectedTool && !selectedTool.pinned) {
3177
- setSelectedTool(null);
4311
+ clearQuoteSelection();
4312
+ if (typeof window !== "undefined") {
4313
+ window.getSelection()?.removeAllRanges();
3178
4314
  }
3179
- setAttachments([]);
3180
- };
4315
+ composerInputRef.current?.focus();
4316
+ }, [clearQuoteSelection, quoteSelection]);
3181
4317
  const handleAttachmentClick = () => {
3182
4318
  fileInputRef.current?.click();
3183
4319
  };
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
- )
3191
- );
3192
- } catch (error) {
4320
+ const handleComposerKeyDown = (event) => {
4321
+ if (event.key !== "Enter") {
4322
+ return;
4323
+ }
4324
+ if (event.shiftKey && (event.metaKey || event.ctrlKey)) {
4325
+ if (event.nativeEvent.isComposing) {
4326
+ return;
4327
+ }
4328
+ event.preventDefault();
4329
+ if (isSendDisabled) {
4330
+ return;
4331
+ }
4332
+ submitDraft(stream.followUpBehavior === "queue" ? "steer" : "queue");
4333
+ return;
4334
+ }
4335
+ if (event.shiftKey) {
4336
+ return;
4337
+ }
4338
+ if (event.nativeEvent.isComposing) {
4339
+ return;
4340
+ }
4341
+ event.preventDefault();
4342
+ if (isSendDisabled) {
4343
+ return;
4344
+ }
4345
+ submitDraft();
4346
+ };
4347
+ const uploadFile = React21.useCallback(
4348
+ async (localId, file) => {
4349
+ try {
4350
+ const result = await stream.client.contexts.uploadFile(file);
4351
+ setAttachments(
4352
+ (prev) => prev.map(
4353
+ (item) => item.localId === localId ? { ...item, status: "success", storageFile: result } : item
4354
+ )
4355
+ );
4356
+ } catch (error) {
4357
+ setAttachments(
4358
+ (prev) => prev.map(
4359
+ (item) => item.localId === localId ? {
4360
+ ...item,
4361
+ status: "error",
4362
+ error: error instanceof Error ? error.message : "Upload failed"
4363
+ } : item
4364
+ )
4365
+ );
4366
+ }
4367
+ },
4368
+ [stream.client]
4369
+ );
4370
+ const handleRetryUpload = React21.useCallback(
4371
+ (localId) => {
4372
+ const attachment = attachments.find((a) => a.localId === localId);
4373
+ if (!attachment || attachment.status !== "error") return;
3193
4374
  setAttachments(
3194
4375
  (prev) => prev.map(
3195
- (item) => item.localId === localId ? {
3196
- ...item,
3197
- status: "error",
3198
- error: error instanceof Error ? error.message : "Upload failed"
3199
- } : item
4376
+ (item) => item.localId === localId ? { ...item, status: "uploading", error: void 0 } : item
3200
4377
  )
3201
4378
  );
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]);
4379
+ void uploadFile(localId, attachment.file);
4380
+ },
4381
+ [attachments, uploadFile]
4382
+ );
3214
4383
  const handleFileChange = (event) => {
3215
4384
  const files = event.target.files;
3216
4385
  if (!files || files.length === 0) return;
@@ -3244,12 +4413,15 @@ function Chat({
3244
4413
  if (!attachment) return;
3245
4414
  if (attachment.status === "success" && attachment.storageFile?.id) {
3246
4415
  try {
3247
- await fetch(`${stream.apiUrl}/contexts/file/${attachment.storageFile.id}`, {
3248
- method: "DELETE",
3249
- headers: {
3250
- "Authorization": `Bearer ${effectiveClientSecret}`
4416
+ await fetch(
4417
+ `${stream.apiUrl}/contexts/file/${attachment.storageFile.id}`,
4418
+ {
4419
+ method: "DELETE",
4420
+ headers: {
4421
+ Authorization: `Bearer ${effectiveClientSecret}`
4422
+ }
3251
4423
  }
3252
- });
4424
+ );
3253
4425
  } catch {
3254
4426
  }
3255
4427
  }
@@ -3259,27 +4431,31 @@ function Chat({
3259
4431
  setSelectedTool((prev) => prev?.id === tool.id ? null : tool);
3260
4432
  };
3261
4433
  const handlePromptClick = (prompt) => {
3262
- if (missingConfig || stream.isLoading || isHistoryLoading) return;
4434
+ if (missingConfig || isHistoryLoading) return;
3263
4435
  const newMessage = {
3264
4436
  id: createMessageId(),
3265
4437
  type: "human",
3266
4438
  content: prompt
3267
4439
  };
4440
+ const nextFollowUpMode = stream.isLoading ? stream.followUpBehavior : void 0;
3268
4441
  stream.submit(
3269
4442
  { input: { input: prompt } },
3270
4443
  {
3271
- optimisticValues: (prev) => {
3272
- const prevMessages = prev?.messages ?? [];
3273
- return { ...prev, messages: [...prevMessages, newMessage] };
3274
- }
4444
+ ...nextFollowUpMode ? { followUpMode: nextFollowUpMode } : {},
4445
+ ...!nextFollowUpMode ? {
4446
+ optimisticValues: (prev) => {
4447
+ const prevMessages = prev?.messages ?? [];
4448
+ return { ...prev, messages: [...prevMessages, newMessage] };
4449
+ }
4450
+ } : {}
3275
4451
  }
3276
4452
  );
3277
4453
  scrollToBottom(true, true);
3278
4454
  };
3279
- const loadConversationMessages = React20.useCallback(
4455
+ const loadConversationMessages = React21.useCallback(
3280
4456
  async (recordId) => {
3281
4457
  if (missingConfig) {
3282
- setHistoryError(t("chat.missingConfigShort"));
4458
+ setHistoryError(missingConfigShortMessage);
3283
4459
  return;
3284
4460
  }
3285
4461
  setHistoryError(null);
@@ -3295,7 +4471,7 @@ function Chat({
3295
4471
  setIsHistoryLoading(false);
3296
4472
  }
3297
4473
  },
3298
- [missingConfig, stream, t]
4474
+ [missingConfig, missingConfigShortMessage, stream, t]
3299
4475
  );
3300
4476
  const handleNewThread = async () => {
3301
4477
  if (missingConfig || isHistoryLoading) return;
@@ -3338,12 +4514,16 @@ function Chat({
3338
4514
  };
3339
4515
  const handleRetry = (messageIndex) => {
3340
4516
  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") {
4517
+ const lastHumanMessage = [...messagesUpToIndex].reverse().find((m) => String(m.type) === "human");
4518
+ const humanInput = buildHumanMessageInputPayload({
4519
+ content: lastHumanMessage && typeof lastHumanMessage.content === "string" ? lastHumanMessage.content : "",
4520
+ submittedInput: lastHumanMessage?.submittedInput,
4521
+ references: lastHumanMessage?.references,
4522
+ referenceComposition: lastHumanMessage?.referenceComposition
4523
+ });
4524
+ if (humanInput) {
3345
4525
  stream.submit(
3346
- { input: { input: lastHumanMessage.content } },
4526
+ { input: humanInput },
3347
4527
  {
3348
4528
  optimisticValues: (prev) => {
3349
4529
  const prevMessages = prev?.messages ?? [];
@@ -3358,18 +4538,18 @@ function Chat({
3358
4538
  }
3359
4539
  };
3360
4540
  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(
4541
+ const currentThread = React21.useMemo(
3362
4542
  () => threads.find((item) => item.id === stream.threadId),
3363
4543
  [threads, stream.threadId]
3364
4544
  );
3365
4545
  const errorMessage = stream.error instanceof Error ? stream.error.message : void 0;
3366
- const threadErrorMessage = React20.useMemo(() => {
4546
+ const threadErrorMessage = React21.useMemo(() => {
3367
4547
  if (currentThread?.status !== "error") return void 0;
3368
4548
  const message = currentThread.error?.trim();
3369
4549
  return message || t("thread.errorToast");
3370
4550
  }, [currentThread, t]);
3371
4551
  const assistantTitle = assistantName || resolvedTitle;
3372
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4552
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3373
4553
  "div",
3374
4554
  {
3375
4555
  ref: viewportRef,
@@ -3378,10 +4558,10 @@ function Chat({
3378
4558
  className
3379
4559
  ),
3380
4560
  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)(
4561
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between border-b p-2 sticky top-0 z-10 bg-background", children: [
4562
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-3 overflow-hidden", children: [
4563
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "relative shrink-0", children: [
4564
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3385
4565
  ChatkitAvatar,
3386
4566
  {
3387
4567
  avatar: assistantAvatar,
@@ -3389,15 +4569,22 @@ function Chat({
3389
4569
  label: assistantTitle
3390
4570
  }
3391
4571
  ),
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" })
4572
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
3393
4573
  ] }),
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") })
4574
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "truncate", children: [
4575
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4576
+ "h2",
4577
+ {
4578
+ className: "text-lg font-semibold truncate",
4579
+ title: assistantTitle,
4580
+ children: assistantTitle
4581
+ }
4582
+ ),
4583
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs text-muted-foreground", children: t("chat.statusOnline") })
3397
4584
  ] })
3398
4585
  ] }),
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)(
4586
+ history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-1", children: [
4587
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3401
4588
  "button",
3402
4589
  {
3403
4590
  type: "button",
@@ -3410,10 +4597,10 @@ function Chat({
3410
4597
  "disabled:opacity-50 disabled:cursor-not-allowed"
3411
4598
  ),
3412
4599
  title: t("history.newThread"),
3413
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.Pencil, { size: 16 })
4600
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.Pencil, { size: 16 })
3414
4601
  }
3415
4602
  ),
3416
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4603
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3417
4604
  HistorySidebar,
3418
4605
  {
3419
4606
  threads,
@@ -3427,23 +4614,45 @@ function Chat({
3427
4614
  )
3428
4615
  ] })
3429
4616
  ] }),
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)(
4617
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 p-4", children: [
4618
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
4619
+ historyError && /* @__PURE__ */ (0, import_jsx_runtime27.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 }),
4620
+ showMissingConfig && /* @__PURE__ */ (0, import_jsx_runtime27.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 }),
4621
+ isHistoryLoading && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
4622
+ messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3436
4623
  StartScreen,
3437
4624
  {
3438
4625
  startScreen,
3439
4626
  onPromptClick: handlePromptClick
3440
4627
  }
3441
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
4628
+ ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "space-y-4", children: [
3442
4629
  messages.map((message, index) => {
3443
4630
  const messageType = String(message.type);
3444
4631
  const isAssistantMessage = messageType === "assistant" || messageType === "ai";
4632
+ const isStreamingMessage = stream.isLoading && index === messages.length - 1;
4633
+ const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
4634
+ {
4635
+ ...message,
4636
+ lastStreamOutputAt: lastStreamOutputAtRef.current
4637
+ },
4638
+ isStreamingMessage,
4639
+ { now: streamingNow }
4640
+ ) : null;
4641
+ if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
4642
+ return null;
4643
+ }
3445
4644
  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)(
4645
+ const hasPlainRenderableContent = messageContent.trim().length > 0;
4646
+ const humanMessage = message;
4647
+ const humanReferences = humanMessage.references ?? [];
4648
+ const humanAttachments = humanMessage.attachments ?? [];
4649
+ const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
4650
+ const canQuoteMessage = message.type === "human" || isAssistantMessage;
4651
+ const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
4652
+ if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanReferences.length === 0) {
4653
+ return null;
4654
+ }
4655
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3447
4656
  "div",
3448
4657
  {
3449
4658
  className: cn(
@@ -3451,53 +4660,66 @@ function Chat({
3451
4660
  message.type === "human" ? "justify-end" : "justify-start -ml-1"
3452
4661
  // AI messages: slightly closer to left
3453
4662
  ),
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)(
4663
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col px-3 overflow-hidden", children: [
4664
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3456
4665
  "div",
3457
4666
  {
4667
+ ...canQuoteMessage ? {
4668
+ "data-quote-message-id": message.id,
4669
+ "data-quote-source": quoteSource
4670
+ } : {},
3458
4671
  className: cn(
3459
4672
  "max-w-full rounded-2xl",
3460
4673
  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
4674
  // AI messages: use chat-specific foreground color
3462
4675
  ),
3463
- children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4676
+ children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3464
4677
  AssistantMessage,
3465
4678
  {
3466
4679
  message: {
3467
4680
  ...message,
3468
4681
  type: "assistant"
3469
4682
  },
3470
- isStreaming: stream.isLoading && index === messages.length - 1
4683
+ isStreaming: isStreamingMessage,
4684
+ streamingStatus
3471
4685
  }
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)(
4686
+ ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
4687
+ message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4688
+ ReferenceChip,
4689
+ {
4690
+ reference,
4691
+ variant: "message"
4692
+ },
4693
+ getReferenceKey(reference)
4694
+ )) }),
4695
+ message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3474
4696
  "div",
3475
4697
  {
3476
4698
  className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
3477
4699
  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 })
4700
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.FileText, { size: 12 }),
4701
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName })
3480
4702
  ]
3481
4703
  },
3482
4704
  fileIndex
3483
4705
  )) }),
3484
- Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4706
+ Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3485
4707
  "p",
3486
4708
  {
3487
4709
  className: "wrap-break-word text-sm leading-relaxed",
3488
4710
  children: formatMessageContent(part)
3489
4711
  },
3490
4712
  `${part.type}-${partIndex}`
3491
- )) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
4713
+ )) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
3492
4714
  ] })
3493
4715
  }
3494
4716
  ),
3495
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4717
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3496
4718
  MessageActions,
3497
4719
  {
3498
4720
  content: messageContent,
3499
4721
  isAssistant: isAssistantMessage,
3500
- isStreaming: stream.isLoading && index === messages.length - 1,
4722
+ isStreaming: isStreamingMessage,
3501
4723
  onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
3502
4724
  }
3503
4725
  )
@@ -3510,18 +4732,34 @@ function Chat({
3510
4732
  const lastMessage = messages[messages.length - 1];
3511
4733
  const lastMessageType = lastMessage ? String(lastMessage.type) : "";
3512
4734
  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
- ] }) }) });
4735
+ const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
4736
+ {
4737
+ ...lastMessage,
4738
+ lastStreamOutputAt: lastStreamOutputAtRef.current
4739
+ },
4740
+ stream.isLoading,
4741
+ { now: streamingNow }
4742
+ ) : null;
4743
+ if (lastAssistantStatus) return null;
4744
+ const fallbackStreamingStatus = getAssistantStreamingStatus(
4745
+ {
4746
+ status: void 0,
4747
+ reasoning: void 0,
4748
+ lastStreamOutputAt: lastStreamOutputAtRef.current
4749
+ },
4750
+ stream.isLoading,
4751
+ { now: streamingNow }
4752
+ );
4753
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4754
+ AssistantStreamingIndicator,
4755
+ {
4756
+ status: fallbackStreamingStatus ?? "loading"
4757
+ }
4758
+ ) }) });
3521
4759
  })()
3522
4760
  ] })
3523
4761
  ] }),
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)(
4762
+ !isAtBottom && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3525
4763
  Button,
3526
4764
  {
3527
4765
  type: "button",
@@ -3534,12 +4772,40 @@ function Chat({
3534
4772
  onClick: () => scrollToBottom(true, true),
3535
4773
  "aria-label": t("chat.scrollToBottom"),
3536
4774
  title: t("chat.scrollToBottom"),
3537
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.ArrowDown, { size: 16 })
4775
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.ArrowDown, { size: 16 })
3538
4776
  }
3539
4777
  ) }),
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)(
4778
+ quoteSelection && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4779
+ "div",
4780
+ {
4781
+ className: "pointer-events-none fixed z-50",
4782
+ style: {
4783
+ top: `${quoteSelection.top}px`,
4784
+ left: `${quoteSelection.left}px`,
4785
+ transform: "translateX(-50%)"
4786
+ },
4787
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
4788
+ Button,
4789
+ {
4790
+ type: "button",
4791
+ size: "sm",
4792
+ variant: "secondary",
4793
+ className: "pointer-events-auto shadow-lg",
4794
+ onMouseDown: (event) => event.preventDefault(),
4795
+ onClick: handleQuoteSelection,
4796
+ "aria-label": t("composer.quoteSelection"),
4797
+ title: t("composer.quoteSelection"),
4798
+ children: [
4799
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.Quote, { size: 14 }),
4800
+ t("composer.quoteSelection")
4801
+ ]
4802
+ }
4803
+ )
4804
+ }
4805
+ ),
4806
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "p-2 sticky bottom-0 z-10 bg-background", children: [
4807
+ threadErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime27.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 }),
4808
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3543
4809
  "input",
3544
4810
  {
3545
4811
  ref: fileInputRef,
@@ -3550,7 +4816,7 @@ function Chat({
3550
4816
  className: "hidden"
3551
4817
  }
3552
4818
  ),
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)(
4819
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: attachments.map((item) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3554
4820
  "div",
3555
4821
  {
3556
4822
  className: cn(
@@ -3558,24 +4824,36 @@ function Chat({
3558
4824
  item.status === "error" ? "bg-destructive/10 border border-destructive/30" : "bg-muted"
3559
4825
  ),
3560
4826
  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)(
4827
+ item.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4828
+ import_lucide_react10.Loader2,
4829
+ {
4830
+ size: 14,
4831
+ className: "animate-spin text-muted-foreground"
4832
+ }
4833
+ ),
4834
+ item.status === "success" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.FileText, { size: 14, className: "text-muted-foreground" }),
4835
+ item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.FileText, { size: 14, className: "text-destructive" }),
4836
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4837
+ "span",
4838
+ {
4839
+ className: cn(
4840
+ "max-w-30 truncate",
4841
+ item.status === "error" && "text-destructive"
4842
+ ),
4843
+ children: item.file.name
4844
+ }
4845
+ ),
4846
+ item.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3569
4847
  "button",
3570
4848
  {
3571
4849
  type: "button",
3572
4850
  onClick: () => handleRetryUpload(item.localId),
3573
4851
  className: "ml-1 rounded-full p-0.5 text-destructive hover:bg-destructive/20",
3574
4852
  title: t("chat.retryUpload"),
3575
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.RefreshCw, { size: 12 })
4853
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.RefreshCw, { size: 12 })
3576
4854
  }
3577
4855
  ),
3578
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4856
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3579
4857
  "button",
3580
4858
  {
3581
4859
  type: "button",
@@ -3584,67 +4862,98 @@ function Chat({
3584
4862
  "ml-1 rounded-full p-0.5",
3585
4863
  item.status === "error" ? "text-destructive hover:bg-destructive/20" : "hover:bg-muted-foreground/20"
3586
4864
  ),
3587
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react9.X, { size: 12 })
4865
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.X, { size: 12 })
3588
4866
  }
3589
4867
  )
3590
4868
  ]
3591
4869
  },
3592
4870
  item.localId
3593
4871
  )) }),
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)(
4872
+ references.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4873
+ ReferenceChip,
4874
+ {
4875
+ reference,
4876
+ variant: "composer",
4877
+ onRemove: () => setReferences(
4878
+ (previous) => previous.filter(
4879
+ (item) => getReferenceKey(item) !== getReferenceKey(reference)
4880
+ )
4881
+ ),
4882
+ removeLabel: t("composer.removeReference")
4883
+ },
4884
+ getReferenceKey(reference)
4885
+ )) }),
4886
+ selectedTool && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "mb-2 flex items-center gap-2", children: [
4887
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-xs font-medium text-primary", children: selectedTool.shortLabel ?? selectedTool.label }),
4888
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3597
4889
  "button",
3598
4890
  {
3599
4891
  type: "button",
3600
4892
  onClick: () => setSelectedTool(null),
3601
4893
  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 })
4894
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react10.X, { size: 12 })
3603
4895
  }
3604
4896
  )
3605
4897
  ] }),
3606
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("form", { className: "flex items-center", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4898
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4899
+ PendingFollowUps,
4900
+ {
4901
+ items: pendingFollowUps,
4902
+ isLoading: stream.isLoading,
4903
+ followUpBehavior: stream.followUpBehavior,
4904
+ onBehaviorChange: stream.setFollowUpBehavior,
4905
+ onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
4906
+ canSendNow: stream.canSendPendingFollowUpNow,
4907
+ onSendNow: (id) => stream.sendPendingFollowUpNow(id),
4908
+ onEdit: handleEditPendingFollowUp,
4909
+ onRemove: stream.removePendingFollowUp
4910
+ }
4911
+ ),
4912
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
3607
4913
  "div",
3608
4914
  {
3609
4915
  className: cn(
3610
- "flex flex-1 items-center gap-1 rounded-xl",
4916
+ "flex flex-1 items-end gap-1 rounded-xl",
3611
4917
  "bg-background border border-border shadow-sm",
3612
4918
  "pl-1.5 pr-1.5 py-1",
3613
4919
  "focus-within:border-muted-foreground/30 focus-within:shadow-md",
3614
- "transition-shadow duration-200"
4920
+ "transition-shadow duration-200",
4921
+ getRoundedClass(theme.radius)
3615
4922
  ),
3616
4923
  children: [
3617
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4924
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3618
4925
  ComposerMenu,
3619
4926
  {
3620
4927
  composer,
3621
4928
  onAttachmentClick: handleAttachmentClick,
3622
4929
  onToolSelect: handleToolSelect,
3623
4930
  selectedTool,
3624
- disabled: stream.isLoading || missingConfig || isHistoryLoading
4931
+ disabled: missingConfig || isHistoryLoading
3625
4932
  }
3626
4933
  ),
3627
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3628
- "input",
4934
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4935
+ "textarea",
3629
4936
  {
3630
- type: "text",
4937
+ ref: composerInputRef,
3631
4938
  value: draft,
3632
4939
  onChange: (event) => setDraft(event.target.value),
4940
+ onKeyDown: handleComposerKeyDown,
4941
+ rows: 1,
3633
4942
  placeholder: inputPlaceholder,
3634
- disabled: stream.isLoading || missingConfig || isHistoryLoading,
4943
+ disabled: missingConfig || isHistoryLoading,
3635
4944
  className: cn(
3636
- "flex-1 bg-transparent text-sm text-foreground outline-none pr-2",
4945
+ "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
4946
  "placeholder:text-muted-foreground",
3638
4947
  "disabled:cursor-not-allowed disabled:opacity-50"
3639
- ),
3640
- autoComplete: "off"
4948
+ )
3641
4949
  }
3642
4950
  ),
3643
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4951
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3644
4952
  SendButton,
3645
4953
  {
3646
4954
  disabled: isSendDisabled,
3647
4955
  isLoading: stream.isLoading,
4956
+ showStop: stream.isLoading && !trimmedDraft,
3648
4957
  onStop: () => stream.stop(),
3649
4958
  stopLabel: t("chat.stop"),
3650
4959
  sendLabel: t("chat.send")
@@ -3653,7 +4962,7 @@ function Chat({
3653
4962
  ]
3654
4963
  }
3655
4964
  ) }),
3656
- disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4965
+ disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3657
4966
  "p",
3658
4967
  {
3659
4968
  className: cn(
@@ -3663,9 +4972,9 @@ function Chat({
3663
4972
  children: disclaimer.text
3664
4973
  }
3665
4974
  ),
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" })
4975
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
4976
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: t("chat.poweredBy") }),
4977
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
3669
4978
  ] })
3670
4979
  ] })
3671
4980
  ]
@@ -3674,11 +4983,11 @@ function Chat({
3674
4983
  }
3675
4984
 
3676
4985
  // 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(
4986
+ var React22 = __toESM(require("react"), 1);
4987
+ var import_jsx_runtime28 = require("react/jsx-runtime");
4988
+ var Input = React22.forwardRef(
3680
4989
  ({ className, type, ...props }, ref) => {
3681
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4990
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3682
4991
  "input",
3683
4992
  {
3684
4993
  ref,
@@ -3695,10 +5004,10 @@ var Input = React21.forwardRef(
3695
5004
  Input.displayName = "Input";
3696
5005
 
3697
5006
  // 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)(
5007
+ var React23 = __toESM(require("react"), 1);
5008
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5009
+ var Separator = React23.forwardRef(
5010
+ ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3702
5011
  "div",
3703
5012
  {
3704
5013
  ref,