@xpert-ai/chatkit-ui 0.4.7 → 0.4.9

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 (337) hide show
  1. package/dist/app/assets/{_baseUniq-zhZsBqC1.js → _baseUniq-CvUv2HwQ.js} +1 -1
  2. package/dist/app/assets/{abap-C1NkPSGQ.js → abap-BO7niWiC.js} +1 -1
  3. package/dist/app/assets/{abnf-JbwQvl8G.js → abnf-CWEz7Drs.js} +1 -1
  4. package/dist/app/assets/{actionscript-DmGKVMdE.js → actionscript-CyOkZZxh.js} +1 -1
  5. package/dist/app/assets/{ada-BFUkZTyl.js → ada-Jlv844Rv.js} +1 -1
  6. package/dist/app/assets/{agda-DaMAzqVU.js → agda-C_kFG5ee.js} +1 -1
  7. package/dist/app/assets/{al-BJTYBSmw.js → al-BJB3bCYn.js} +1 -1
  8. package/dist/app/assets/{antlr4-Dp3xUyR5.js → antlr4-CxC5pLeu.js} +1 -1
  9. package/dist/app/assets/{apacheconf-CNs6LiCv.js → apacheconf-Do-yEyZc.js} +1 -1
  10. package/dist/app/assets/{apex-Cb-6Ow2z.js → apex-_x2gfDUc.js} +1 -1
  11. package/dist/app/assets/{apl-Caij2pyM.js → apl-CV7O96Vz.js} +1 -1
  12. package/dist/app/assets/{applescript-Za6DtdYI.js → applescript-BBZjdzgl.js} +1 -1
  13. package/dist/app/assets/{aql-rq-zV86w.js → aql-CPRi8JU5.js} +1 -1
  14. package/dist/app/assets/{arc-OYw_1mUi.js → arc-COu-nBNR.js} +1 -1
  15. package/dist/app/assets/{architectureDiagram-Q4EWVU46-DB9yrqvi.js → architectureDiagram-Q4EWVU46-D-ddveKc.js} +1 -1
  16. package/dist/app/assets/{arduino-BaodkhmL.js → arduino-B_V9Srpy.js} +1 -1
  17. package/dist/app/assets/{arff-CtdflkdY.js → arff-DsGhNcbT.js} +1 -1
  18. package/dist/app/assets/{asciidoc-YRCvqvDt.js → asciidoc-B5CEO5fh.js} +1 -1
  19. package/dist/app/assets/{asm6502-DQmj6WYF.js → asm6502-D2a8tVul.js} +1 -1
  20. package/dist/app/assets/{asmatmel-B_b34PU9.js → asmatmel-DUTqaTnC.js} +1 -1
  21. package/dist/app/assets/{aspnet-DikoFau7.js → aspnet-DLUpHuHv.js} +1 -1
  22. package/dist/app/assets/{autohotkey-DtLs5eHy.js → autohotkey-BSB_nyws.js} +1 -1
  23. package/dist/app/assets/{autoit-CV5yNCU9.js → autoit-BwgYwpuM.js} +1 -1
  24. package/dist/app/assets/{avisynth-Cvl9Dxbj.js → avisynth-Cgf1pYso.js} +1 -1
  25. package/dist/app/assets/{avro-idl-CHxahZY6.js → avro-idl-XqteGdRE.js} +1 -1
  26. package/dist/app/assets/{bash-B5Db2471.js → bash-Dk281cbu.js} +1 -1
  27. package/dist/app/assets/{basic-SxMwItEb.js → basic-uRpIiMGe.js} +1 -1
  28. package/dist/app/assets/{batch-BBcoFjlC.js → batch-C4-m-mLr.js} +1 -1
  29. package/dist/app/assets/{bbcode-BjiejoUJ.js → bbcode-B1LUoNFx.js} +1 -1
  30. package/dist/app/assets/{bicep-KsVmEn1g.js → bicep-CqsJcsXf.js} +1 -1
  31. package/dist/app/assets/{birb-B8jRVP3x.js → birb-DXU3R8QI.js} +1 -1
  32. package/dist/app/assets/{bison-CCal2Z3u.js → bison-BLjm1RgB.js} +1 -1
  33. package/dist/app/assets/{blockDiagram-DXYQGD6D-4aEcQrY2.js → blockDiagram-DXYQGD6D-BHxMFapA.js} +1 -1
  34. package/dist/app/assets/{bnf-D9700Acc.js → bnf-D-7oTwhm.js} +1 -1
  35. package/dist/app/assets/{brainfuck-D8nhdXqW.js → brainfuck-I-YgfuEr.js} +1 -1
  36. package/dist/app/assets/{brightscript-Dj-vu9BW.js → brightscript-CkF_ucD-.js} +1 -1
  37. package/dist/app/assets/{bro-Cd22dEet.js → bro-CPPYpjZw.js} +1 -1
  38. package/dist/app/assets/{bsl-glz5E-bI.js → bsl-CVgUnXO6.js} +1 -1
  39. package/dist/app/assets/{c-BT_dkbEx.js → c-BS7yj6Yf.js} +1 -1
  40. package/dist/app/assets/{c4Diagram-AHTNJAMY-k4XfyLu9.js → c4Diagram-AHTNJAMY-BuCOREEO.js} +1 -1
  41. package/dist/app/assets/{cfscript-C3JXuiQs.js → cfscript-CIVISA6c.js} +1 -1
  42. package/dist/app/assets/{chaiscript-CtAXHhN2.js → chaiscript-DPJ77ndP.js} +1 -1
  43. package/dist/app/assets/channel-DqqmKvlV.js +1 -0
  44. package/dist/app/assets/{chunk-4BX2VUAB-ufyL9ML5.js → chunk-4BX2VUAB-C9mHTP0m.js} +1 -1
  45. package/dist/app/assets/{chunk-4TB4RGXK-BcWB3V7R.js → chunk-4TB4RGXK-B9VoBVJp.js} +1 -1
  46. package/dist/app/assets/{chunk-55IACEB6-B-bXUWk6.js → chunk-55IACEB6-N4Q-mlk6.js} +1 -1
  47. package/dist/app/assets/{chunk-EDXVE4YY-Sb8Q75g2.js → chunk-EDXVE4YY-D-MWM76q.js} +1 -1
  48. package/dist/app/assets/{chunk-FMBD7UC4-BKt1Qj6I.js → chunk-FMBD7UC4-DDGTq6jI.js} +1 -1
  49. package/dist/app/assets/{chunk-OYMX7WX6-D22I1Lke.js → chunk-OYMX7WX6-BBZDoYQI.js} +1 -1
  50. package/dist/app/assets/{chunk-QZHKN3VN-OBgxRqO-.js → chunk-QZHKN3VN-DdnHt9oV.js} +1 -1
  51. package/dist/app/assets/{chunk-YZCP3GAM-pUxs6dq2.js → chunk-YZCP3GAM-CDlHGJHz.js} +1 -1
  52. package/dist/app/assets/{cil-Aus-_gof.js → cil-DZ05JSZt.js} +1 -1
  53. package/dist/app/assets/classDiagram-6PBFFD2Q-DDmxiqHK.js +1 -0
  54. package/dist/app/assets/classDiagram-v2-HSJHXN6E-DDmxiqHK.js +1 -0
  55. package/dist/app/assets/{clike-BmPHnJ_s.js → clike-C-dce4Yl.js} +1 -1
  56. package/dist/app/assets/{clojure-CW-GjCE-.js → clojure-Cik0pyKG.js} +1 -1
  57. package/dist/app/assets/clone-DzAFCb4d.js +1 -0
  58. package/dist/app/assets/{cmake-B9JwnXJm.js → cmake-ClItZh_8.js} +1 -1
  59. package/dist/app/assets/{cobol-MM2iB1tf.js → cobol-DWNFtn0e.js} +1 -1
  60. package/dist/app/assets/{coffeescript-BYj4cAte.js → coffeescript-DFxA9g0F.js} +1 -1
  61. package/dist/app/assets/{concurnas-Dvsu2_MG.js → concurnas-uPVT6qf5.js} +1 -1
  62. package/dist/app/assets/{coq-CgVwYmnQ.js → coq-BSKv5Z4t.js} +1 -1
  63. package/dist/app/assets/{core-C_147WSZ.js → core-CqabDKxB.js} +1 -1
  64. package/dist/app/assets/{cose-bilkent-S5V4N54A-D1OYkuPl.js → cose-bilkent-S5V4N54A-BRQTAZ30.js} +1 -1
  65. package/dist/app/assets/{cpp-BXHX6A9n.js → cpp-BKB6xq7P.js} +1 -1
  66. package/dist/app/assets/{crystal-CjFk19Ts.js → crystal-ptPEIgBt.js} +1 -1
  67. package/dist/app/assets/{csharp-CmTfGjFs.js → csharp-DKCrBSIr.js} +1 -1
  68. package/dist/app/assets/{cshtml-BCUe0yaT.js → cshtml-DnjmY1aO.js} +1 -1
  69. package/dist/app/assets/{csp-CCHnC8Po.js → csp-CzmWWq7i.js} +1 -1
  70. package/dist/app/assets/{css-extras-DK4mKYOO.js → css-extras-CZ9kQxJC.js} +1 -1
  71. package/dist/app/assets/{css-C8eNDHXz.js → css-nabIgEws.js} +1 -1
  72. package/dist/app/assets/{csv-qe24SbyQ.js → csv-BG0H1N52.js} +1 -1
  73. package/dist/app/assets/{cypher-DTaNl2V1.js → cypher-DyEzG7ti.js} +1 -1
  74. package/dist/app/assets/{d-DTUhWIJ2.js → d-BMmV-4z1.js} +1 -1
  75. package/dist/app/assets/{dagre-KV5264BT-DwXVdlOV.js → dagre-KV5264BT-B8BjxTZj.js} +1 -1
  76. package/dist/app/assets/{dart-C5UOys48.js → dart-CpGxTj2o.js} +1 -1
  77. package/dist/app/assets/{dataweave-Dj0pMNyP.js → dataweave-DhQPX3BU.js} +1 -1
  78. package/dist/app/assets/{dax-CEobCOU5.js → dax-C_hSU3cL.js} +1 -1
  79. package/dist/app/assets/{dhall-B1ZNT4vf.js → dhall-DHj_sxCo.js} +1 -1
  80. package/dist/app/assets/{diagram-5BDNPKRD-D0Dhsrwn.js → diagram-5BDNPKRD-CAiueCI6.js} +1 -1
  81. package/dist/app/assets/{diagram-G4DWMVQ6-CKzhB2Vi.js → diagram-G4DWMVQ6-DlsV8l1r.js} +1 -1
  82. package/dist/app/assets/{diagram-MMDJMWI5-CVK8DZmo.js → diagram-MMDJMWI5-Kv6CoQdl.js} +1 -1
  83. package/dist/app/assets/{diagram-TYMM5635-C63pXHON.js → diagram-TYMM5635-BznfcBm-.js} +1 -1
  84. package/dist/app/assets/{diff-DUbfn8vo.js → diff-TDLgKsTC.js} +1 -1
  85. package/dist/app/assets/{django-BqtTf9W_.js → django-BGA6uMwl.js} +1 -1
  86. package/dist/app/assets/{dns-zone-file-HiFRqdUC.js → dns-zone-file-CS7N29Nh.js} +1 -1
  87. package/dist/app/assets/{docker-DGrPELO1.js → docker-CFuWEMG4.js} +1 -1
  88. package/dist/app/assets/{dot-BSr3hUqB.js → dot-BuI3fIl5.js} +1 -1
  89. package/dist/app/assets/{ebnf-B6oU2VcU.js → ebnf-0yXcRKzq.js} +1 -1
  90. package/dist/app/assets/{editorconfig-CR4Ao-pW.js → editorconfig-ZwKFQrw_.js} +1 -1
  91. package/dist/app/assets/{eiffel-whkSHtSL.js → eiffel-CCkWkof9.js} +1 -1
  92. package/dist/app/assets/{ejs-BW2scL4F.js → ejs-C9upEEvN.js} +1 -1
  93. package/dist/app/assets/{elixir-CUNINv_i.js → elixir-DpngNXg2.js} +1 -1
  94. package/dist/app/assets/{elm-DmNP9VV8.js → elm-F-WH2jVY.js} +1 -1
  95. package/dist/app/assets/{erDiagram-SMLLAGMA-Bzh8tjuV.js → erDiagram-SMLLAGMA-evVGq9aA.js} +1 -1
  96. package/dist/app/assets/{erb-Ch3DT-PT.js → erb-BGEr245J.js} +1 -1
  97. package/dist/app/assets/{erlang-BaS46QcW.js → erlang-R3_RAdeP.js} +1 -1
  98. package/dist/app/assets/{etlua-Cw5-5TpW.js → etlua-DqqAkZdO.js} +1 -1
  99. package/dist/app/assets/{excel-formula-B7JQQYH7.js → excel-formula-CSiml3ju.js} +1 -1
  100. package/dist/app/assets/{factor-CVzm3y29.js → factor-DmMNhX8j.js} +1 -1
  101. package/dist/app/assets/{false-DFa4x2p8.js → false-BRxcTXb3.js} +1 -1
  102. package/dist/app/assets/{firestore-security-rules-BWCfa1-J.js → firestore-security-rules-QUZ9d15G.js} +1 -1
  103. package/dist/app/assets/{flow-Bt3qEnW5.js → flow-CM8Ul_F8.js} +1 -1
  104. package/dist/app/assets/{flowDiagram-DWJPFMVM-Dvq1OIJB.js → flowDiagram-DWJPFMVM-CRC5ztDh.js} +1 -1
  105. package/dist/app/assets/{fortran-CCu-4Ium.js → fortran-4BoXeWjv.js} +1 -1
  106. package/dist/app/assets/{fsharp-CDiO0qvE.js → fsharp-aLuIEWkd.js} +1 -1
  107. package/dist/app/assets/{ftl-DkrbBJ6h.js → ftl-CiEvcjAh.js} +1 -1
  108. package/dist/app/assets/{ganttDiagram-T4ZO3ILL-BtaWNNLn.js → ganttDiagram-T4ZO3ILL-BA5PQPVx.js} +1 -1
  109. package/dist/app/assets/{gap-CElgN_G6.js → gap-DRHnZupb.js} +1 -1
  110. package/dist/app/assets/{gcode-D1m1Jx_m.js → gcode-Ci4yyT_S.js} +1 -1
  111. package/dist/app/assets/{gdscript-CQyrpld6.js → gdscript-CwHuZksE.js} +1 -1
  112. package/dist/app/assets/{gedcom-C0t2XJjb.js → gedcom-514pRwDC.js} +1 -1
  113. package/dist/app/assets/{gherkin-D2Z-kIb5.js → gherkin-CHJmGFl4.js} +1 -1
  114. package/dist/app/assets/{git-COtp78Yi.js → git-Cpt88esC.js} +1 -1
  115. package/dist/app/assets/{gitGraphDiagram-UUTBAWPF-CwEA20GK.js → gitGraphDiagram-UUTBAWPF-r2T7lPpJ.js} +1 -1
  116. package/dist/app/assets/{glsl-BOfIEs6F.js → glsl-BfrS8yJO.js} +1 -1
  117. package/dist/app/assets/{gml-DEJcGKIl.js → gml-DDgXE7W7.js} +1 -1
  118. package/dist/app/assets/{gn-D2URDt4C.js → gn-CoQG_0n5.js} +1 -1
  119. package/dist/app/assets/{go-H9iqUz92.js → go-B5zj8JkX.js} +1 -1
  120. package/dist/app/assets/{go-module-CI1Cdki8.js → go-module-EmzvkBoA.js} +1 -1
  121. package/dist/app/assets/{graph-DNTBpla7.js → graph-Cf1KoQrp.js} +1 -1
  122. package/dist/app/assets/{graphql-CfY3OrBB.js → graphql-BiDysM4-.js} +1 -1
  123. package/dist/app/assets/{groovy-DKOMKQyq.js → groovy-CpSog8z5.js} +1 -1
  124. package/dist/app/assets/{haml-tAB3bBZc.js → haml-CvSPf2h1.js} +1 -1
  125. package/dist/app/assets/{handlebars-CMRoFkcp.js → handlebars-D-WQRJEB.js} +1 -1
  126. package/dist/app/assets/{haskell-BIno1Xj8.js → haskell-C7BRSZIe.js} +1 -1
  127. package/dist/app/assets/{haxe-BjUHc9TK.js → haxe-_Hcflzq6.js} +1 -1
  128. package/dist/app/assets/{hcl-d_N2T1VA.js → hcl-CWqWstRc.js} +1 -1
  129. package/dist/app/assets/{hlsl-Czs9_QAo.js → hlsl-BxXCCGJZ.js} +1 -1
  130. package/dist/app/assets/{hoon-1-5xCFh9.js → hoon-CwaQ-EFH.js} +1 -1
  131. package/dist/app/assets/{hpkp-BDx00Z1B.js → hpkp-DQmRthIx.js} +1 -1
  132. package/dist/app/assets/{hsts-D_MF-HB_.js → hsts-D8Ur8bD-.js} +1 -1
  133. package/dist/app/assets/{http-D5BtxMl1.js → http-Cw3RkimR.js} +1 -1
  134. package/dist/app/assets/{ichigojam-DMEwRzWG.js → ichigojam-CM6bS6zb.js} +1 -1
  135. package/dist/app/assets/{icon-BePaZLuK.js → icon-CtcSAZYC.js} +1 -1
  136. package/dist/app/assets/{icu-message-format-BlPybne8.js → icu-message-format-DF5LqWc8.js} +1 -1
  137. package/dist/app/assets/{idris-DZlcuSA9.js → idris-BFiVs7gd.js} +1 -1
  138. package/dist/app/assets/{iecst-BkjvfWtO.js → iecst-DdrMjXQ5.js} +1 -1
  139. package/dist/app/assets/{ignore-CdeiHJ0n.js → ignore-DIq2g2-l.js} +1 -1
  140. package/dist/app/assets/index-o0o3Q2hC.css +1 -0
  141. package/dist/app/assets/index-tsW7eKsE.js +762 -0
  142. package/dist/app/assets/{infoDiagram-42DDH7IO-BHLFr032.js → infoDiagram-42DDH7IO-wYyuNxNj.js} +1 -1
  143. package/dist/app/assets/{inform7-cMmC84KD.js → inform7-DzmXERkt.js} +1 -1
  144. package/dist/app/assets/{ini-DVzqNVZv.js → ini-D5KL9MSR.js} +1 -1
  145. package/dist/app/assets/{io-DZZuQgET.js → io-DhsFH1Tp.js} +1 -1
  146. package/dist/app/assets/{ishikawaDiagram-UXIWVN3A-Cfb4YddV.js → ishikawaDiagram-UXIWVN3A-C4-BPurQ.js} +1 -1
  147. package/dist/app/assets/{j-CJ-4uAlV.js → j-5x99BUy1.js} +1 -1
  148. package/dist/app/assets/{java-DCXkSxET.js → java-BF9JoKMx.js} +1 -1
  149. package/dist/app/assets/{javadoc-CrVMKEsI.js → javadoc-BxSJmEM7.js} +1 -1
  150. package/dist/app/assets/{javadoclike-D2L56h5j.js → javadoclike-CPt-8K6_.js} +1 -1
  151. package/dist/app/assets/{javascript-hgymZZUH.js → javascript-BssOsFWy.js} +1 -1
  152. package/dist/app/assets/{javastacktrace-ChLmPkJH.js → javastacktrace-Dd6I7h5J.js} +1 -1
  153. package/dist/app/assets/{jexl-Cv8EINDe.js → jexl-CUEZVd6g.js} +1 -1
  154. package/dist/app/assets/{jolie-C8GHrQQz.js → jolie-D4tUWCAe.js} +1 -1
  155. package/dist/app/assets/{journeyDiagram-VCZTEJTY-BTArqTvD.js → journeyDiagram-VCZTEJTY-4dsXMpZz.js} +1 -1
  156. package/dist/app/assets/{jq-BNVdoY6Z.js → jq-DA4saxp1.js} +1 -1
  157. package/dist/app/assets/{js-extras-BlUxCYhv.js → js-extras-BHoZQrc7.js} +1 -1
  158. package/dist/app/assets/{js-templates-DXYRbGAM.js → js-templates-DHIHpncv.js} +1 -1
  159. package/dist/app/assets/{jsdoc-CMLYNOYD.js → jsdoc-DiRqJjfA.js} +1 -1
  160. package/dist/app/assets/{json-odBxYu2B.js → json-WG7VBScH.js} +1 -1
  161. package/dist/app/assets/{json5-DP7aJM4_.js → json5-TZgr9JRE.js} +1 -1
  162. package/dist/app/assets/{jsonp-B2xUHyW0.js → jsonp-Dv9WqRYx.js} +1 -1
  163. package/dist/app/assets/{jsstacktrace-CmkoO76I.js → jsstacktrace-Gz4Bje7i.js} +1 -1
  164. package/dist/app/assets/{jsx-45IrULtU.js → jsx-Bw3uULWP.js} +1 -1
  165. package/dist/app/assets/{julia-ClR9qq8g.js → julia-D8b2chKD.js} +1 -1
  166. package/dist/app/assets/{kanban-definition-6JOO6SKY-JROcHSgz.js → kanban-definition-6JOO6SKY-BpSZrzpV.js} +1 -1
  167. package/dist/app/assets/{keepalived-C-KownHW.js → keepalived-CxrShb2S.js} +1 -1
  168. package/dist/app/assets/{keyman-CYpySklF.js → keyman-CiksSo_Q.js} +1 -1
  169. package/dist/app/assets/{kotlin-CQbGs2Ue.js → kotlin-DrUdw5kE.js} +1 -1
  170. package/dist/app/assets/{kumir-DToHbC4q.js → kumir-D7RWib-C.js} +1 -1
  171. package/dist/app/assets/{kusto-B6SHYgRi.js → kusto-BV4XMg16.js} +1 -1
  172. package/dist/app/assets/{latex-DrhQGKi6.js → latex-BC0Uyc-d.js} +1 -1
  173. package/dist/app/assets/{latte-BatIWxZM.js → latte-tPT1UrWz.js} +1 -1
  174. package/dist/app/assets/{layout-CmJisaFk.js → layout-BOlQN9Mo.js} +1 -1
  175. package/dist/app/assets/{less-BJapF0M4.js → less-oxG_fu4g.js} +1 -1
  176. package/dist/app/assets/{lilypond-DHb81Qrb.js → lilypond-C88RotJr.js} +1 -1
  177. package/dist/app/assets/{linear-HilAl6Kl.js → linear-BfflU34i.js} +1 -1
  178. package/dist/app/assets/{liquid-BYBkN767.js → liquid-C7TfcW57.js} +1 -1
  179. package/dist/app/assets/{lisp-PTlDHAFe.js → lisp-Buz4RfpM.js} +1 -1
  180. package/dist/app/assets/{livescript-D7mEGuFt.js → livescript-1DQfUkd-.js} +1 -1
  181. package/dist/app/assets/{llvm-BOF01C_Q.js → llvm-JvopDbcE.js} +1 -1
  182. package/dist/app/assets/{log-D_oLYdec.js → log-BnfCB9DE.js} +1 -1
  183. package/dist/app/assets/{lolcode-BOp3ZdpE.js → lolcode-D_D_7GzE.js} +1 -1
  184. package/dist/app/assets/{lua-CdyGJajb.js → lua-CO1cU0XH.js} +1 -1
  185. package/dist/app/assets/{magma-asqA2vhX.js → magma-B1G7u0t4.js} +1 -1
  186. package/dist/app/assets/{makefile-CYytCSPK.js → makefile-AeGGTOcq.js} +1 -1
  187. package/dist/app/assets/{markdown-jxdlECxY.js → markdown-C8OTDGWj.js} +1 -1
  188. package/dist/app/assets/{markup-CLxozN6F.js → markup-fcpLEWs9.js} +1 -1
  189. package/dist/app/assets/{markup-templating-Cs7ayZpi.js → markup-templating-BJPOJotJ.js} +1 -1
  190. package/dist/app/assets/{matlab-BoNKjSLV.js → matlab-C5u9cVSe.js} +1 -1
  191. package/dist/app/assets/{maxscript-xgjeOfTE.js → maxscript-D1j46lZY.js} +1 -1
  192. package/dist/app/assets/{mel-DnN2qY7Z.js → mel-4T8xB3kc.js} +1 -1
  193. package/dist/app/assets/{mermaid-Di7Rvujk.js → mermaid-D2CuapgG.js} +1 -1
  194. package/dist/app/assets/{min-D-U2U04w.js → min-C6bAU5tf.js} +1 -1
  195. package/dist/app/assets/{mindmap-definition-QFDTVHPH-7f0wW_f6.js → mindmap-definition-QFDTVHPH-DQCqFXf4.js} +1 -1
  196. package/dist/app/assets/{mizar-DNfbYlTh.js → mizar-6YzPCneu.js} +1 -1
  197. package/dist/app/assets/{mongodb-BDy5e9Pj.js → mongodb-rU_FNrrO.js} +1 -1
  198. package/dist/app/assets/{monkey-BRH4J8qW.js → monkey-DHTaMD5j.js} +1 -1
  199. package/dist/app/assets/{moonscript-CH8q91fg.js → moonscript-B4Q1sWnw.js} +1 -1
  200. package/dist/app/assets/{n1ql-Cnsejlzs.js → n1ql-C-kQ4Dz0.js} +1 -1
  201. package/dist/app/assets/{n4js-B3Iq3-1_.js → n4js-B4Kuv0gT.js} +1 -1
  202. package/dist/app/assets/{nand2tetris-hdl-CU1IJ4Jw.js → nand2tetris-hdl-BEZvFDwm.js} +1 -1
  203. package/dist/app/assets/{naniscript-jbrJD2kA.js → naniscript-0DISbVj5.js} +1 -1
  204. package/dist/app/assets/{nasm-CknzFEer.js → nasm-Cy_rHjd9.js} +1 -1
  205. package/dist/app/assets/{neon-26-IayFN.js → neon-CQPnGFjU.js} +1 -1
  206. package/dist/app/assets/{nevod-BJEC391b.js → nevod-Cc2uvwJy.js} +1 -1
  207. package/dist/app/assets/{nginx-Vpvjjaaf.js → nginx-CtSV-zWN.js} +1 -1
  208. package/dist/app/assets/{nim-DyKtgNBt.js → nim-Cx8sXTrq.js} +1 -1
  209. package/dist/app/assets/{nix-BMFnBzg-.js → nix-fzCInmbw.js} +1 -1
  210. package/dist/app/assets/{nsis-SbQZmFez.js → nsis-B-WmXulG.js} +1 -1
  211. package/dist/app/assets/{objectivec-BHCbn7Vg.js → objectivec-B7mP6oMV.js} +1 -1
  212. package/dist/app/assets/{ocaml-B_NbRFYO.js → ocaml-BCNitKcz.js} +1 -1
  213. package/dist/app/assets/{opencl-DGGnjyh8.js → opencl-Ccg1YnSK.js} +1 -1
  214. package/dist/app/assets/{openqasm-BB7WCrXB.js → openqasm-CtnHTd2G.js} +1 -1
  215. package/dist/app/assets/{oz-CHFXD-ie.js → oz-DXv1OItd.js} +1 -1
  216. package/dist/app/assets/{parigp-hCut1WJq.js → parigp-Cb_kuYUA.js} +1 -1
  217. package/dist/app/assets/{parser-Cst8mRu7.js → parser-CwT8uubF.js} +1 -1
  218. package/dist/app/assets/{pascal-BCJwXon0.js → pascal-B5wSlm8n.js} +1 -1
  219. package/dist/app/assets/{pascaligo-B6Cgg9Mq.js → pascaligo-D7-1FMxX.js} +1 -1
  220. package/dist/app/assets/{pcaxis-C4xWQM2D.js → pcaxis-DbHPrVNE.js} +1 -1
  221. package/dist/app/assets/{peoplecode-Dkb6XtUf.js → peoplecode-Bwty_AUm.js} +1 -1
  222. package/dist/app/assets/{perl-H221EXvJ.js → perl-BiIJMtwN.js} +1 -1
  223. package/dist/app/assets/{php-BShmZ9_M.js → php-6mreideO.js} +1 -1
  224. package/dist/app/assets/{php-extras-ByhH4OKy.js → php-extras-CBjQ7vIX.js} +1 -1
  225. package/dist/app/assets/{phpdoc-p3qE-fVK.js → phpdoc-B62bzA5k.js} +1 -1
  226. package/dist/app/assets/{pieDiagram-DEJITSTG-BpxQ_Sug.js → pieDiagram-DEJITSTG-URmplZD6.js} +1 -1
  227. package/dist/app/assets/{plsql-Bq0RDvXx.js → plsql-BAj_vv6G.js} +1 -1
  228. package/dist/app/assets/{powerquery-DRH8DvSi.js → powerquery-CzCmbNz6.js} +1 -1
  229. package/dist/app/assets/{powershell-Bevaimo1.js → powershell-CpwS-v1m.js} +1 -1
  230. package/dist/app/assets/{processing-C0GbD3oE.js → processing-9HFL_Kda.js} +1 -1
  231. package/dist/app/assets/{prolog-Di4z8LJE.js → prolog-D71hnbvz.js} +1 -1
  232. package/dist/app/assets/{promql-03Fgifpl.js → promql-Cr4QC9HL.js} +1 -1
  233. package/dist/app/assets/{properties-D1Z19tT1.js → properties-J9p1gfGR.js} +1 -1
  234. package/dist/app/assets/{protobuf-DWz8yR_O.js → protobuf-DMxIf431.js} +1 -1
  235. package/dist/app/assets/{psl-tBEfR2Sh.js → psl-CTytrTSB.js} +1 -1
  236. package/dist/app/assets/{pug-C7eejEs9.js → pug-jEAnZaKi.js} +1 -1
  237. package/dist/app/assets/{puppet-B7zctoCl.js → puppet-DGT0PXLM.js} +1 -1
  238. package/dist/app/assets/{pure-BtT7EWOj.js → pure-DFlG-Euv.js} +1 -1
  239. package/dist/app/assets/{purebasic-Ccj2c-Ej.js → purebasic-fdJezgk1.js} +1 -1
  240. package/dist/app/assets/{purescript-DMkp7ORC.js → purescript-WUURLlSz.js} +1 -1
  241. package/dist/app/assets/{q-DnC31I_1.js → q-CmD9Xmj5.js} +1 -1
  242. package/dist/app/assets/{qml-qQROczBb.js → qml-BMG0y4hi.js} +1 -1
  243. package/dist/app/assets/{qore-CYWTKmh1.js → qore-ndBZlJKP.js} +1 -1
  244. package/dist/app/assets/{qsharp-DGDhAWfE.js → qsharp-DLCEDNKN.js} +1 -1
  245. package/dist/app/assets/{quadrantDiagram-34T5L4WZ-BCvqKtV-.js → quadrantDiagram-34T5L4WZ-DYv3ycY4.js} +1 -1
  246. package/dist/app/assets/{r-DvcBehxz.js → r-B8Kaj2hw.js} +1 -1
  247. package/dist/app/assets/{racket-XWJUhFHR.js → racket-BmjGoXCu.js} +1 -1
  248. package/dist/app/assets/{reason-DpsxmggQ.js → reason-BMBey7GD.js} +1 -1
  249. package/dist/app/assets/{regex-DQtV1_Nu.js → regex-CcOJ-RBo.js} +1 -1
  250. package/dist/app/assets/{rego-D2-FjG8h.js → rego-BIXa5YcP.js} +1 -1
  251. package/dist/app/assets/{renpy-C3S_oPNw.js → renpy-DFVE_JD1.js} +1 -1
  252. package/dist/app/assets/{requirementDiagram-MS252O5E-BICcpYGT.js → requirementDiagram-MS252O5E-enCn9qyU.js} +1 -1
  253. package/dist/app/assets/{rest-DXmPPeBy.js → rest-B9H-hgOJ.js} +1 -1
  254. package/dist/app/assets/{rip-NSOmDEr3.js → rip-Bv5Hr1Jw.js} +1 -1
  255. package/dist/app/assets/{roboconf-CuCQ-NJX.js → roboconf-jRCQTbv5.js} +1 -1
  256. package/dist/app/assets/{robotframework-BsCP1w9s.js → robotframework-B5SYb3S6.js} +1 -1
  257. package/dist/app/assets/{ruby-CJnf6nnh.js → ruby-B9xBZ2-7.js} +1 -1
  258. package/dist/app/assets/{rust-DESdYva3.js → rust-DxSKWUH3.js} +1 -1
  259. package/dist/app/assets/{sankeyDiagram-XADWPNL6-69KpnHMz.js → sankeyDiagram-XADWPNL6-Bhc5bfvg.js} +1 -1
  260. package/dist/app/assets/{sas-DZFbJKR-.js → sas-Ufzee22m.js} +1 -1
  261. package/dist/app/assets/{sass-AnS1s1br.js → sass-D2SeUbd3.js} +1 -1
  262. package/dist/app/assets/{scala-CwhoAHEC.js → scala-1mDQ7lT3.js} +1 -1
  263. package/dist/app/assets/{scheme-C_ljvZBy.js → scheme-C1DE_OtV.js} +1 -1
  264. package/dist/app/assets/{scss-DL1XxErH.js → scss-CG-uC_jx.js} +1 -1
  265. package/dist/app/assets/{sequenceDiagram-FGHM5R23-D7oS24WP.js → sequenceDiagram-FGHM5R23-CDe6bCwe.js} +1 -1
  266. package/dist/app/assets/{shell-session-Cz9O3eeT.js → shell-session-BXrndzdM.js} +1 -1
  267. package/dist/app/assets/{smali-CB-r7O-_.js → smali-QM7yFavH.js} +1 -1
  268. package/dist/app/assets/{smalltalk-CVFZJVem.js → smalltalk-C-fITGMb.js} +1 -1
  269. package/dist/app/assets/{smarty-BzZkcGHn.js → smarty-4kJKkU5q.js} +1 -1
  270. package/dist/app/assets/{sml-D9RGeV5i.js → sml-ot95negB.js} +1 -1
  271. package/dist/app/assets/{solidity-Dz-wQnyp.js → solidity-Dx_IP6eq.js} +1 -1
  272. package/dist/app/assets/{solution-file-DkmD5yqD.js → solution-file-wapuUhtE.js} +1 -1
  273. package/dist/app/assets/{soy-D85tR8Fr.js → soy-D-5oz9aj.js} +1 -1
  274. package/dist/app/assets/{sparql-BgbB63AF.js → sparql--6Q0TOqj.js} +1 -1
  275. package/dist/app/assets/{splunk-spl-BCo2DCmB.js → splunk-spl-CNbdZc4Q.js} +1 -1
  276. package/dist/app/assets/{sqf-CiA74sHU.js → sqf-DSKo3YQF.js} +1 -1
  277. package/dist/app/assets/{sql-hLzyaqCr.js → sql-gNTttuTN.js} +1 -1
  278. package/dist/app/assets/{squirrel-zcX4QdBa.js → squirrel-DBA8eFXS.js} +1 -1
  279. package/dist/app/assets/{stan-Ckw12XOd.js → stan-DDf1Y7DO.js} +1 -1
  280. package/dist/app/assets/{stateDiagram-FHFEXIEX-BvjpuD2U.js → stateDiagram-FHFEXIEX-p42Be8mf.js} +1 -1
  281. package/dist/app/assets/stateDiagram-v2-QKLJ7IA2-CAhlZfwO.js +1 -0
  282. package/dist/app/assets/{stylus-v6XOnT6H.js → stylus-CjUUyrES.js} +1 -1
  283. package/dist/app/assets/{swift-5_1e6kft.js → swift-CKnKs81t.js} +1 -1
  284. package/dist/app/assets/{systemd-DrgFw48M.js → systemd-C10k014a.js} +1 -1
  285. package/dist/app/assets/{t4-cs-DM0v3lxQ.js → t4-cs-DDiM4sZJ.js} +1 -1
  286. package/dist/app/assets/{t4-templating-DD8VmPrg.js → t4-templating-7kKJq4TZ.js} +1 -1
  287. package/dist/app/assets/{t4-vb-DycV_cM9.js → t4-vb-DuiSnonv.js} +1 -1
  288. package/dist/app/assets/{tap-DGpedrqN.js → tap-IQ8yl2oh.js} +1 -1
  289. package/dist/app/assets/{tcl-c2qhHAdq.js → tcl-DURyRJDt.js} +1 -1
  290. package/dist/app/assets/{textile-C8oUBrkr.js → textile-DQ_JtUdC.js} +1 -1
  291. package/dist/app/assets/{timeline-definition-GMOUNBTQ-B4Jcyau2.js → timeline-definition-GMOUNBTQ-B4uPbG-W.js} +1 -1
  292. package/dist/app/assets/{toml-BGo5hlUM.js → toml-IQN2CNuI.js} +1 -1
  293. package/dist/app/assets/{tremor-eRNxuoON.js → tremor-Bny5MqnS.js} +1 -1
  294. package/dist/app/assets/{tt2-Di8pz9fy.js → tt2-DcdeYRm9.js} +1 -1
  295. package/dist/app/assets/{turtle-vJP3xRTT.js → turtle-ePfiwKUJ.js} +1 -1
  296. package/dist/app/assets/{twig-BnhrPMSB.js → twig-DYNpPvPW.js} +1 -1
  297. package/dist/app/assets/{typescript-37w5F4sD.js → typescript-myhWeMeg.js} +1 -1
  298. package/dist/app/assets/{typoscript-CsApf0xg.js → typoscript-BtWmq6lK.js} +1 -1
  299. package/dist/app/assets/{unrealscript-dRcLpqab.js → unrealscript-BdPAyGL5.js} +1 -1
  300. package/dist/app/assets/{uorazor-30r9Eeul.js → uorazor-CdoHfnCa.js} +1 -1
  301. package/dist/app/assets/{uri-D77IB2tJ.js → uri-8lWJiWx5.js} +1 -1
  302. package/dist/app/assets/{v-CKeEdKLN.js → v-0tJN9Hku.js} +1 -1
  303. package/dist/app/assets/{vala-BetNh6ws.js → vala-XUiF0ZAF.js} +1 -1
  304. package/dist/app/assets/{vbnet-BEMab70S.js → vbnet-BUEocEyh.js} +1 -1
  305. package/dist/app/assets/{velocity-DrfQgf6-.js → velocity-BEOmqWKD.js} +1 -1
  306. package/dist/app/assets/{vennDiagram-DHZGUBPP-CegebJbe.js → vennDiagram-DHZGUBPP-CiBcI7a1.js} +1 -1
  307. package/dist/app/assets/{verilog-uQXkk7Nj.js → verilog-BBKGGmem.js} +1 -1
  308. package/dist/app/assets/{vhdl-DDmmL8UD.js → vhdl-B-_TUb2S.js} +1 -1
  309. package/dist/app/assets/{vim-BDNt86iz.js → vim-D12Uaiun.js} +1 -1
  310. package/dist/app/assets/{visual-basic-pucIF_mU.js → visual-basic-Bt6yOtui.js} +1 -1
  311. package/dist/app/assets/{wardley-RL74JXVD-DsKO1a_J.js → wardley-RL74JXVD-CAHah9aU.js} +1 -1
  312. package/dist/app/assets/{wardleyDiagram-NUSXRM2D-B2JNwjAB.js → wardleyDiagram-NUSXRM2D-DuJOM0rD.js} +1 -1
  313. package/dist/app/assets/{warpscript-CHmOiWY2.js → warpscript-CeTM4-Gj.js} +1 -1
  314. package/dist/app/assets/{wasm-4NqiPBMD.js → wasm-SfMoRKqG.js} +1 -1
  315. package/dist/app/assets/{web-idl-LsIw2yg-.js → web-idl-D20E2F0O.js} +1 -1
  316. package/dist/app/assets/{wiki-nXUE249D.js → wiki-D8abQrQq.js} +1 -1
  317. package/dist/app/assets/{wolfram-Df8JMtQM.js → wolfram-CGEar8g5.js} +1 -1
  318. package/dist/app/assets/{wren-Cs5S9jF3.js → wren-D2cfeRDa.js} +1 -1
  319. package/dist/app/assets/{xeora-BFuaZkC6.js → xeora-CjjXFLG8.js} +1 -1
  320. package/dist/app/assets/{xml-doc-gKIq2LAK.js → xml-doc-3_owB9PN.js} +1 -1
  321. package/dist/app/assets/{xojo-pDFvmFo8.js → xojo-C312JS6O.js} +1 -1
  322. package/dist/app/assets/{xquery-B1ncakta.js → xquery-Cn9l8bPn.js} +1 -1
  323. package/dist/app/assets/{xychartDiagram-5P7HB3ND-WNR7ZTqi.js → xychartDiagram-5P7HB3ND-CvrNIPqq.js} +1 -1
  324. package/dist/app/assets/{yaml-Bar2VcxI.js → yaml-OkW6jhVj.js} +1 -1
  325. package/dist/app/assets/{yang-CpPBz6Mu.js → yang-Dg93mnQG.js} +1 -1
  326. package/dist/app/assets/{zig-BtNZL4AA.js → zig-CD6h8YdZ.js} +1 -1
  327. package/dist/app/index.html +2 -2
  328. package/dist/index.cjs +2341 -872
  329. package/dist/index.js +2354 -873
  330. package/package.json +4 -4
  331. package/dist/app/assets/channel-DVMXuD76.js +0 -1
  332. package/dist/app/assets/classDiagram-6PBFFD2Q-ninoD-P9.js +0 -1
  333. package/dist/app/assets/classDiagram-v2-HSJHXN6E-ninoD-P9.js +0 -1
  334. package/dist/app/assets/clone-BeYqBERf.js +0 -1
  335. package/dist/app/assets/index-AMzNmc5s.js +0 -756
  336. package/dist/app/assets/index-CSm4lUOB.css +0 -1
  337. package/dist/app/assets/stateDiagram-v2-QKLJ7IA2-BcXNYcdm.js +0 -1
package/dist/index.cjs CHANGED
@@ -67,8 +67,9 @@ __export(index_exports, {
67
67
  module.exports = __toCommonJS(index_exports);
68
68
 
69
69
  // src/components/chat.tsx
70
- var React52 = __toESM(require("react"), 1);
71
- var import_lucide_react30 = require("lucide-react");
70
+ var React54 = __toESM(require("react"), 1);
71
+ var import_lucide_react31 = require("lucide-react");
72
+ var import_chatkit_types14 = require("@xpert-ai/chatkit-types");
72
73
 
73
74
  // src/lib/utils.ts
74
75
  var import_clsx = require("clsx");
@@ -412,6 +413,15 @@ function toLineNumber(value) {
412
413
  function isOptionalNumber(value) {
413
414
  return value === void 0 || Number.isFinite(value);
414
415
  }
416
+ function isElementAttribute(value) {
417
+ if (!isObjectLike(value)) {
418
+ return false;
419
+ }
420
+ return "name" in value && "value" in value && typeof value.name === "string" && typeof value.value === "string";
421
+ }
422
+ function isElementAttributes(value) {
423
+ return Array.isArray(value) && value.every(isElementAttribute);
424
+ }
415
425
  function toOptionalNumber(value, options) {
416
426
  const allowZero = options?.allowZero ?? false;
417
427
  if (!Number.isFinite(value)) {
@@ -447,6 +457,20 @@ function isImageReferenceCandidate(value) {
447
457
  const candidate = value;
448
458
  return candidate.type === "image" && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.text) && isOptionalString(candidate.fileId) && isOptionalString(candidate.url) && isOptionalString(candidate.mimeType) && isOptionalString(candidate.name) && isOptionalNumber(candidate.size) && isOptionalNumber(candidate.width) && isOptionalNumber(candidate.height) && hasImageReferenceLocator(candidate);
449
459
  }
460
+ function isElementReferenceCandidate(value) {
461
+ if (!isObjectLike(value)) {
462
+ return false;
463
+ }
464
+ const candidate = value;
465
+ return candidate.type === "element" && isElementAttributes(candidate.attributes) && isNonEmptyString(candidate.outerHtml) && isNonEmptyString(candidate.pageUrl) && isNonEmptyString(candidate.selector) && isNonEmptyString(candidate.serviceId) && isNonEmptyString(candidate.tagName) && toReferenceText(candidate.text) !== null && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.pageTitle) && isOptionalString(candidate.role);
466
+ }
467
+ function isFileElementReferenceCandidate(value) {
468
+ if (!isObjectLike(value)) {
469
+ return false;
470
+ }
471
+ const candidate = value;
472
+ return candidate.type === "file_element" && isElementAttributes(candidate.attributes) && isNonEmptyString(candidate.domPath) && isNonEmptyString(candidate.filePath) && isNonEmptyString(candidate.outerHtml) && isNonEmptyString(candidate.selector) && isNonEmptyString(candidate.tagName) && toReferenceText(candidate.text) !== null && isOptionalString(candidate.id) && isOptionalString(candidate.label) && isOptionalString(candidate.documentTitle) && isOptionalString(candidate.role) && isOptionalNumber(candidate.sourceStartLine) && isOptionalNumber(candidate.sourceEndLine);
473
+ }
450
474
  function toCodeReference(candidate) {
451
475
  return {
452
476
  type: "code",
@@ -491,6 +515,48 @@ function toImageReference(candidate) {
491
515
  ...toOptionalNumber(candidate.height) !== void 0 ? { height: toOptionalNumber(candidate.height) } : {}
492
516
  };
493
517
  }
518
+ function toElementReference(candidate) {
519
+ const id = toOptionalString(candidate.id);
520
+ const label = toOptionalString(candidate.label);
521
+ const pageTitle = toOptionalString(candidate.pageTitle);
522
+ const role = toOptionalString(candidate.role);
523
+ return {
524
+ type: "element",
525
+ ...id ? { id } : {},
526
+ ...label ? { label } : {},
527
+ attributes: candidate.attributes,
528
+ outerHtml: candidate.outerHtml,
529
+ ...pageTitle ? { pageTitle } : {},
530
+ pageUrl: candidate.pageUrl.trim(),
531
+ ...role ? { role } : {},
532
+ selector: candidate.selector,
533
+ serviceId: candidate.serviceId,
534
+ tagName: candidate.tagName,
535
+ text: candidate.text
536
+ };
537
+ }
538
+ function toFileElementReference(candidate) {
539
+ const id = toOptionalString(candidate.id);
540
+ const label = toOptionalString(candidate.label);
541
+ const documentTitle = toOptionalString(candidate.documentTitle);
542
+ const role = toOptionalString(candidate.role);
543
+ return {
544
+ type: "file_element",
545
+ ...id ? { id } : {},
546
+ ...label ? { label } : {},
547
+ attributes: candidate.attributes,
548
+ ...documentTitle ? { documentTitle } : {},
549
+ domPath: candidate.domPath,
550
+ filePath: candidate.filePath,
551
+ outerHtml: candidate.outerHtml,
552
+ ...role ? { role } : {},
553
+ selector: candidate.selector,
554
+ ...toOptionalNumber(candidate.sourceStartLine) !== void 0 ? { sourceStartLine: candidate.sourceStartLine } : {},
555
+ ...toOptionalNumber(candidate.sourceEndLine) !== void 0 ? { sourceEndLine: candidate.sourceEndLine } : {},
556
+ tagName: candidate.tagName,
557
+ text: candidate.text
558
+ };
559
+ }
494
560
  function isLegacyCodeReference(candidate) {
495
561
  return candidate.type === void 0 && isNonEmptyString(candidate.path) && toLineNumber(candidate.startLine) !== null && toLineNumber(candidate.endLine) !== null && toReferenceText(candidate.text) !== null;
496
562
  }
@@ -509,6 +575,12 @@ function normalizeReference(value) {
509
575
  if (isImageReferenceCandidate(candidate)) {
510
576
  return toImageReference(candidate);
511
577
  }
578
+ if (isElementReferenceCandidate(candidate)) {
579
+ return toElementReference(candidate);
580
+ }
581
+ if (isFileElementReferenceCandidate(candidate)) {
582
+ return toFileElementReference(candidate);
583
+ }
512
584
  if (type === void 0 && isLegacyCodeReference(candidate)) {
513
585
  return toCodeReference(candidate);
514
586
  }
@@ -583,6 +655,22 @@ function getReferenceKey(reference) {
583
655
  reference.text
584
656
  ].join(":");
585
657
  }
658
+ if (reference.type === "element") {
659
+ return [
660
+ reference.type,
661
+ reference.serviceId,
662
+ reference.pageUrl,
663
+ reference.selector
664
+ ].join(":");
665
+ }
666
+ if (reference.type === "file_element") {
667
+ return [
668
+ reference.type,
669
+ reference.filePath,
670
+ reference.domPath,
671
+ reference.selector
672
+ ].join(":");
673
+ }
586
674
  return [
587
675
  reference.type,
588
676
  reference.messageId ?? "",
@@ -615,7 +703,13 @@ function getReferenceLabel(reference) {
615
703
  if (reference.type === "image") {
616
704
  return reference.name?.trim() || "Pasted image";
617
705
  }
618
- if (reference.source && reference.source.trim()) {
706
+ if (reference.type === "element") {
707
+ return reference.pageTitle?.trim() || reference.tagName;
708
+ }
709
+ if (reference.type === "file_element") {
710
+ return reference.documentTitle?.trim() || reference.filePath;
711
+ }
712
+ if (reference.type === "quote" && reference.source?.trim()) {
619
713
  return reference.source.trim();
620
714
  }
621
715
  return getQuoteExcerpt(reference);
@@ -628,10 +722,18 @@ function getReferenceMetaLine(reference) {
628
722
  const parts = getImageReferenceMetaParts(reference);
629
723
  return parts.length ? parts.join(" \u2022 ") : null;
630
724
  }
631
- if (reference.source && reference.source.trim()) {
725
+ if (reference.type === "element") {
726
+ return reference.pageUrl;
727
+ }
728
+ if (reference.type === "file_element") {
729
+ const start = reference.sourceStartLine;
730
+ const end = reference.sourceEndLine ?? start;
731
+ return start ? `${reference.filePath}:${start}${end === start ? "" : `-${end}`}` : reference.filePath;
732
+ }
733
+ if (reference.type === "quote" && reference.source?.trim()) {
632
734
  return getQuoteExcerpt(reference);
633
735
  }
634
- if (reference.messageId && reference.messageId.trim()) {
736
+ if (reference.type === "quote" && reference.messageId?.trim()) {
635
737
  return `Message ${reference.messageId.trim()}`;
636
738
  }
637
739
  return null;
@@ -657,6 +759,17 @@ ${reference.text}`;
657
759
  }
658
760
  return titleLines.join("\n");
659
761
  }
762
+ if (reference.type === "element") {
763
+ return `${getReferenceLabel(reference)}
764
+ ${reference.pageUrl}
765
+
766
+ ${reference.text}`;
767
+ }
768
+ if (reference.type === "file_element") {
769
+ return `${getReferenceMetaLine(reference) ?? reference.filePath}
770
+
771
+ ${reference.text}`;
772
+ }
660
773
  const header = reference.label?.trim() || reference.source?.trim() || "Quoted text";
661
774
  return `${header}
662
775
 
@@ -1277,6 +1390,550 @@ function countCompletedTodos(items) {
1277
1390
  return items.filter((item) => item.status === "completed").length;
1278
1391
  }
1279
1392
 
1393
+ // src/lib/task-summary.ts
1394
+ var PLAN_PATTERN = /<proposed_plan>\s*([\s\S]*?)\s*<\/proposed_plan>/i;
1395
+ function isObject(value) {
1396
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1397
+ }
1398
+ function stringValue(value) {
1399
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
1400
+ }
1401
+ function timestamp(value) {
1402
+ const parsed = value ? Date.parse(value) : 0;
1403
+ return Number.isNaN(parsed) ? 0 : parsed;
1404
+ }
1405
+ function contentParts(content) {
1406
+ return Array.isArray(content) ? content.filter((part) => isObject(part)) : [];
1407
+ }
1408
+ function messageText(content) {
1409
+ if (typeof content === "string") return content;
1410
+ return contentParts(content).map(
1411
+ (part) => isObject(part) && "text" in part ? stringValue(part.text) ?? "" : ""
1412
+ ).join("\n");
1413
+ }
1414
+ function normalizeTaskSummaryContribution(value) {
1415
+ if (!isObject(value)) return null;
1416
+ const candidate = value;
1417
+ if (candidate.version !== 1) return null;
1418
+ const plan = normalizePlan(candidate.plan);
1419
+ const todos = normalizeTodos(candidate.todos);
1420
+ const outputs = Array.isArray(candidate.outputs) ? candidate.outputs.flatMap((item) => normalizeOutput(item) ?? []) : [];
1421
+ const sources = Array.isArray(candidate.sources) ? candidate.sources.flatMap((item) => normalizeSource(item) ?? []) : [];
1422
+ return {
1423
+ version: 1,
1424
+ ...plan ? { plan } : {},
1425
+ ...todos ? { todos } : {},
1426
+ ...outputs.length ? { outputs } : {},
1427
+ ...sources.length ? { sources } : {}
1428
+ };
1429
+ }
1430
+ function normalizePlan(value) {
1431
+ if (!isObject(value)) return null;
1432
+ const candidate = value;
1433
+ const title = stringValue(candidate.title);
1434
+ const excerpt = stringValue(candidate.excerpt);
1435
+ return title && excerpt ? {
1436
+ title,
1437
+ excerpt,
1438
+ messageId: stringValue(candidate.messageId),
1439
+ updatedAt: stringValue(candidate.updatedAt)
1440
+ } : null;
1441
+ }
1442
+ function normalizeTodos(value) {
1443
+ if (!isObject(value)) return null;
1444
+ const candidate = value;
1445
+ const componentId = stringValue(candidate.componentId);
1446
+ if (!componentId || !Array.isArray(candidate.items)) return null;
1447
+ const items = candidate.items.flatMap((item) => {
1448
+ if (!isObject(item)) return [];
1449
+ const todo = item;
1450
+ const id = stringValue(todo.id);
1451
+ const content = stringValue(todo.content);
1452
+ const status = todo.status;
1453
+ return id && content && isTodoStatus(status) ? [{ id, content, status }] : [];
1454
+ });
1455
+ return items.length ? {
1456
+ componentId,
1457
+ title: stringValue(candidate.title),
1458
+ items,
1459
+ messageId: stringValue(candidate.messageId),
1460
+ updatedAt: stringValue(candidate.updatedAt)
1461
+ } : null;
1462
+ }
1463
+ function isTodoStatus(value) {
1464
+ return value === "pending" || value === "in_progress" || value === "completed";
1465
+ }
1466
+ function normalizeOutput(value) {
1467
+ if (!isObject(value)) return null;
1468
+ const candidate = value;
1469
+ const id = stringValue(candidate.id);
1470
+ const title = stringValue(candidate.title);
1471
+ const kind = artifactKind(candidate.kind);
1472
+ if (!id || !title || !kind) return null;
1473
+ const status = candidate.status;
1474
+ return {
1475
+ id,
1476
+ kind,
1477
+ title,
1478
+ description: stringValue(candidate.description),
1479
+ status: status === "pending" || status === "running" || status === "success" || status === "error" ? status : void 0,
1480
+ resource: normalizeResource(candidate.resource),
1481
+ messageId: stringValue(candidate.messageId),
1482
+ updatedAt: stringValue(candidate.updatedAt)
1483
+ };
1484
+ }
1485
+ function normalizeSource(value) {
1486
+ if (!isObject(value)) return null;
1487
+ const candidate = value;
1488
+ const id = stringValue(candidate.id);
1489
+ const title = stringValue(candidate.title);
1490
+ if (!id || !title || !isSourceKind(candidate.kind)) return null;
1491
+ return {
1492
+ id,
1493
+ kind: candidate.kind,
1494
+ title,
1495
+ description: stringValue(candidate.description),
1496
+ resource: normalizeResource(candidate.resource),
1497
+ messageId: stringValue(candidate.messageId),
1498
+ updatedAt: stringValue(candidate.updatedAt)
1499
+ };
1500
+ }
1501
+ function normalizeResource(value) {
1502
+ if (!isObject(value)) return void 0;
1503
+ const candidate = value;
1504
+ if (candidate.type === "message") {
1505
+ const messageId = stringValue(candidate.messageId);
1506
+ return messageId ? { type: "message", messageId } : void 0;
1507
+ }
1508
+ if (candidate.type === "workspace_file") {
1509
+ const workspacePath = stringValue(candidate.workspacePath);
1510
+ return workspacePath ? {
1511
+ type: "workspace_file",
1512
+ workspacePath,
1513
+ fileAssetId: stringValue(candidate.fileAssetId),
1514
+ storageFileId: stringValue(candidate.storageFileId)
1515
+ } : void 0;
1516
+ }
1517
+ if (candidate.type === "artifact") {
1518
+ const artifactId = stringValue(candidate.artifactId);
1519
+ return artifactId ? { type: "artifact", artifactId } : void 0;
1520
+ }
1521
+ if (candidate.type === "browser") {
1522
+ const serviceId = stringValue(candidate.serviceId);
1523
+ const url = stringValue(candidate.url);
1524
+ return serviceId || url ? { type: "browser", serviceId, url } : void 0;
1525
+ }
1526
+ if (candidate.type === "url") {
1527
+ const url = stringValue(candidate.url);
1528
+ return url ? { type: "url", url } : void 0;
1529
+ }
1530
+ return void 0;
1531
+ }
1532
+ function isSourceKind(value) {
1533
+ return value === "attachment" || value === "code" || value === "quote" || value === "image" || value === "web_page" || value === "file_element" || value === "knowledge" || value === "skill" || value === "plugin" || value === "sub_agent";
1534
+ }
1535
+ function contributionFromPart(part) {
1536
+ if (part.type !== "component" || !isObject(part.data)) return null;
1537
+ const data = part.data;
1538
+ const direct = normalizeTaskSummaryContribution(data.taskSummary);
1539
+ if (direct) return direct;
1540
+ if (!isObject(data._meta)) return null;
1541
+ return normalizeTaskSummaryContribution(
1542
+ data._meta["xpertai/taskSummary"]
1543
+ );
1544
+ }
1545
+ function extractPlan(message) {
1546
+ const match = PLAN_PATTERN.exec(messageText(message.content));
1547
+ const markdown = match?.[1]?.trim();
1548
+ if (!markdown) return void 0;
1549
+ const title = markdown.split(/\r?\n/).map((line) => line.replace(/^#{1,6}\s+/, "").trim()).find(Boolean);
1550
+ const excerpt = markdown.replace(/\s+/g, " ").trim();
1551
+ return {
1552
+ title: title ?? "Plan",
1553
+ excerpt: excerpt.length <= 160 ? excerpt : `${excerpt.slice(0, 157).trimEnd()}...`,
1554
+ messageId: message.id,
1555
+ updatedAt: message.updatedAt ?? message.createdAt
1556
+ };
1557
+ }
1558
+ function artifactKind(value) {
1559
+ switch (value) {
1560
+ case "file":
1561
+ case "image":
1562
+ case "document":
1563
+ case "spreadsheet":
1564
+ case "presentation":
1565
+ case "site":
1566
+ case "url":
1567
+ case "mcp_app":
1568
+ return value;
1569
+ case "html":
1570
+ return "site";
1571
+ case "markdown":
1572
+ case "pdf":
1573
+ return "document";
1574
+ case "pptx":
1575
+ return "presentation";
1576
+ default:
1577
+ return null;
1578
+ }
1579
+ }
1580
+ function knownPartOutputs(part, message) {
1581
+ const updatedAt = message.updatedAt ?? message.createdAt;
1582
+ if (part.type === "image_url") {
1583
+ const url = stringValue(part.image_url) ?? (isObject(part.image_url) && "url" in part.image_url ? stringValue(part.image_url.url) : void 0);
1584
+ return url ? [
1585
+ {
1586
+ id: `image:${url}`,
1587
+ kind: "image",
1588
+ title: stringValue(part.title) ?? "Image",
1589
+ resource: { type: "url", url },
1590
+ messageId: message.id,
1591
+ updatedAt
1592
+ }
1593
+ ] : [];
1594
+ }
1595
+ if (part.type === "iframe") {
1596
+ const url = stringValue(part.url) ?? (isObject(part.data) ? stringValue(part.data.url) : void 0);
1597
+ return url ? [
1598
+ {
1599
+ id: `url:${url}`,
1600
+ kind: "url",
1601
+ title: stringValue(part.title) ?? url,
1602
+ resource: { type: "url", url },
1603
+ messageId: message.id,
1604
+ updatedAt
1605
+ }
1606
+ ] : [];
1607
+ }
1608
+ if (part.type !== "component" || !isObject(part.data)) return [];
1609
+ const data = part.data;
1610
+ const outputs = [...contributionFromPart(part)?.outputs ?? []];
1611
+ if (data.type === "McpApp") {
1612
+ outputs.push({
1613
+ id: `mcp-app:${stringValue(part.id) ?? message.id ?? "message"}`,
1614
+ kind: "mcp_app",
1615
+ title: stringValue(data.title) ?? "MCP App",
1616
+ resource: message.id ? { type: "message", messageId: message.id } : void 0,
1617
+ messageId: message.id,
1618
+ updatedAt
1619
+ });
1620
+ }
1621
+ if (isObject(data.artifact)) {
1622
+ const artifact = data.artifact;
1623
+ const artifactId = stringValue(artifact.artifactId) ?? stringValue(artifact.id);
1624
+ const workspacePath = stringValue(artifact.workspacePath);
1625
+ const kind = artifactKind(artifact.kind) ?? "file";
1626
+ const id = artifactId ?? stringValue(artifact.fileAssetId) ?? workspacePath;
1627
+ if (kind && id && (artifactId || workspacePath)) {
1628
+ outputs.push({
1629
+ id: `artifact:${id}`,
1630
+ kind,
1631
+ title: stringValue(artifact.title) ?? id,
1632
+ description: stringValue(artifact.description),
1633
+ resource: artifactId ? { type: "artifact", artifactId } : {
1634
+ type: "workspace_file",
1635
+ workspacePath,
1636
+ fileAssetId: stringValue(artifact.fileAssetId),
1637
+ storageFileId: stringValue(artifact.storageFileId)
1638
+ },
1639
+ messageId: message.id,
1640
+ updatedAt
1641
+ });
1642
+ }
1643
+ }
1644
+ for (const value of [data.artifactLink, data.file]) {
1645
+ if (!isObject(value)) continue;
1646
+ const artifact = value;
1647
+ const artifactId = stringValue(artifact.artifactId) ?? stringValue(artifact.id);
1648
+ const workspacePath = stringValue(artifact.workspacePath);
1649
+ const id = artifactId ?? stringValue(artifact.fileAssetId) ?? workspacePath;
1650
+ if (!id || !artifactId && !workspacePath) continue;
1651
+ outputs.push({
1652
+ id: `artifact:${id}`,
1653
+ kind: artifactKind(artifact.kind) ?? "file",
1654
+ title: stringValue(artifact.title) ?? id,
1655
+ description: stringValue(artifact.description),
1656
+ resource: artifactId ? { type: "artifact", artifactId } : {
1657
+ type: "workspace_file",
1658
+ workspacePath,
1659
+ fileAssetId: stringValue(artifact.fileAssetId),
1660
+ storageFileId: stringValue(artifact.storageFileId)
1661
+ },
1662
+ messageId: message.id,
1663
+ updatedAt
1664
+ });
1665
+ }
1666
+ return outputs;
1667
+ }
1668
+ function sourceFromReference(reference, message) {
1669
+ const updatedAt = message.updatedAt ?? message.createdAt;
1670
+ const common = {
1671
+ id: reference.id ?? `${reference.type}:${reference.text}`,
1672
+ title: reference.label?.trim() || reference.text.trim().slice(0, 80),
1673
+ messageId: message.id,
1674
+ updatedAt
1675
+ };
1676
+ if (reference.type === "code") {
1677
+ return {
1678
+ ...common,
1679
+ kind: "code",
1680
+ title: reference.label ?? reference.path,
1681
+ description: `${reference.path}:${reference.startLine}-${reference.endLine}`,
1682
+ resource: message.id ? { type: "message", messageId: message.id } : void 0
1683
+ };
1684
+ }
1685
+ if (reference.type === "image") {
1686
+ return {
1687
+ ...common,
1688
+ kind: "image",
1689
+ title: reference.name ?? common.title,
1690
+ resource: reference.url ? { type: "url", url: reference.url } : void 0
1691
+ };
1692
+ }
1693
+ if (reference.type === "element") {
1694
+ return {
1695
+ ...common,
1696
+ kind: "web_page",
1697
+ title: reference.pageTitle ?? reference.pageUrl,
1698
+ description: reference.pageUrl,
1699
+ resource: {
1700
+ type: "browser",
1701
+ serviceId: reference.serviceId,
1702
+ url: reference.pageUrl
1703
+ }
1704
+ };
1705
+ }
1706
+ if (reference.type === "file_element") {
1707
+ return {
1708
+ ...common,
1709
+ kind: "file_element",
1710
+ title: reference.documentTitle ?? reference.filePath,
1711
+ description: reference.filePath,
1712
+ resource: { type: "workspace_file", workspacePath: reference.filePath }
1713
+ };
1714
+ }
1715
+ return { ...common, kind: "quote", description: reference.source };
1716
+ }
1717
+ function fileSources(files, message) {
1718
+ return (files ?? []).flatMap((file) => {
1719
+ const id = stringValue(file.fileAssetId) ?? stringValue(file.id) ?? stringValue(file.storageFileId);
1720
+ const title = stringValue(file.originalName) ?? stringValue(file.name) ?? stringValue(file.fileName);
1721
+ if (!id || !title) return [];
1722
+ const workspacePath = stringValue(file.workspacePath);
1723
+ return [
1724
+ {
1725
+ id: `attachment:${id}`,
1726
+ kind: "attachment",
1727
+ title,
1728
+ resource: workspacePath ? {
1729
+ type: "workspace_file",
1730
+ workspacePath,
1731
+ fileAssetId: stringValue(file.fileAssetId) ?? stringValue(file.id),
1732
+ storageFileId: stringValue(file.storageFileId)
1733
+ } : message.id ? { type: "message", messageId: message.id } : void 0,
1734
+ messageId: message.id,
1735
+ updatedAt: message.updatedAt ?? message.createdAt
1736
+ }
1737
+ ];
1738
+ });
1739
+ }
1740
+ function capabilitySources(message) {
1741
+ const selection = message.runtimeCapabilities;
1742
+ if (!selection) return [];
1743
+ const updatedAt = message.updatedAt ?? message.createdAt;
1744
+ const common = { messageId: message.id, updatedAt };
1745
+ return [
1746
+ ...selection.skills.ids.map((id) => ({
1747
+ ...common,
1748
+ id: `skill:${id}`,
1749
+ kind: "skill",
1750
+ title: id
1751
+ })),
1752
+ ...selection.plugins.nodeKeys.map((id) => ({
1753
+ ...common,
1754
+ id: `plugin:${id}`,
1755
+ kind: "plugin",
1756
+ title: id
1757
+ }))
1758
+ ];
1759
+ }
1760
+ function collectLiveTaskSummary({
1761
+ messages,
1762
+ goal,
1763
+ todos,
1764
+ pending,
1765
+ running,
1766
+ agentNames
1767
+ }) {
1768
+ const contributions = messages.flatMap((message) => [
1769
+ ...message.taskSummary?.version === 1 ? [message.taskSummary] : [],
1770
+ ...contentParts(message.content).flatMap(
1771
+ (part) => contributionFromPart(part) ?? []
1772
+ )
1773
+ ]);
1774
+ const messagePlans = messages.flatMap(
1775
+ (message) => extractPlan(message) ?? []
1776
+ );
1777
+ const agentRuns = messages.flatMap(
1778
+ (message) => (message.agentRuns ?? []).filter((run) => Boolean(run.parentId)).map((run) => ({
1779
+ id: run.id,
1780
+ parentId: run.parentId,
1781
+ level: agentRunLevel(run, messages),
1782
+ agentKey: run.agentKey,
1783
+ title: (run.agentKey ? agentNames?.get(run.agentKey) : void 0) ?? run.title ?? run.xpertName ?? run.agentKey ?? "Agent",
1784
+ status: taskSummaryAgentStatus(run.status),
1785
+ elapsedTime: run.elapsedTime,
1786
+ error: typeof run.error === "string" ? run.error : void 0,
1787
+ messageId: message.id,
1788
+ updatedAt: run.updatedAt ?? run.endedAt ?? run.startedAt ?? message.updatedAt
1789
+ }))
1790
+ );
1791
+ return {
1792
+ goal,
1793
+ plan: newest([
1794
+ ...contributions.flatMap((item) => item.plan ?? []),
1795
+ ...messagePlans
1796
+ ]),
1797
+ todos: todos ? {
1798
+ componentId: todos.componentId,
1799
+ title: todos.title,
1800
+ items: todos.items,
1801
+ updatedAt: todos.endDate ?? todos.createdDate
1802
+ } : newest(contributions.flatMap((item) => item.todos ?? [])),
1803
+ outputs: mergeLatest([
1804
+ ...contributions.flatMap((item) => item.outputs ?? []),
1805
+ ...messages.flatMap(
1806
+ (message) => contentParts(message.content).flatMap(
1807
+ (part) => knownPartOutputs(part, message)
1808
+ )
1809
+ )
1810
+ ]),
1811
+ sources: mergeLatest([
1812
+ ...contributions.flatMap((item) => item.sources ?? []).filter((source) => source.kind !== "sub_agent"),
1813
+ ...messages.flatMap((message) => [
1814
+ ...(message.references ?? []).map(
1815
+ (reference) => sourceFromReference(reference, message)
1816
+ ),
1817
+ ...fileSources(message.fileAssets, message),
1818
+ ...fileSources(message.attachments, message),
1819
+ ...capabilitySources(message)
1820
+ ])
1821
+ ]),
1822
+ agents: mergeAgents(agentRuns),
1823
+ pending: pending ?? [],
1824
+ running: running ?? []
1825
+ };
1826
+ }
1827
+ function mergeTaskSummary(history, live, historySections) {
1828
+ const outputs = mergeLatest([
1829
+ ...historySections?.outputs ?? history?.outputs.items ?? [],
1830
+ ...live.outputs
1831
+ ]);
1832
+ const sources = mergeLatest([
1833
+ ...historySections?.sources ?? history?.sources.items ?? [],
1834
+ ...live.sources
1835
+ ]);
1836
+ const agents = mergeAgents([
1837
+ ...(historySections?.agents ?? history?.agents.items ?? []).filter(
1838
+ (agent) => Boolean(agent.parentId)
1839
+ ),
1840
+ ...live.agents
1841
+ ]);
1842
+ const pending = mergePending([
1843
+ ...historySections?.pending ?? history?.pending.items ?? [],
1844
+ ...live.pending
1845
+ ]);
1846
+ return {
1847
+ goal: live.goal ?? history?.task.goal,
1848
+ plan: newest(
1849
+ [history?.task.plan, live.plan].filter(
1850
+ (item) => Boolean(item)
1851
+ )
1852
+ ),
1853
+ todos: newest(
1854
+ [history?.task.todos, live.todos].filter(
1855
+ (item) => Boolean(item)
1856
+ )
1857
+ ),
1858
+ outputs,
1859
+ sources,
1860
+ agents,
1861
+ pending,
1862
+ running: live.running,
1863
+ totals: {
1864
+ outputs: Math.max(history?.outputs.total ?? 0, outputs.length),
1865
+ sources: Math.max(history?.sources.total ?? 0, sources.length),
1866
+ agents: agents.length,
1867
+ pending: Math.max(history?.pending.total ?? 0, pending.length)
1868
+ }
1869
+ };
1870
+ }
1871
+ function mergeLatest(items) {
1872
+ const byId = /* @__PURE__ */ new Map();
1873
+ items.forEach((item) => {
1874
+ const current = byId.get(item.id);
1875
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1876
+ byId.set(item.id, item);
1877
+ }
1878
+ });
1879
+ return [...byId.values()].sort(
1880
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1881
+ );
1882
+ }
1883
+ function mergeAgents(items) {
1884
+ const byAgent = /* @__PURE__ */ new Map();
1885
+ items.forEach((item) => {
1886
+ const key = item.agentKey?.trim() || item.id;
1887
+ const current = byAgent.get(key);
1888
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1889
+ byAgent.set(key, item);
1890
+ }
1891
+ });
1892
+ return [...byAgent.values()].sort(
1893
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1894
+ );
1895
+ }
1896
+ function mergePending(items) {
1897
+ const byId = new Map(items.map((item) => [item.id, item]));
1898
+ return [...byId.values()].sort(
1899
+ (left, right) => timestamp(right.createdAt) - timestamp(left.createdAt)
1900
+ );
1901
+ }
1902
+ function taskSummaryAgentStatus(status) {
1903
+ switch (status) {
1904
+ case "running":
1905
+ case "success":
1906
+ case "error":
1907
+ case "pending":
1908
+ case "timeout":
1909
+ case "interrupted":
1910
+ return status;
1911
+ default:
1912
+ return void 0;
1913
+ }
1914
+ }
1915
+ function newest(items) {
1916
+ return [...items].sort(
1917
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1918
+ )[0];
1919
+ }
1920
+ function agentRunLevel(run, messages) {
1921
+ const byId = new Map(
1922
+ messages.flatMap(
1923
+ (message) => (message.agentRuns ?? []).map((item) => [item.id, item])
1924
+ )
1925
+ );
1926
+ let parentId = run.parentId;
1927
+ let level = 0;
1928
+ const visited = /* @__PURE__ */ new Set();
1929
+ while (parentId && !visited.has(parentId)) {
1930
+ visited.add(parentId);
1931
+ level += 1;
1932
+ parentId = byId.get(parentId)?.parentId;
1933
+ }
1934
+ return level;
1935
+ }
1936
+
1280
1937
  // src/providers/Stream.tsx
1281
1938
  var import_jsx_runtime2 = require("react/jsx-runtime");
1282
1939
  var import_meta = {};
@@ -1714,6 +2371,39 @@ var en_US_default = {
1714
2371
  failed: "Failed to render diagram"
1715
2372
  }
1716
2373
  },
2374
+ taskSummary: {
2375
+ title: "Task summary",
2376
+ description: "Current task, outputs, sources, running services, agent activity, and pending requests.",
2377
+ open: "Open task summary",
2378
+ empty: "Task activity will appear here.",
2379
+ historyError: "Some historical summary data failed to load. Live activity is still available.",
2380
+ retry: "Retry",
2381
+ viewAll: "View all",
2382
+ loadMore: "Load more",
2383
+ collapse: "Show less",
2384
+ createOutput: "Create files or sites",
2385
+ addOutput: "Create output",
2386
+ addSource: "Add source",
2387
+ sections: {
2388
+ task: "Task",
2389
+ outputs: "Outputs",
2390
+ sources: "Sources",
2391
+ running: "Running",
2392
+ agents: "Agent activity",
2393
+ pending: "Pending"
2394
+ },
2395
+ status: {
2396
+ pending: "Pending",
2397
+ in_progress: "In progress",
2398
+ completed: "Completed"
2399
+ },
2400
+ pending: {
2401
+ approval: "Approval required",
2402
+ userInput: "Input required",
2403
+ followUp: "Pending follow-up message",
2404
+ steer: "Pending steering message"
2405
+ }
2406
+ },
1717
2407
  thread: {
1718
2408
  errorToast: "An error occurred. Please try again.",
1719
2409
  errorLabel: "Error:",
@@ -2122,6 +2812,39 @@ var zh_CN_default = {
2122
2812
  failed: "\u56FE\u8868\u6E32\u67D3\u5931\u8D25"
2123
2813
  }
2124
2814
  },
2815
+ taskSummary: {
2816
+ title: "\u4EFB\u52A1\u6458\u8981",
2817
+ description: "\u5F53\u524D\u4EFB\u52A1\u3001\u4EA7\u51FA\u3001\u6765\u6E90\u3001\u8FD0\u884C\u4E2D\u670D\u52A1\u3001Agent \u6D3B\u52A8\u548C\u5F85\u5904\u7406\u8BF7\u6C42\u3002",
2818
+ open: "\u6253\u5F00\u4EFB\u52A1\u6458\u8981",
2819
+ empty: "\u4EFB\u52A1\u6D3B\u52A8\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002",
2820
+ historyError: "\u90E8\u5206\u5386\u53F2\u6458\u8981\u52A0\u8F7D\u5931\u8D25\uFF0C\u5B9E\u65F6\u6D3B\u52A8\u4ECD\u53EF\u4F7F\u7528\u3002",
2821
+ retry: "\u91CD\u8BD5",
2822
+ viewAll: "\u67E5\u770B\u5168\u90E8",
2823
+ loadMore: "\u52A0\u8F7D\u66F4\u591A",
2824
+ collapse: "\u6536\u8D77",
2825
+ createOutput: "\u521B\u5EFA\u6587\u4EF6\u6216\u7AD9\u70B9",
2826
+ addOutput: "\u521B\u5EFA\u4EA7\u51FA",
2827
+ addSource: "\u6DFB\u52A0\u6765\u6E90",
2828
+ sections: {
2829
+ task: "\u4EFB\u52A1",
2830
+ outputs: "\u4EA7\u51FA",
2831
+ sources: "\u6765\u6E90",
2832
+ running: "\u8FD0\u884C\u4E2D",
2833
+ agents: "Agent \u6D3B\u52A8",
2834
+ pending: "\u5F85\u5904\u7406"
2835
+ },
2836
+ status: {
2837
+ pending: "\u5F85\u5904\u7406",
2838
+ in_progress: "\u8FDB\u884C\u4E2D",
2839
+ completed: "\u5DF2\u5B8C\u6210"
2840
+ },
2841
+ pending: {
2842
+ approval: "\u9700\u8981\u5BA1\u6279",
2843
+ userInput: "\u9700\u8981\u8F93\u5165",
2844
+ followUp: "\u7B49\u5F85\u53D1\u9001\u7684\u8DDF\u8FDB\u6D88\u606F",
2845
+ steer: "\u7B49\u5F85\u53D1\u9001\u7684\u5F15\u5BFC\u6D88\u606F"
2846
+ }
2847
+ },
2125
2848
  thread: {
2126
2849
  errorToast: "\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u91CD\u8BD5\u3002",
2127
2850
  errorLabel: "\u9519\u8BEF\uFF1A",
@@ -4853,8 +5576,8 @@ function JsonTreeNode({
4853
5576
  depth = 0
4854
5577
  }) {
4855
5578
  const isArray = Array.isArray(value);
4856
- const isObject = isJsonObjectValue(value);
4857
- const isExpandable = isArray || isObject;
5579
+ const isObject2 = isJsonObjectValue(value);
5580
+ const isExpandable = isArray || isObject2;
4858
5581
  const [isExpanded, setIsExpanded] = React18.useState(depth < 2);
4859
5582
  if (!isExpandable) {
4860
5583
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex min-w-0 gap-2 leading-6", children: [
@@ -5249,7 +5972,7 @@ function HITLApprovalPanel({
5249
5972
  }
5250
5973
  const argsText = currentDraft.argsText ?? formatArgs(currentAction.args);
5251
5974
  const argsJsonValue = toJsonValue(currentAction.args) ?? {};
5252
- const messageText = currentDraft.message ?? "";
5975
+ const messageText2 = currentDraft.message ?? "";
5253
5976
  const isCurrentInvalid = validation.error?.actionIndex === currentActionIndex;
5254
5977
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5255
5978
  "section",
@@ -5411,7 +6134,7 @@ function HITLApprovalPanel({
5411
6134
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5412
6135
  "textarea",
5413
6136
  {
5414
- value: messageText,
6137
+ value: messageText2,
5415
6138
  onChange: (event) => updateCurrentDraft({
5416
6139
  ...currentDraft,
5417
6140
  message: event.target.value
@@ -6874,6 +7597,59 @@ var UploadDroppedFiles = React23.forwardRef(function UploadDroppedFiles2({
6874
7597
  );
6875
7598
  });
6876
7599
 
7600
+ // src/components/chat/message-files.ts
7601
+ function addIdentity(identities, value) {
7602
+ const identity = value?.trim();
7603
+ if (identity) {
7604
+ identities.add(identity);
7605
+ }
7606
+ }
7607
+ function getAttachmentIdentities(file) {
7608
+ const identities = /* @__PURE__ */ new Set();
7609
+ addIdentity(identities, file.id);
7610
+ addIdentity(identities, file.fileId);
7611
+ addIdentity(identities, file.storageFileId);
7612
+ addIdentity(identities, file.url);
7613
+ addIdentity(identities, file.fileUrl);
7614
+ addIdentity(identities, file.thumbUrl);
7615
+ return identities;
7616
+ }
7617
+ function getImageReferenceIdentities(references) {
7618
+ const identities = /* @__PURE__ */ new Set();
7619
+ references.forEach((reference) => {
7620
+ if (reference.type !== "image") {
7621
+ return;
7622
+ }
7623
+ addIdentity(identities, reference.id);
7624
+ addIdentity(identities, reference.fileId);
7625
+ addIdentity(identities, reference.url);
7626
+ });
7627
+ return identities;
7628
+ }
7629
+ function getVisibleHumanAttachments(attachments, references) {
7630
+ const imageReferenceIdentities = getImageReferenceIdentities(references);
7631
+ const visibleAttachmentIdentities = /* @__PURE__ */ new Set();
7632
+ return attachments.filter((attachment) => {
7633
+ const identities = getAttachmentIdentities(attachment);
7634
+ const isImageReference = [...identities].some(
7635
+ (identity) => imageReferenceIdentities.has(identity)
7636
+ );
7637
+ if (isImageReference) {
7638
+ return false;
7639
+ }
7640
+ const isDuplicate = [...identities].some(
7641
+ (identity) => visibleAttachmentIdentities.has(identity)
7642
+ );
7643
+ if (isDuplicate) {
7644
+ return false;
7645
+ }
7646
+ identities.forEach(
7647
+ (identity) => visibleAttachmentIdentities.add(identity)
7648
+ );
7649
+ return true;
7650
+ });
7651
+ }
7652
+
6877
7653
  // src/components/chat/usePetAutoState.ts
6878
7654
  var React24 = __toESM(require("react"), 1);
6879
7655
  function usePetAutoState({
@@ -7837,14 +8613,14 @@ function isComponentContent(content) {
7837
8613
  }
7838
8614
  function parseDateValue(value) {
7839
8615
  if (value instanceof Date) {
7840
- const timestamp2 = value.getTime();
7841
- return Number.isNaN(timestamp2) ? null : timestamp2;
8616
+ const timestamp3 = value.getTime();
8617
+ return Number.isNaN(timestamp3) ? null : timestamp3;
7842
8618
  }
7843
8619
  if (typeof value !== "string") {
7844
8620
  return null;
7845
8621
  }
7846
- const timestamp = Date.parse(value);
7847
- return Number.isNaN(timestamp) ? null : timestamp;
8622
+ const timestamp2 = Date.parse(value);
8623
+ return Number.isNaN(timestamp2) ? null : timestamp2;
7848
8624
  }
7849
8625
  function readContentTitle(content) {
7850
8626
  if (typeof content === "string") return void 0;
@@ -10611,14 +11387,14 @@ function getToolStepData(content) {
10611
11387
  }
10612
11388
  function parseStepDate(value) {
10613
11389
  if (value instanceof Date) {
10614
- const timestamp2 = value.getTime();
10615
- return Number.isNaN(timestamp2) ? null : timestamp2;
11390
+ const timestamp3 = value.getTime();
11391
+ return Number.isNaN(timestamp3) ? null : timestamp3;
10616
11392
  }
10617
11393
  if (typeof value !== "string") {
10618
11394
  return null;
10619
11395
  }
10620
- const timestamp = Date.parse(value);
10621
- return Number.isNaN(timestamp) ? null : timestamp;
11396
+ const timestamp2 = Date.parse(value);
11397
+ return Number.isNaN(timestamp2) ? null : timestamp2;
10622
11398
  }
10623
11399
  function isThreadKnownIdle(isThreadRunning) {
10624
11400
  return isThreadRunning === false;
@@ -12882,14 +13658,14 @@ function MemoryBlock({ content }) {
12882
13658
  }
12883
13659
  function parseStepDate2(value) {
12884
13660
  if (value instanceof Date) {
12885
- const timestamp2 = value.getTime();
12886
- return Number.isNaN(timestamp2) ? null : timestamp2;
13661
+ const timestamp3 = value.getTime();
13662
+ return Number.isNaN(timestamp3) ? null : timestamp3;
12887
13663
  }
12888
13664
  if (typeof value !== "string") {
12889
13665
  return null;
12890
13666
  }
12891
- const timestamp = Date.parse(value);
12892
- return Number.isNaN(timestamp) ? null : timestamp;
13667
+ const timestamp2 = Date.parse(value);
13668
+ return Number.isNaN(timestamp2) ? null : timestamp2;
12893
13669
  }
12894
13670
  function formatStepDuration3(durationMs) {
12895
13671
  if (durationMs < 1e3) {
@@ -13658,9 +14434,9 @@ var getThreadTitle = (threadRecord) => {
13658
14434
  };
13659
14435
  var toDate = (value) => {
13660
14436
  if (!value) return void 0;
13661
- const timestamp = Date.parse(value);
13662
- if (Number.isNaN(timestamp)) return void 0;
13663
- return new Date(timestamp);
14437
+ const timestamp2 = Date.parse(value);
14438
+ if (Number.isNaN(timestamp2)) return void 0;
14439
+ return new Date(timestamp2);
13664
14440
  };
13665
14441
  var getErrorMessage2 = (error) => {
13666
14442
  if (!error) return void 0;
@@ -16415,42 +17191,478 @@ function buildMessageNavigationItems(messages, options) {
16415
17191
  return items;
16416
17192
  }
16417
17193
 
16418
- // src/components/chat.tsx
16419
- var import_jsx_runtime57 = require("react/jsx-runtime");
16420
- var import_meta2 = {};
16421
- var defaultApiUrl2 = import_meta2.env.VITE_XPERTAI_API_URL;
16422
- var COMPOSER_INPUT_MAX_HEIGHT = 128;
16423
- var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
16424
- var GOAL_RUN_INPUT = "Continue working toward the active goal.";
16425
- function isGoalAdapter(value) {
16426
- return Boolean(value) && typeof value === "object" && typeof value.getGoal === "function" && typeof value.setGoal === "function" && typeof value.updateGoal === "function" && typeof value.clearGoal === "function";
16427
- }
16428
- function formatGoalElapsed(seconds) {
16429
- if (seconds < 60) {
16430
- return `${seconds}s`;
16431
- }
16432
- const minutes = Math.floor(seconds / 60);
16433
- const remainingSeconds = seconds % 60;
16434
- return remainingSeconds ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
16435
- }
16436
- async function readImageDimensions(file) {
16437
- if (typeof window === "undefined" || typeof URL === "undefined") {
16438
- return {};
16439
- }
16440
- return new Promise((resolve) => {
16441
- const objectUrl = URL.createObjectURL(file);
16442
- const image = new window.Image();
16443
- const cleanup = () => {
16444
- URL.revokeObjectURL(objectUrl);
16445
- };
16446
- image.onload = () => {
16447
- resolve({
16448
- width: image.naturalWidth || void 0,
16449
- height: image.naturalHeight || void 0
16450
- });
16451
- cleanup();
17194
+ // src/hooks/useTaskSummary.ts
17195
+ var React52 = __toESM(require("react"), 1);
17196
+ function useTaskSummary({
17197
+ enabled,
17198
+ conversationId,
17199
+ client,
17200
+ live
17201
+ }) {
17202
+ const [loaded, setLoaded] = React52.useState(null);
17203
+ const [historySections, setHistorySections] = React52.useState({});
17204
+ const [historySectionsConversationId, setHistorySectionsConversationId] = React52.useState(null);
17205
+ const [loadingSections, setLoadingSections] = React52.useState({});
17206
+ const [error, setError] = React52.useState(null);
17207
+ const [retryVersion, setRetryVersion] = React52.useState(0);
17208
+ const requestVersionRef = React52.useRef(0);
17209
+ const conversationIdRef = React52.useRef(conversationId);
17210
+ const sectionControllersRef = React52.useRef(
17211
+ /* @__PURE__ */ new Map()
17212
+ );
17213
+ conversationIdRef.current = conversationId;
17214
+ const abortSectionRequests = React52.useCallback(() => {
17215
+ sectionControllersRef.current.forEach((controller) => controller.abort());
17216
+ sectionControllersRef.current.clear();
17217
+ }, []);
17218
+ React52.useEffect(() => {
17219
+ abortSectionRequests();
17220
+ setHistorySections({});
17221
+ setHistorySectionsConversationId(conversationId);
17222
+ setLoadingSections({});
17223
+ setError(null);
17224
+ if (!enabled || !conversationId) {
17225
+ setLoaded(null);
17226
+ setHistorySectionsConversationId(null);
17227
+ return;
17228
+ }
17229
+ const controller = new AbortController();
17230
+ const requestVersion = ++requestVersionRef.current;
17231
+ client.conversations.getTaskSummary(conversationId, { signal: controller.signal }).then((snapshot2) => {
17232
+ if (requestVersionRef.current !== requestVersion) return;
17233
+ setLoaded({ conversationId, snapshot: snapshot2 });
17234
+ }).catch((nextError) => {
17235
+ if (controller.signal.aborted || requestVersionRef.current !== requestVersion)
17236
+ return;
17237
+ setLoaded(null);
17238
+ setError(nextError);
17239
+ });
17240
+ return () => {
17241
+ controller.abort();
17242
+ abortSectionRequests();
17243
+ requestVersionRef.current += 1;
16452
17244
  };
16453
- image.onerror = () => {
17245
+ }, [abortSectionRequests, client, conversationId, enabled, retryVersion]);
17246
+ const snapshot = loaded?.conversationId === conversationId ? loaded.snapshot : null;
17247
+ const activeHistorySections = React52.useMemo(
17248
+ () => historySectionsConversationId === conversationId ? historySections : {},
17249
+ [conversationId, historySections, historySectionsConversationId]
17250
+ );
17251
+ const loadSection = React52.useCallback(
17252
+ async (section) => {
17253
+ if (!enabled || !conversationId || loadingSections[section]) {
17254
+ return;
17255
+ }
17256
+ const current = activeHistorySections[section]?.length ?? 0;
17257
+ const controller = new AbortController();
17258
+ sectionControllersRef.current.get(section)?.abort();
17259
+ sectionControllersRef.current.set(section, controller);
17260
+ setLoadingSections((state) => ({ ...state, [section]: true }));
17261
+ try {
17262
+ const page = await client.conversations.listTaskSummaryItems(
17263
+ conversationId,
17264
+ section,
17265
+ { offset: current, limit: 50, signal: controller.signal }
17266
+ );
17267
+ if (conversationIdRef.current !== conversationId) return;
17268
+ setHistorySections(
17269
+ (state) => ({
17270
+ ...state,
17271
+ [section]: [...state[section] ?? [], ...page.items]
17272
+ })
17273
+ );
17274
+ } catch (nextError) {
17275
+ if (!controller.signal.aborted) {
17276
+ setError(nextError);
17277
+ }
17278
+ } finally {
17279
+ if (sectionControllersRef.current.get(section) === controller) {
17280
+ sectionControllersRef.current.delete(section);
17281
+ }
17282
+ if (conversationIdRef.current === conversationId) {
17283
+ setLoadingSections((state) => ({ ...state, [section]: false }));
17284
+ }
17285
+ }
17286
+ },
17287
+ [
17288
+ activeHistorySections,
17289
+ client,
17290
+ conversationId,
17291
+ enabled,
17292
+ loadingSections
17293
+ ]
17294
+ );
17295
+ return {
17296
+ summary: mergeTaskSummary(snapshot, live, activeHistorySections),
17297
+ historyError: error,
17298
+ retryHistory: () => setRetryVersion((version) => version + 1),
17299
+ loadSection,
17300
+ loadingSections,
17301
+ loadedSectionCounts: {
17302
+ outputs: activeHistorySections.outputs?.length ?? 0,
17303
+ sources: activeHistorySections.sources?.length ?? 0,
17304
+ agents: activeHistorySections.agents?.length ?? 0,
17305
+ pending: activeHistorySections.pending?.length ?? 0
17306
+ }
17307
+ };
17308
+ }
17309
+
17310
+ // src/components/task-summary/TaskSummary.tsx
17311
+ var React53 = __toESM(require("react"), 1);
17312
+ var import_lucide_react30 = require("lucide-react");
17313
+ var import_jsx_runtime57 = require("react/jsx-runtime");
17314
+ var PREVIEW_SIZE = 3;
17315
+ function TaskSummaryTrigger({
17316
+ displayMode = "popover",
17317
+ open: controlledOpen,
17318
+ onOpenChange,
17319
+ ...props
17320
+ }) {
17321
+ const { t } = useChatkitTranslation();
17322
+ const [uncontrolledOpen, setUncontrolledOpen] = React53.useState(false);
17323
+ const open = controlledOpen ?? uncontrolledOpen;
17324
+ const setOpen = React53.useCallback(
17325
+ (nextOpen) => {
17326
+ if (controlledOpen === void 0) {
17327
+ setUncontrolledOpen(nextOpen);
17328
+ }
17329
+ onOpenChange?.(nextOpen);
17330
+ },
17331
+ [controlledOpen, onOpenChange]
17332
+ );
17333
+ const triggerButton = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17334
+ "button",
17335
+ {
17336
+ type: "button",
17337
+ className: "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
17338
+ "aria-label": t("taskSummary.open"),
17339
+ "aria-expanded": open,
17340
+ onClick: displayMode === "docked" ? () => setOpen(!open) : void 0,
17341
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { size: 16 })
17342
+ }
17343
+ );
17344
+ if (displayMode === "docked") {
17345
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
17346
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: triggerButton }),
17347
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17348
+ ] });
17349
+ }
17350
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
17351
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
17352
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PopoverTrigger, { asChild: true, children: triggerButton }) }),
17353
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17354
+ ] }),
17355
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17356
+ PopoverContent,
17357
+ {
17358
+ align: "end",
17359
+ sideOffset: 8,
17360
+ className: "w-[min(20rem,calc(100vw-2rem))] max-h-[min(44rem,calc(100vh-5rem))] overflow-y-auto rounded-2xl border-border/70 bg-popover p-0 shadow-lg",
17361
+ "aria-label": t("taskSummary.title"),
17362
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TaskSummaryContent, { ...props })
17363
+ }
17364
+ )
17365
+ ] });
17366
+ }
17367
+ function TaskSummaryPanel({
17368
+ className,
17369
+ ...props
17370
+ }) {
17371
+ const { t } = useChatkitTranslation();
17372
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17373
+ "aside",
17374
+ {
17375
+ "data-slot": "task-summary-panel",
17376
+ "aria-label": t("taskSummary.title"),
17377
+ className: cn(
17378
+ "h-fit max-h-full overflow-y-auto rounded-2xl border border-border/70 bg-popover text-popover-foreground shadow-lg",
17379
+ className
17380
+ ),
17381
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TaskSummaryContent, { ...props })
17382
+ }
17383
+ );
17384
+ }
17385
+ function TaskSummaryContent({
17386
+ summary,
17387
+ historyError,
17388
+ loadingSections = {},
17389
+ loadedSectionCounts = { outputs: 0, sources: 0, agents: 0, pending: 0 },
17390
+ onRetryHistory,
17391
+ onLoadSection,
17392
+ onNavigateMessage,
17393
+ onFocusComposer,
17394
+ onOpenResource
17395
+ }) {
17396
+ const { t } = useChatkitTranslation();
17397
+ const [expanded, setExpanded] = React53.useState({});
17398
+ const hasTask = Boolean(
17399
+ summary.goal || summary.plan || summary.todos?.items.length
17400
+ );
17401
+ const toggleSection = (section) => {
17402
+ if (expanded[section]) {
17403
+ setExpanded((state) => ({ ...state, [section]: false }));
17404
+ return;
17405
+ }
17406
+ setExpanded((state) => ({ ...state, [section]: true }));
17407
+ if (loadedSectionCounts[section] === 0) {
17408
+ void onLoadSection(section);
17409
+ }
17410
+ };
17411
+ const sectionItems = (section, items) => expanded[section] ? items : items.slice(0, PREVIEW_SIZE);
17412
+ const openSummaryItem = (resource, messageId, title) => {
17413
+ if (resource?.type === "message") {
17414
+ onNavigateMessage(resource.messageId);
17415
+ return;
17416
+ }
17417
+ if (resource) {
17418
+ onOpenResource(resource, messageId, title);
17419
+ return;
17420
+ }
17421
+ if (messageId) {
17422
+ onNavigateMessage(messageId);
17423
+ }
17424
+ };
17425
+ const sectionAction = (section, total2) => {
17426
+ if (total2 <= PREVIEW_SIZE && !expanded[section]) return null;
17427
+ const loading = loadingSections[section];
17428
+ const canLoadMore = Boolean(expanded[section]) && loadedSectionCounts[section] < total2;
17429
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17430
+ "button",
17431
+ {
17432
+ type: "button",
17433
+ className: "mt-1 flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left text-sm text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
17434
+ disabled: loading,
17435
+ onClick: () => canLoadMore ? void onLoadSection(section) : toggleSection(section),
17436
+ children: [
17437
+ loading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Loader2, { className: "size-3 animate-spin" }),
17438
+ !loading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { className: "size-3.5" }),
17439
+ canLoadMore ? t("taskSummary.loadMore") : expanded[section] ? t("taskSummary.collapse") : t("taskSummary.viewAll", { count: total2 })
17440
+ ]
17441
+ }
17442
+ );
17443
+ };
17444
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "divide-y divide-border/70", children: [
17445
+ Boolean(historyError) && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "m-3 flex items-start justify-between gap-3 rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [
17446
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: t("taskSummary.historyError") }),
17447
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17448
+ "button",
17449
+ {
17450
+ type: "button",
17451
+ className: "inline-flex shrink-0 items-center gap-1 font-medium hover:underline",
17452
+ onClick: onRetryHistory,
17453
+ children: [
17454
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.RotateCcw, { className: "size-3" }),
17455
+ t("taskSummary.retry")
17456
+ ]
17457
+ }
17458
+ )
17459
+ ] }),
17460
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17461
+ SummarySection,
17462
+ {
17463
+ title: t("taskSummary.sections.outputs"),
17464
+ children: [
17465
+ summary.outputs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SummaryPrompt, { onClick: onFocusComposer, children: t("taskSummary.createOutput") }) : sectionItems("outputs", summary.outputs).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17466
+ SummaryButton,
17467
+ {
17468
+ title: item.title,
17469
+ description: item.description ?? item.status,
17470
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.FileOutput, { className: "size-4" }),
17471
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17472
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17473
+ },
17474
+ item.id
17475
+ )),
17476
+ sectionAction("outputs", summary.totals.outputs)
17477
+ ]
17478
+ }
17479
+ ),
17480
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17481
+ SummarySection,
17482
+ {
17483
+ title: t("taskSummary.sections.sources"),
17484
+ children: [
17485
+ sectionItems("sources", summary.sources).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17486
+ SummaryButton,
17487
+ {
17488
+ title: item.title,
17489
+ description: item.description,
17490
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.BookOpen, { className: "size-4" }),
17491
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17492
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17493
+ },
17494
+ item.id
17495
+ )),
17496
+ sectionAction("sources", summary.totals.sources)
17497
+ ]
17498
+ }
17499
+ ),
17500
+ hasTask && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.task"), children: [
17501
+ summary.goal && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17502
+ SummaryButton,
17503
+ {
17504
+ title: summary.goal.objective,
17505
+ description: summary.goal.status,
17506
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Target, { className: "size-4" }),
17507
+ onClick: onFocusComposer
17508
+ }
17509
+ ),
17510
+ summary.plan && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17511
+ SummaryButton,
17512
+ {
17513
+ title: summary.plan.title,
17514
+ description: summary.plan.excerpt,
17515
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { className: "size-4" }),
17516
+ onClick: () => summary.plan?.messageId ? onNavigateMessage(summary.plan.messageId) : onFocusComposer()
17517
+ }
17518
+ ),
17519
+ (summary.todos?.items ?? []).slice(0, PREVIEW_SIZE).map((todo) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17520
+ SummaryButton,
17521
+ {
17522
+ title: todo.content,
17523
+ description: t(`taskSummary.status.${todo.status}`),
17524
+ leading: todo.status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.CheckCircle2, { className: "size-4 text-muted-foreground" }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.CircleEllipsis, { className: "size-4 text-muted-foreground" }),
17525
+ onClick: () => summary.todos?.messageId ? onNavigateMessage(summary.todos.messageId) : onFocusComposer()
17526
+ },
17527
+ todo.id
17528
+ ))
17529
+ ] }),
17530
+ summary.running.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SummarySection, { title: t("taskSummary.sections.running"), children: summary.running.slice(0, PREVIEW_SIZE).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17531
+ SummaryButton,
17532
+ {
17533
+ title: item.title,
17534
+ description: item.description ?? item.status,
17535
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.PlayCircle, { className: "size-4" }),
17536
+ trailing: item.resource ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17537
+ onClick: () => item.resource && onOpenResource(item.resource, void 0, item.title)
17538
+ },
17539
+ item.id
17540
+ )) }),
17541
+ summary.agents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.agents"), children: [
17542
+ sectionItems("agents", summary.agents).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17543
+ SummaryButton,
17544
+ {
17545
+ title: item.title,
17546
+ description: [item.status, formatElapsed(item.elapsedTime)].filter(Boolean).join(" \xB7 "),
17547
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Bot, { className: "size-4" }),
17548
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17549
+ },
17550
+ item.id
17551
+ )),
17552
+ sectionAction("agents", summary.totals.agents)
17553
+ ] }),
17554
+ summary.pending.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.pending"), children: [
17555
+ sectionItems("pending", summary.pending).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17556
+ SummaryButton,
17557
+ {
17558
+ title: item.title,
17559
+ description: item.description,
17560
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.CircleEllipsis, { className: "size-4" }),
17561
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17562
+ },
17563
+ item.id
17564
+ )),
17565
+ sectionAction("pending", summary.totals.pending)
17566
+ ] })
17567
+ ] });
17568
+ }
17569
+ function SummarySection({
17570
+ title,
17571
+ children
17572
+ }) {
17573
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("section", { "aria-label": title, className: "px-4 py-3", children: [
17574
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex min-h-7 items-center justify-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { className: "text-sm font-medium text-muted-foreground", children: title }) }),
17575
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mt-1 space-y-0.5", children })
17576
+ ] });
17577
+ }
17578
+ function SummaryPrompt({
17579
+ children,
17580
+ onClick
17581
+ }) {
17582
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17583
+ "button",
17584
+ {
17585
+ type: "button",
17586
+ className: "block rounded-md py-1 text-left text-sm text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
17587
+ onClick,
17588
+ children
17589
+ }
17590
+ );
17591
+ }
17592
+ function SummaryButton({
17593
+ title,
17594
+ description,
17595
+ leading,
17596
+ trailing,
17597
+ onClick
17598
+ }) {
17599
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17600
+ "button",
17601
+ {
17602
+ type: "button",
17603
+ disabled: !onClick,
17604
+ onClick,
17605
+ className: cn(
17606
+ "flex w-full min-w-0 items-start gap-2.5 rounded-lg px-2 py-1.5 text-left transition-colors",
17607
+ onClick && "hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
17608
+ !onClick && "cursor-default"
17609
+ ),
17610
+ children: [
17611
+ leading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: leading }),
17612
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "min-w-0 flex-1", children: [
17613
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "block truncate text-sm font-medium leading-5 text-foreground", children: title }),
17614
+ description && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 block line-clamp-2 text-xs text-muted-foreground", children: description })
17615
+ ] }),
17616
+ trailing && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 text-muted-foreground", children: trailing })
17617
+ ]
17618
+ }
17619
+ );
17620
+ }
17621
+ function formatElapsed(value) {
17622
+ if (typeof value !== "number" || !Number.isFinite(value)) return "";
17623
+ if (value < 1e3) return `${Math.round(value)}ms`;
17624
+ return `${(value / 1e3).toFixed(1)}s`;
17625
+ }
17626
+
17627
+ // src/components/chat.tsx
17628
+ var import_jsx_runtime58 = require("react/jsx-runtime");
17629
+ var import_meta2 = {};
17630
+ var defaultApiUrl2 = import_meta2.env.VITE_XPERTAI_API_URL;
17631
+ var COMPOSER_INPUT_MAX_HEIGHT = 128;
17632
+ var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
17633
+ var GOAL_RUN_INPUT = "Continue working toward the active goal.";
17634
+ var TASK_SUMMARY_PANEL_WIDTH_REM = 20;
17635
+ var TASK_SUMMARY_PANEL_EDGE_INSET_REM = 1.25;
17636
+ var TASK_SUMMARY_PANEL_SAFE_GAP_REM = 0.75;
17637
+ function isGoalAdapter(value) {
17638
+ return Boolean(value) && typeof value === "object" && typeof value.getGoal === "function" && typeof value.setGoal === "function" && typeof value.updateGoal === "function" && typeof value.clearGoal === "function";
17639
+ }
17640
+ function formatGoalElapsed(seconds) {
17641
+ if (seconds < 60) {
17642
+ return `${seconds}s`;
17643
+ }
17644
+ const minutes = Math.floor(seconds / 60);
17645
+ const remainingSeconds = seconds % 60;
17646
+ return remainingSeconds ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
17647
+ }
17648
+ async function readImageDimensions(file) {
17649
+ if (typeof window === "undefined" || typeof URL === "undefined") {
17650
+ return {};
17651
+ }
17652
+ return new Promise((resolve) => {
17653
+ const objectUrl = URL.createObjectURL(file);
17654
+ const image = new window.Image();
17655
+ const cleanup = () => {
17656
+ URL.revokeObjectURL(objectUrl);
17657
+ };
17658
+ image.onload = () => {
17659
+ resolve({
17660
+ width: image.naturalWidth || void 0,
17661
+ height: image.naturalHeight || void 0
17662
+ });
17663
+ cleanup();
17664
+ };
17665
+ image.onerror = () => {
16454
17666
  resolve({});
16455
17667
  cleanup();
16456
17668
  };
@@ -16520,8 +17732,8 @@ function ReferenceChip({
16520
17732
  }) {
16521
17733
  const metaLine = getReferenceMetaLine(reference);
16522
17734
  const isComposer = variant === "composer";
16523
- const Icon = reference.type === "quote" ? import_lucide_react30.Quote : reference.type === "image" ? import_lucide_react30.ImageIcon : import_lucide_react30.FileText;
16524
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17735
+ const Icon = reference.type === "quote" ? import_lucide_react31.Quote : reference.type === "image" ? import_lucide_react31.ImageIcon : import_lucide_react31.FileText;
17736
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
16525
17737
  "div",
16526
17738
  {
16527
17739
  className: cn(
@@ -16530,7 +17742,7 @@ function ReferenceChip({
16530
17742
  ),
16531
17743
  title: getReferenceTitle(reference),
16532
17744
  children: [
16533
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17745
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16534
17746
  Icon,
16535
17747
  {
16536
17748
  size: isComposer ? 14 : 12,
@@ -16540,8 +17752,8 @@ function ReferenceChip({
16540
17752
  )
16541
17753
  }
16542
17754
  ),
16543
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "min-w-0 flex-1", children: [
16544
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17755
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0 flex-1", children: [
17756
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16545
17757
  "div",
16546
17758
  {
16547
17759
  className: cn(
@@ -16551,7 +17763,7 @@ function ReferenceChip({
16551
17763
  children: getReferenceLabel(reference)
16552
17764
  }
16553
17765
  ),
16554
- metaLine && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17766
+ metaLine && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16555
17767
  "div",
16556
17768
  {
16557
17769
  className: cn(
@@ -16562,7 +17774,7 @@ function ReferenceChip({
16562
17774
  }
16563
17775
  )
16564
17776
  ] }),
16565
- onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17777
+ onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16566
17778
  "button",
16567
17779
  {
16568
17780
  type: "button",
@@ -16573,7 +17785,7 @@ function ReferenceChip({
16573
17785
  ),
16574
17786
  title: removeLabel,
16575
17787
  "aria-label": removeLabel,
16576
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.X, { size: 12 })
17788
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.X, { size: 12 })
16577
17789
  }
16578
17790
  )
16579
17791
  ]
@@ -16604,7 +17816,7 @@ function Chat({
16604
17816
  clientSecret: effectiveClientSecret
16605
17817
  });
16606
17818
  const missingConfig = Boolean(missingConfigKind);
16607
- const missingConfigShortMessage = React52.useMemo(() => {
17819
+ const missingConfigShortMessage = React54.useMemo(() => {
16608
17820
  switch (missingConfigKind) {
16609
17821
  case "apiUrl":
16610
17822
  return t("chat.missingApiUrlShort");
@@ -16616,7 +17828,7 @@ function Chat({
16616
17828
  return t("chat.missingConfigShort");
16617
17829
  }
16618
17830
  }, [missingConfigKind, t]);
16619
- const missingConfigDetailMessage = React52.useMemo(() => {
17831
+ const missingConfigDetailMessage = React54.useMemo(() => {
16620
17832
  switch (missingConfigKind) {
16621
17833
  case "apiUrl":
16622
17834
  return t("chat.missingApiUrlDetail");
@@ -16628,26 +17840,26 @@ function Chat({
16628
17840
  return t("chat.missingConfigDetail");
16629
17841
  }
16630
17842
  }, [missingConfigKind, t]);
16631
- const [isHistoryLoading, setIsHistoryLoading] = React52.useState(false);
16632
- const [historyError, setHistoryError] = React52.useState(null);
16633
- const [assistantName, setAssistantName] = React52.useState(null);
16634
- const [assistantAvatar, setAssistantAvatar] = React52.useState(null);
16635
- const [threadGoal, setThreadGoal] = React52.useState(null);
16636
- const [goalError, setGoalError] = React52.useState(null);
16637
- const [isGoalLoading, setIsGoalLoading] = React52.useState(false);
16638
- const [isGoalPanelOpen, setIsGoalPanelOpen] = React52.useState(false);
16639
- const [isGoalObjectiveExpanded, setIsGoalObjectiveExpanded] = React52.useState(false);
16640
- const [goalElapsedStartedAt, setGoalElapsedStartedAt] = React52.useState(null);
17843
+ const [isHistoryLoading, setIsHistoryLoading] = React54.useState(false);
17844
+ const [historyError, setHistoryError] = React54.useState(null);
17845
+ const [assistantName, setAssistantName] = React54.useState(null);
17846
+ const [assistantAvatar, setAssistantAvatar] = React54.useState(null);
17847
+ const [threadGoal, setThreadGoal] = React54.useState(null);
17848
+ const [goalError, setGoalError] = React54.useState(null);
17849
+ const [isGoalLoading, setIsGoalLoading] = React54.useState(false);
17850
+ const [isGoalPanelOpen, setIsGoalPanelOpen] = React54.useState(false);
17851
+ const [isGoalObjectiveExpanded, setIsGoalObjectiveExpanded] = React54.useState(false);
17852
+ const [goalElapsedStartedAt, setGoalElapsedStartedAt] = React54.useState(null);
16641
17853
  const LOADING_DOTS_MIN_DURATION = 800;
16642
17854
  const STREAMING_STATUS_REFRESH_MS = 250;
16643
- const [showLoadingDots, setShowLoadingDots] = React52.useState(false);
16644
- const [streamingNow, setStreamingNow] = React52.useState(() => Date.now());
16645
- const loadingStartTimeRef = React52.useRef(null);
16646
- const lastStreamOutputAtRef = React52.useRef(null);
16647
- React52.useEffect(() => {
17855
+ const [showLoadingDots, setShowLoadingDots] = React54.useState(false);
17856
+ const [streamingNow, setStreamingNow] = React54.useState(() => Date.now());
17857
+ const loadingStartTimeRef = React54.useRef(null);
17858
+ const lastStreamOutputAtRef = React54.useRef(null);
17859
+ React54.useEffect(() => {
16648
17860
  setStream(stream);
16649
17861
  }, [setStream, stream]);
16650
- React52.useEffect(() => {
17862
+ React54.useEffect(() => {
16651
17863
  if (stream.isLoading) {
16652
17864
  if (!loadingStartTimeRef.current) {
16653
17865
  loadingStartTimeRef.current = Date.now();
@@ -16670,7 +17882,7 @@ function Chat({
16670
17882
  }
16671
17883
  }
16672
17884
  }, [stream.isLoading]);
16673
- React52.useEffect(() => {
17885
+ React54.useEffect(() => {
16674
17886
  if (!stream.isLoading) {
16675
17887
  lastStreamOutputAtRef.current = null;
16676
17888
  setStreamingNow(Date.now());
@@ -16680,7 +17892,7 @@ function Chat({
16680
17892
  lastStreamOutputAtRef.current = now;
16681
17893
  setStreamingNow(now);
16682
17894
  }, [stream.messages, stream.isLoading]);
16683
- React52.useEffect(() => {
17895
+ React54.useEffect(() => {
16684
17896
  if (!stream.isLoading) {
16685
17897
  return;
16686
17898
  }
@@ -16689,7 +17901,7 @@ function Chat({
16689
17901
  }, STREAMING_STATUS_REFRESH_MS);
16690
17902
  return () => window.clearInterval(timer);
16691
17903
  }, [stream.isLoading]);
16692
- React52.useEffect(() => {
17904
+ React54.useEffect(() => {
16693
17905
  if (threadGoal?.status === "active" && stream.isLoading) {
16694
17906
  setGoalElapsedStartedAt(Date.now());
16695
17907
  return;
@@ -16701,54 +17913,55 @@ function Chat({
16701
17913
  threadGoal?.id,
16702
17914
  threadGoal?.status
16703
17915
  ]);
16704
- React52.useEffect(() => {
17916
+ React54.useEffect(() => {
16705
17917
  setIsGoalObjectiveExpanded(false);
16706
17918
  }, [threadGoal?.id]);
16707
- const [composerParts, setComposerParts] = React52.useState([]);
16708
- const [renderedComposerParts, setRenderedComposerParts] = React52.useState([]);
16709
- const [composerDomVersion, setComposerDomVersion] = React52.useState(0);
16710
- const [selectedTool, setSelectedTool] = React52.useState(
17919
+ const [composerParts, setComposerParts] = React54.useState([]);
17920
+ const [renderedComposerParts, setRenderedComposerParts] = React54.useState([]);
17921
+ const [composerDomVersion, setComposerDomVersion] = React54.useState(0);
17922
+ const [selectedTool, setSelectedTool] = React54.useState(
16711
17923
  null
16712
17924
  );
16713
- const [planModeEnabled, setPlanModeEnabled] = React52.useState(false);
16714
- const [petSettingsOpen, setPetSettingsOpen] = React52.useState(false);
16715
- const [petLocalSettings, setPetLocalSettings] = React52.useState(() => readPetLocalSettings());
16716
- const [attachmentState, setAttachmentState] = React52.useState({
17925
+ const [planModeEnabled, setPlanModeEnabled] = React54.useState(false);
17926
+ const [petSettingsOpen, setPetSettingsOpen] = React54.useState(false);
17927
+ const [petLocalSettings, setPetLocalSettings] = React54.useState(() => readPetLocalSettings());
17928
+ const [attachmentState, setAttachmentState] = React54.useState({
16717
17929
  uploadedFiles: [],
16718
17930
  hasUploadingFiles: false,
16719
17931
  hasParsingFiles: false
16720
17932
  });
16721
- const [references, setReferences] = React52.useState([]);
16722
- const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React52.useState(false);
16723
- const [quoteSelection, setQuoteSelection] = React52.useState(null);
16724
- const [isAtBottom, setIsAtBottom] = React52.useState(true);
16725
- const [hasUpdatesBelow, setHasUpdatesBelow] = React52.useState(false);
17933
+ const [references, setReferences] = React54.useState([]);
17934
+ const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React54.useState(false);
17935
+ const [quoteSelection, setQuoteSelection] = React54.useState(null);
17936
+ const [isAtBottom, setIsAtBottom] = React54.useState(true);
17937
+ const [hasUpdatesBelow, setHasUpdatesBelow] = React54.useState(false);
16726
17938
  const {
16727
17939
  threads,
16728
17940
  deleteThread,
16729
17941
  refreshThreads,
16730
17942
  isLoading: isThreadsLoading
16731
17943
  } = useThreads();
16732
- const viewportRef = React52.useRef(null);
16733
- const messageNavigationAnchorsRef = React52.useRef(
17944
+ const viewportRef = React54.useRef(null);
17945
+ const chatColumnRef = React54.useRef(null);
17946
+ const messageNavigationAnchorsRef = React54.useRef(
16734
17947
  /* @__PURE__ */ new Map()
16735
17948
  );
16736
- const attachmentsRef = React52.useRef(null);
16737
- const composerInputRef = React52.useRef(null);
16738
- const slashPaletteRef = React52.useRef(null);
16739
- const slashPaletteOptionRefs = React52.useRef(
17949
+ const attachmentsRef = React54.useRef(null);
17950
+ const composerInputRef = React54.useRef(null);
17951
+ const slashPaletteRef = React54.useRef(null);
17952
+ const slashPaletteOptionRefs = React54.useRef(
16740
17953
  []
16741
17954
  );
16742
- const composerPartsRef = React52.useRef([]);
16743
- const pendingComposerCaretOffsetRef = React52.useRef(null);
16744
- const shouldAutoScrollRef = React52.useRef(true);
16745
- const forceFollowRef = React52.useRef(false);
16746
- const previousMessageCountRef = React52.useRef(0);
16747
- const previousScrollTopRef = React52.useRef(0);
16748
- const isPrependingHistoryMessagesRef = React52.useRef(false);
16749
- const autoScrollFrameRef = React52.useRef(null);
16750
- const isPointerDownRef = React52.useRef(false);
16751
- const lastTouchYRef = React52.useRef(null);
17955
+ const composerPartsRef = React54.useRef([]);
17956
+ const pendingComposerCaretOffsetRef = React54.useRef(null);
17957
+ const shouldAutoScrollRef = React54.useRef(true);
17958
+ const forceFollowRef = React54.useRef(false);
17959
+ const previousMessageCountRef = React54.useRef(0);
17960
+ const previousScrollTopRef = React54.useRef(0);
17961
+ const isPrependingHistoryMessagesRef = React54.useRef(false);
17962
+ const autoScrollFrameRef = React54.useRef(null);
17963
+ const isPointerDownRef = React54.useRef(false);
17964
+ const lastTouchYRef = React54.useRef(null);
16752
17965
  const {
16753
17966
  runtimeCapabilities,
16754
17967
  runtimeCapabilitiesReady,
@@ -16777,24 +17990,24 @@ function Chat({
16777
17990
  const resolvedPlaceholder = placeholder ?? t("chat.placeholder");
16778
17991
  const assistantTitle = assistantName || resolvedTitle;
16779
17992
  const petRequired = options?.displayMode === "pet";
16780
- const basePetSettings = React52.useMemo(
17993
+ const basePetSettings = React54.useMemo(
16781
17994
  () => derivePetLocalSettings(options?.pet),
16782
17995
  [options?.pet]
16783
17996
  );
16784
- const displayedPetSettings = React52.useMemo(
17997
+ const displayedPetSettings = React54.useMemo(
16785
17998
  () => ({
16786
17999
  ...petLocalSettings ?? basePetSettings,
16787
18000
  ...petRequired ? { enabled: true } : {}
16788
18001
  }),
16789
18002
  [basePetSettings, petLocalSettings, petRequired]
16790
18003
  );
16791
- const effectivePet = React52.useMemo(() => {
18004
+ const effectivePet = React54.useMemo(() => {
16792
18005
  if (petRequired || petLocalSettings) {
16793
18006
  return buildPetOptionsFromLocalSettings(displayedPetSettings);
16794
18007
  }
16795
18008
  return options?.pet ?? null;
16796
18009
  }, [displayedPetSettings, options?.pet, petLocalSettings, petRequired]);
16797
- const savePetLocalSettings = React52.useCallback(
18010
+ const savePetLocalSettings = React54.useCallback(
16798
18011
  (settings) => {
16799
18012
  const nextSettings = petRequired ? { ...settings, enabled: true } : settings;
16800
18013
  setPetLocalSettings(nextSettings);
@@ -16802,7 +18015,7 @@ function Chat({
16802
18015
  },
16803
18016
  [petRequired]
16804
18017
  );
16805
- const handlePetCommand = React52.useCallback(
18018
+ const handlePetCommand = React54.useCallback(
16806
18019
  (mode) => {
16807
18020
  if (mode === "settings") {
16808
18021
  setPetSettingsOpen(true);
@@ -16824,11 +18037,11 @@ function Chat({
16824
18037
  [displayedPetSettings, effectivePet, petRequired, savePetLocalSettings]
16825
18038
  );
16826
18039
  const inputPlaceholder = selectedTool?.placeholderOverride ?? composer?.placeholder ?? resolvedPlaceholder;
16827
- const messages = React52.useMemo(
18040
+ const messages = React54.useMemo(
16828
18041
  () => stream.messages ?? [],
16829
18042
  [stream.messages]
16830
18043
  );
16831
- const messageNavigationLabels = React52.useMemo(
18044
+ const messageNavigationLabels = React54.useMemo(
16832
18045
  () => ({
16833
18046
  user: t("chat.youLabel"),
16834
18047
  assistant: assistantTitle,
@@ -16847,7 +18060,7 @@ function Chat({
16847
18060
  }),
16848
18061
  [assistantTitle, t]
16849
18062
  );
16850
- const messageNavigationItems = React52.useMemo(
18063
+ const messageNavigationItems = React54.useMemo(
16851
18064
  () => messageNavigationEnabled ? buildMessageNavigationItems(
16852
18065
  messages,
16853
18066
  {
@@ -16870,7 +18083,7 @@ function Chat({
16870
18083
  historyMessagePagination?.isLoadingMore
16871
18084
  );
16872
18085
  const canLoadMoreMessages = Boolean(historyMessagePagination?.hasMore);
16873
- const draft = React52.useMemo(
18086
+ const draft = React54.useMemo(
16874
18087
  () => getComposerPlainText(composerParts),
16875
18088
  [composerParts]
16876
18089
  );
@@ -16884,7 +18097,7 @@ function Chat({
16884
18097
  isEmpty: isComposerInputEmpty,
16885
18098
  isStacked: isComposerStacked
16886
18099
  });
16887
- const pendingFollowUps = React52.useMemo(
18100
+ const pendingFollowUps = React54.useMemo(
16888
18101
  () => sortVisiblePendingFollowUps(stream.pendingFollowUps ?? []),
16889
18102
  [stream.pendingFollowUps]
16890
18103
  );
@@ -16893,7 +18106,7 @@ function Chat({
16893
18106
  const hasPendingHITLRequest = Boolean(stream.pendingHITLRequest);
16894
18107
  const hasPendingInteractiveRequest = hasPendingRequestUserInput || hasPendingHITLRequest;
16895
18108
  const hasPendingTodos = Boolean(stream.todos?.items.length);
16896
- const goalAdapter = React52.useMemo(() => {
18109
+ const goalAdapter = React54.useMemo(() => {
16897
18110
  if (isGoalAdapter(options?.goal)) {
16898
18111
  return options.goal;
16899
18112
  }
@@ -16906,10 +18119,10 @@ function Chat({
16906
18119
  "goal"
16907
18120
  );
16908
18121
  const showGoalStatus = goalCommandAvailable && !hasCompletedGoal && (Boolean(goalError) || threadGoal?.status === "active" && stream.isLoading);
16909
- const clearQuoteSelection = React52.useCallback(() => {
18122
+ const clearQuoteSelection = React54.useCallback(() => {
16910
18123
  setQuoteSelection(null);
16911
18124
  }, []);
16912
- const commitComposerParts = React52.useCallback(
18125
+ const commitComposerParts = React54.useCallback(
16913
18126
  (nextParts, options2) => {
16914
18127
  const normalized = normalizeComposerParts(nextParts);
16915
18128
  const previous = composerPartsRef.current;
@@ -16939,7 +18152,7 @@ function Chat({
16939
18152
  },
16940
18153
  [setRunRuntimeCapabilities]
16941
18154
  );
16942
- const setComposerText = React52.useCallback(
18155
+ const setComposerText = React54.useCallback(
16943
18156
  (text, caretOffset = text.length) => {
16944
18157
  commitComposerParts(createComposerTextParts(text), {
16945
18158
  caretOffset,
@@ -16949,7 +18162,7 @@ function Chat({
16949
18162
  },
16950
18163
  [commitComposerParts]
16951
18164
  );
16952
- const focusComposerAt = React52.useCallback((position) => {
18165
+ const focusComposerAt = React54.useCallback((position) => {
16953
18166
  const nextPosition = position ?? getComposerEditingLength(composerPartsRef.current);
16954
18167
  pendingComposerCaretOffsetRef.current = nextPosition;
16955
18168
  requestAnimationFrame(() => {
@@ -16978,7 +18191,7 @@ function Chat({
16978
18191
  focusComposerAt
16979
18192
  });
16980
18193
  const parentMessenger = useParentMessenger({
16981
- onSetComposerValue: React52.useCallback(
18194
+ onSetComposerValue: React54.useCallback(
16982
18195
  (payload) => {
16983
18196
  if (!payload) {
16984
18197
  return;
@@ -17006,16 +18219,16 @@ function Chat({
17006
18219
  },
17007
18220
  [applyComposerValueRuntimeCapabilities, composer?.tools, setComposerText]
17008
18221
  ),
17009
- onSetRuntimeCapabilities: React52.useCallback(
18222
+ onSetRuntimeCapabilities: React54.useCallback(
17010
18223
  (selection) => {
17011
18224
  applyExternalRuntimeCapabilities(selection);
17012
18225
  },
17013
18226
  [applyExternalRuntimeCapabilities]
17014
18227
  ),
17015
- onFocusComposer: React52.useCallback(() => {
18228
+ onFocusComposer: React54.useCallback(() => {
17016
18229
  composerInputRef.current?.focus();
17017
18230
  }, []),
17018
- onSetPetEnabled: React52.useCallback(
18231
+ onSetPetEnabled: React54.useCallback(
17019
18232
  (enabled) => {
17020
18233
  if (petRequired) {
17021
18234
  return;
@@ -17029,10 +18242,10 @@ function Chat({
17029
18242
  )
17030
18243
  });
17031
18244
  const canMinimizeToPet = parentMessenger?.isParentAvailable === true && isPetEnabled(effectivePet);
17032
- const handleMinimizeToPet = React52.useCallback(() => {
18245
+ const handleMinimizeToPet = React54.useCallback(() => {
17033
18246
  parentMessenger?.sendEvent("chat_minimize_change", { minimized: true });
17034
18247
  }, [parentMessenger]);
17035
- const syncQuoteSelection = React52.useCallback(() => {
18248
+ const syncQuoteSelection = React54.useCallback(() => {
17036
18249
  if (typeof window === "undefined") {
17037
18250
  clearQuoteSelection();
17038
18251
  return;
@@ -17077,23 +18290,23 @@ function Chat({
17077
18290
  left
17078
18291
  });
17079
18292
  }, [clearQuoteSelection]);
17080
- const cancelPendingAutoScroll = React52.useCallback(() => {
18293
+ const cancelPendingAutoScroll = React54.useCallback(() => {
17081
18294
  if (autoScrollFrameRef.current !== null) {
17082
18295
  cancelAnimationFrame(autoScrollFrameRef.current);
17083
18296
  autoScrollFrameRef.current = null;
17084
18297
  }
17085
18298
  }, []);
17086
- const disableAutoFollow = React52.useCallback(() => {
18299
+ const disableAutoFollow = React54.useCallback(() => {
17087
18300
  forceFollowRef.current = false;
17088
18301
  shouldAutoScrollRef.current = false;
17089
18302
  cancelPendingAutoScroll();
17090
18303
  }, [cancelPendingAutoScroll]);
17091
- const enableAutoFollow = React52.useCallback(() => {
18304
+ const enableAutoFollow = React54.useCallback(() => {
17092
18305
  forceFollowRef.current = true;
17093
18306
  shouldAutoScrollRef.current = true;
17094
18307
  setHasUpdatesBelow(false);
17095
18308
  }, []);
17096
- const scrollToBottom = React52.useCallback(
18309
+ const scrollToBottom = React54.useCallback(
17097
18310
  (smooth = false, force = false) => {
17098
18311
  if (force) {
17099
18312
  enableAutoFollow();
@@ -17120,7 +18333,7 @@ function Chat({
17120
18333
  },
17121
18334
  [cancelPendingAutoScroll, enableAutoFollow]
17122
18335
  );
17123
- const setMessageNavigationAnchor = React52.useCallback(
18336
+ const setMessageNavigationAnchor = React54.useCallback(
17124
18337
  (id, node) => {
17125
18338
  if (node) {
17126
18339
  messageNavigationAnchorsRef.current.set(id, node);
@@ -17130,15 +18343,165 @@ function Chat({
17130
18343
  },
17131
18344
  []
17132
18345
  );
17133
- const getMessageNavigationAnchor = React52.useCallback(
18346
+ const getMessageNavigationAnchor = React54.useCallback(
17134
18347
  (item) => messageNavigationAnchorsRef.current.get(item.id) ?? null,
17135
18348
  []
17136
18349
  );
17137
- const handleMessageNavigationNavigate = React52.useCallback(() => {
18350
+ const handleMessageNavigationNavigate = React54.useCallback(() => {
17138
18351
  disableAutoFollow();
17139
18352
  clearQuoteSelection();
17140
18353
  }, [clearQuoteSelection, disableAutoFollow]);
17141
- React52.useEffect(() => {
18354
+ const taskSummaryEnabled = options?.taskSummary?.enabled === true;
18355
+ const taskSummaryConversationId = stream.conversationId ?? null;
18356
+ const [taskSummaryDocked, setTaskSummaryDocked] = React54.useState(false);
18357
+ const [taskSummaryOpen, setTaskSummaryOpen] = React54.useState(false);
18358
+ const manuallyClosedTaskSummaryConversationIdsRef = React54.useRef(
18359
+ /* @__PURE__ */ new Set()
18360
+ );
18361
+ const liveTaskSummaryPending = React54.useMemo(() => {
18362
+ const followUps = pendingFollowUps.map((item) => ({
18363
+ id: `follow-up:${item.id}`,
18364
+ kind: "follow_up",
18365
+ title: item.mode === "steer" ? t("taskSummary.pending.steer") : t("taskSummary.pending.followUp"),
18366
+ messageId: item.clientMessageId,
18367
+ createdAt: new Date(item.createdAt).toISOString()
18368
+ }));
18369
+ const userInput = stream.pendingRequestUserInput ? [
18370
+ {
18371
+ id: `user-input:${stream.pendingRequestUserInput.id}`,
18372
+ kind: "user_input",
18373
+ title: stream.pendingRequestUserInput.params.questions[0]?.header || t("taskSummary.pending.userInput"),
18374
+ createdAt: new Date(
18375
+ stream.pendingRequestUserInput.createdAt
18376
+ ).toISOString()
18377
+ }
18378
+ ] : [];
18379
+ const approvals = stream.pendingHITLRequest ? [
18380
+ {
18381
+ id: `approval:${stream.pendingHITLRequest.id}`,
18382
+ kind: "approval",
18383
+ title: t("taskSummary.pending.approval"),
18384
+ createdAt: new Date(
18385
+ stream.pendingHITLRequest.createdAt
18386
+ ).toISOString()
18387
+ }
18388
+ ] : [];
18389
+ return [...approvals, ...userInput, ...followUps];
18390
+ }, [
18391
+ pendingFollowUps,
18392
+ stream.pendingHITLRequest,
18393
+ stream.pendingRequestUserInput,
18394
+ t
18395
+ ]);
18396
+ const liveTaskSummaryRunning = React54.useMemo(
18397
+ () => stream.runtimeActivities.sandboxServices.services.filter(
18398
+ (service) => service.status === "starting" || service.status === "running" || service.status === "stopping"
18399
+ ).map((service) => ({
18400
+ id: service.id ?? `${service.provider}:${service.name}:${service.actualPort ?? service.requestedPort ?? ""}`,
18401
+ title: service.name,
18402
+ status: service.status,
18403
+ description: service.actualPort || service.requestedPort ? `:${service.actualPort ?? service.requestedPort}` : void 0,
18404
+ resource: {
18405
+ type: "browser",
18406
+ serviceId: service.id,
18407
+ url: service.previewUrl ?? void 0
18408
+ },
18409
+ updatedAt: service.startedAt ?? void 0
18410
+ })),
18411
+ [stream.runtimeActivities.sandboxServices.services]
18412
+ );
18413
+ const taskSummaryAgentNames = React54.useMemo(() => {
18414
+ const names = /* @__PURE__ */ new Map();
18415
+ runtimeCapabilityOptions.forEach((option) => {
18416
+ if (option.type !== "subAgent") return;
18417
+ const name = option.capability.name?.trim();
18418
+ if (!name) return;
18419
+ names.set(option.id, name);
18420
+ const agentKey = option.capability.agentKey?.trim();
18421
+ if (agentKey) names.set(agentKey, name);
18422
+ });
18423
+ return names;
18424
+ }, [runtimeCapabilityOptions]);
18425
+ const liveTaskSummary = React54.useMemo(
18426
+ () => collectLiveTaskSummary({
18427
+ messages: messages.map(
18428
+ (message) => ({
18429
+ id: message.id,
18430
+ content: message.content,
18431
+ createdAt: message.createdAt,
18432
+ updatedAt: message.updatedAt,
18433
+ taskSummary: message.taskSummary,
18434
+ references: message.references,
18435
+ attachments: message.attachments,
18436
+ fileAssets: message.fileAssets,
18437
+ agentRuns: message.agentRuns,
18438
+ runtimeCapabilities: message.runtimeCapabilities
18439
+ })
18440
+ ),
18441
+ goal: threadGoal,
18442
+ todos: stream.todos,
18443
+ pending: liveTaskSummaryPending,
18444
+ running: liveTaskSummaryRunning,
18445
+ agentNames: taskSummaryAgentNames
18446
+ }),
18447
+ [
18448
+ liveTaskSummaryPending,
18449
+ liveTaskSummaryRunning,
18450
+ messages,
18451
+ stream.todos,
18452
+ taskSummaryAgentNames,
18453
+ threadGoal
18454
+ ]
18455
+ );
18456
+ const taskSummary = useTaskSummary({
18457
+ enabled: taskSummaryEnabled,
18458
+ conversationId: taskSummaryConversationId,
18459
+ client: stream.client,
18460
+ live: liveTaskSummary
18461
+ });
18462
+ const navigateToTaskSummaryMessage = React54.useCallback(
18463
+ async (messageId) => {
18464
+ try {
18465
+ let anchor = messageNavigationAnchorsRef.current.get(messageId);
18466
+ let pageCount = 0;
18467
+ while (!anchor && pageCount < 100) {
18468
+ const loaded = await stream.loadMoreConversationMessages();
18469
+ if (!loaded.length) break;
18470
+ pageCount += 1;
18471
+ await new Promise(
18472
+ (resolve) => requestAnimationFrame(() => resolve())
18473
+ );
18474
+ anchor = messageNavigationAnchorsRef.current.get(messageId);
18475
+ }
18476
+ if (!anchor) return;
18477
+ disableAutoFollow();
18478
+ clearQuoteSelection();
18479
+ anchor.scrollIntoView({ behavior: "smooth", block: "center" });
18480
+ } catch (error) {
18481
+ console.warn("Failed to locate task summary message", error);
18482
+ }
18483
+ },
18484
+ [clearQuoteSelection, disableAutoFollow, stream]
18485
+ );
18486
+ const openTaskSummaryResource = React54.useCallback(
18487
+ (resource, messageId, resourceTitle) => {
18488
+ const data = {
18489
+ resource,
18490
+ conversationId: taskSummaryConversationId ?? void 0,
18491
+ messageId,
18492
+ title: resourceTitle
18493
+ };
18494
+ parentMessenger.sendEvent("public_event", [
18495
+ "effect",
18496
+ {
18497
+ name: import_chatkit_types14.CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT,
18498
+ data
18499
+ }
18500
+ ]);
18501
+ },
18502
+ [parentMessenger, taskSummaryConversationId]
18503
+ );
18504
+ React54.useEffect(() => {
17142
18505
  const viewport = viewportRef.current;
17143
18506
  if (!viewport) return;
17144
18507
  previousScrollTopRef.current = viewport.scrollTop;
@@ -17219,14 +18582,14 @@ function Chat({
17219
18582
  window.removeEventListener("pointercancel", stopPointerTracking);
17220
18583
  };
17221
18584
  }, [cancelPendingAutoScroll, disableAutoFollow]);
17222
- React52.useEffect(() => {
18585
+ React54.useEffect(() => {
17223
18586
  shouldAutoScrollRef.current = true;
17224
18587
  forceFollowRef.current = false;
17225
18588
  previousScrollTopRef.current = 0;
17226
18589
  setIsAtBottom(true);
17227
18590
  setHasUpdatesBelow(false);
17228
18591
  }, [stream.threadId]);
17229
- React52.useEffect(() => {
18592
+ React54.useEffect(() => {
17230
18593
  const messageCountChanged = messages.length !== previousMessageCountRef.current;
17231
18594
  previousMessageCountRef.current = messages.length;
17232
18595
  if (isPrependingHistoryMessagesRef.current) {
@@ -17248,7 +18611,7 @@ function Chat({
17248
18611
  const isSubmissionBlocked = hasPendingInteractiveRequest || missingConfig || isHistoryLoading || hasUploadingFiles || isUploadingReferenceImages;
17249
18612
  const isSendDisabled = !trimmedDraft && !hasReferences || isSubmissionBlocked;
17250
18613
  const isPromptEditDisabled = hasPendingInteractiveRequest || missingConfig || isHistoryLoading;
17251
- const resizeComposerInput = React52.useCallback(() => {
18614
+ const resizeComposerInput = React54.useCallback(() => {
17252
18615
  const input = composerInputRef.current;
17253
18616
  if (!input) {
17254
18617
  return;
@@ -17256,7 +18619,7 @@ function Chat({
17256
18619
  input.style.maxHeight = `${COMPOSER_INPUT_MAX_HEIGHT}px`;
17257
18620
  input.style.overflowY = input.scrollHeight > COMPOSER_INPUT_MAX_HEIGHT ? "auto" : "hidden";
17258
18621
  }, []);
17259
- React52.useLayoutEffect(() => {
18622
+ React54.useLayoutEffect(() => {
17260
18623
  composerPartsRef.current = composerParts;
17261
18624
  resizeComposerInput();
17262
18625
  const caretOffset = pendingComposerCaretOffsetRef.current;
@@ -17268,13 +18631,13 @@ function Chat({
17268
18631
  }
17269
18632
  }
17270
18633
  }, [composerDomVersion, composerParts, resizeComposerInput]);
17271
- React52.useEffect(() => {
18634
+ React54.useEffect(() => {
17272
18635
  document.addEventListener("selectionchange", syncQuoteSelection);
17273
18636
  return () => {
17274
18637
  document.removeEventListener("selectionchange", syncQuoteSelection);
17275
18638
  };
17276
18639
  }, [syncQuoteSelection]);
17277
- React52.useEffect(() => {
18640
+ React54.useEffect(() => {
17278
18641
  const viewport = viewportRef.current;
17279
18642
  if (!viewport) {
17280
18643
  return;
@@ -17291,14 +18654,14 @@ function Chat({
17291
18654
  window.removeEventListener("resize", handleViewportScroll);
17292
18655
  };
17293
18656
  }, [clearQuoteSelection]);
17294
- React52.useEffect(() => {
18657
+ React54.useEffect(() => {
17295
18658
  clearQuoteSelection();
17296
18659
  }, [messages.length, stream.threadId, clearQuoteSelection]);
17297
- React52.useEffect(() => {
18660
+ React54.useEffect(() => {
17298
18661
  if (missingConfig) return;
17299
18662
  void refreshThreads();
17300
18663
  }, [missingConfig, refreshThreads]);
17301
- React52.useEffect(() => {
18664
+ React54.useEffect(() => {
17302
18665
  if (missingConfig || !stream.client || !stream.assistantId) {
17303
18666
  setAssistantName(null);
17304
18667
  setAssistantAvatar(null);
@@ -17321,10 +18684,10 @@ function Chat({
17321
18684
  cancelled = true;
17322
18685
  };
17323
18686
  }, [missingConfig, stream.client, stream.assistantId]);
17324
- React52.useEffect(() => {
18687
+ React54.useEffect(() => {
17325
18688
  setThreadGoal(stream.threadGoal);
17326
18689
  }, [stream.threadGoal]);
17327
- React52.useEffect(() => {
18690
+ React54.useEffect(() => {
17328
18691
  const threadId = stream.threadId?.trim();
17329
18692
  if (!threadId || !goalCommandAvailable) {
17330
18693
  setThreadGoal(null);
@@ -17365,7 +18728,7 @@ function Chat({
17365
18728
  return () => controller.abort();
17366
18729
  }, [goalAdapter, goalCommandAvailable, stream.threadId]);
17367
18730
  const uploadedFiles = attachmentState.uploadedFiles;
17368
- const syncComposerInputFromElement = React52.useCallback(
18731
+ const syncComposerInputFromElement = React54.useCallback(
17369
18732
  (input) => {
17370
18733
  const previousCapabilities = getComposerCapabilityPartMap(
17371
18734
  composerPartsRef.current
@@ -17383,25 +18746,25 @@ function Chat({
17383
18746
  },
17384
18747
  [commitComposerParts, updateRuntimeCapabilityPalette]
17385
18748
  );
17386
- const handleComposerInput = React52.useCallback(
18749
+ const handleComposerInput = React54.useCallback(
17387
18750
  (event) => {
17388
18751
  syncComposerInputFromElement(event.currentTarget);
17389
18752
  },
17390
18753
  [syncComposerInputFromElement]
17391
18754
  );
17392
- const handleComposerCompositionEnd = React52.useCallback(
18755
+ const handleComposerCompositionEnd = React54.useCallback(
17393
18756
  (event) => {
17394
18757
  syncComposerInputFromElement(event.currentTarget);
17395
18758
  },
17396
18759
  [syncComposerInputFromElement]
17397
18760
  );
17398
- const handleComposerSelect = React52.useCallback(() => {
18761
+ const handleComposerSelect = React54.useCallback(() => {
17399
18762
  updateRuntimeCapabilityPalette(
17400
18763
  composerPartsRef.current,
17401
18764
  composerInputRef.current ? getComposerSelectionOffset(composerInputRef.current) : void 0
17402
18765
  );
17403
18766
  }, [updateRuntimeCapabilityPalette]);
17404
- const submitDraft = React52.useCallback(
18767
+ const submitDraft = React54.useCallback(
17405
18768
  (submitOptions = {}) => {
17406
18769
  if (isSubmissionBlocked) return;
17407
18770
  const contentToSubmit = (submitOptions.inputText ?? trimmedDraft).trim();
@@ -17507,7 +18870,7 @@ function Chat({
17507
18870
  t
17508
18871
  ]
17509
18872
  );
17510
- const handleGoalCommand = React52.useCallback(
18873
+ const handleGoalCommand = React54.useCallback(
17511
18874
  async ({
17512
18875
  args,
17513
18876
  commandSource,
@@ -17613,7 +18976,7 @@ function Chat({
17613
18976
  t
17614
18977
  ]
17615
18978
  );
17616
- const handleGoalPanelOpenChange = React52.useCallback((open) => {
18979
+ const handleGoalPanelOpenChange = React54.useCallback((open) => {
17617
18980
  setIsGoalPanelOpen(open);
17618
18981
  }, []);
17619
18982
  const {
@@ -17657,7 +19020,7 @@ function Chat({
17657
19020
  plugin: t("composer.slashCommands.empty.loadingCapabilities"),
17658
19021
  subAgent: t("composer.slashCommands.empty.loadingCapabilities")
17659
19022
  };
17660
- React52.useEffect(() => {
19023
+ React54.useEffect(() => {
17661
19024
  if (!runtimeCapabilityPalette) {
17662
19025
  return;
17663
19026
  }
@@ -17676,7 +19039,7 @@ function Chat({
17676
19039
  );
17677
19040
  }
17678
19041
  }, [slashPaletteOptions.length, runtimeCapabilityPalette]);
17679
- React52.useLayoutEffect(() => {
19042
+ React54.useLayoutEffect(() => {
17680
19043
  if (!runtimeCapabilityPalette) {
17681
19044
  return;
17682
19045
  }
@@ -17693,7 +19056,7 @@ function Chat({
17693
19056
  container.scrollTop += optionRect.bottom - containerRect.bottom;
17694
19057
  }
17695
19058
  }, [runtimeCapabilityPalette, slashPaletteOptions.length]);
17696
- const submitGoalModeDraft = React52.useCallback(() => {
19059
+ const submitGoalModeDraft = React54.useCallback(() => {
17697
19060
  const objective = getComposerPlainText(composerPartsRef.current).trim();
17698
19061
  if (!isGoalModeOpen || !goalCommandAvailable || !objective) {
17699
19062
  return false;
@@ -17731,7 +19094,7 @@ function Chat({
17731
19094
  }
17732
19095
  submitDraft();
17733
19096
  };
17734
- const handleEditPendingFollowUp = React52.useCallback(
19097
+ const handleEditPendingFollowUp = React54.useCallback(
17735
19098
  (id) => {
17736
19099
  const item = pendingFollowUps.find(
17737
19100
  (entry) => entry.id === id && entry.mode === "queue"
@@ -17758,7 +19121,7 @@ function Chat({
17758
19121
  },
17759
19122
  [pendingFollowUps, setComposerText, stream]
17760
19123
  );
17761
- const handleQuoteSelection = React52.useCallback(() => {
19124
+ const handleQuoteSelection = React54.useCallback(() => {
17762
19125
  if (!quoteSelection) {
17763
19126
  return;
17764
19127
  }
@@ -17774,7 +19137,7 @@ function Chat({
17774
19137
  const handleAttachmentClick = () => {
17775
19138
  attachmentsRef.current?.openFilePicker();
17776
19139
  };
17777
- const uploadContextFile = React52.useCallback(
19140
+ const uploadContextFile = React54.useCallback(
17778
19141
  (file) => {
17779
19142
  const formData = new FormData();
17780
19143
  formData.append("file", file, file.name || "upload");
@@ -17793,13 +19156,13 @@ function Chat({
17793
19156
  },
17794
19157
  [stream.assistantId, stream.client, stream.threadId]
17795
19158
  );
17796
- const getContextFileStatus = React52.useCallback(
19159
+ const getContextFileStatus = React54.useCallback(
17797
19160
  (fileId) => stream.client.contexts.fetch(`/files/${fileId}/status`, {
17798
19161
  method: "GET"
17799
19162
  }),
17800
19163
  [stream.client]
17801
19164
  );
17802
- const deleteContextFile = React52.useCallback(
19165
+ const deleteContextFile = React54.useCallback(
17803
19166
  (storageFileId) => stream.client.contexts.deleteFile(storageFileId),
17804
19167
  [stream.client]
17805
19168
  );
@@ -17907,7 +19270,7 @@ function Chat({
17907
19270
  }
17908
19271
  submitDraft();
17909
19272
  };
17910
- const handleComposerPaste = React52.useCallback(
19273
+ const handleComposerPaste = React54.useCallback(
17911
19274
  (event) => {
17912
19275
  const clipboardData = event.clipboardData;
17913
19276
  if (!clipboardData) {
@@ -18009,13 +19372,13 @@ function Chat({
18009
19372
  const handleToolSelect = (tool) => {
18010
19373
  setSelectedTool((prev) => prev?.id === tool.id ? null : tool);
18011
19374
  };
18012
- const handlePromptClick = React52.useCallback(
19375
+ const handlePromptClick = React54.useCallback(
18013
19376
  (prompt) => {
18014
19377
  submitDraft({ inputText: prompt, displayText: prompt });
18015
19378
  },
18016
19379
  [submitDraft]
18017
19380
  );
18018
- const handlePromptEdit = React52.useCallback(
19381
+ const handlePromptEdit = React54.useCallback(
18019
19382
  (prompt) => {
18020
19383
  if (isPromptEditDisabled) return;
18021
19384
  setComposerText(prompt, prompt.length);
@@ -18024,7 +19387,7 @@ function Chat({
18024
19387
  },
18025
19388
  [focusComposerAt, isPromptEditDisabled, setComposerText]
18026
19389
  );
18027
- const loadConversationMessages = React52.useCallback(
19390
+ const loadConversationMessages = React54.useCallback(
18028
19391
  async (recordId) => {
18029
19392
  if (missingConfig) {
18030
19393
  setHistoryError(missingConfigShortMessage);
@@ -18045,7 +19408,7 @@ function Chat({
18045
19408
  },
18046
19409
  [missingConfig, missingConfigShortMessage, stream, t]
18047
19410
  );
18048
- const handleLoadMoreMessages = React52.useCallback(async () => {
19411
+ const handleLoadMoreMessages = React54.useCallback(async () => {
18049
19412
  if (!canLoadMoreMessages || isLoadingMoreMessages) {
18050
19413
  return;
18051
19414
  }
@@ -18154,19 +19517,19 @@ function Chat({
18154
19517
  };
18155
19518
  const acceptMimes = composer?.attachments?.accept ? Object.entries(composer.attachments.accept).map(([mime, exts]) => [mime, ...exts.map((e) => `.${e}`)].join(",")).join(",") : void 0;
18156
19519
  const canUploadDroppedFiles = composer?.attachments?.enabled === true && !missingConfig && !isHistoryLoading && !hasPendingInteractiveRequest;
18157
- const handleDroppedFiles = React52.useCallback((files) => {
19520
+ const handleDroppedFiles = React54.useCallback((files) => {
18158
19521
  return attachmentsRef.current?.queueFiles(files) ?? false;
18159
19522
  }, []);
18160
- const currentThread = React52.useMemo(
19523
+ const currentThread = React54.useMemo(
18161
19524
  () => threads.find((item) => item.id === stream.threadId),
18162
19525
  [threads, stream.threadId]
18163
19526
  );
18164
- const assistantStatusText = React52.useMemo(() => {
19527
+ const assistantStatusText = React54.useMemo(() => {
18165
19528
  if (!stream.threadId) return t("chat.statusOnline");
18166
19529
  return currentThread?.title?.trim() || t("chat.statusOnline");
18167
19530
  }, [currentThread?.title, stream.threadId, t]);
18168
19531
  const streamErrorMessage = stream.error instanceof Error ? stream.error.message : void 0;
18169
- const threadErrorMessage = React52.useMemo(() => {
19532
+ const threadErrorMessage = React54.useMemo(() => {
18170
19533
  if (streamErrorMessage?.trim()) return streamErrorMessage.trim();
18171
19534
  if (currentThread?.status !== "error") return void 0;
18172
19535
  const message = currentThread.error?.trim();
@@ -18197,777 +19560,883 @@ function Chat({
18197
19560
  fallbackTitle: t("history.threadFallback")
18198
19561
  });
18199
19562
  const layoutMaxWidth = options?.layout?.maxWidth;
18200
- const chatColumnStyle = React52.useMemo(() => {
19563
+ const chatColumnStyle = React54.useMemo(() => {
18201
19564
  if (layoutMaxWidth === void 0 || layoutMaxWidth === null || layoutMaxWidth === "") {
18202
19565
  return void 0;
18203
19566
  }
18204
19567
  return { maxWidth: layoutMaxWidth };
18205
19568
  }, [layoutMaxWidth]);
18206
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18207
- UploadDroppedFiles,
18208
- {
18209
- ref: viewportRef,
18210
- "data-chatkit-root": "",
18211
- enabled: canUploadDroppedFiles,
18212
- dropTitle: t("chat.dropFilesTitle"),
18213
- dropHint: t("chat.dropFilesHint"),
18214
- activeClassName: "ring-2 ring-primary/40 ring-inset",
18215
- onFiles: handleDroppedFiles,
18216
- className: cn(
18217
- "relative flex h-full w-full flex-col flex-1 overflow-y-auto bg-background shadow-sm transition-[box-shadow] duration-150",
18218
- className
18219
- ),
18220
- children: [
18221
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18222
- "div",
18223
- {
18224
- "data-slot": "chatkit-chat-header",
18225
- className: "mx-auto flex w-full items-center justify-between border-b p-2 sticky top-0 z-10 bg-background",
18226
- style: chatColumnStyle,
18227
- children: [
18228
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex min-w-0 items-center gap-3 overflow-hidden", children: [
18229
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "relative shrink-0", children: [
18230
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18231
- ChatkitAvatar,
18232
- {
18233
- avatar: assistantAvatar,
18234
- className: "h-9 w-9 border border-border/60",
18235
- label: assistantTitle
18236
- }
18237
- ),
18238
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
18239
- ] }),
18240
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "min-w-0", children: [
18241
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18242
- "h2",
18243
- {
18244
- className: "text-lg font-semibold truncate",
18245
- title: assistantTitle,
18246
- children: assistantTitle
18247
- }
18248
- ),
18249
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18250
- "p",
18251
- {
18252
- className: "truncate text-xs text-muted-foreground",
18253
- title: assistantStatusText,
18254
- children: assistantStatusText
18255
- }
18256
- )
18257
- ] })
18258
- ] }),
18259
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center gap-1", children: [
18260
- canMinimizeToPet && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18261
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18262
- "button",
18263
- {
18264
- type: "button",
18265
- onClick: handleMinimizeToPet,
18266
- className: cn(
18267
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18268
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18269
- "transition-colors duration-150"
18270
- ),
18271
- "aria-label": t("chat.minimizeToPet"),
18272
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Minus, { size: 16 })
18273
- }
18274
- ) }) }),
18275
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("chat.minimizeToPet") })
18276
- ] }),
18277
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18278
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18279
- "button",
18280
- {
18281
- type: "button",
18282
- onClick: () => setPetSettingsOpen(true),
18283
- className: cn(
18284
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18285
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18286
- "transition-colors duration-150"
18287
- ),
18288
- "aria-label": t("settings.open"),
18289
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Settings, { size: 16 })
18290
- }
18291
- ) }) }),
18292
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("settings.open") })
18293
- ] }),
18294
- history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
18295
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18296
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18297
- "button",
18298
- {
18299
- type: "button",
18300
- onClick: handleNewThread,
18301
- disabled: missingConfig || isHistoryLoading,
18302
- className: cn(
18303
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18304
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18305
- "transition-colors duration-150",
18306
- "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed"
18307
- ),
18308
- "aria-label": t("history.newThread"),
18309
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Pencil, { size: 16 })
18310
- }
18311
- ) }) }),
18312
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("history.newThread") })
18313
- ] }),
18314
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18315
- HistorySidebar,
18316
- {
18317
- threads,
18318
- currentThreadId: stream.threadId ?? void 0,
18319
- onNewThread: handleNewThread,
18320
- onSelectThread: handleSelectThread,
18321
- onDeleteThread: handleDeleteThread,
18322
- showDelete: history?.showDelete !== false,
18323
- disabled: missingConfig || isThreadsLoading || isHistoryLoading
18324
- }
18325
- )
18326
- ] })
18327
- ] })
18328
- ]
18329
- }
18330
- ),
18331
- showMessageNavigation && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18332
- MessageNavigator,
18333
- {
18334
- items: messageNavigationItems,
18335
- viewportRef,
18336
- getAnchor: getMessageNavigationAnchor,
18337
- onNavigate: handleMessageNavigationNavigate,
18338
- label: t("message.navigation.label"),
18339
- tagsOverflowLabel: (count) => t("message.navigation.moreTags", { count })
18340
- }
18341
- ),
18342
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18343
- "div",
18344
- {
18345
- "data-slot": "chatkit-chat-content",
18346
- className: "mx-auto w-full flex-1 p-4",
18347
- style: chatColumnStyle,
18348
- children: [
18349
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
18350
- historyError && /* @__PURE__ */ (0, import_jsx_runtime57.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 }),
18351
- showMissingConfig && /* @__PURE__ */ (0, import_jsx_runtime57.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 }),
18352
- isHistoryLoading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
18353
- messages.length === 0 && !canLoadMoreMessages ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18354
- StartScreen,
18355
- {
18356
- startScreen,
18357
- onPromptClick: handlePromptClick,
18358
- onPromptEdit: handlePromptEdit,
18359
- promptSendDisabled: isSubmissionBlocked,
18360
- promptEditDisabled: isPromptEditDisabled
18361
- }
18362
- ) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "space-y-4", children: [
18363
- canLoadMoreMessages && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center gap-3 py-1", children: [
18364
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" }),
18365
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18366
- Button,
18367
- {
18368
- type: "button",
18369
- variant: "ghost",
18370
- size: "sm",
18371
- onClick: handleLoadMoreMessages,
18372
- disabled: isLoadingMoreMessages,
18373
- className: "h-7 px-2 text-xs font-medium text-muted-foreground hover:text-foreground",
18374
- children: isLoadingMoreMessages ? t("chat.loadingMoreMessages") : t("chat.loadMoreMessages")
18375
- }
18376
- ),
18377
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" })
18378
- ] }),
18379
- messages.map((message, index) => {
18380
- const messageType = String(message.type);
18381
- const isAssistantMessage = messageType === "assistant" || messageType === "ai";
18382
- const isStreamingMessage = stream.isLoading && index === messages.length - 1;
18383
- const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
18384
- {
18385
- ...message,
18386
- lastStreamOutputAt: lastStreamOutputAtRef.current
18387
- },
18388
- isStreamingMessage,
18389
- { now: streamingNow }
18390
- ) : null;
18391
- if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
18392
- return null;
18393
- }
18394
- const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
18395
- const hasPlainRenderableContent = messageContent.trim().length > 0;
18396
- const humanMessage = message;
18397
- const humanReferences = humanMessage.references ?? [];
18398
- const humanAttachments = [
18399
- ...humanMessage.fileAssets ?? [],
18400
- ...humanMessage.attachments ?? []
18401
- ];
18402
- const humanRuntimeCapabilityOptions = message.type === "human" ? humanMessage.runtimeCapabilityOptions ?? getRuntimeCapabilityOptionsForSelection(
18403
- getRecommendedRuntimeCapabilitiesSelection(
18404
- humanMessage.runtimeCapabilities
18405
- ),
18406
- runtimeCapabilityOptions
18407
- ) : [];
18408
- const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
18409
- const canQuoteMessage = message.type === "human" || isAssistantMessage;
18410
- const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
18411
- const messageNavigationId = getMessageNavigationItemId(
18412
- message,
18413
- index
18414
- );
18415
- if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanRuntimeCapabilityOptions.length === 0 && humanReferences.length === 0) {
18416
- return null;
18417
- }
18418
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18419
- "div",
18420
- {
18421
- ref: (node) => setMessageNavigationAnchor(messageNavigationId, node),
18422
- "data-message-navigation-id": messageNavigationId,
18423
- className: cn(
18424
- "group flex gap-3",
18425
- message.type === "human" ? "justify-end" : "justify-start -ml-1"
18426
- // AI messages: slightly closer to left
18427
- ),
18428
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18429
- "div",
18430
- {
18431
- className: cn(
18432
- "flex flex-col px-3 overflow-hidden",
18433
- isAssistantMessage && "min-w-0 flex-1"
18434
- ),
18435
- children: [
18436
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18437
- "div",
18438
- {
18439
- ...canQuoteMessage ? {
18440
- "data-quote-message-id": message.id,
18441
- "data-quote-source": quoteSource
18442
- } : {},
18443
- className: cn(
18444
- "max-w-full rounded-2xl",
18445
- 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"
18446
- // AI messages: use chat-specific foreground color
18447
- ),
18448
- children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18449
- AssistantMessage,
18450
- {
18451
- message: {
18452
- ...message,
18453
- type: "assistant"
18454
- },
18455
- messages: messages.slice(0, index + 1).map(
18456
- (item) => ({
18457
- ...item,
18458
- type: String(item.type) === "ai" ? "assistant" : item.type
18459
- })
18460
- ),
18461
- isStreaming: isStreamingMessage,
18462
- streamingStatus,
18463
- isThreadRunning: currentThreadIsRunning,
18464
- organizationId: stream.organizationId,
18465
- apiUrl: stream.apiUrl,
18466
- pet: effectivePet
18467
- }
18468
- ) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
18469
- message.type === "human" && humanRuntimeCapabilityOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18470
- HumanRuntimeCapabilityChips,
18471
- {
18472
- options: humanRuntimeCapabilityOptions
18473
- }
18474
- ),
18475
- message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18476
- ReferenceChip,
18477
- {
18478
- reference,
18479
- variant: "message"
18480
- },
18481
- getReferenceKey(reference)
18482
- )) }),
18483
- message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18484
- "div",
18485
- {
18486
- className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
18487
- children: [
18488
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.FileText, { size: 12 }),
18489
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName ?? file.id })
18490
- ]
18491
- },
18492
- fileIndex
18493
- )) }),
18494
- Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18495
- "p",
18496
- {
18497
- className: "wrap-break-word text-sm leading-relaxed",
18498
- children: formatMessageContent(part)
18499
- },
18500
- `${part.type}-${partIndex}`
18501
- )) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
18502
- ] })
18503
- }
18504
- ),
18505
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18506
- MessageActions,
18507
- {
18508
- content: messageContent,
18509
- isAssistant: isAssistantMessage,
18510
- isStreaming: isStreamingMessage,
18511
- onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
18512
- }
18513
- )
18514
- ]
18515
- }
18516
- )
18517
- },
18518
- message.id ?? `${message.type}-${index}`
18519
- );
18520
- }),
18521
- showLoadingDots && (() => {
18522
- const lastMessage = messages[messages.length - 1];
18523
- const lastMessageType = lastMessage ? String(lastMessage.type) : "";
18524
- const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
18525
- const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
18526
- {
18527
- ...lastMessage,
18528
- lastStreamOutputAt: lastStreamOutputAtRef.current
18529
- },
18530
- stream.isLoading,
18531
- { now: streamingNow }
18532
- ) : null;
18533
- if (lastAssistantStatus) return null;
18534
- const fallbackStreamingStatus = getAssistantStreamingStatus(
18535
- {
18536
- status: void 0,
18537
- reasoning: void 0,
18538
- lastStreamOutputAt: lastStreamOutputAtRef.current
18539
- },
18540
- stream.isLoading,
18541
- { now: streamingNow }
18542
- );
18543
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18544
- AssistantStreamingIndicator,
18545
- {
18546
- status: fallbackStreamingStatus ?? "loading"
18547
- }
18548
- ) }) });
18549
- })()
18550
- ] })
18551
- ]
18552
- }
18553
- ),
18554
- !isAtBottom && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18555
- Button,
19569
+ React54.useLayoutEffect(() => {
19570
+ if (!taskSummaryEnabled) {
19571
+ setTaskSummaryDocked(false);
19572
+ return;
19573
+ }
19574
+ const viewport = viewportRef.current;
19575
+ const chatColumn = chatColumnRef.current;
19576
+ if (!viewport || !chatColumn) {
19577
+ setTaskSummaryDocked(false);
19578
+ return;
19579
+ }
19580
+ const updateDockedState = () => {
19581
+ const viewportRect = viewport.getBoundingClientRect();
19582
+ const chatColumnRect = chatColumn.getBoundingClientRect();
19583
+ const rootFontSize = Number.parseFloat(
19584
+ window.getComputedStyle(document.documentElement).fontSize
19585
+ );
19586
+ const remInPixels = Number.isFinite(rootFontSize) ? rootFontSize : 16;
19587
+ const requiredSideSpace = (TASK_SUMMARY_PANEL_WIDTH_REM + TASK_SUMMARY_PANEL_EDGE_INSET_REM + TASK_SUMMARY_PANEL_SAFE_GAP_REM) * remInPixels;
19588
+ const availableSideSpace = viewportRect.right - chatColumnRect.right;
19589
+ setTaskSummaryDocked(availableSideSpace >= requiredSideSpace);
19590
+ };
19591
+ updateDockedState();
19592
+ window.addEventListener("resize", updateDockedState);
19593
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(updateDockedState) : null;
19594
+ resizeObserver?.observe(viewport);
19595
+ resizeObserver?.observe(chatColumn);
19596
+ return () => {
19597
+ window.removeEventListener("resize", updateDockedState);
19598
+ resizeObserver?.disconnect();
19599
+ };
19600
+ }, [layoutMaxWidth, taskSummaryEnabled]);
19601
+ const taskSummaryAvailable = Boolean(
19602
+ taskSummaryEnabled && stream.threadId && taskSummaryConversationId
19603
+ );
19604
+ const handleTaskSummaryOpenChange = React54.useCallback(
19605
+ (open) => {
19606
+ setTaskSummaryOpen(open);
19607
+ if (!taskSummaryConversationId) return;
19608
+ if (open) {
19609
+ manuallyClosedTaskSummaryConversationIdsRef.current.delete(
19610
+ taskSummaryConversationId
19611
+ );
19612
+ return;
19613
+ }
19614
+ manuallyClosedTaskSummaryConversationIdsRef.current.add(
19615
+ taskSummaryConversationId
19616
+ );
19617
+ },
19618
+ [taskSummaryConversationId]
19619
+ );
19620
+ React54.useEffect(() => {
19621
+ if (!taskSummaryDocked) {
19622
+ setTaskSummaryOpen(false);
19623
+ }
19624
+ }, [taskSummaryDocked]);
19625
+ React54.useEffect(() => {
19626
+ if (!taskSummaryDocked || !taskSummaryAvailable || !taskSummaryConversationId || manuallyClosedTaskSummaryConversationIdsRef.current.has(
19627
+ taskSummaryConversationId
19628
+ )) {
19629
+ return;
19630
+ }
19631
+ setTaskSummaryOpen(true);
19632
+ }, [taskSummaryAvailable, taskSummaryConversationId, taskSummaryDocked]);
19633
+ const taskSummaryProps = {
19634
+ summary: taskSummary.summary,
19635
+ historyError: taskSummary.historyError,
19636
+ loadingSections: taskSummary.loadingSections,
19637
+ loadedSectionCounts: taskSummary.loadedSectionCounts,
19638
+ onRetryHistory: taskSummary.retryHistory,
19639
+ onLoadSection: taskSummary.loadSection,
19640
+ onNavigateMessage: (messageId) => {
19641
+ void navigateToTaskSummaryMessage(messageId);
19642
+ },
19643
+ onFocusComposer: () => focusComposerAt(),
19644
+ onOpenResource: openTaskSummaryResource
19645
+ };
19646
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19647
+ "div",
19648
+ {
19649
+ className: "relative flex h-full w-full min-w-0 bg-background",
19650
+ "data-task-summary-layout": taskSummaryDocked ? "docked" : "popover",
19651
+ children: [
19652
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19653
+ UploadDroppedFiles,
18556
19654
  {
18557
- type: "button",
18558
- size: "icon-sm",
18559
- variant: hasUpdatesBelow ? "default" : "outline",
19655
+ ref: viewportRef,
19656
+ "data-chatkit-root": "",
19657
+ enabled: canUploadDroppedFiles,
19658
+ dropTitle: t("chat.dropFilesTitle"),
19659
+ dropHint: t("chat.dropFilesHint"),
19660
+ activeClassName: "ring-2 ring-primary/40 ring-inset",
19661
+ onFiles: handleDroppedFiles,
18560
19662
  className: cn(
18561
- "pointer-events-auto rounded-full shadow-md dark:border-white/20 dark:ring-1 dark:ring-white/15 dark:shadow-[0_0_0_1px_rgba(255,255,255,0.06),0_10px_30px_rgba(0,0,0,0.45)]",
18562
- hasUpdatesBelow && "animate-bounce"
19663
+ "relative flex h-full w-full min-w-0 flex-col flex-1 overflow-y-auto bg-background shadow-sm transition-[box-shadow] duration-150",
19664
+ className
18563
19665
  ),
18564
- onClick: () => scrollToBottom(true, true),
18565
- "aria-label": t("chat.scrollToBottom"),
18566
- title: t("chat.scrollToBottom"),
18567
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ArrowDown, { size: 16 })
18568
- }
18569
- ) }),
18570
- quoteSelection && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18571
- "div",
18572
- {
18573
- className: "pointer-events-none fixed z-50",
18574
- style: {
18575
- top: `${quoteSelection.top}px`,
18576
- left: `${quoteSelection.left}px`,
18577
- transform: "translateX(-50%)"
18578
- },
18579
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18580
- Button,
18581
- {
18582
- type: "button",
18583
- size: "sm",
18584
- variant: "secondary",
18585
- className: "pointer-events-auto shadow-lg",
18586
- onMouseDown: (event) => event.preventDefault(),
18587
- onClick: handleQuoteSelection,
18588
- "aria-label": t("composer.quoteSelection"),
18589
- title: t("composer.quoteSelection"),
18590
- children: [
18591
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Quote, { size: 14 }),
18592
- t("composer.quoteSelection")
18593
- ]
18594
- }
18595
- )
18596
- }
18597
- ),
18598
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18599
- "div",
18600
- {
18601
- "data-slot": "chatkit-chat-composer",
18602
- className: "mx-auto w-full p-2 sticky bottom-0 z-10 bg-background",
18603
- style: chatColumnStyle,
18604
19666
  children: [
18605
- threadErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime57.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 }),
18606
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18607
- ChatAttachments,
18608
- {
18609
- ref: attachmentsRef,
18610
- accept: acceptMimes,
18611
- maxCount: composer?.attachments?.maxCount ?? 10,
18612
- maxSize: composer?.attachments?.maxSize ?? 100 * 1024 * 1024,
18613
- retryUploadLabel: t("chat.retryUpload"),
18614
- uploadFile: uploadContextFile,
18615
- deleteFile: deleteContextFile,
18616
- getFileStatus: getContextFileStatus,
18617
- onStateChange: setAttachmentState
18618
- }
18619
- ),
18620
- references.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18621
- ReferenceChip,
18622
- {
18623
- reference,
18624
- variant: "composer",
18625
- onRemove: () => setReferences(
18626
- (previous) => previous.filter(
18627
- (item) => getReferenceKey(item) !== getReferenceKey(reference)
18628
- )
18629
- ),
18630
- removeLabel: t("composer.removeReference")
18631
- },
18632
- getReferenceKey(reference)
18633
- )) }),
18634
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18635
- DetachedRunRuntimeCapabilities,
18636
- {
18637
- options: detachedRunRuntimeCapabilityOptions,
18638
- runOnlyLabel: t("composer.capabilities.runOnly"),
18639
- removeLabel: t("composer.capabilities.removeRunCapability"),
18640
- onRemove: removeRunRuntimeCapability
18641
- }
18642
- ),
18643
- showGoalStatus && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
19667
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18644
19668
  "div",
18645
19669
  {
18646
- className: cn(
18647
- "mb-2 flex min-h-10 gap-2 rounded-md border border-border bg-background px-2.5 py-2 text-xs text-foreground shadow-sm",
18648
- isGoalObjectiveExpanded ? "items-start" : "items-center"
18649
- ),
19670
+ ref: chatColumnRef,
19671
+ "data-slot": "chatkit-chat-header",
19672
+ className: "mx-auto flex w-full items-center justify-between border-b p-2 sticky top-0 z-10 bg-background",
19673
+ style: chatColumnStyle,
18650
19674
  children: [
18651
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18652
- import_lucide_react30.Target,
18653
- {
18654
- className: cn(
18655
- "size-4 shrink-0 text-muted-foreground",
18656
- isGoalObjectiveExpanded && "mt-1"
18657
- )
18658
- }
18659
- ),
18660
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "min-w-0 flex-1", children: [
18661
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
18662
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "font-medium", children: t("chat.goal.label") }),
18663
- threadGoal && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "shrink-0 rounded-md bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground", children: t(`chat.goal.status.${threadGoal.status}`) }),
18664
- isGoalLoading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Loader2, { className: "size-3 animate-spin text-muted-foreground" })
19675
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex min-w-0 items-center gap-3 overflow-hidden", children: [
19676
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "relative shrink-0", children: [
19677
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19678
+ ChatkitAvatar,
19679
+ {
19680
+ avatar: assistantAvatar,
19681
+ className: "h-9 w-9 border border-border/60",
19682
+ label: assistantTitle
19683
+ }
19684
+ ),
19685
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
18665
19686
  ] }),
18666
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18667
- "div",
19687
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0", children: [
19688
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19689
+ "h2",
19690
+ {
19691
+ className: "text-lg font-semibold truncate",
19692
+ title: assistantTitle,
19693
+ children: assistantTitle
19694
+ }
19695
+ ),
19696
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19697
+ "p",
19698
+ {
19699
+ className: "truncate text-xs text-muted-foreground",
19700
+ title: assistantStatusText,
19701
+ children: assistantStatusText
19702
+ }
19703
+ )
19704
+ ] })
19705
+ ] }),
19706
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-1", children: [
19707
+ taskSummaryAvailable && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19708
+ TaskSummaryTrigger,
18668
19709
  {
18669
- className: cn(
18670
- "mt-0.5 text-muted-foreground",
18671
- threadGoal?.objective && !goalError && isGoalObjectiveExpanded ? "whitespace-pre-wrap break-words" : "truncate"
18672
- ),
18673
- children: goalError || threadGoal?.objective
19710
+ ...taskSummaryProps,
19711
+ displayMode: taskSummaryDocked ? "docked" : "popover",
19712
+ open: taskSummaryOpen,
19713
+ onOpenChange: handleTaskSummaryOpenChange
18674
19714
  }
18675
19715
  ),
18676
- threadGoal && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: t("chat.goal.elapsed", {
18677
- elapsed: formatGoalElapsed(displayedGoalElapsedSeconds)
18678
- }) }) })
18679
- ] }),
18680
- threadGoal && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
18681
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18682
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18683
- Button,
19716
+ canMinimizeToPet && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
19717
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19718
+ "button",
18684
19719
  {
18685
19720
  type: "button",
18686
- variant: "ghost",
18687
- size: "icon-xs",
18688
- disabled: isGoalLoading,
18689
- onClick: () => {
18690
- const prefix = "/goal edit ";
18691
- setComposerText(`${prefix}${threadGoal.objective}`);
18692
- },
18693
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Pencil, { className: "size-3" })
19721
+ onClick: handleMinimizeToPet,
19722
+ className: cn(
19723
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19724
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19725
+ "transition-colors duration-150"
19726
+ ),
19727
+ "aria-label": t("chat.minimizeToPet"),
19728
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Minus, { size: 16 })
18694
19729
  }
18695
- ) }),
18696
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: t("chat.goal.edit") })
19730
+ ) }) }),
19731
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("chat.minimizeToPet") })
18697
19732
  ] }),
18698
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18699
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18700
- Button,
19733
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
19734
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19735
+ "button",
18701
19736
  {
18702
19737
  type: "button",
18703
- variant: "ghost",
18704
- size: "icon-xs",
18705
- disabled: isGoalLoading,
18706
- onClick: () => void handleGoalCommand({
18707
- args: threadGoal.status === "paused" ? "resume" : "pause",
18708
- commandSource: {
18709
- type: "slash_command",
18710
- name: "goal",
18711
- source: "runtime",
18712
- executionType: "insert_invocation"
18713
- }
18714
- }),
18715
- children: threadGoal.status === "paused" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Play, { className: "size-3" }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Pause, { className: "size-3" })
19738
+ onClick: () => setPetSettingsOpen(true),
19739
+ className: cn(
19740
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19741
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19742
+ "transition-colors duration-150"
19743
+ ),
19744
+ "aria-label": t("settings.open"),
19745
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Settings, { size: 16 })
18716
19746
  }
18717
- ) }),
18718
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
19747
+ ) }) }),
19748
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("settings.open") })
18719
19749
  ] }),
18720
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18721
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
19750
+ history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
19751
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
19752
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19753
+ "button",
19754
+ {
19755
+ type: "button",
19756
+ onClick: handleNewThread,
19757
+ disabled: missingConfig || isHistoryLoading,
19758
+ className: cn(
19759
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19760
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19761
+ "transition-colors duration-150",
19762
+ "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed"
19763
+ ),
19764
+ "aria-label": t("history.newThread"),
19765
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Pencil, { size: 16 })
19766
+ }
19767
+ ) }) }),
19768
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("history.newThread") })
19769
+ ] }),
19770
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19771
+ HistorySidebar,
19772
+ {
19773
+ threads,
19774
+ currentThreadId: stream.threadId ?? void 0,
19775
+ onNewThread: handleNewThread,
19776
+ onSelectThread: handleSelectThread,
19777
+ onDeleteThread: handleDeleteThread,
19778
+ showDelete: history?.showDelete !== false,
19779
+ disabled: missingConfig || isThreadsLoading || isHistoryLoading
19780
+ }
19781
+ )
19782
+ ] })
19783
+ ] })
19784
+ ]
19785
+ }
19786
+ ),
19787
+ showMessageNavigation && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19788
+ MessageNavigator,
19789
+ {
19790
+ items: messageNavigationItems,
19791
+ viewportRef,
19792
+ getAnchor: getMessageNavigationAnchor,
19793
+ onNavigate: handleMessageNavigationNavigate,
19794
+ label: t("message.navigation.label"),
19795
+ tagsOverflowLabel: (count) => t("message.navigation.moreTags", { count })
19796
+ }
19797
+ ),
19798
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19799
+ "div",
19800
+ {
19801
+ "data-slot": "chatkit-chat-content",
19802
+ className: "mx-auto w-full flex-1 p-4",
19803
+ style: chatColumnStyle,
19804
+ children: [
19805
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
19806
+ historyError && /* @__PURE__ */ (0, import_jsx_runtime58.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 }),
19807
+ showMissingConfig && /* @__PURE__ */ (0, import_jsx_runtime58.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 }),
19808
+ isHistoryLoading && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
19809
+ messages.length === 0 && !canLoadMoreMessages ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19810
+ StartScreen,
19811
+ {
19812
+ startScreen,
19813
+ onPromptClick: handlePromptClick,
19814
+ onPromptEdit: handlePromptEdit,
19815
+ promptSendDisabled: isSubmissionBlocked,
19816
+ promptEditDisabled: isPromptEditDisabled
19817
+ }
19818
+ ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "space-y-4", children: [
19819
+ canLoadMoreMessages && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-3 py-1", children: [
19820
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" }),
19821
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18722
19822
  Button,
18723
19823
  {
18724
19824
  type: "button",
18725
19825
  variant: "ghost",
18726
- size: "icon-xs",
18727
- disabled: isGoalLoading,
18728
- onClick: () => void handleGoalCommand({
18729
- args: "clear",
18730
- commandSource: {
18731
- type: "slash_command",
18732
- name: "goal",
18733
- source: "runtime",
18734
- executionType: "insert_invocation"
18735
- }
18736
- }),
18737
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Trash2, { className: "size-3" })
19826
+ size: "sm",
19827
+ onClick: handleLoadMoreMessages,
19828
+ disabled: isLoadingMoreMessages,
19829
+ className: "h-7 px-2 text-xs font-medium text-muted-foreground hover:text-foreground",
19830
+ children: isLoadingMoreMessages ? t("chat.loadingMoreMessages") : t("chat.loadMoreMessages")
18738
19831
  }
18739
- ) }),
18740
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: t("chat.goal.clear") })
19832
+ ),
19833
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" })
18741
19834
  ] }),
18742
- threadGoal.objective && !goalError && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
18743
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18744
- Button,
19835
+ messages.map((message, index) => {
19836
+ const messageType = String(message.type);
19837
+ const isAssistantMessage = messageType === "assistant" || messageType === "ai";
19838
+ const isStreamingMessage = stream.isLoading && index === messages.length - 1;
19839
+ const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
18745
19840
  {
18746
- type: "button",
18747
- variant: "ghost",
18748
- size: "icon-xs",
18749
- "aria-expanded": isGoalObjectiveExpanded,
18750
- "aria-label": isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective"),
18751
- onClick: () => setIsGoalObjectiveExpanded((expanded) => !expanded),
18752
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18753
- import_lucide_react30.ChevronDown,
19841
+ ...message,
19842
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19843
+ },
19844
+ isStreamingMessage,
19845
+ { now: streamingNow }
19846
+ ) : null;
19847
+ if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
19848
+ return null;
19849
+ }
19850
+ const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
19851
+ const hasPlainRenderableContent = messageContent.trim().length > 0;
19852
+ const humanMessage = message;
19853
+ const humanReferences = humanMessage.references ?? [];
19854
+ const humanAttachments = getVisibleHumanAttachments(
19855
+ [
19856
+ ...humanMessage.fileAssets ?? [],
19857
+ ...humanMessage.attachments ?? []
19858
+ ],
19859
+ humanReferences
19860
+ );
19861
+ const humanRuntimeCapabilityOptions = message.type === "human" ? humanMessage.runtimeCapabilityOptions ?? getRuntimeCapabilityOptionsForSelection(
19862
+ getRecommendedRuntimeCapabilitiesSelection(
19863
+ humanMessage.runtimeCapabilities
19864
+ ),
19865
+ runtimeCapabilityOptions
19866
+ ) : [];
19867
+ const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
19868
+ const canQuoteMessage = message.type === "human" || isAssistantMessage;
19869
+ const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
19870
+ const messageNavigationId = getMessageNavigationItemId(
19871
+ message,
19872
+ index
19873
+ );
19874
+ if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanRuntimeCapabilityOptions.length === 0 && humanReferences.length === 0) {
19875
+ return null;
19876
+ }
19877
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19878
+ "div",
19879
+ {
19880
+ ref: (node) => setMessageNavigationAnchor(messageNavigationId, node),
19881
+ "data-message-navigation-id": messageNavigationId,
19882
+ className: cn(
19883
+ "group flex gap-3",
19884
+ message.type === "human" ? "justify-end" : "justify-start -ml-1"
19885
+ // AI messages: slightly closer to left
19886
+ ),
19887
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19888
+ "div",
18754
19889
  {
18755
19890
  className: cn(
18756
- "size-3 transition-transform",
18757
- isGoalObjectiveExpanded && "rotate-180"
18758
- )
19891
+ "flex flex-col px-3 overflow-hidden",
19892
+ isAssistantMessage && "min-w-0 flex-1"
19893
+ ),
19894
+ children: [
19895
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19896
+ "div",
19897
+ {
19898
+ ...canQuoteMessage ? {
19899
+ "data-quote-message-id": message.id,
19900
+ "data-quote-source": quoteSource
19901
+ } : {},
19902
+ className: cn(
19903
+ "max-w-full rounded-2xl",
19904
+ 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"
19905
+ // AI messages: use chat-specific foreground color
19906
+ ),
19907
+ children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19908
+ AssistantMessage,
19909
+ {
19910
+ message: {
19911
+ ...message,
19912
+ type: "assistant"
19913
+ },
19914
+ messages: messages.slice(0, index + 1).map(
19915
+ (item) => ({
19916
+ ...item,
19917
+ type: String(item.type) === "ai" ? "assistant" : item.type
19918
+ })
19919
+ ),
19920
+ isStreaming: isStreamingMessage,
19921
+ streamingStatus,
19922
+ isThreadRunning: currentThreadIsRunning,
19923
+ organizationId: stream.organizationId,
19924
+ apiUrl: stream.apiUrl,
19925
+ pet: effectivePet
19926
+ }
19927
+ ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
19928
+ message.type === "human" && humanRuntimeCapabilityOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19929
+ HumanRuntimeCapabilityChips,
19930
+ {
19931
+ options: humanRuntimeCapabilityOptions
19932
+ }
19933
+ ),
19934
+ message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19935
+ ReferenceChip,
19936
+ {
19937
+ reference,
19938
+ variant: "message"
19939
+ },
19940
+ getReferenceKey(reference)
19941
+ )) }),
19942
+ message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19943
+ "div",
19944
+ {
19945
+ className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
19946
+ children: [
19947
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.FileText, { size: 12 }),
19948
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName ?? file.id })
19949
+ ]
19950
+ },
19951
+ fileIndex
19952
+ )) }),
19953
+ Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19954
+ "p",
19955
+ {
19956
+ className: "wrap-break-word text-sm leading-relaxed",
19957
+ children: formatMessageContent(part)
19958
+ },
19959
+ `${part.type}-${partIndex}`
19960
+ )) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
19961
+ ] })
19962
+ }
19963
+ ),
19964
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19965
+ MessageActions,
19966
+ {
19967
+ content: messageContent,
19968
+ isAssistant: isAssistantMessage,
19969
+ isStreaming: isStreamingMessage,
19970
+ onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
19971
+ }
19972
+ )
19973
+ ]
18759
19974
  }
18760
19975
  )
19976
+ },
19977
+ message.id ?? `${message.type}-${index}`
19978
+ );
19979
+ }),
19980
+ showLoadingDots && (() => {
19981
+ const lastMessage = messages[messages.length - 1];
19982
+ const lastMessageType = lastMessage ? String(lastMessage.type) : "";
19983
+ const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
19984
+ const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
19985
+ {
19986
+ ...lastMessage,
19987
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19988
+ },
19989
+ stream.isLoading,
19990
+ { now: streamingNow }
19991
+ ) : null;
19992
+ if (lastAssistantStatus) return null;
19993
+ const fallbackStreamingStatus = getAssistantStreamingStatus(
19994
+ {
19995
+ status: void 0,
19996
+ reasoning: void 0,
19997
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19998
+ },
19999
+ stream.isLoading,
20000
+ { now: streamingNow }
20001
+ );
20002
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20003
+ AssistantStreamingIndicator,
20004
+ {
20005
+ status: fallbackStreamingStatus ?? "loading"
18761
20006
  }
18762
- ) }),
18763
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
18764
- ] })
20007
+ ) }) });
20008
+ })()
18765
20009
  ] })
18766
20010
  ]
18767
20011
  }
18768
20012
  ),
18769
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18770
- PendingRuntimeServices,
20013
+ !isAtBottom && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20014
+ Button,
18771
20015
  {
18772
- state: stream.runtimeActivities.sandboxServices,
18773
- onStopService: (serviceId) => stream.stopRuntimeActivityItem("sandbox-services", serviceId),
18774
- attachToComposer: !hasPendingTodos && !hasPendingFollowUps,
18775
- className: hasPendingTodos || hasPendingFollowUps ? "mb-2" : void 0
18776
- }
18777
- ),
18778
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18779
- PendingTodos,
18780
- {
18781
- snapshot: stream.todos,
18782
- attachToComposer: !hasPendingFollowUps,
18783
- className: hasPendingFollowUps ? "mb-2" : void 0
18784
- }
18785
- ),
18786
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18787
- PendingFollowUps,
18788
- {
18789
- items: pendingFollowUps,
18790
- isLoading: stream.isLoading,
18791
- onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
18792
- canSendNow: stream.canSendPendingFollowUpNow,
18793
- onSendNow: (id) => stream.sendPendingFollowUpNow(id),
18794
- onEdit: handleEditPendingFollowUp,
18795
- onRemove: stream.removePendingFollowUp,
18796
- attachToComposer: true
18797
- }
18798
- ),
18799
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18800
- RequestUserInputPanel,
18801
- {
18802
- request: stream.pendingRequestUserInput,
18803
- onSubmit: stream.submitRequestUserInput,
18804
- onDismiss: stream.stop,
18805
- attachToComposer: true
18806
- }
18807
- ),
18808
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18809
- HITLApprovalPanel,
18810
- {
18811
- request: stream.pendingHITLRequest,
18812
- onSubmit: stream.submitHITLDecision,
18813
- onDismiss: stream.stop,
18814
- attachToComposer: true
20016
+ type: "button",
20017
+ size: "icon-sm",
20018
+ variant: hasUpdatesBelow ? "default" : "outline",
20019
+ className: cn(
20020
+ "pointer-events-auto rounded-full shadow-md dark:border-white/20 dark:ring-1 dark:ring-white/15 dark:shadow-[0_0_0_1px_rgba(255,255,255,0.06),0_10px_30px_rgba(0,0,0,0.45)]",
20021
+ hasUpdatesBelow && "animate-bounce"
20022
+ ),
20023
+ onClick: () => scrollToBottom(true, true),
20024
+ "aria-label": t("chat.scrollToBottom"),
20025
+ title: t("chat.scrollToBottom"),
20026
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.ArrowDown, { size: 16 })
18815
20027
  }
18816
- ),
18817
- runtimeCapabilityPalette && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18818
- SlashPalette,
20028
+ ) }),
20029
+ quoteSelection && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20030
+ "div",
18819
20031
  {
18820
- palette: runtimeCapabilityPalette,
18821
- options: slashPaletteOptions,
18822
- paletteRef: slashPaletteRef,
18823
- optionRefs: slashPaletteOptionRefs,
18824
- panelRoundedClass: getPanelRoundedClass(theme.radius),
18825
- itemRoundedClass: getMenuItemRoundedClass(theme.radius),
18826
- emptyLabel: slashPaletteEmptyLabel,
18827
- capabilityEmptyLabels: slashPaletteCapabilityEmptyLabels,
18828
- onSelect: selectSlashPaletteOption
20032
+ className: "pointer-events-none fixed z-50",
20033
+ style: {
20034
+ top: `${quoteSelection.top}px`,
20035
+ left: `${quoteSelection.left}px`,
20036
+ transform: "translateX(-50%)"
20037
+ },
20038
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20039
+ Button,
20040
+ {
20041
+ type: "button",
20042
+ size: "sm",
20043
+ variant: "secondary",
20044
+ className: "pointer-events-auto shadow-lg",
20045
+ onMouseDown: (event) => event.preventDefault(),
20046
+ onClick: handleQuoteSelection,
20047
+ "aria-label": t("composer.quoteSelection"),
20048
+ title: t("composer.quoteSelection"),
20049
+ children: [
20050
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Quote, { size: 14 }),
20051
+ t("composer.quoteSelection")
20052
+ ]
20053
+ }
20054
+ )
18829
20055
  }
18830
20056
  ),
18831
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
20057
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18832
20058
  "div",
18833
20059
  {
18834
- "data-slot": "composer-input-shell",
18835
- "data-layout": isComposerStacked ? "stacked" : "inline",
18836
- className: cn(
18837
- "relative flex flex-1 overflow-hidden",
18838
- "bg-background border border-border shadow-sm",
18839
- isComposerStacked ? "min-h-[5.5rem] px-1.5 pt-1.5 pb-12" : "min-h-12 px-1.5 py-1",
18840
- "focus-within:border-muted-foreground/30 focus-within:shadow-md",
18841
- "transition-[min-height,padding,border-radius,box-shadow,border-color] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
18842
- composerInputRoundedClass
18843
- ),
20060
+ "data-slot": "chatkit-chat-composer",
20061
+ className: "mx-auto w-full p-2 sticky bottom-0 z-10 bg-background",
20062
+ style: chatColumnStyle,
18844
20063
  children: [
18845
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18846
- "div",
20064
+ threadErrorMessage && /* @__PURE__ */ (0, import_jsx_runtime58.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 }),
20065
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20066
+ ChatAttachments,
18847
20067
  {
18848
- ref: composerInputRef,
18849
- role: "textbox",
18850
- "aria-multiline": "true",
18851
- "aria-disabled": missingConfig || isHistoryLoading || hasPendingInteractiveRequest,
18852
- contentEditable: !(missingConfig || isHistoryLoading || hasPendingInteractiveRequest),
18853
- suppressContentEditableWarning: true,
18854
- onInput: handleComposerInput,
18855
- onCompositionEnd: handleComposerCompositionEnd,
18856
- onSelect: handleComposerSelect,
18857
- onPaste: handleComposerPaste,
18858
- onKeyDown: handleComposerKeyDown,
18859
- "data-placeholder": inputPlaceholder,
18860
- className: cn(
18861
- "min-h-8 max-h-32 w-full overflow-hidden whitespace-pre-wrap break-words bg-transparent text-sm leading-5 text-foreground outline-none transition-[padding,min-height] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
18862
- isComposerStacked ? "px-2 py-1.5" : "py-1 pr-11 pl-11 mt-1",
18863
- "empty:before:pointer-events-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
18864
- (missingConfig || isHistoryLoading || hasPendingInteractiveRequest) && "cursor-not-allowed opacity-50"
20068
+ ref: attachmentsRef,
20069
+ accept: acceptMimes,
20070
+ maxCount: composer?.attachments?.maxCount ?? 10,
20071
+ maxSize: composer?.attachments?.maxSize ?? 100 * 1024 * 1024,
20072
+ retryUploadLabel: t("chat.retryUpload"),
20073
+ uploadFile: uploadContextFile,
20074
+ deleteFile: deleteContextFile,
20075
+ getFileStatus: getContextFileStatus,
20076
+ onStateChange: setAttachmentState
20077
+ }
20078
+ ),
20079
+ references.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20080
+ ReferenceChip,
20081
+ {
20082
+ reference,
20083
+ variant: "composer",
20084
+ onRemove: () => setReferences(
20085
+ (previous) => previous.filter(
20086
+ (item) => getReferenceKey(item) !== getReferenceKey(reference)
20087
+ )
18865
20088
  ),
18866
- children: renderedComposerParts.map(
18867
- (part, index) => part.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(React52.Fragment, { children: part.text }, `text-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ComposerCapabilityToken, { part }, part.key)
18868
- )
20089
+ removeLabel: t("composer.removeReference")
18869
20090
  },
18870
- composerDomVersion
20091
+ getReferenceKey(reference)
20092
+ )) }),
20093
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20094
+ DetachedRunRuntimeCapabilities,
20095
+ {
20096
+ options: detachedRunRuntimeCapabilityOptions,
20097
+ runOnlyLabel: t("composer.capabilities.runOnly"),
20098
+ removeLabel: t("composer.capabilities.removeRunCapability"),
20099
+ onRemove: removeRunRuntimeCapability
20100
+ }
18871
20101
  ),
18872
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
20102
+ showGoalStatus && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18873
20103
  "div",
18874
20104
  {
18875
- "data-slot": "composer-action-bar",
18876
- className: "pointer-events-none absolute inset-x-1.5 bottom-1 flex min-h-10 items-center justify-between gap-2",
20105
+ className: cn(
20106
+ "mb-2 flex min-h-10 gap-2 rounded-md border border-border bg-background px-2.5 py-2 text-xs text-foreground shadow-sm",
20107
+ isGoalObjectiveExpanded ? "items-start" : "items-center"
20108
+ ),
18877
20109
  children: [
18878
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "pointer-events-none flex min-w-0 flex-1 items-center gap-1.5", children: [
18879
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "pointer-events-auto flex shrink-0 items-center gap-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18880
- ComposerMenu,
20110
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20111
+ import_lucide_react31.Target,
20112
+ {
20113
+ className: cn(
20114
+ "size-4 shrink-0 text-muted-foreground",
20115
+ isGoalObjectiveExpanded && "mt-1"
20116
+ )
20117
+ }
20118
+ ),
20119
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0 flex-1", children: [
20120
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
20121
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "font-medium", children: t("chat.goal.label") }),
20122
+ threadGoal && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "shrink-0 rounded-md bg-muted px-1.5 py-0.5 text-[11px] text-muted-foreground", children: t(`chat.goal.status.${threadGoal.status}`) }),
20123
+ isGoalLoading && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Loader2, { className: "size-3 animate-spin text-muted-foreground" })
20124
+ ] }),
20125
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20126
+ "div",
18881
20127
  {
18882
- composer,
18883
- onAttachmentClick: handleAttachmentClick,
18884
- onToolSelect: handleToolSelect,
18885
- selectedTool,
18886
- planModeEnabled,
18887
- onPlanModeChange: setPlanModeEnabled,
18888
- goalCommandAvailable,
18889
- goalPanelOpen: isGoalModeOpen,
18890
- onGoalPanelOpenChange: handleGoalPanelOpenChange,
18891
- runtimeCapabilities: runtimeCapabilitiesReady ? runtimeCapabilities : null,
18892
- selectedRuntimeCapabilities: effectiveSessionRuntimeCapabilities,
18893
- onRuntimeCapabilityToggle: handleSessionRuntimeCapabilityToggle,
18894
- disabled: missingConfig || isHistoryLoading || hasPendingInteractiveRequest
20128
+ className: cn(
20129
+ "mt-0.5 text-muted-foreground",
20130
+ threadGoal?.objective && !goalError && isGoalObjectiveExpanded ? "whitespace-pre-wrap break-words" : "truncate"
20131
+ ),
20132
+ children: goalError || threadGoal?.objective
18895
20133
  }
18896
- ) }),
18897
- selectedTool && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "pointer-events-auto inline-flex h-8 min-w-0 max-w-[14rem] shrink items-center gap-1.5 rounded-full bg-primary/10 px-2 text-xs font-medium text-primary transition-all duration-200", children: [
18898
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "truncate", children: selectedTool.shortLabel ?? selectedTool.label }),
18899
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18900
- "button",
20134
+ ),
20135
+ threadGoal && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: t("chat.goal.elapsed", {
20136
+ elapsed: formatGoalElapsed(displayedGoalElapsedSeconds)
20137
+ }) }) })
20138
+ ] }),
20139
+ threadGoal && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
20140
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20141
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20142
+ Button,
18901
20143
  {
18902
20144
  type: "button",
18903
- onClick: () => setSelectedTool(null),
18904
- className: "shrink-0 rounded-full p-0.5 text-primary/70 hover:bg-primary/10 hover:text-primary",
18905
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.X, { size: 12 })
20145
+ variant: "ghost",
20146
+ size: "icon-xs",
20147
+ disabled: isGoalLoading,
20148
+ onClick: () => {
20149
+ const prefix = "/goal edit ";
20150
+ setComposerText(`${prefix}${threadGoal.objective}`);
20151
+ },
20152
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Pencil, { className: "size-3" })
18906
20153
  }
18907
- )
18908
- ] })
18909
- ] }),
18910
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "pointer-events-auto shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18911
- SendButton,
18912
- {
18913
- disabled: isSendDisabled,
18914
- isLoading: stream.isLoading,
18915
- showStop: stream.isLoading && (!trimmedDraft || hasPendingInteractiveRequest),
18916
- onStop: () => stream.stop(),
18917
- stopLabel: t("chat.stop"),
18918
- sendLabel: t("chat.send"),
18919
- shortcuts: stream.isLoading && trimmedDraft ? [
20154
+ ) }),
20155
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: t("chat.goal.edit") })
20156
+ ] }),
20157
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20158
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20159
+ Button,
20160
+ {
20161
+ type: "button",
20162
+ variant: "ghost",
20163
+ size: "icon-xs",
20164
+ disabled: isGoalLoading,
20165
+ onClick: () => void handleGoalCommand({
20166
+ args: threadGoal.status === "paused" ? "resume" : "pause",
20167
+ commandSource: {
20168
+ type: "slash_command",
20169
+ name: "goal",
20170
+ source: "runtime",
20171
+ executionType: "insert_invocation"
20172
+ }
20173
+ }),
20174
+ children: threadGoal.status === "paused" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Play, { className: "size-3" }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Pause, { className: "size-3" })
20175
+ }
20176
+ ) }),
20177
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
20178
+ ] }),
20179
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20180
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20181
+ Button,
18920
20182
  {
18921
- label: t("chat.followUps.queue"),
18922
- keys: "Enter"
20183
+ type: "button",
20184
+ variant: "ghost",
20185
+ size: "icon-xs",
20186
+ disabled: isGoalLoading,
20187
+ onClick: () => void handleGoalCommand({
20188
+ args: "clear",
20189
+ commandSource: {
20190
+ type: "slash_command",
20191
+ name: "goal",
20192
+ source: "runtime",
20193
+ executionType: "insert_invocation"
20194
+ }
20195
+ }),
20196
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Trash2, { className: "size-3" })
18923
20197
  }
18924
- ] : void 0
20198
+ ) }),
20199
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: t("chat.goal.clear") })
20200
+ ] }),
20201
+ threadGoal.objective && !goalError && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20202
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20203
+ Button,
20204
+ {
20205
+ type: "button",
20206
+ variant: "ghost",
20207
+ size: "icon-xs",
20208
+ "aria-expanded": isGoalObjectiveExpanded,
20209
+ "aria-label": isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective"),
20210
+ onClick: () => setIsGoalObjectiveExpanded((expanded) => !expanded),
20211
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20212
+ import_lucide_react31.ChevronDown,
20213
+ {
20214
+ className: cn(
20215
+ "size-3 transition-transform",
20216
+ isGoalObjectiveExpanded && "rotate-180"
20217
+ )
20218
+ }
20219
+ )
20220
+ }
20221
+ ) }),
20222
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
20223
+ ] })
20224
+ ] })
20225
+ ]
20226
+ }
20227
+ ),
20228
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20229
+ PendingRuntimeServices,
20230
+ {
20231
+ state: stream.runtimeActivities.sandboxServices,
20232
+ onStopService: (serviceId) => stream.stopRuntimeActivityItem("sandbox-services", serviceId),
20233
+ attachToComposer: !hasPendingTodos && !hasPendingFollowUps,
20234
+ className: hasPendingTodos || hasPendingFollowUps ? "mb-2" : void 0
20235
+ }
20236
+ ),
20237
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20238
+ PendingTodos,
20239
+ {
20240
+ snapshot: stream.todos,
20241
+ attachToComposer: !hasPendingFollowUps,
20242
+ className: hasPendingFollowUps ? "mb-2" : void 0
20243
+ }
20244
+ ),
20245
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20246
+ PendingFollowUps,
20247
+ {
20248
+ items: pendingFollowUps,
20249
+ isLoading: stream.isLoading,
20250
+ onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
20251
+ canSendNow: stream.canSendPendingFollowUpNow,
20252
+ onSendNow: (id) => stream.sendPendingFollowUpNow(id),
20253
+ onEdit: handleEditPendingFollowUp,
20254
+ onRemove: stream.removePendingFollowUp,
20255
+ attachToComposer: true
20256
+ }
20257
+ ),
20258
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20259
+ RequestUserInputPanel,
20260
+ {
20261
+ request: stream.pendingRequestUserInput,
20262
+ onSubmit: stream.submitRequestUserInput,
20263
+ onDismiss: stream.stop,
20264
+ attachToComposer: true
20265
+ }
20266
+ ),
20267
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20268
+ HITLApprovalPanel,
20269
+ {
20270
+ request: stream.pendingHITLRequest,
20271
+ onSubmit: stream.submitHITLDecision,
20272
+ onDismiss: stream.stop,
20273
+ attachToComposer: true
20274
+ }
20275
+ ),
20276
+ runtimeCapabilityPalette && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20277
+ SlashPalette,
20278
+ {
20279
+ palette: runtimeCapabilityPalette,
20280
+ options: slashPaletteOptions,
20281
+ paletteRef: slashPaletteRef,
20282
+ optionRefs: slashPaletteOptionRefs,
20283
+ panelRoundedClass: getPanelRoundedClass(theme.radius),
20284
+ itemRoundedClass: getMenuItemRoundedClass(theme.radius),
20285
+ emptyLabel: slashPaletteEmptyLabel,
20286
+ capabilityEmptyLabels: slashPaletteCapabilityEmptyLabels,
20287
+ onSelect: selectSlashPaletteOption
20288
+ }
20289
+ ),
20290
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20291
+ "div",
20292
+ {
20293
+ "data-slot": "composer-input-shell",
20294
+ "data-layout": isComposerStacked ? "stacked" : "inline",
20295
+ className: cn(
20296
+ "relative flex flex-1 overflow-hidden",
20297
+ "bg-background border border-border shadow-sm",
20298
+ isComposerStacked ? "min-h-[5.5rem] px-1.5 pt-1.5 pb-12" : "min-h-12 px-1.5 py-1",
20299
+ "focus-within:border-muted-foreground/30 focus-within:shadow-md",
20300
+ "transition-[min-height,padding,border-radius,box-shadow,border-color] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
20301
+ composerInputRoundedClass
20302
+ ),
20303
+ children: [
20304
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20305
+ "div",
20306
+ {
20307
+ ref: composerInputRef,
20308
+ role: "textbox",
20309
+ "aria-multiline": "true",
20310
+ "aria-disabled": missingConfig || isHistoryLoading || hasPendingInteractiveRequest,
20311
+ contentEditable: !(missingConfig || isHistoryLoading || hasPendingInteractiveRequest),
20312
+ suppressContentEditableWarning: true,
20313
+ onInput: handleComposerInput,
20314
+ onCompositionEnd: handleComposerCompositionEnd,
20315
+ onSelect: handleComposerSelect,
20316
+ onPaste: handleComposerPaste,
20317
+ onKeyDown: handleComposerKeyDown,
20318
+ "data-placeholder": inputPlaceholder,
20319
+ className: cn(
20320
+ "min-h-8 max-h-32 w-full overflow-hidden whitespace-pre-wrap break-words bg-transparent text-sm leading-5 text-foreground outline-none transition-[padding,min-height] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
20321
+ isComposerStacked ? "px-2 py-1.5" : "py-1 pr-11 pl-11 mt-1",
20322
+ "empty:before:pointer-events-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
20323
+ (missingConfig || isHistoryLoading || hasPendingInteractiveRequest) && "cursor-not-allowed opacity-50"
20324
+ ),
20325
+ children: renderedComposerParts.map(
20326
+ (part, index) => part.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(React54.Fragment, { children: part.text }, `text-${index}`) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ComposerCapabilityToken, { part }, part.key)
20327
+ )
20328
+ },
20329
+ composerDomVersion
20330
+ ),
20331
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20332
+ "div",
20333
+ {
20334
+ "data-slot": "composer-action-bar",
20335
+ className: "pointer-events-none absolute inset-x-1.5 bottom-1 flex min-h-10 items-center justify-between gap-2",
20336
+ children: [
20337
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "pointer-events-none flex min-w-0 flex-1 items-center gap-1.5", children: [
20338
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pointer-events-auto flex shrink-0 items-center gap-1.5", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20339
+ ComposerMenu,
20340
+ {
20341
+ composer,
20342
+ onAttachmentClick: handleAttachmentClick,
20343
+ onToolSelect: handleToolSelect,
20344
+ selectedTool,
20345
+ planModeEnabled,
20346
+ onPlanModeChange: setPlanModeEnabled,
20347
+ goalCommandAvailable,
20348
+ goalPanelOpen: isGoalModeOpen,
20349
+ onGoalPanelOpenChange: handleGoalPanelOpenChange,
20350
+ runtimeCapabilities: runtimeCapabilitiesReady ? runtimeCapabilities : null,
20351
+ selectedRuntimeCapabilities: effectiveSessionRuntimeCapabilities,
20352
+ onRuntimeCapabilityToggle: handleSessionRuntimeCapabilityToggle,
20353
+ disabled: missingConfig || isHistoryLoading || hasPendingInteractiveRequest
20354
+ }
20355
+ ) }),
20356
+ selectedTool && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "pointer-events-auto inline-flex h-8 min-w-0 max-w-[14rem] shrink items-center gap-1.5 rounded-full bg-primary/10 px-2 text-xs font-medium text-primary transition-all duration-200", children: [
20357
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "truncate", children: selectedTool.shortLabel ?? selectedTool.label }),
20358
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20359
+ "button",
20360
+ {
20361
+ type: "button",
20362
+ onClick: () => setSelectedTool(null),
20363
+ className: "shrink-0 rounded-full p-0.5 text-primary/70 hover:bg-primary/10 hover:text-primary",
20364
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.X, { size: 12 })
20365
+ }
20366
+ )
20367
+ ] })
20368
+ ] }),
20369
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pointer-events-auto shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20370
+ SendButton,
20371
+ {
20372
+ disabled: isSendDisabled,
20373
+ isLoading: stream.isLoading,
20374
+ showStop: stream.isLoading && (!trimmedDraft || hasPendingInteractiveRequest),
20375
+ onStop: () => stream.stop(),
20376
+ stopLabel: t("chat.stop"),
20377
+ sendLabel: t("chat.send"),
20378
+ shortcuts: stream.isLoading && trimmedDraft ? [
20379
+ {
20380
+ label: t("chat.followUps.queue"),
20381
+ keys: "Enter"
20382
+ }
20383
+ ] : void 0
20384
+ }
20385
+ ) })
20386
+ ]
18925
20387
  }
18926
- ) })
20388
+ )
18927
20389
  ]
18928
20390
  }
18929
- )
20391
+ ) }),
20392
+ disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20393
+ "p",
20394
+ {
20395
+ className: cn(
20396
+ "mt-2 text-center text-xs",
20397
+ disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
20398
+ ),
20399
+ children: disclaimer.text
20400
+ }
20401
+ ),
20402
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
20403
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: t("chat.poweredBy") }),
20404
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
20405
+ ] })
18930
20406
  ]
18931
20407
  }
18932
- ) }),
18933
- disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18934
- "p",
20408
+ ),
20409
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20410
+ SettingsSheet,
18935
20411
  {
18936
- className: cn(
18937
- "mt-2 text-center text-xs",
18938
- disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
18939
- ),
18940
- children: disclaimer.text
20412
+ open: petSettingsOpen,
20413
+ settings: displayedPetSettings,
20414
+ petRequired,
20415
+ onOpenChange: setPetSettingsOpen,
20416
+ onSave: savePetLocalSettings
18941
20417
  }
18942
20418
  ),
18943
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
18944
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: t("chat.poweredBy") }),
18945
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
18946
- ] })
20419
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PetBridge, { pet: effectivePet, state: petAutoState })
18947
20420
  ]
18948
20421
  }
18949
20422
  ),
18950
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18951
- SettingsSheet,
20423
+ taskSummaryAvailable && taskSummaryDocked && taskSummaryOpen && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pointer-events-none absolute right-5 top-3 z-20 max-h-[calc(100%-1.5rem)] w-80", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20424
+ TaskSummaryPanel,
18952
20425
  {
18953
- open: petSettingsOpen,
18954
- settings: displayedPetSettings,
18955
- petRequired,
18956
- onOpenChange: setPetSettingsOpen,
18957
- onSave: savePetLocalSettings
20426
+ ...taskSummaryProps,
20427
+ className: "pointer-events-auto max-h-full"
18958
20428
  }
18959
- ),
18960
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PetBridge, { pet: effectivePet, state: petAutoState })
20429
+ ) })
18961
20430
  ]
18962
20431
  }
18963
20432
  );
18964
20433
  }
18965
20434
 
18966
20435
  // src/components/ui/separator.tsx
18967
- var React53 = __toESM(require("react"), 1);
18968
- var import_jsx_runtime58 = require("react/jsx-runtime");
18969
- var Separator = React53.forwardRef(
18970
- ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20436
+ var React55 = __toESM(require("react"), 1);
20437
+ var import_jsx_runtime59 = require("react/jsx-runtime");
20438
+ var Separator = React55.forwardRef(
20439
+ ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
18971
20440
  "div",
18972
20441
  {
18973
20442
  ref,