@xpert-ai/chatkit-ui 0.4.7 → 0.4.8

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-C6U_mLmt.js} +1 -1
  2. package/dist/app/assets/{abap-C1NkPSGQ.js → abap-CcH23nd8.js} +1 -1
  3. package/dist/app/assets/{abnf-JbwQvl8G.js → abnf-CcTozIAH.js} +1 -1
  4. package/dist/app/assets/{actionscript-DmGKVMdE.js → actionscript-CoivGHtF.js} +1 -1
  5. package/dist/app/assets/{ada-BFUkZTyl.js → ada-C9rMfFQ2.js} +1 -1
  6. package/dist/app/assets/{agda-DaMAzqVU.js → agda-Bz9A_vdo.js} +1 -1
  7. package/dist/app/assets/{al-BJTYBSmw.js → al-Bt-02J-s.js} +1 -1
  8. package/dist/app/assets/{antlr4-Dp3xUyR5.js → antlr4-BNx5A1Xt.js} +1 -1
  9. package/dist/app/assets/{apacheconf-CNs6LiCv.js → apacheconf-DSKCb2ki.js} +1 -1
  10. package/dist/app/assets/{apex-Cb-6Ow2z.js → apex-DINStiCL.js} +1 -1
  11. package/dist/app/assets/{apl-Caij2pyM.js → apl-AO49PfU1.js} +1 -1
  12. package/dist/app/assets/{applescript-Za6DtdYI.js → applescript-BC9fwUi_.js} +1 -1
  13. package/dist/app/assets/{aql-rq-zV86w.js → aql-oBSTXQFj.js} +1 -1
  14. package/dist/app/assets/{arc-OYw_1mUi.js → arc-DavEcsQh.js} +1 -1
  15. package/dist/app/assets/{architectureDiagram-Q4EWVU46-DB9yrqvi.js → architectureDiagram-Q4EWVU46-CtkK_g0L.js} +1 -1
  16. package/dist/app/assets/{arduino-BaodkhmL.js → arduino-1fv4jo7s.js} +1 -1
  17. package/dist/app/assets/{arff-CtdflkdY.js → arff-LW8sOGDM.js} +1 -1
  18. package/dist/app/assets/{asciidoc-YRCvqvDt.js → asciidoc-703-ScGE.js} +1 -1
  19. package/dist/app/assets/{asm6502-DQmj6WYF.js → asm6502-DB8JZa03.js} +1 -1
  20. package/dist/app/assets/{asmatmel-B_b34PU9.js → asmatmel-Btlc_tzy.js} +1 -1
  21. package/dist/app/assets/{aspnet-DikoFau7.js → aspnet-wQ_HhpYf.js} +1 -1
  22. package/dist/app/assets/{autohotkey-DtLs5eHy.js → autohotkey-D15yjPMp.js} +1 -1
  23. package/dist/app/assets/{autoit-CV5yNCU9.js → autoit-DuEk6Vrw.js} +1 -1
  24. package/dist/app/assets/{avisynth-Cvl9Dxbj.js → avisynth-8PXPQqJm.js} +1 -1
  25. package/dist/app/assets/{avro-idl-CHxahZY6.js → avro-idl-B4LHX7lx.js} +1 -1
  26. package/dist/app/assets/{bash-B5Db2471.js → bash-CAl-DTFS.js} +1 -1
  27. package/dist/app/assets/{basic-SxMwItEb.js → basic-6_zI9xWs.js} +1 -1
  28. package/dist/app/assets/{batch-BBcoFjlC.js → batch-CkIHxOb5.js} +1 -1
  29. package/dist/app/assets/{bbcode-BjiejoUJ.js → bbcode-DdH_7cN9.js} +1 -1
  30. package/dist/app/assets/{bicep-KsVmEn1g.js → bicep-C2D-5P3M.js} +1 -1
  31. package/dist/app/assets/{birb-B8jRVP3x.js → birb-BxPQYdER.js} +1 -1
  32. package/dist/app/assets/{bison-CCal2Z3u.js → bison-DVhbkcwM.js} +1 -1
  33. package/dist/app/assets/{blockDiagram-DXYQGD6D-4aEcQrY2.js → blockDiagram-DXYQGD6D-uAEDUNeD.js} +1 -1
  34. package/dist/app/assets/{bnf-D9700Acc.js → bnf-BDcDik47.js} +1 -1
  35. package/dist/app/assets/{brainfuck-D8nhdXqW.js → brainfuck-DvwxcSfp.js} +1 -1
  36. package/dist/app/assets/{brightscript-Dj-vu9BW.js → brightscript-DrC2sVzH.js} +1 -1
  37. package/dist/app/assets/{bro-Cd22dEet.js → bro-CdiB8Vjz.js} +1 -1
  38. package/dist/app/assets/{bsl-glz5E-bI.js → bsl--EGACD0d.js} +1 -1
  39. package/dist/app/assets/{c-BT_dkbEx.js → c-T5LJVYFQ.js} +1 -1
  40. package/dist/app/assets/{c4Diagram-AHTNJAMY-k4XfyLu9.js → c4Diagram-AHTNJAMY-Cy7BexXy.js} +1 -1
  41. package/dist/app/assets/{cfscript-C3JXuiQs.js → cfscript-CkvoB6kq.js} +1 -1
  42. package/dist/app/assets/{chaiscript-CtAXHhN2.js → chaiscript-D8YjRpTE.js} +1 -1
  43. package/dist/app/assets/channel-CpiXauIP.js +1 -0
  44. package/dist/app/assets/{chunk-4BX2VUAB-ufyL9ML5.js → chunk-4BX2VUAB-BLOHlOIE.js} +1 -1
  45. package/dist/app/assets/{chunk-4TB4RGXK-BcWB3V7R.js → chunk-4TB4RGXK-GGVNH0HE.js} +1 -1
  46. package/dist/app/assets/{chunk-55IACEB6-B-bXUWk6.js → chunk-55IACEB6-Dt53EJCz.js} +1 -1
  47. package/dist/app/assets/{chunk-EDXVE4YY-Sb8Q75g2.js → chunk-EDXVE4YY-DA8yCpS4.js} +1 -1
  48. package/dist/app/assets/{chunk-FMBD7UC4-BKt1Qj6I.js → chunk-FMBD7UC4-D3NDzGii.js} +1 -1
  49. package/dist/app/assets/{chunk-OYMX7WX6-D22I1Lke.js → chunk-OYMX7WX6-BEFBL2ui.js} +1 -1
  50. package/dist/app/assets/{chunk-QZHKN3VN-OBgxRqO-.js → chunk-QZHKN3VN-BLRkTao2.js} +1 -1
  51. package/dist/app/assets/{chunk-YZCP3GAM-pUxs6dq2.js → chunk-YZCP3GAM-Ln8KYG-C.js} +1 -1
  52. package/dist/app/assets/{cil-Aus-_gof.js → cil-BMOdiOTj.js} +1 -1
  53. package/dist/app/assets/classDiagram-6PBFFD2Q-CMyc6UTy.js +1 -0
  54. package/dist/app/assets/classDiagram-v2-HSJHXN6E-CMyc6UTy.js +1 -0
  55. package/dist/app/assets/{clike-BmPHnJ_s.js → clike-BKmn_NGD.js} +1 -1
  56. package/dist/app/assets/{clojure-CW-GjCE-.js → clojure-JNOvV7IM.js} +1 -1
  57. package/dist/app/assets/clone-S4ogDYsl.js +1 -0
  58. package/dist/app/assets/{cmake-B9JwnXJm.js → cmake-DH8Q92q8.js} +1 -1
  59. package/dist/app/assets/{cobol-MM2iB1tf.js → cobol-BriCC1-T.js} +1 -1
  60. package/dist/app/assets/{coffeescript-BYj4cAte.js → coffeescript-C3QDcrFj.js} +1 -1
  61. package/dist/app/assets/{concurnas-Dvsu2_MG.js → concurnas-cn0Ztzwi.js} +1 -1
  62. package/dist/app/assets/{coq-CgVwYmnQ.js → coq-pVa-qWuT.js} +1 -1
  63. package/dist/app/assets/{core-C_147WSZ.js → core-CO_hkCHt.js} +1 -1
  64. package/dist/app/assets/{cose-bilkent-S5V4N54A-D1OYkuPl.js → cose-bilkent-S5V4N54A-IvqOuEw1.js} +1 -1
  65. package/dist/app/assets/{cpp-BXHX6A9n.js → cpp-DHlUNzHO.js} +1 -1
  66. package/dist/app/assets/{crystal-CjFk19Ts.js → crystal-BxytmI3X.js} +1 -1
  67. package/dist/app/assets/{csharp-CmTfGjFs.js → csharp-CABZUnw0.js} +1 -1
  68. package/dist/app/assets/{cshtml-BCUe0yaT.js → cshtml-hPk8iuT1.js} +1 -1
  69. package/dist/app/assets/{csp-CCHnC8Po.js → csp-BUUc6ABa.js} +1 -1
  70. package/dist/app/assets/{css-C8eNDHXz.js → css-Cr-rqtQ9.js} +1 -1
  71. package/dist/app/assets/{css-extras-DK4mKYOO.js → css-extras-Bful3yLw.js} +1 -1
  72. package/dist/app/assets/{csv-qe24SbyQ.js → csv-BNROrvsS.js} +1 -1
  73. package/dist/app/assets/{cypher-DTaNl2V1.js → cypher-CQHYzOO2.js} +1 -1
  74. package/dist/app/assets/{d-DTUhWIJ2.js → d-D0mPNje9.js} +1 -1
  75. package/dist/app/assets/{dagre-KV5264BT-DwXVdlOV.js → dagre-KV5264BT-t9M87--R.js} +1 -1
  76. package/dist/app/assets/{dart-C5UOys48.js → dart-DgLSuOUy.js} +1 -1
  77. package/dist/app/assets/{dataweave-Dj0pMNyP.js → dataweave-DUSnVjPj.js} +1 -1
  78. package/dist/app/assets/{dax-CEobCOU5.js → dax-CdYNzYFY.js} +1 -1
  79. package/dist/app/assets/{dhall-B1ZNT4vf.js → dhall-TjMKe2aM.js} +1 -1
  80. package/dist/app/assets/{diagram-5BDNPKRD-D0Dhsrwn.js → diagram-5BDNPKRD-CRqiAZ2u.js} +1 -1
  81. package/dist/app/assets/{diagram-G4DWMVQ6-CKzhB2Vi.js → diagram-G4DWMVQ6-DSq-1jRd.js} +1 -1
  82. package/dist/app/assets/{diagram-MMDJMWI5-CVK8DZmo.js → diagram-MMDJMWI5-vijnkKl_.js} +1 -1
  83. package/dist/app/assets/{diagram-TYMM5635-C63pXHON.js → diagram-TYMM5635-CKwsSqRR.js} +1 -1
  84. package/dist/app/assets/{diff-DUbfn8vo.js → diff-RTBTqfpO.js} +1 -1
  85. package/dist/app/assets/{django-BqtTf9W_.js → django-CKug-XpS.js} +1 -1
  86. package/dist/app/assets/{dns-zone-file-HiFRqdUC.js → dns-zone-file-CsSAkNKg.js} +1 -1
  87. package/dist/app/assets/{docker-DGrPELO1.js → docker-B5S-QETH.js} +1 -1
  88. package/dist/app/assets/{dot-BSr3hUqB.js → dot-C9Lx6Pap.js} +1 -1
  89. package/dist/app/assets/{ebnf-B6oU2VcU.js → ebnf-D-x85hBH.js} +1 -1
  90. package/dist/app/assets/{editorconfig-CR4Ao-pW.js → editorconfig-CE6n_qeK.js} +1 -1
  91. package/dist/app/assets/{eiffel-whkSHtSL.js → eiffel-DHdg0bSF.js} +1 -1
  92. package/dist/app/assets/{ejs-BW2scL4F.js → ejs-CZB-fGTN.js} +1 -1
  93. package/dist/app/assets/{elixir-CUNINv_i.js → elixir-OdfgIE90.js} +1 -1
  94. package/dist/app/assets/{elm-DmNP9VV8.js → elm-v6XgiDmz.js} +1 -1
  95. package/dist/app/assets/{erDiagram-SMLLAGMA-Bzh8tjuV.js → erDiagram-SMLLAGMA-BJgsWqEg.js} +1 -1
  96. package/dist/app/assets/{erb-Ch3DT-PT.js → erb-BMC1ZtTs.js} +1 -1
  97. package/dist/app/assets/{erlang-BaS46QcW.js → erlang-B-S555FZ.js} +1 -1
  98. package/dist/app/assets/{etlua-Cw5-5TpW.js → etlua-BHDYZtNc.js} +1 -1
  99. package/dist/app/assets/{excel-formula-B7JQQYH7.js → excel-formula-pWfrX2zg.js} +1 -1
  100. package/dist/app/assets/{factor-CVzm3y29.js → factor-DZ3GbHyA.js} +1 -1
  101. package/dist/app/assets/{false-DFa4x2p8.js → false-iqL9BHU1.js} +1 -1
  102. package/dist/app/assets/{firestore-security-rules-BWCfa1-J.js → firestore-security-rules-Bl7uTal3.js} +1 -1
  103. package/dist/app/assets/{flow-Bt3qEnW5.js → flow-GUjKSDGw.js} +1 -1
  104. package/dist/app/assets/{flowDiagram-DWJPFMVM-Dvq1OIJB.js → flowDiagram-DWJPFMVM-CkZQBdZr.js} +1 -1
  105. package/dist/app/assets/{fortran-CCu-4Ium.js → fortran-BeqpuFCA.js} +1 -1
  106. package/dist/app/assets/{fsharp-CDiO0qvE.js → fsharp-DZSHGb7H.js} +1 -1
  107. package/dist/app/assets/{ftl-DkrbBJ6h.js → ftl-DmEWSMUl.js} +1 -1
  108. package/dist/app/assets/{ganttDiagram-T4ZO3ILL-BtaWNNLn.js → ganttDiagram-T4ZO3ILL-DBltjUCi.js} +1 -1
  109. package/dist/app/assets/{gap-CElgN_G6.js → gap-BjqhWB_-.js} +1 -1
  110. package/dist/app/assets/{gcode-D1m1Jx_m.js → gcode-AKkUkh18.js} +1 -1
  111. package/dist/app/assets/{gdscript-CQyrpld6.js → gdscript-CXkLDcqy.js} +1 -1
  112. package/dist/app/assets/{gedcom-C0t2XJjb.js → gedcom-zomiHg3l.js} +1 -1
  113. package/dist/app/assets/{gherkin-D2Z-kIb5.js → gherkin-CeMVXbM6.js} +1 -1
  114. package/dist/app/assets/{git-COtp78Yi.js → git-DpCni8L5.js} +1 -1
  115. package/dist/app/assets/{gitGraphDiagram-UUTBAWPF-CwEA20GK.js → gitGraphDiagram-UUTBAWPF-DGVplyDN.js} +1 -1
  116. package/dist/app/assets/{glsl-BOfIEs6F.js → glsl-zoUbbmGA.js} +1 -1
  117. package/dist/app/assets/{gml-DEJcGKIl.js → gml-CuzTrbLx.js} +1 -1
  118. package/dist/app/assets/{gn-D2URDt4C.js → gn-DDqAM2Nt.js} +1 -1
  119. package/dist/app/assets/{go-H9iqUz92.js → go-DfGlh_fI.js} +1 -1
  120. package/dist/app/assets/{go-module-CI1Cdki8.js → go-module-B43_pol8.js} +1 -1
  121. package/dist/app/assets/{graph-DNTBpla7.js → graph-CTHXWjkl.js} +1 -1
  122. package/dist/app/assets/{graphql-CfY3OrBB.js → graphql-BD4WHbDL.js} +1 -1
  123. package/dist/app/assets/{groovy-DKOMKQyq.js → groovy-D1mwDBPA.js} +1 -1
  124. package/dist/app/assets/{haml-tAB3bBZc.js → haml-DQ1ifuh3.js} +1 -1
  125. package/dist/app/assets/{handlebars-CMRoFkcp.js → handlebars-BbKVi9k7.js} +1 -1
  126. package/dist/app/assets/{haskell-BIno1Xj8.js → haskell-DR3U9E3I.js} +1 -1
  127. package/dist/app/assets/{haxe-BjUHc9TK.js → haxe-DxuWxMdv.js} +1 -1
  128. package/dist/app/assets/{hcl-d_N2T1VA.js → hcl-BlmRVySH.js} +1 -1
  129. package/dist/app/assets/{hlsl-Czs9_QAo.js → hlsl-b70nK4nC.js} +1 -1
  130. package/dist/app/assets/{hoon-1-5xCFh9.js → hoon-CFk_83C2.js} +1 -1
  131. package/dist/app/assets/{hpkp-BDx00Z1B.js → hpkp-CXk7yU3y.js} +1 -1
  132. package/dist/app/assets/{hsts-D_MF-HB_.js → hsts-Cn-v3YAw.js} +1 -1
  133. package/dist/app/assets/{http-D5BtxMl1.js → http-CJ3HdMDk.js} +1 -1
  134. package/dist/app/assets/{ichigojam-DMEwRzWG.js → ichigojam-CEG-TsR7.js} +1 -1
  135. package/dist/app/assets/{icon-BePaZLuK.js → icon-BjSINS6k.js} +1 -1
  136. package/dist/app/assets/{icu-message-format-BlPybne8.js → icu-message-format-C19IL-8o.js} +1 -1
  137. package/dist/app/assets/{idris-DZlcuSA9.js → idris-CTFj0zyA.js} +1 -1
  138. package/dist/app/assets/{iecst-BkjvfWtO.js → iecst-DczabB55.js} +1 -1
  139. package/dist/app/assets/{ignore-CdeiHJ0n.js → ignore-DWfEQzDI.js} +1 -1
  140. package/dist/app/assets/index-81T8nJoC.js +762 -0
  141. package/dist/app/assets/index-BuZAXEsU.css +1 -0
  142. package/dist/app/assets/{infoDiagram-42DDH7IO-BHLFr032.js → infoDiagram-42DDH7IO-D42FAKXi.js} +1 -1
  143. package/dist/app/assets/{inform7-cMmC84KD.js → inform7-Bt3cWsOU.js} +1 -1
  144. package/dist/app/assets/{ini-DVzqNVZv.js → ini-DpFDn41X.js} +1 -1
  145. package/dist/app/assets/{io-DZZuQgET.js → io-CgGAFAHi.js} +1 -1
  146. package/dist/app/assets/{ishikawaDiagram-UXIWVN3A-Cfb4YddV.js → ishikawaDiagram-UXIWVN3A-C8zjjQQw.js} +1 -1
  147. package/dist/app/assets/{j-CJ-4uAlV.js → j-BJV61y_I.js} +1 -1
  148. package/dist/app/assets/{java-DCXkSxET.js → java-BmdQrLLO.js} +1 -1
  149. package/dist/app/assets/{javadoc-CrVMKEsI.js → javadoc-G5yNdvan.js} +1 -1
  150. package/dist/app/assets/{javadoclike-D2L56h5j.js → javadoclike-BRhUyCMI.js} +1 -1
  151. package/dist/app/assets/{javascript-hgymZZUH.js → javascript-X5fFJKSj.js} +1 -1
  152. package/dist/app/assets/{javastacktrace-ChLmPkJH.js → javastacktrace-D95RSPmw.js} +1 -1
  153. package/dist/app/assets/{jexl-Cv8EINDe.js → jexl-Bahcu24V.js} +1 -1
  154. package/dist/app/assets/{jolie-C8GHrQQz.js → jolie-BbdL97sV.js} +1 -1
  155. package/dist/app/assets/{journeyDiagram-VCZTEJTY-BTArqTvD.js → journeyDiagram-VCZTEJTY-fQoNAiQs.js} +1 -1
  156. package/dist/app/assets/{jq-BNVdoY6Z.js → jq-BJaVY7-k.js} +1 -1
  157. package/dist/app/assets/{js-extras-BlUxCYhv.js → js-extras-CzHFPwB7.js} +1 -1
  158. package/dist/app/assets/{js-templates-DXYRbGAM.js → js-templates-D9Jze0AG.js} +1 -1
  159. package/dist/app/assets/{jsdoc-CMLYNOYD.js → jsdoc-CwJWJCwH.js} +1 -1
  160. package/dist/app/assets/{json-odBxYu2B.js → json-BfOH7ju9.js} +1 -1
  161. package/dist/app/assets/{json5-DP7aJM4_.js → json5-DkNVWQsa.js} +1 -1
  162. package/dist/app/assets/{jsonp-B2xUHyW0.js → jsonp-B9H6yTcQ.js} +1 -1
  163. package/dist/app/assets/{jsstacktrace-CmkoO76I.js → jsstacktrace-DB1HESYr.js} +1 -1
  164. package/dist/app/assets/{jsx-45IrULtU.js → jsx-BZEoAwNB.js} +1 -1
  165. package/dist/app/assets/{julia-ClR9qq8g.js → julia-Du0-OWWc.js} +1 -1
  166. package/dist/app/assets/{kanban-definition-6JOO6SKY-JROcHSgz.js → kanban-definition-6JOO6SKY-D9G630CO.js} +1 -1
  167. package/dist/app/assets/{keepalived-C-KownHW.js → keepalived-D2o2MKOk.js} +1 -1
  168. package/dist/app/assets/{keyman-CYpySklF.js → keyman-CQNdJfg5.js} +1 -1
  169. package/dist/app/assets/{kotlin-CQbGs2Ue.js → kotlin-BdGy0G3D.js} +1 -1
  170. package/dist/app/assets/{kumir-DToHbC4q.js → kumir-W9XS3J-N.js} +1 -1
  171. package/dist/app/assets/{kusto-B6SHYgRi.js → kusto-U5GL2okH.js} +1 -1
  172. package/dist/app/assets/{latex-DrhQGKi6.js → latex-DjywwdZn.js} +1 -1
  173. package/dist/app/assets/{latte-BatIWxZM.js → latte-CWlwFAGC.js} +1 -1
  174. package/dist/app/assets/{layout-CmJisaFk.js → layout-CJ5sbb4i.js} +1 -1
  175. package/dist/app/assets/{less-BJapF0M4.js → less-B_-Y8EIj.js} +1 -1
  176. package/dist/app/assets/{lilypond-DHb81Qrb.js → lilypond-de2Bbq8o.js} +1 -1
  177. package/dist/app/assets/{linear-HilAl6Kl.js → linear-cpVyzYBv.js} +1 -1
  178. package/dist/app/assets/{liquid-BYBkN767.js → liquid-B7YoglCS.js} +1 -1
  179. package/dist/app/assets/{lisp-PTlDHAFe.js → lisp-rkefVxKe.js} +1 -1
  180. package/dist/app/assets/{livescript-D7mEGuFt.js → livescript-Dthz2vuR.js} +1 -1
  181. package/dist/app/assets/{llvm-BOF01C_Q.js → llvm-CdkfgaFY.js} +1 -1
  182. package/dist/app/assets/{log-D_oLYdec.js → log-DKL--ZdV.js} +1 -1
  183. package/dist/app/assets/{lolcode-BOp3ZdpE.js → lolcode-DZMyfvHz.js} +1 -1
  184. package/dist/app/assets/{lua-CdyGJajb.js → lua-BozQlwCm.js} +1 -1
  185. package/dist/app/assets/{magma-asqA2vhX.js → magma-Bo1HQ3yw.js} +1 -1
  186. package/dist/app/assets/{makefile-CYytCSPK.js → makefile-Cd7k8M7c.js} +1 -1
  187. package/dist/app/assets/{markdown-jxdlECxY.js → markdown-CyEGGExX.js} +1 -1
  188. package/dist/app/assets/{markup-CLxozN6F.js → markup-C6j7maqE.js} +1 -1
  189. package/dist/app/assets/{markup-templating-Cs7ayZpi.js → markup-templating-zo98qosd.js} +1 -1
  190. package/dist/app/assets/{matlab-BoNKjSLV.js → matlab-7DGA36_N.js} +1 -1
  191. package/dist/app/assets/{maxscript-xgjeOfTE.js → maxscript-BXhKpjV3.js} +1 -1
  192. package/dist/app/assets/{mel-DnN2qY7Z.js → mel-DzuwbU9S.js} +1 -1
  193. package/dist/app/assets/{mermaid-Di7Rvujk.js → mermaid-Fxy9aqV6.js} +1 -1
  194. package/dist/app/assets/{min-D-U2U04w.js → min-iRYxaflu.js} +1 -1
  195. package/dist/app/assets/{mindmap-definition-QFDTVHPH-7f0wW_f6.js → mindmap-definition-QFDTVHPH-CDhGnvWF.js} +1 -1
  196. package/dist/app/assets/{mizar-DNfbYlTh.js → mizar-C6LRd3BH.js} +1 -1
  197. package/dist/app/assets/{mongodb-BDy5e9Pj.js → mongodb-PpRT4row.js} +1 -1
  198. package/dist/app/assets/{monkey-BRH4J8qW.js → monkey-BtPIcibQ.js} +1 -1
  199. package/dist/app/assets/{moonscript-CH8q91fg.js → moonscript-B2sOvzdl.js} +1 -1
  200. package/dist/app/assets/{n1ql-Cnsejlzs.js → n1ql-BUgP-sLq.js} +1 -1
  201. package/dist/app/assets/{n4js-B3Iq3-1_.js → n4js-DitGNUV9.js} +1 -1
  202. package/dist/app/assets/{nand2tetris-hdl-CU1IJ4Jw.js → nand2tetris-hdl-C4eb-97E.js} +1 -1
  203. package/dist/app/assets/{naniscript-jbrJD2kA.js → naniscript-C76x5pWn.js} +1 -1
  204. package/dist/app/assets/{nasm-CknzFEer.js → nasm-DY15scmn.js} +1 -1
  205. package/dist/app/assets/{neon-26-IayFN.js → neon-XUFSke3O.js} +1 -1
  206. package/dist/app/assets/{nevod-BJEC391b.js → nevod-D-O5x2vT.js} +1 -1
  207. package/dist/app/assets/{nginx-Vpvjjaaf.js → nginx-C1LAx9GQ.js} +1 -1
  208. package/dist/app/assets/{nim-DyKtgNBt.js → nim-BIB3hils.js} +1 -1
  209. package/dist/app/assets/{nix-BMFnBzg-.js → nix-Cp83P7Ah.js} +1 -1
  210. package/dist/app/assets/{nsis-SbQZmFez.js → nsis-BEIuRoEV.js} +1 -1
  211. package/dist/app/assets/{objectivec-BHCbn7Vg.js → objectivec-DvCOEh_z.js} +1 -1
  212. package/dist/app/assets/{ocaml-B_NbRFYO.js → ocaml-C8YXwmdc.js} +1 -1
  213. package/dist/app/assets/{opencl-DGGnjyh8.js → opencl-sPESon4V.js} +1 -1
  214. package/dist/app/assets/{openqasm-BB7WCrXB.js → openqasm-BCiw5qy5.js} +1 -1
  215. package/dist/app/assets/{oz-CHFXD-ie.js → oz-F9dEXSFB.js} +1 -1
  216. package/dist/app/assets/{parigp-hCut1WJq.js → parigp-BZl0w0Sc.js} +1 -1
  217. package/dist/app/assets/{parser-Cst8mRu7.js → parser-C9sPAbgK.js} +1 -1
  218. package/dist/app/assets/{pascal-BCJwXon0.js → pascal-BUnXeRKA.js} +1 -1
  219. package/dist/app/assets/{pascaligo-B6Cgg9Mq.js → pascaligo-BBA1mDzk.js} +1 -1
  220. package/dist/app/assets/{pcaxis-C4xWQM2D.js → pcaxis-CE-kTu54.js} +1 -1
  221. package/dist/app/assets/{peoplecode-Dkb6XtUf.js → peoplecode-Cavd8OkS.js} +1 -1
  222. package/dist/app/assets/{perl-H221EXvJ.js → perl-rub0iNje.js} +1 -1
  223. package/dist/app/assets/{php-BShmZ9_M.js → php-Dh1U-FUh.js} +1 -1
  224. package/dist/app/assets/{php-extras-ByhH4OKy.js → php-extras-BIJCxnPs.js} +1 -1
  225. package/dist/app/assets/{phpdoc-p3qE-fVK.js → phpdoc-CCJjW2TW.js} +1 -1
  226. package/dist/app/assets/{pieDiagram-DEJITSTG-BpxQ_Sug.js → pieDiagram-DEJITSTG-RYQuMD8b.js} +1 -1
  227. package/dist/app/assets/{plsql-Bq0RDvXx.js → plsql-5_KwCAwn.js} +1 -1
  228. package/dist/app/assets/{powerquery-DRH8DvSi.js → powerquery-52u5POE8.js} +1 -1
  229. package/dist/app/assets/{powershell-Bevaimo1.js → powershell-BHLNENsC.js} +1 -1
  230. package/dist/app/assets/{processing-C0GbD3oE.js → processing-DI_nysTy.js} +1 -1
  231. package/dist/app/assets/{prolog-Di4z8LJE.js → prolog-DqF8gKCU.js} +1 -1
  232. package/dist/app/assets/{promql-03Fgifpl.js → promql-Be65e_se.js} +1 -1
  233. package/dist/app/assets/{properties-D1Z19tT1.js → properties-BKITDSLH.js} +1 -1
  234. package/dist/app/assets/{protobuf-DWz8yR_O.js → protobuf-CJaLUYPZ.js} +1 -1
  235. package/dist/app/assets/{psl-tBEfR2Sh.js → psl-B2zDw4FQ.js} +1 -1
  236. package/dist/app/assets/{pug-C7eejEs9.js → pug-BLNDkbe-.js} +1 -1
  237. package/dist/app/assets/{puppet-B7zctoCl.js → puppet-CYkyNd7_.js} +1 -1
  238. package/dist/app/assets/{pure-BtT7EWOj.js → pure-aHZtfBs8.js} +1 -1
  239. package/dist/app/assets/{purebasic-Ccj2c-Ej.js → purebasic-Chreb9G1.js} +1 -1
  240. package/dist/app/assets/{purescript-DMkp7ORC.js → purescript-BrDQpBsd.js} +1 -1
  241. package/dist/app/assets/{q-DnC31I_1.js → q-CG-Uw9fW.js} +1 -1
  242. package/dist/app/assets/{qml-qQROczBb.js → qml-D7JdcaL5.js} +1 -1
  243. package/dist/app/assets/{qore-CYWTKmh1.js → qore-DTAFeEzJ.js} +1 -1
  244. package/dist/app/assets/{qsharp-DGDhAWfE.js → qsharp-KMk1VB77.js} +1 -1
  245. package/dist/app/assets/{quadrantDiagram-34T5L4WZ-BCvqKtV-.js → quadrantDiagram-34T5L4WZ-kcs3XBjB.js} +1 -1
  246. package/dist/app/assets/{r-DvcBehxz.js → r-Mcc_meDu.js} +1 -1
  247. package/dist/app/assets/{racket-XWJUhFHR.js → racket-Bi1SH8gG.js} +1 -1
  248. package/dist/app/assets/{reason-DpsxmggQ.js → reason-BkN_evMO.js} +1 -1
  249. package/dist/app/assets/{regex-DQtV1_Nu.js → regex-BpPSlJan.js} +1 -1
  250. package/dist/app/assets/{rego-D2-FjG8h.js → rego-CFPB8a0W.js} +1 -1
  251. package/dist/app/assets/{renpy-C3S_oPNw.js → renpy-C10TEcfx.js} +1 -1
  252. package/dist/app/assets/{requirementDiagram-MS252O5E-BICcpYGT.js → requirementDiagram-MS252O5E-Da2Rot0k.js} +1 -1
  253. package/dist/app/assets/{rest-DXmPPeBy.js → rest-jaxR3Nwi.js} +1 -1
  254. package/dist/app/assets/{rip-NSOmDEr3.js → rip-BIYDMCQi.js} +1 -1
  255. package/dist/app/assets/{roboconf-CuCQ-NJX.js → roboconf-D3YJW0OU.js} +1 -1
  256. package/dist/app/assets/{robotframework-BsCP1w9s.js → robotframework-Cl5CDWUM.js} +1 -1
  257. package/dist/app/assets/{ruby-CJnf6nnh.js → ruby-BAtxbduJ.js} +1 -1
  258. package/dist/app/assets/{rust-DESdYva3.js → rust-j3d_4yXH.js} +1 -1
  259. package/dist/app/assets/{sankeyDiagram-XADWPNL6-69KpnHMz.js → sankeyDiagram-XADWPNL6-CHYndDqh.js} +1 -1
  260. package/dist/app/assets/{sas-DZFbJKR-.js → sas-B7xuz-f8.js} +1 -1
  261. package/dist/app/assets/{sass-AnS1s1br.js → sass-CPSHzvOP.js} +1 -1
  262. package/dist/app/assets/{scala-CwhoAHEC.js → scala-XzuQPU4U.js} +1 -1
  263. package/dist/app/assets/{scheme-C_ljvZBy.js → scheme-CZDNceJr.js} +1 -1
  264. package/dist/app/assets/{scss-DL1XxErH.js → scss-ByPGJ9oR.js} +1 -1
  265. package/dist/app/assets/{sequenceDiagram-FGHM5R23-D7oS24WP.js → sequenceDiagram-FGHM5R23-Bqf-MI3-.js} +1 -1
  266. package/dist/app/assets/{shell-session-Cz9O3eeT.js → shell-session-DkYs23hw.js} +1 -1
  267. package/dist/app/assets/{smali-CB-r7O-_.js → smali-8ta0pDs5.js} +1 -1
  268. package/dist/app/assets/{smalltalk-CVFZJVem.js → smalltalk-CL3O-9hG.js} +1 -1
  269. package/dist/app/assets/{smarty-BzZkcGHn.js → smarty-DptYuPV-.js} +1 -1
  270. package/dist/app/assets/{sml-D9RGeV5i.js → sml-DL5Ntsze.js} +1 -1
  271. package/dist/app/assets/{solidity-Dz-wQnyp.js → solidity-DLjXKpH8.js} +1 -1
  272. package/dist/app/assets/{solution-file-DkmD5yqD.js → solution-file-BGEYO2UZ.js} +1 -1
  273. package/dist/app/assets/{soy-D85tR8Fr.js → soy-C_hNpojZ.js} +1 -1
  274. package/dist/app/assets/{sparql-BgbB63AF.js → sparql-DpyP9nSL.js} +1 -1
  275. package/dist/app/assets/{splunk-spl-BCo2DCmB.js → splunk-spl-CMqLBBNV.js} +1 -1
  276. package/dist/app/assets/{sqf-CiA74sHU.js → sqf-Bjd7tODT.js} +1 -1
  277. package/dist/app/assets/{sql-hLzyaqCr.js → sql-DaOPtORA.js} +1 -1
  278. package/dist/app/assets/{squirrel-zcX4QdBa.js → squirrel-BmkSCHAM.js} +1 -1
  279. package/dist/app/assets/{stan-Ckw12XOd.js → stan-BQDOZ5BG.js} +1 -1
  280. package/dist/app/assets/{stateDiagram-FHFEXIEX-BvjpuD2U.js → stateDiagram-FHFEXIEX-DomIxG6V.js} +1 -1
  281. package/dist/app/assets/stateDiagram-v2-QKLJ7IA2-BIm6BAJU.js +1 -0
  282. package/dist/app/assets/{stylus-v6XOnT6H.js → stylus-D9zxJMZd.js} +1 -1
  283. package/dist/app/assets/{swift-5_1e6kft.js → swift-ChDi7zm1.js} +1 -1
  284. package/dist/app/assets/{systemd-DrgFw48M.js → systemd-DrHR6OtL.js} +1 -1
  285. package/dist/app/assets/{t4-cs-DM0v3lxQ.js → t4-cs-BK7AaUNw.js} +1 -1
  286. package/dist/app/assets/{t4-templating-DD8VmPrg.js → t4-templating-DyWWFL-2.js} +1 -1
  287. package/dist/app/assets/{t4-vb-DycV_cM9.js → t4-vb-ImonnXyV.js} +1 -1
  288. package/dist/app/assets/{tap-DGpedrqN.js → tap-gG3Miq0y.js} +1 -1
  289. package/dist/app/assets/{tcl-c2qhHAdq.js → tcl-CPOB0Qpi.js} +1 -1
  290. package/dist/app/assets/{textile-C8oUBrkr.js → textile-DUS100rB.js} +1 -1
  291. package/dist/app/assets/{timeline-definition-GMOUNBTQ-B4Jcyau2.js → timeline-definition-GMOUNBTQ-B9xACmrN.js} +1 -1
  292. package/dist/app/assets/{toml-BGo5hlUM.js → toml-Br-z_Jni.js} +1 -1
  293. package/dist/app/assets/{tremor-eRNxuoON.js → tremor-CUpHsqn-.js} +1 -1
  294. package/dist/app/assets/{tt2-Di8pz9fy.js → tt2-CwqefxcQ.js} +1 -1
  295. package/dist/app/assets/{turtle-vJP3xRTT.js → turtle-C-8311-l.js} +1 -1
  296. package/dist/app/assets/{twig-BnhrPMSB.js → twig-6K8m9JZO.js} +1 -1
  297. package/dist/app/assets/{typescript-37w5F4sD.js → typescript-D-ov05ni.js} +1 -1
  298. package/dist/app/assets/{typoscript-CsApf0xg.js → typoscript-GY6i6lok.js} +1 -1
  299. package/dist/app/assets/{unrealscript-dRcLpqab.js → unrealscript-BWUIUQQm.js} +1 -1
  300. package/dist/app/assets/{uorazor-30r9Eeul.js → uorazor-BnpMbbKh.js} +1 -1
  301. package/dist/app/assets/{uri-D77IB2tJ.js → uri-BTJvCkTQ.js} +1 -1
  302. package/dist/app/assets/{v-CKeEdKLN.js → v-ClrvUxC7.js} +1 -1
  303. package/dist/app/assets/{vala-BetNh6ws.js → vala-QMoS4Hez.js} +1 -1
  304. package/dist/app/assets/{vbnet-BEMab70S.js → vbnet-BhW2Anfz.js} +1 -1
  305. package/dist/app/assets/{velocity-DrfQgf6-.js → velocity-65hYA_Fv.js} +1 -1
  306. package/dist/app/assets/{vennDiagram-DHZGUBPP-CegebJbe.js → vennDiagram-DHZGUBPP-CLUcaL0s.js} +1 -1
  307. package/dist/app/assets/{verilog-uQXkk7Nj.js → verilog-XFjWUf7Y.js} +1 -1
  308. package/dist/app/assets/{vhdl-DDmmL8UD.js → vhdl-BR397r1w.js} +1 -1
  309. package/dist/app/assets/{vim-BDNt86iz.js → vim-Bmv-wH4S.js} +1 -1
  310. package/dist/app/assets/{visual-basic-pucIF_mU.js → visual-basic-Ek4Wcu5h.js} +1 -1
  311. package/dist/app/assets/{wardley-RL74JXVD-DsKO1a_J.js → wardley-RL74JXVD-DUvVrvQ2.js} +1 -1
  312. package/dist/app/assets/{wardleyDiagram-NUSXRM2D-B2JNwjAB.js → wardleyDiagram-NUSXRM2D-B0G-KJsH.js} +1 -1
  313. package/dist/app/assets/{warpscript-CHmOiWY2.js → warpscript-CLIqJxp0.js} +1 -1
  314. package/dist/app/assets/{wasm-4NqiPBMD.js → wasm-CXr1clzP.js} +1 -1
  315. package/dist/app/assets/{web-idl-LsIw2yg-.js → web-idl-zfka4Lik.js} +1 -1
  316. package/dist/app/assets/{wiki-nXUE249D.js → wiki-09K2_Yl-.js} +1 -1
  317. package/dist/app/assets/{wolfram-Df8JMtQM.js → wolfram-ZVF__pfW.js} +1 -1
  318. package/dist/app/assets/{wren-Cs5S9jF3.js → wren-CiCJbNJW.js} +1 -1
  319. package/dist/app/assets/{xeora-BFuaZkC6.js → xeora-CC6uLYDD.js} +1 -1
  320. package/dist/app/assets/{xml-doc-gKIq2LAK.js → xml-doc-BcU55lcM.js} +1 -1
  321. package/dist/app/assets/{xojo-pDFvmFo8.js → xojo-BO8S8YTP.js} +1 -1
  322. package/dist/app/assets/{xquery-B1ncakta.js → xquery-iEr-F5Ux.js} +1 -1
  323. package/dist/app/assets/{xychartDiagram-5P7HB3ND-WNR7ZTqi.js → xychartDiagram-5P7HB3ND-cDfO6IE-.js} +1 -1
  324. package/dist/app/assets/{yaml-Bar2VcxI.js → yaml-PzXxTEay.js} +1 -1
  325. package/dist/app/assets/{yang-CpPBz6Mu.js → yang-d0o4_4YD.js} +1 -1
  326. package/dist/app/assets/{zig-BtNZL4AA.js → zig-C_1JL5rU.js} +1 -1
  327. package/dist/app/index.html +2 -2
  328. package/dist/index.cjs +2316 -885
  329. package/dist/index.js +2293 -849
  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,548 @@ 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 ?? []).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 ?? [],
1838
+ ...live.agents
1839
+ ]);
1840
+ const pending = mergePending([
1841
+ ...historySections?.pending ?? history?.pending.items ?? [],
1842
+ ...live.pending
1843
+ ]);
1844
+ return {
1845
+ goal: live.goal ?? history?.task.goal,
1846
+ plan: newest(
1847
+ [history?.task.plan, live.plan].filter(
1848
+ (item) => Boolean(item)
1849
+ )
1850
+ ),
1851
+ todos: newest(
1852
+ [history?.task.todos, live.todos].filter(
1853
+ (item) => Boolean(item)
1854
+ )
1855
+ ),
1856
+ outputs,
1857
+ sources,
1858
+ agents,
1859
+ pending,
1860
+ running: live.running,
1861
+ totals: {
1862
+ outputs: Math.max(history?.outputs.total ?? 0, outputs.length),
1863
+ sources: Math.max(history?.sources.total ?? 0, sources.length),
1864
+ agents: agents.length,
1865
+ pending: Math.max(history?.pending.total ?? 0, pending.length)
1866
+ }
1867
+ };
1868
+ }
1869
+ function mergeLatest(items) {
1870
+ const byId = /* @__PURE__ */ new Map();
1871
+ items.forEach((item) => {
1872
+ const current = byId.get(item.id);
1873
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1874
+ byId.set(item.id, item);
1875
+ }
1876
+ });
1877
+ return [...byId.values()].sort(
1878
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1879
+ );
1880
+ }
1881
+ function mergeAgents(items) {
1882
+ const byAgent = /* @__PURE__ */ new Map();
1883
+ items.forEach((item) => {
1884
+ const key = item.agentKey?.trim() || item.id;
1885
+ const current = byAgent.get(key);
1886
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1887
+ byAgent.set(key, item);
1888
+ }
1889
+ });
1890
+ return [...byAgent.values()].sort(
1891
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1892
+ );
1893
+ }
1894
+ function mergePending(items) {
1895
+ const byId = new Map(items.map((item) => [item.id, item]));
1896
+ return [...byId.values()].sort(
1897
+ (left, right) => timestamp(right.createdAt) - timestamp(left.createdAt)
1898
+ );
1899
+ }
1900
+ function taskSummaryAgentStatus(status) {
1901
+ switch (status) {
1902
+ case "running":
1903
+ case "success":
1904
+ case "error":
1905
+ case "pending":
1906
+ case "timeout":
1907
+ case "interrupted":
1908
+ return status;
1909
+ default:
1910
+ return void 0;
1911
+ }
1912
+ }
1913
+ function newest(items) {
1914
+ return [...items].sort(
1915
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1916
+ )[0];
1917
+ }
1918
+ function agentRunLevel(run, messages) {
1919
+ const byId = new Map(
1920
+ messages.flatMap(
1921
+ (message) => (message.agentRuns ?? []).map((item) => [item.id, item])
1922
+ )
1923
+ );
1924
+ let parentId = run.parentId;
1925
+ let level = 0;
1926
+ const visited = /* @__PURE__ */ new Set();
1927
+ while (parentId && !visited.has(parentId)) {
1928
+ visited.add(parentId);
1929
+ level += 1;
1930
+ parentId = byId.get(parentId)?.parentId;
1931
+ }
1932
+ return level;
1933
+ }
1934
+
1280
1935
  // src/providers/Stream.tsx
1281
1936
  var import_jsx_runtime2 = require("react/jsx-runtime");
1282
1937
  var import_meta = {};
@@ -1714,6 +2369,39 @@ var en_US_default = {
1714
2369
  failed: "Failed to render diagram"
1715
2370
  }
1716
2371
  },
2372
+ taskSummary: {
2373
+ title: "Task summary",
2374
+ description: "Current task, outputs, sources, running services, agent activity, and pending requests.",
2375
+ open: "Open task summary",
2376
+ empty: "Task activity will appear here.",
2377
+ historyError: "Some historical summary data failed to load. Live activity is still available.",
2378
+ retry: "Retry",
2379
+ viewAll: "View all",
2380
+ loadMore: "Load more",
2381
+ collapse: "Show less",
2382
+ createOutput: "Create files or sites",
2383
+ addOutput: "Create output",
2384
+ addSource: "Add source",
2385
+ sections: {
2386
+ task: "Task",
2387
+ outputs: "Outputs",
2388
+ sources: "Sources",
2389
+ running: "Running",
2390
+ agents: "Agent activity",
2391
+ pending: "Pending"
2392
+ },
2393
+ status: {
2394
+ pending: "Pending",
2395
+ in_progress: "In progress",
2396
+ completed: "Completed"
2397
+ },
2398
+ pending: {
2399
+ approval: "Approval required",
2400
+ userInput: "Input required",
2401
+ followUp: "Pending follow-up message",
2402
+ steer: "Pending steering message"
2403
+ }
2404
+ },
1717
2405
  thread: {
1718
2406
  errorToast: "An error occurred. Please try again.",
1719
2407
  errorLabel: "Error:",
@@ -2122,6 +2810,39 @@ var zh_CN_default = {
2122
2810
  failed: "\u56FE\u8868\u6E32\u67D3\u5931\u8D25"
2123
2811
  }
2124
2812
  },
2813
+ taskSummary: {
2814
+ title: "\u4EFB\u52A1\u6458\u8981",
2815
+ 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",
2816
+ open: "\u6253\u5F00\u4EFB\u52A1\u6458\u8981",
2817
+ empty: "\u4EFB\u52A1\u6D3B\u52A8\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002",
2818
+ historyError: "\u90E8\u5206\u5386\u53F2\u6458\u8981\u52A0\u8F7D\u5931\u8D25\uFF0C\u5B9E\u65F6\u6D3B\u52A8\u4ECD\u53EF\u4F7F\u7528\u3002",
2819
+ retry: "\u91CD\u8BD5",
2820
+ viewAll: "\u67E5\u770B\u5168\u90E8",
2821
+ loadMore: "\u52A0\u8F7D\u66F4\u591A",
2822
+ collapse: "\u6536\u8D77",
2823
+ createOutput: "\u521B\u5EFA\u6587\u4EF6\u6216\u7AD9\u70B9",
2824
+ addOutput: "\u521B\u5EFA\u4EA7\u51FA",
2825
+ addSource: "\u6DFB\u52A0\u6765\u6E90",
2826
+ sections: {
2827
+ task: "\u4EFB\u52A1",
2828
+ outputs: "\u4EA7\u51FA",
2829
+ sources: "\u6765\u6E90",
2830
+ running: "\u8FD0\u884C\u4E2D",
2831
+ agents: "Agent \u6D3B\u52A8",
2832
+ pending: "\u5F85\u5904\u7406"
2833
+ },
2834
+ status: {
2835
+ pending: "\u5F85\u5904\u7406",
2836
+ in_progress: "\u8FDB\u884C\u4E2D",
2837
+ completed: "\u5DF2\u5B8C\u6210"
2838
+ },
2839
+ pending: {
2840
+ approval: "\u9700\u8981\u5BA1\u6279",
2841
+ userInput: "\u9700\u8981\u8F93\u5165",
2842
+ followUp: "\u7B49\u5F85\u53D1\u9001\u7684\u8DDF\u8FDB\u6D88\u606F",
2843
+ steer: "\u7B49\u5F85\u53D1\u9001\u7684\u5F15\u5BFC\u6D88\u606F"
2844
+ }
2845
+ },
2125
2846
  thread: {
2126
2847
  errorToast: "\u53D1\u751F\u9519\u8BEF\uFF0C\u8BF7\u91CD\u8BD5\u3002",
2127
2848
  errorLabel: "\u9519\u8BEF\uFF1A",
@@ -4853,8 +5574,8 @@ function JsonTreeNode({
4853
5574
  depth = 0
4854
5575
  }) {
4855
5576
  const isArray = Array.isArray(value);
4856
- const isObject = isJsonObjectValue(value);
4857
- const isExpandable = isArray || isObject;
5577
+ const isObject2 = isJsonObjectValue(value);
5578
+ const isExpandable = isArray || isObject2;
4858
5579
  const [isExpanded, setIsExpanded] = React18.useState(depth < 2);
4859
5580
  if (!isExpandable) {
4860
5581
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex min-w-0 gap-2 leading-6", children: [
@@ -5249,7 +5970,7 @@ function HITLApprovalPanel({
5249
5970
  }
5250
5971
  const argsText = currentDraft.argsText ?? formatArgs(currentAction.args);
5251
5972
  const argsJsonValue = toJsonValue(currentAction.args) ?? {};
5252
- const messageText = currentDraft.message ?? "";
5973
+ const messageText2 = currentDraft.message ?? "";
5253
5974
  const isCurrentInvalid = validation.error?.actionIndex === currentActionIndex;
5254
5975
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
5255
5976
  "section",
@@ -5411,7 +6132,7 @@ function HITLApprovalPanel({
5411
6132
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5412
6133
  "textarea",
5413
6134
  {
5414
- value: messageText,
6135
+ value: messageText2,
5415
6136
  onChange: (event) => updateCurrentDraft({
5416
6137
  ...currentDraft,
5417
6138
  message: event.target.value
@@ -7837,14 +8558,14 @@ function isComponentContent(content) {
7837
8558
  }
7838
8559
  function parseDateValue(value) {
7839
8560
  if (value instanceof Date) {
7840
- const timestamp2 = value.getTime();
7841
- return Number.isNaN(timestamp2) ? null : timestamp2;
8561
+ const timestamp3 = value.getTime();
8562
+ return Number.isNaN(timestamp3) ? null : timestamp3;
7842
8563
  }
7843
8564
  if (typeof value !== "string") {
7844
8565
  return null;
7845
8566
  }
7846
- const timestamp = Date.parse(value);
7847
- return Number.isNaN(timestamp) ? null : timestamp;
8567
+ const timestamp2 = Date.parse(value);
8568
+ return Number.isNaN(timestamp2) ? null : timestamp2;
7848
8569
  }
7849
8570
  function readContentTitle(content) {
7850
8571
  if (typeof content === "string") return void 0;
@@ -10611,14 +11332,14 @@ function getToolStepData(content) {
10611
11332
  }
10612
11333
  function parseStepDate(value) {
10613
11334
  if (value instanceof Date) {
10614
- const timestamp2 = value.getTime();
10615
- return Number.isNaN(timestamp2) ? null : timestamp2;
11335
+ const timestamp3 = value.getTime();
11336
+ return Number.isNaN(timestamp3) ? null : timestamp3;
10616
11337
  }
10617
11338
  if (typeof value !== "string") {
10618
11339
  return null;
10619
11340
  }
10620
- const timestamp = Date.parse(value);
10621
- return Number.isNaN(timestamp) ? null : timestamp;
11341
+ const timestamp2 = Date.parse(value);
11342
+ return Number.isNaN(timestamp2) ? null : timestamp2;
10622
11343
  }
10623
11344
  function isThreadKnownIdle(isThreadRunning) {
10624
11345
  return isThreadRunning === false;
@@ -12882,14 +13603,14 @@ function MemoryBlock({ content }) {
12882
13603
  }
12883
13604
  function parseStepDate2(value) {
12884
13605
  if (value instanceof Date) {
12885
- const timestamp2 = value.getTime();
12886
- return Number.isNaN(timestamp2) ? null : timestamp2;
13606
+ const timestamp3 = value.getTime();
13607
+ return Number.isNaN(timestamp3) ? null : timestamp3;
12887
13608
  }
12888
13609
  if (typeof value !== "string") {
12889
13610
  return null;
12890
13611
  }
12891
- const timestamp = Date.parse(value);
12892
- return Number.isNaN(timestamp) ? null : timestamp;
13612
+ const timestamp2 = Date.parse(value);
13613
+ return Number.isNaN(timestamp2) ? null : timestamp2;
12893
13614
  }
12894
13615
  function formatStepDuration3(durationMs) {
12895
13616
  if (durationMs < 1e3) {
@@ -13658,9 +14379,9 @@ var getThreadTitle = (threadRecord) => {
13658
14379
  };
13659
14380
  var toDate = (value) => {
13660
14381
  if (!value) return void 0;
13661
- const timestamp = Date.parse(value);
13662
- if (Number.isNaN(timestamp)) return void 0;
13663
- return new Date(timestamp);
14382
+ const timestamp2 = Date.parse(value);
14383
+ if (Number.isNaN(timestamp2)) return void 0;
14384
+ return new Date(timestamp2);
13664
14385
  };
13665
14386
  var getErrorMessage2 = (error) => {
13666
14387
  if (!error) return void 0;
@@ -16415,57 +17136,513 @@ function buildMessageNavigationItems(messages, options) {
16415
17136
  return items;
16416
17137
  }
16417
17138
 
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();
16452
- };
16453
- image.onerror = () => {
16454
- resolve({});
16455
- cleanup();
17139
+ // src/hooks/useTaskSummary.ts
17140
+ var React52 = __toESM(require("react"), 1);
17141
+ function useTaskSummary({
17142
+ enabled,
17143
+ conversationId,
17144
+ client,
17145
+ live
17146
+ }) {
17147
+ const [loaded, setLoaded] = React52.useState(null);
17148
+ const [historySections, setHistorySections] = React52.useState({});
17149
+ const [historySectionsConversationId, setHistorySectionsConversationId] = React52.useState(null);
17150
+ const [loadingSections, setLoadingSections] = React52.useState({});
17151
+ const [error, setError] = React52.useState(null);
17152
+ const [retryVersion, setRetryVersion] = React52.useState(0);
17153
+ const requestVersionRef = React52.useRef(0);
17154
+ const conversationIdRef = React52.useRef(conversationId);
17155
+ const sectionControllersRef = React52.useRef(
17156
+ /* @__PURE__ */ new Map()
17157
+ );
17158
+ conversationIdRef.current = conversationId;
17159
+ const abortSectionRequests = React52.useCallback(() => {
17160
+ sectionControllersRef.current.forEach((controller) => controller.abort());
17161
+ sectionControllersRef.current.clear();
17162
+ }, []);
17163
+ React52.useEffect(() => {
17164
+ abortSectionRequests();
17165
+ setHistorySections({});
17166
+ setHistorySectionsConversationId(conversationId);
17167
+ setLoadingSections({});
17168
+ setError(null);
17169
+ if (!enabled || !conversationId) {
17170
+ setLoaded(null);
17171
+ setHistorySectionsConversationId(null);
17172
+ return;
17173
+ }
17174
+ const controller = new AbortController();
17175
+ const requestVersion = ++requestVersionRef.current;
17176
+ client.conversations.getTaskSummary(conversationId, { signal: controller.signal }).then((snapshot2) => {
17177
+ if (requestVersionRef.current !== requestVersion) return;
17178
+ setLoaded({ conversationId, snapshot: snapshot2 });
17179
+ }).catch((nextError) => {
17180
+ if (controller.signal.aborted || requestVersionRef.current !== requestVersion)
17181
+ return;
17182
+ setLoaded(null);
17183
+ setError(nextError);
17184
+ });
17185
+ return () => {
17186
+ controller.abort();
17187
+ abortSectionRequests();
17188
+ requestVersionRef.current += 1;
16456
17189
  };
16457
- image.src = objectUrl;
16458
- });
16459
- }
16460
- function getUploadedFileUrl(file) {
16461
- return file.url ?? file.fileUrl ?? file.thumbUrl;
16462
- }
16463
- function buildPastedImageReference(file, uploadedFile, dimensions) {
16464
- const name = uploadedFile.originalName?.trim() || file.name.trim() || "Pasted image";
16465
- const mimeType = uploadedFile.mimeType?.trim() || file.type.trim() || "image/*";
16466
- const size2 = uploadedFile.size ?? file.size;
16467
- const width = dimensions?.width;
16468
- const height = dimensions?.height;
17190
+ }, [abortSectionRequests, client, conversationId, enabled, retryVersion]);
17191
+ const snapshot = loaded?.conversationId === conversationId ? loaded.snapshot : null;
17192
+ const activeHistorySections = React52.useMemo(
17193
+ () => historySectionsConversationId === conversationId ? historySections : {},
17194
+ [conversationId, historySections, historySectionsConversationId]
17195
+ );
17196
+ const loadSection = React52.useCallback(
17197
+ async (section) => {
17198
+ if (!enabled || !conversationId || loadingSections[section]) {
17199
+ return;
17200
+ }
17201
+ const current = activeHistorySections[section]?.length ?? 0;
17202
+ const controller = new AbortController();
17203
+ sectionControllersRef.current.get(section)?.abort();
17204
+ sectionControllersRef.current.set(section, controller);
17205
+ setLoadingSections((state) => ({ ...state, [section]: true }));
17206
+ try {
17207
+ const page = await client.conversations.listTaskSummaryItems(
17208
+ conversationId,
17209
+ section,
17210
+ { offset: current, limit: 50, signal: controller.signal }
17211
+ );
17212
+ if (conversationIdRef.current !== conversationId) return;
17213
+ setHistorySections(
17214
+ (state) => ({
17215
+ ...state,
17216
+ [section]: [...state[section] ?? [], ...page.items]
17217
+ })
17218
+ );
17219
+ } catch (nextError) {
17220
+ if (!controller.signal.aborted) {
17221
+ setError(nextError);
17222
+ }
17223
+ } finally {
17224
+ if (sectionControllersRef.current.get(section) === controller) {
17225
+ sectionControllersRef.current.delete(section);
17226
+ }
17227
+ if (conversationIdRef.current === conversationId) {
17228
+ setLoadingSections((state) => ({ ...state, [section]: false }));
17229
+ }
17230
+ }
17231
+ },
17232
+ [
17233
+ activeHistorySections,
17234
+ client,
17235
+ conversationId,
17236
+ enabled,
17237
+ loadingSections
17238
+ ]
17239
+ );
17240
+ return {
17241
+ summary: mergeTaskSummary(snapshot, live, activeHistorySections),
17242
+ historyError: error,
17243
+ retryHistory: () => setRetryVersion((version) => version + 1),
17244
+ loadSection,
17245
+ loadingSections,
17246
+ loadedSectionCounts: {
17247
+ outputs: activeHistorySections.outputs?.length ?? 0,
17248
+ sources: activeHistorySections.sources?.length ?? 0,
17249
+ agents: activeHistorySections.agents?.length ?? 0,
17250
+ pending: activeHistorySections.pending?.length ?? 0
17251
+ }
17252
+ };
17253
+ }
17254
+
17255
+ // src/components/task-summary/TaskSummary.tsx
17256
+ var React53 = __toESM(require("react"), 1);
17257
+ var import_lucide_react30 = require("lucide-react");
17258
+ var import_jsx_runtime57 = require("react/jsx-runtime");
17259
+ var PREVIEW_SIZE = 3;
17260
+ function TaskSummaryTrigger({
17261
+ displayMode = "popover",
17262
+ open: controlledOpen,
17263
+ onOpenChange,
17264
+ ...props
17265
+ }) {
17266
+ const { t } = useChatkitTranslation();
17267
+ const [uncontrolledOpen, setUncontrolledOpen] = React53.useState(false);
17268
+ const open = controlledOpen ?? uncontrolledOpen;
17269
+ const setOpen = React53.useCallback(
17270
+ (nextOpen) => {
17271
+ if (controlledOpen === void 0) {
17272
+ setUncontrolledOpen(nextOpen);
17273
+ }
17274
+ onOpenChange?.(nextOpen);
17275
+ },
17276
+ [controlledOpen, onOpenChange]
17277
+ );
17278
+ const triggerButton = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17279
+ "button",
17280
+ {
17281
+ type: "button",
17282
+ 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",
17283
+ "aria-label": t("taskSummary.open"),
17284
+ "aria-expanded": open,
17285
+ onClick: displayMode === "docked" ? () => setOpen(!open) : void 0,
17286
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { size: 16 })
17287
+ }
17288
+ );
17289
+ if (displayMode === "docked") {
17290
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
17291
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: triggerButton }),
17292
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17293
+ ] });
17294
+ }
17295
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
17296
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip, { children: [
17297
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PopoverTrigger, { asChild: true, children: triggerButton }) }),
17298
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17299
+ ] }),
17300
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17301
+ PopoverContent,
17302
+ {
17303
+ align: "end",
17304
+ sideOffset: 8,
17305
+ 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",
17306
+ "aria-label": t("taskSummary.title"),
17307
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TaskSummaryContent, { ...props })
17308
+ }
17309
+ )
17310
+ ] });
17311
+ }
17312
+ function TaskSummaryPanel({
17313
+ className,
17314
+ ...props
17315
+ }) {
17316
+ const { t } = useChatkitTranslation();
17317
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17318
+ "aside",
17319
+ {
17320
+ "data-slot": "task-summary-panel",
17321
+ "aria-label": t("taskSummary.title"),
17322
+ className: cn(
17323
+ "h-fit max-h-full overflow-y-auto rounded-2xl border border-border/70 bg-popover text-popover-foreground shadow-lg",
17324
+ className
17325
+ ),
17326
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TaskSummaryContent, { ...props })
17327
+ }
17328
+ );
17329
+ }
17330
+ function TaskSummaryContent({
17331
+ summary,
17332
+ historyError,
17333
+ loadingSections = {},
17334
+ loadedSectionCounts = { outputs: 0, sources: 0, agents: 0, pending: 0 },
17335
+ onRetryHistory,
17336
+ onLoadSection,
17337
+ onNavigateMessage,
17338
+ onFocusComposer,
17339
+ onOpenResource
17340
+ }) {
17341
+ const { t } = useChatkitTranslation();
17342
+ const [expanded, setExpanded] = React53.useState({});
17343
+ const hasTask = Boolean(
17344
+ summary.goal || summary.plan || summary.todos?.items.length
17345
+ );
17346
+ const toggleSection = (section) => {
17347
+ if (expanded[section]) {
17348
+ setExpanded((state) => ({ ...state, [section]: false }));
17349
+ return;
17350
+ }
17351
+ setExpanded((state) => ({ ...state, [section]: true }));
17352
+ if (loadedSectionCounts[section] === 0) {
17353
+ void onLoadSection(section);
17354
+ }
17355
+ };
17356
+ const sectionItems = (section, items) => expanded[section] ? items : items.slice(0, PREVIEW_SIZE);
17357
+ const openSummaryItem = (resource, messageId, title) => {
17358
+ if (resource?.type === "message") {
17359
+ onNavigateMessage(resource.messageId);
17360
+ return;
17361
+ }
17362
+ if (resource) {
17363
+ onOpenResource(resource, messageId, title);
17364
+ return;
17365
+ }
17366
+ if (messageId) {
17367
+ onNavigateMessage(messageId);
17368
+ }
17369
+ };
17370
+ const sectionAction = (section, total2) => {
17371
+ if (total2 <= PREVIEW_SIZE && !expanded[section]) return null;
17372
+ const loading = loadingSections[section];
17373
+ const canLoadMore = Boolean(expanded[section]) && loadedSectionCounts[section] < total2;
17374
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17375
+ "button",
17376
+ {
17377
+ type: "button",
17378
+ 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",
17379
+ disabled: loading,
17380
+ onClick: () => canLoadMore ? void onLoadSection(section) : toggleSection(section),
17381
+ children: [
17382
+ loading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Loader2, { className: "size-3 animate-spin" }),
17383
+ !loading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { className: "size-3.5" }),
17384
+ canLoadMore ? t("taskSummary.loadMore") : expanded[section] ? t("taskSummary.collapse") : t("taskSummary.viewAll", { count: total2 })
17385
+ ]
17386
+ }
17387
+ );
17388
+ };
17389
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "divide-y divide-border/70", children: [
17390
+ 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: [
17391
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: t("taskSummary.historyError") }),
17392
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17393
+ "button",
17394
+ {
17395
+ type: "button",
17396
+ className: "inline-flex shrink-0 items-center gap-1 font-medium hover:underline",
17397
+ onClick: onRetryHistory,
17398
+ children: [
17399
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.RotateCcw, { className: "size-3" }),
17400
+ t("taskSummary.retry")
17401
+ ]
17402
+ }
17403
+ )
17404
+ ] }),
17405
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17406
+ SummarySection,
17407
+ {
17408
+ title: t("taskSummary.sections.outputs"),
17409
+ actionLabel: t("taskSummary.addOutput"),
17410
+ onAction: onFocusComposer,
17411
+ children: [
17412
+ 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)(
17413
+ SummaryButton,
17414
+ {
17415
+ title: item.title,
17416
+ description: item.description ?? item.status,
17417
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.FileOutput, { className: "size-4" }),
17418
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17419
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17420
+ },
17421
+ item.id
17422
+ )),
17423
+ sectionAction("outputs", summary.totals.outputs)
17424
+ ]
17425
+ }
17426
+ ),
17427
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17428
+ SummarySection,
17429
+ {
17430
+ title: t("taskSummary.sections.sources"),
17431
+ actionLabel: t("taskSummary.addSource"),
17432
+ onAction: onFocusComposer,
17433
+ children: [
17434
+ sectionItems("sources", summary.sources).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17435
+ SummaryButton,
17436
+ {
17437
+ title: item.title,
17438
+ description: item.description,
17439
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.BookOpen, { className: "size-4" }),
17440
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17441
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17442
+ },
17443
+ item.id
17444
+ )),
17445
+ sectionAction("sources", summary.totals.sources)
17446
+ ]
17447
+ }
17448
+ ),
17449
+ hasTask && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.task"), children: [
17450
+ summary.goal && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17451
+ SummaryButton,
17452
+ {
17453
+ title: summary.goal.objective,
17454
+ description: summary.goal.status,
17455
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Target, { className: "size-4" }),
17456
+ onClick: onFocusComposer
17457
+ }
17458
+ ),
17459
+ summary.plan && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17460
+ SummaryButton,
17461
+ {
17462
+ title: summary.plan.title,
17463
+ description: summary.plan.excerpt,
17464
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ListChecks, { className: "size-4" }),
17465
+ onClick: () => summary.plan?.messageId ? onNavigateMessage(summary.plan.messageId) : onFocusComposer()
17466
+ }
17467
+ ),
17468
+ (summary.todos?.items ?? []).slice(0, PREVIEW_SIZE).map((todo) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17469
+ SummaryButton,
17470
+ {
17471
+ title: todo.content,
17472
+ description: t(`taskSummary.status.${todo.status}`),
17473
+ 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" }),
17474
+ onClick: () => summary.todos?.messageId ? onNavigateMessage(summary.todos.messageId) : onFocusComposer()
17475
+ },
17476
+ todo.id
17477
+ ))
17478
+ ] }),
17479
+ 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)(
17480
+ SummaryButton,
17481
+ {
17482
+ title: item.title,
17483
+ description: item.description ?? item.status,
17484
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.PlayCircle, { className: "size-4" }),
17485
+ trailing: item.resource ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.ExternalLink, { className: "size-3.5" }) : void 0,
17486
+ onClick: () => item.resource && onOpenResource(item.resource, void 0, item.title)
17487
+ },
17488
+ item.id
17489
+ )) }),
17490
+ summary.agents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.agents"), children: [
17491
+ sectionItems("agents", summary.agents).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17492
+ SummaryButton,
17493
+ {
17494
+ title: item.title,
17495
+ description: [item.status, formatElapsed(item.elapsedTime)].filter(Boolean).join(" \xB7 "),
17496
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Bot, { className: "size-4" }),
17497
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17498
+ },
17499
+ item.id
17500
+ )),
17501
+ sectionAction("agents", summary.totals.agents)
17502
+ ] }),
17503
+ summary.pending.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(SummarySection, { title: t("taskSummary.sections.pending"), children: [
17504
+ sectionItems("pending", summary.pending).map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17505
+ SummaryButton,
17506
+ {
17507
+ title: item.title,
17508
+ description: item.description,
17509
+ leading: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.CircleEllipsis, { className: "size-4" }),
17510
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17511
+ },
17512
+ item.id
17513
+ )),
17514
+ sectionAction("pending", summary.totals.pending)
17515
+ ] })
17516
+ ] });
17517
+ }
17518
+ function SummarySection({
17519
+ title,
17520
+ actionLabel,
17521
+ onAction,
17522
+ children
17523
+ }) {
17524
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("section", { "aria-label": title, className: "px-4 py-3", children: [
17525
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex min-h-7 items-center justify-between gap-3", children: [
17526
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { className: "text-sm font-medium text-muted-foreground", children: title }),
17527
+ onAction && actionLabel && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17528
+ Button,
17529
+ {
17530
+ type: "button",
17531
+ variant: "ghost",
17532
+ size: "icon-xs",
17533
+ className: "size-7 rounded-lg bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground",
17534
+ "aria-label": actionLabel,
17535
+ onClick: onAction,
17536
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.Plus, { className: "size-4" })
17537
+ }
17538
+ )
17539
+ ] }),
17540
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "mt-1 space-y-0.5", children })
17541
+ ] });
17542
+ }
17543
+ function SummaryPrompt({
17544
+ children,
17545
+ onClick
17546
+ }) {
17547
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17548
+ "button",
17549
+ {
17550
+ type: "button",
17551
+ 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",
17552
+ onClick,
17553
+ children
17554
+ }
17555
+ );
17556
+ }
17557
+ function SummaryButton({
17558
+ title,
17559
+ description,
17560
+ leading,
17561
+ trailing,
17562
+ onClick
17563
+ }) {
17564
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
17565
+ "button",
17566
+ {
17567
+ type: "button",
17568
+ disabled: !onClick,
17569
+ onClick,
17570
+ className: cn(
17571
+ "flex w-full min-w-0 items-start gap-2.5 rounded-lg px-2 py-1.5 text-left transition-colors",
17572
+ onClick && "hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
17573
+ !onClick && "cursor-default"
17574
+ ),
17575
+ children: [
17576
+ leading && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: leading }),
17577
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "min-w-0 flex-1", children: [
17578
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "block truncate text-sm font-medium leading-5 text-foreground", children: title }),
17579
+ description && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 block line-clamp-2 text-xs text-muted-foreground", children: description })
17580
+ ] }),
17581
+ trailing && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "mt-0.5 text-muted-foreground", children: trailing })
17582
+ ]
17583
+ }
17584
+ );
17585
+ }
17586
+ function formatElapsed(value) {
17587
+ if (typeof value !== "number" || !Number.isFinite(value)) return "";
17588
+ if (value < 1e3) return `${Math.round(value)}ms`;
17589
+ return `${(value / 1e3).toFixed(1)}s`;
17590
+ }
17591
+
17592
+ // src/components/chat.tsx
17593
+ var import_jsx_runtime58 = require("react/jsx-runtime");
17594
+ var import_meta2 = {};
17595
+ var defaultApiUrl2 = import_meta2.env.VITE_XPERTAI_API_URL;
17596
+ var COMPOSER_INPUT_MAX_HEIGHT = 128;
17597
+ var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
17598
+ var GOAL_RUN_INPUT = "Continue working toward the active goal.";
17599
+ var TASK_SUMMARY_PANEL_WIDTH_REM = 20;
17600
+ var TASK_SUMMARY_PANEL_EDGE_INSET_REM = 1.25;
17601
+ var TASK_SUMMARY_PANEL_SAFE_GAP_REM = 0.75;
17602
+ function isGoalAdapter(value) {
17603
+ return Boolean(value) && typeof value === "object" && typeof value.getGoal === "function" && typeof value.setGoal === "function" && typeof value.updateGoal === "function" && typeof value.clearGoal === "function";
17604
+ }
17605
+ function formatGoalElapsed(seconds) {
17606
+ if (seconds < 60) {
17607
+ return `${seconds}s`;
17608
+ }
17609
+ const minutes = Math.floor(seconds / 60);
17610
+ const remainingSeconds = seconds % 60;
17611
+ return remainingSeconds ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
17612
+ }
17613
+ async function readImageDimensions(file) {
17614
+ if (typeof window === "undefined" || typeof URL === "undefined") {
17615
+ return {};
17616
+ }
17617
+ return new Promise((resolve) => {
17618
+ const objectUrl = URL.createObjectURL(file);
17619
+ const image = new window.Image();
17620
+ const cleanup = () => {
17621
+ URL.revokeObjectURL(objectUrl);
17622
+ };
17623
+ image.onload = () => {
17624
+ resolve({
17625
+ width: image.naturalWidth || void 0,
17626
+ height: image.naturalHeight || void 0
17627
+ });
17628
+ cleanup();
17629
+ };
17630
+ image.onerror = () => {
17631
+ resolve({});
17632
+ cleanup();
17633
+ };
17634
+ image.src = objectUrl;
17635
+ });
17636
+ }
17637
+ function getUploadedFileUrl(file) {
17638
+ return file.url ?? file.fileUrl ?? file.thumbUrl;
17639
+ }
17640
+ function buildPastedImageReference(file, uploadedFile, dimensions) {
17641
+ const name = uploadedFile.originalName?.trim() || file.name.trim() || "Pasted image";
17642
+ const mimeType = uploadedFile.mimeType?.trim() || file.type.trim() || "image/*";
17643
+ const size2 = uploadedFile.size ?? file.size;
17644
+ const width = dimensions?.width;
17645
+ const height = dimensions?.height;
16469
17646
  const metaParts = [
16470
17647
  mimeType,
16471
17648
  width && height ? `${width}x${height}` : null,
@@ -16520,8 +17697,8 @@ function ReferenceChip({
16520
17697
  }) {
16521
17698
  const metaLine = getReferenceMetaLine(reference);
16522
17699
  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)(
17700
+ const Icon = reference.type === "quote" ? import_lucide_react31.Quote : reference.type === "image" ? import_lucide_react31.ImageIcon : import_lucide_react31.FileText;
17701
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
16525
17702
  "div",
16526
17703
  {
16527
17704
  className: cn(
@@ -16530,7 +17707,7 @@ function ReferenceChip({
16530
17707
  ),
16531
17708
  title: getReferenceTitle(reference),
16532
17709
  children: [
16533
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17710
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16534
17711
  Icon,
16535
17712
  {
16536
17713
  size: isComposer ? 14 : 12,
@@ -16540,8 +17717,8 @@ function ReferenceChip({
16540
17717
  )
16541
17718
  }
16542
17719
  ),
16543
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "min-w-0 flex-1", children: [
16544
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17720
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0 flex-1", children: [
17721
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16545
17722
  "div",
16546
17723
  {
16547
17724
  className: cn(
@@ -16551,7 +17728,7 @@ function ReferenceChip({
16551
17728
  children: getReferenceLabel(reference)
16552
17729
  }
16553
17730
  ),
16554
- metaLine && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17731
+ metaLine && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16555
17732
  "div",
16556
17733
  {
16557
17734
  className: cn(
@@ -16562,7 +17739,7 @@ function ReferenceChip({
16562
17739
  }
16563
17740
  )
16564
17741
  ] }),
16565
- onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
17742
+ onRemove && removeLabel && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
16566
17743
  "button",
16567
17744
  {
16568
17745
  type: "button",
@@ -16573,7 +17750,7 @@ function ReferenceChip({
16573
17750
  ),
16574
17751
  title: removeLabel,
16575
17752
  "aria-label": removeLabel,
16576
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react30.X, { size: 12 })
17753
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.X, { size: 12 })
16577
17754
  }
16578
17755
  )
16579
17756
  ]
@@ -16604,7 +17781,7 @@ function Chat({
16604
17781
  clientSecret: effectiveClientSecret
16605
17782
  });
16606
17783
  const missingConfig = Boolean(missingConfigKind);
16607
- const missingConfigShortMessage = React52.useMemo(() => {
17784
+ const missingConfigShortMessage = React54.useMemo(() => {
16608
17785
  switch (missingConfigKind) {
16609
17786
  case "apiUrl":
16610
17787
  return t("chat.missingApiUrlShort");
@@ -16616,7 +17793,7 @@ function Chat({
16616
17793
  return t("chat.missingConfigShort");
16617
17794
  }
16618
17795
  }, [missingConfigKind, t]);
16619
- const missingConfigDetailMessage = React52.useMemo(() => {
17796
+ const missingConfigDetailMessage = React54.useMemo(() => {
16620
17797
  switch (missingConfigKind) {
16621
17798
  case "apiUrl":
16622
17799
  return t("chat.missingApiUrlDetail");
@@ -16628,26 +17805,26 @@ function Chat({
16628
17805
  return t("chat.missingConfigDetail");
16629
17806
  }
16630
17807
  }, [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);
17808
+ const [isHistoryLoading, setIsHistoryLoading] = React54.useState(false);
17809
+ const [historyError, setHistoryError] = React54.useState(null);
17810
+ const [assistantName, setAssistantName] = React54.useState(null);
17811
+ const [assistantAvatar, setAssistantAvatar] = React54.useState(null);
17812
+ const [threadGoal, setThreadGoal] = React54.useState(null);
17813
+ const [goalError, setGoalError] = React54.useState(null);
17814
+ const [isGoalLoading, setIsGoalLoading] = React54.useState(false);
17815
+ const [isGoalPanelOpen, setIsGoalPanelOpen] = React54.useState(false);
17816
+ const [isGoalObjectiveExpanded, setIsGoalObjectiveExpanded] = React54.useState(false);
17817
+ const [goalElapsedStartedAt, setGoalElapsedStartedAt] = React54.useState(null);
16641
17818
  const LOADING_DOTS_MIN_DURATION = 800;
16642
17819
  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(() => {
17820
+ const [showLoadingDots, setShowLoadingDots] = React54.useState(false);
17821
+ const [streamingNow, setStreamingNow] = React54.useState(() => Date.now());
17822
+ const loadingStartTimeRef = React54.useRef(null);
17823
+ const lastStreamOutputAtRef = React54.useRef(null);
17824
+ React54.useEffect(() => {
16648
17825
  setStream(stream);
16649
17826
  }, [setStream, stream]);
16650
- React52.useEffect(() => {
17827
+ React54.useEffect(() => {
16651
17828
  if (stream.isLoading) {
16652
17829
  if (!loadingStartTimeRef.current) {
16653
17830
  loadingStartTimeRef.current = Date.now();
@@ -16670,7 +17847,7 @@ function Chat({
16670
17847
  }
16671
17848
  }
16672
17849
  }, [stream.isLoading]);
16673
- React52.useEffect(() => {
17850
+ React54.useEffect(() => {
16674
17851
  if (!stream.isLoading) {
16675
17852
  lastStreamOutputAtRef.current = null;
16676
17853
  setStreamingNow(Date.now());
@@ -16680,7 +17857,7 @@ function Chat({
16680
17857
  lastStreamOutputAtRef.current = now;
16681
17858
  setStreamingNow(now);
16682
17859
  }, [stream.messages, stream.isLoading]);
16683
- React52.useEffect(() => {
17860
+ React54.useEffect(() => {
16684
17861
  if (!stream.isLoading) {
16685
17862
  return;
16686
17863
  }
@@ -16689,7 +17866,7 @@ function Chat({
16689
17866
  }, STREAMING_STATUS_REFRESH_MS);
16690
17867
  return () => window.clearInterval(timer);
16691
17868
  }, [stream.isLoading]);
16692
- React52.useEffect(() => {
17869
+ React54.useEffect(() => {
16693
17870
  if (threadGoal?.status === "active" && stream.isLoading) {
16694
17871
  setGoalElapsedStartedAt(Date.now());
16695
17872
  return;
@@ -16701,54 +17878,55 @@ function Chat({
16701
17878
  threadGoal?.id,
16702
17879
  threadGoal?.status
16703
17880
  ]);
16704
- React52.useEffect(() => {
17881
+ React54.useEffect(() => {
16705
17882
  setIsGoalObjectiveExpanded(false);
16706
17883
  }, [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(
17884
+ const [composerParts, setComposerParts] = React54.useState([]);
17885
+ const [renderedComposerParts, setRenderedComposerParts] = React54.useState([]);
17886
+ const [composerDomVersion, setComposerDomVersion] = React54.useState(0);
17887
+ const [selectedTool, setSelectedTool] = React54.useState(
16711
17888
  null
16712
17889
  );
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({
17890
+ const [planModeEnabled, setPlanModeEnabled] = React54.useState(false);
17891
+ const [petSettingsOpen, setPetSettingsOpen] = React54.useState(false);
17892
+ const [petLocalSettings, setPetLocalSettings] = React54.useState(() => readPetLocalSettings());
17893
+ const [attachmentState, setAttachmentState] = React54.useState({
16717
17894
  uploadedFiles: [],
16718
17895
  hasUploadingFiles: false,
16719
17896
  hasParsingFiles: false
16720
17897
  });
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);
17898
+ const [references, setReferences] = React54.useState([]);
17899
+ const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React54.useState(false);
17900
+ const [quoteSelection, setQuoteSelection] = React54.useState(null);
17901
+ const [isAtBottom, setIsAtBottom] = React54.useState(true);
17902
+ const [hasUpdatesBelow, setHasUpdatesBelow] = React54.useState(false);
16726
17903
  const {
16727
17904
  threads,
16728
17905
  deleteThread,
16729
17906
  refreshThreads,
16730
17907
  isLoading: isThreadsLoading
16731
17908
  } = useThreads();
16732
- const viewportRef = React52.useRef(null);
16733
- const messageNavigationAnchorsRef = React52.useRef(
17909
+ const viewportRef = React54.useRef(null);
17910
+ const chatColumnRef = React54.useRef(null);
17911
+ const messageNavigationAnchorsRef = React54.useRef(
16734
17912
  /* @__PURE__ */ new Map()
16735
17913
  );
16736
- const attachmentsRef = React52.useRef(null);
16737
- const composerInputRef = React52.useRef(null);
16738
- const slashPaletteRef = React52.useRef(null);
16739
- const slashPaletteOptionRefs = React52.useRef(
17914
+ const attachmentsRef = React54.useRef(null);
17915
+ const composerInputRef = React54.useRef(null);
17916
+ const slashPaletteRef = React54.useRef(null);
17917
+ const slashPaletteOptionRefs = React54.useRef(
16740
17918
  []
16741
17919
  );
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);
17920
+ const composerPartsRef = React54.useRef([]);
17921
+ const pendingComposerCaretOffsetRef = React54.useRef(null);
17922
+ const shouldAutoScrollRef = React54.useRef(true);
17923
+ const forceFollowRef = React54.useRef(false);
17924
+ const previousMessageCountRef = React54.useRef(0);
17925
+ const previousScrollTopRef = React54.useRef(0);
17926
+ const isPrependingHistoryMessagesRef = React54.useRef(false);
17927
+ const autoScrollFrameRef = React54.useRef(null);
17928
+ const isPointerDownRef = React54.useRef(false);
17929
+ const lastTouchYRef = React54.useRef(null);
16752
17930
  const {
16753
17931
  runtimeCapabilities,
16754
17932
  runtimeCapabilitiesReady,
@@ -16777,24 +17955,24 @@ function Chat({
16777
17955
  const resolvedPlaceholder = placeholder ?? t("chat.placeholder");
16778
17956
  const assistantTitle = assistantName || resolvedTitle;
16779
17957
  const petRequired = options?.displayMode === "pet";
16780
- const basePetSettings = React52.useMemo(
17958
+ const basePetSettings = React54.useMemo(
16781
17959
  () => derivePetLocalSettings(options?.pet),
16782
17960
  [options?.pet]
16783
17961
  );
16784
- const displayedPetSettings = React52.useMemo(
17962
+ const displayedPetSettings = React54.useMemo(
16785
17963
  () => ({
16786
17964
  ...petLocalSettings ?? basePetSettings,
16787
17965
  ...petRequired ? { enabled: true } : {}
16788
17966
  }),
16789
17967
  [basePetSettings, petLocalSettings, petRequired]
16790
17968
  );
16791
- const effectivePet = React52.useMemo(() => {
17969
+ const effectivePet = React54.useMemo(() => {
16792
17970
  if (petRequired || petLocalSettings) {
16793
17971
  return buildPetOptionsFromLocalSettings(displayedPetSettings);
16794
17972
  }
16795
17973
  return options?.pet ?? null;
16796
17974
  }, [displayedPetSettings, options?.pet, petLocalSettings, petRequired]);
16797
- const savePetLocalSettings = React52.useCallback(
17975
+ const savePetLocalSettings = React54.useCallback(
16798
17976
  (settings) => {
16799
17977
  const nextSettings = petRequired ? { ...settings, enabled: true } : settings;
16800
17978
  setPetLocalSettings(nextSettings);
@@ -16802,7 +17980,7 @@ function Chat({
16802
17980
  },
16803
17981
  [petRequired]
16804
17982
  );
16805
- const handlePetCommand = React52.useCallback(
17983
+ const handlePetCommand = React54.useCallback(
16806
17984
  (mode) => {
16807
17985
  if (mode === "settings") {
16808
17986
  setPetSettingsOpen(true);
@@ -16824,11 +18002,11 @@ function Chat({
16824
18002
  [displayedPetSettings, effectivePet, petRequired, savePetLocalSettings]
16825
18003
  );
16826
18004
  const inputPlaceholder = selectedTool?.placeholderOverride ?? composer?.placeholder ?? resolvedPlaceholder;
16827
- const messages = React52.useMemo(
18005
+ const messages = React54.useMemo(
16828
18006
  () => stream.messages ?? [],
16829
18007
  [stream.messages]
16830
18008
  );
16831
- const messageNavigationLabels = React52.useMemo(
18009
+ const messageNavigationLabels = React54.useMemo(
16832
18010
  () => ({
16833
18011
  user: t("chat.youLabel"),
16834
18012
  assistant: assistantTitle,
@@ -16847,7 +18025,7 @@ function Chat({
16847
18025
  }),
16848
18026
  [assistantTitle, t]
16849
18027
  );
16850
- const messageNavigationItems = React52.useMemo(
18028
+ const messageNavigationItems = React54.useMemo(
16851
18029
  () => messageNavigationEnabled ? buildMessageNavigationItems(
16852
18030
  messages,
16853
18031
  {
@@ -16870,7 +18048,7 @@ function Chat({
16870
18048
  historyMessagePagination?.isLoadingMore
16871
18049
  );
16872
18050
  const canLoadMoreMessages = Boolean(historyMessagePagination?.hasMore);
16873
- const draft = React52.useMemo(
18051
+ const draft = React54.useMemo(
16874
18052
  () => getComposerPlainText(composerParts),
16875
18053
  [composerParts]
16876
18054
  );
@@ -16884,7 +18062,7 @@ function Chat({
16884
18062
  isEmpty: isComposerInputEmpty,
16885
18063
  isStacked: isComposerStacked
16886
18064
  });
16887
- const pendingFollowUps = React52.useMemo(
18065
+ const pendingFollowUps = React54.useMemo(
16888
18066
  () => sortVisiblePendingFollowUps(stream.pendingFollowUps ?? []),
16889
18067
  [stream.pendingFollowUps]
16890
18068
  );
@@ -16893,7 +18071,7 @@ function Chat({
16893
18071
  const hasPendingHITLRequest = Boolean(stream.pendingHITLRequest);
16894
18072
  const hasPendingInteractiveRequest = hasPendingRequestUserInput || hasPendingHITLRequest;
16895
18073
  const hasPendingTodos = Boolean(stream.todos?.items.length);
16896
- const goalAdapter = React52.useMemo(() => {
18074
+ const goalAdapter = React54.useMemo(() => {
16897
18075
  if (isGoalAdapter(options?.goal)) {
16898
18076
  return options.goal;
16899
18077
  }
@@ -16906,10 +18084,10 @@ function Chat({
16906
18084
  "goal"
16907
18085
  );
16908
18086
  const showGoalStatus = goalCommandAvailable && !hasCompletedGoal && (Boolean(goalError) || threadGoal?.status === "active" && stream.isLoading);
16909
- const clearQuoteSelection = React52.useCallback(() => {
18087
+ const clearQuoteSelection = React54.useCallback(() => {
16910
18088
  setQuoteSelection(null);
16911
18089
  }, []);
16912
- const commitComposerParts = React52.useCallback(
18090
+ const commitComposerParts = React54.useCallback(
16913
18091
  (nextParts, options2) => {
16914
18092
  const normalized = normalizeComposerParts(nextParts);
16915
18093
  const previous = composerPartsRef.current;
@@ -16939,7 +18117,7 @@ function Chat({
16939
18117
  },
16940
18118
  [setRunRuntimeCapabilities]
16941
18119
  );
16942
- const setComposerText = React52.useCallback(
18120
+ const setComposerText = React54.useCallback(
16943
18121
  (text, caretOffset = text.length) => {
16944
18122
  commitComposerParts(createComposerTextParts(text), {
16945
18123
  caretOffset,
@@ -16949,7 +18127,7 @@ function Chat({
16949
18127
  },
16950
18128
  [commitComposerParts]
16951
18129
  );
16952
- const focusComposerAt = React52.useCallback((position) => {
18130
+ const focusComposerAt = React54.useCallback((position) => {
16953
18131
  const nextPosition = position ?? getComposerEditingLength(composerPartsRef.current);
16954
18132
  pendingComposerCaretOffsetRef.current = nextPosition;
16955
18133
  requestAnimationFrame(() => {
@@ -16978,7 +18156,7 @@ function Chat({
16978
18156
  focusComposerAt
16979
18157
  });
16980
18158
  const parentMessenger = useParentMessenger({
16981
- onSetComposerValue: React52.useCallback(
18159
+ onSetComposerValue: React54.useCallback(
16982
18160
  (payload) => {
16983
18161
  if (!payload) {
16984
18162
  return;
@@ -17006,16 +18184,16 @@ function Chat({
17006
18184
  },
17007
18185
  [applyComposerValueRuntimeCapabilities, composer?.tools, setComposerText]
17008
18186
  ),
17009
- onSetRuntimeCapabilities: React52.useCallback(
18187
+ onSetRuntimeCapabilities: React54.useCallback(
17010
18188
  (selection) => {
17011
18189
  applyExternalRuntimeCapabilities(selection);
17012
18190
  },
17013
18191
  [applyExternalRuntimeCapabilities]
17014
18192
  ),
17015
- onFocusComposer: React52.useCallback(() => {
18193
+ onFocusComposer: React54.useCallback(() => {
17016
18194
  composerInputRef.current?.focus();
17017
18195
  }, []),
17018
- onSetPetEnabled: React52.useCallback(
18196
+ onSetPetEnabled: React54.useCallback(
17019
18197
  (enabled) => {
17020
18198
  if (petRequired) {
17021
18199
  return;
@@ -17029,10 +18207,10 @@ function Chat({
17029
18207
  )
17030
18208
  });
17031
18209
  const canMinimizeToPet = parentMessenger?.isParentAvailable === true && isPetEnabled(effectivePet);
17032
- const handleMinimizeToPet = React52.useCallback(() => {
18210
+ const handleMinimizeToPet = React54.useCallback(() => {
17033
18211
  parentMessenger?.sendEvent("chat_minimize_change", { minimized: true });
17034
18212
  }, [parentMessenger]);
17035
- const syncQuoteSelection = React52.useCallback(() => {
18213
+ const syncQuoteSelection = React54.useCallback(() => {
17036
18214
  if (typeof window === "undefined") {
17037
18215
  clearQuoteSelection();
17038
18216
  return;
@@ -17077,23 +18255,23 @@ function Chat({
17077
18255
  left
17078
18256
  });
17079
18257
  }, [clearQuoteSelection]);
17080
- const cancelPendingAutoScroll = React52.useCallback(() => {
18258
+ const cancelPendingAutoScroll = React54.useCallback(() => {
17081
18259
  if (autoScrollFrameRef.current !== null) {
17082
18260
  cancelAnimationFrame(autoScrollFrameRef.current);
17083
18261
  autoScrollFrameRef.current = null;
17084
18262
  }
17085
18263
  }, []);
17086
- const disableAutoFollow = React52.useCallback(() => {
18264
+ const disableAutoFollow = React54.useCallback(() => {
17087
18265
  forceFollowRef.current = false;
17088
18266
  shouldAutoScrollRef.current = false;
17089
18267
  cancelPendingAutoScroll();
17090
18268
  }, [cancelPendingAutoScroll]);
17091
- const enableAutoFollow = React52.useCallback(() => {
18269
+ const enableAutoFollow = React54.useCallback(() => {
17092
18270
  forceFollowRef.current = true;
17093
18271
  shouldAutoScrollRef.current = true;
17094
18272
  setHasUpdatesBelow(false);
17095
18273
  }, []);
17096
- const scrollToBottom = React52.useCallback(
18274
+ const scrollToBottom = React54.useCallback(
17097
18275
  (smooth = false, force = false) => {
17098
18276
  if (force) {
17099
18277
  enableAutoFollow();
@@ -17120,7 +18298,7 @@ function Chat({
17120
18298
  },
17121
18299
  [cancelPendingAutoScroll, enableAutoFollow]
17122
18300
  );
17123
- const setMessageNavigationAnchor = React52.useCallback(
18301
+ const setMessageNavigationAnchor = React54.useCallback(
17124
18302
  (id, node) => {
17125
18303
  if (node) {
17126
18304
  messageNavigationAnchorsRef.current.set(id, node);
@@ -17130,15 +18308,165 @@ function Chat({
17130
18308
  },
17131
18309
  []
17132
18310
  );
17133
- const getMessageNavigationAnchor = React52.useCallback(
18311
+ const getMessageNavigationAnchor = React54.useCallback(
17134
18312
  (item) => messageNavigationAnchorsRef.current.get(item.id) ?? null,
17135
18313
  []
17136
18314
  );
17137
- const handleMessageNavigationNavigate = React52.useCallback(() => {
18315
+ const handleMessageNavigationNavigate = React54.useCallback(() => {
17138
18316
  disableAutoFollow();
17139
18317
  clearQuoteSelection();
17140
18318
  }, [clearQuoteSelection, disableAutoFollow]);
17141
- React52.useEffect(() => {
18319
+ const taskSummaryEnabled = options?.taskSummary?.enabled === true;
18320
+ const taskSummaryConversationId = stream.conversationId ?? null;
18321
+ const [taskSummaryDocked, setTaskSummaryDocked] = React54.useState(false);
18322
+ const [taskSummaryOpen, setTaskSummaryOpen] = React54.useState(false);
18323
+ const manuallyClosedTaskSummaryConversationIdsRef = React54.useRef(
18324
+ /* @__PURE__ */ new Set()
18325
+ );
18326
+ const liveTaskSummaryPending = React54.useMemo(() => {
18327
+ const followUps = pendingFollowUps.map((item) => ({
18328
+ id: `follow-up:${item.id}`,
18329
+ kind: "follow_up",
18330
+ title: item.mode === "steer" ? t("taskSummary.pending.steer") : t("taskSummary.pending.followUp"),
18331
+ messageId: item.clientMessageId,
18332
+ createdAt: new Date(item.createdAt).toISOString()
18333
+ }));
18334
+ const userInput = stream.pendingRequestUserInput ? [
18335
+ {
18336
+ id: `user-input:${stream.pendingRequestUserInput.id}`,
18337
+ kind: "user_input",
18338
+ title: stream.pendingRequestUserInput.params.questions[0]?.header || t("taskSummary.pending.userInput"),
18339
+ createdAt: new Date(
18340
+ stream.pendingRequestUserInput.createdAt
18341
+ ).toISOString()
18342
+ }
18343
+ ] : [];
18344
+ const approvals = stream.pendingHITLRequest ? [
18345
+ {
18346
+ id: `approval:${stream.pendingHITLRequest.id}`,
18347
+ kind: "approval",
18348
+ title: t("taskSummary.pending.approval"),
18349
+ createdAt: new Date(
18350
+ stream.pendingHITLRequest.createdAt
18351
+ ).toISOString()
18352
+ }
18353
+ ] : [];
18354
+ return [...approvals, ...userInput, ...followUps];
18355
+ }, [
18356
+ pendingFollowUps,
18357
+ stream.pendingHITLRequest,
18358
+ stream.pendingRequestUserInput,
18359
+ t
18360
+ ]);
18361
+ const liveTaskSummaryRunning = React54.useMemo(
18362
+ () => stream.runtimeActivities.sandboxServices.services.filter(
18363
+ (service) => service.status === "starting" || service.status === "running" || service.status === "stopping"
18364
+ ).map((service) => ({
18365
+ id: service.id ?? `${service.provider}:${service.name}:${service.actualPort ?? service.requestedPort ?? ""}`,
18366
+ title: service.name,
18367
+ status: service.status,
18368
+ description: service.actualPort || service.requestedPort ? `:${service.actualPort ?? service.requestedPort}` : void 0,
18369
+ resource: {
18370
+ type: "browser",
18371
+ serviceId: service.id,
18372
+ url: service.previewUrl ?? void 0
18373
+ },
18374
+ updatedAt: service.startedAt ?? void 0
18375
+ })),
18376
+ [stream.runtimeActivities.sandboxServices.services]
18377
+ );
18378
+ const taskSummaryAgentNames = React54.useMemo(() => {
18379
+ const names = /* @__PURE__ */ new Map();
18380
+ runtimeCapabilityOptions.forEach((option) => {
18381
+ if (option.type !== "subAgent") return;
18382
+ const name = option.capability.name?.trim();
18383
+ if (!name) return;
18384
+ names.set(option.id, name);
18385
+ const agentKey = option.capability.agentKey?.trim();
18386
+ if (agentKey) names.set(agentKey, name);
18387
+ });
18388
+ return names;
18389
+ }, [runtimeCapabilityOptions]);
18390
+ const liveTaskSummary = React54.useMemo(
18391
+ () => collectLiveTaskSummary({
18392
+ messages: messages.map(
18393
+ (message) => ({
18394
+ id: message.id,
18395
+ content: message.content,
18396
+ createdAt: message.createdAt,
18397
+ updatedAt: message.updatedAt,
18398
+ taskSummary: message.taskSummary,
18399
+ references: message.references,
18400
+ attachments: message.attachments,
18401
+ fileAssets: message.fileAssets,
18402
+ agentRuns: message.agentRuns,
18403
+ runtimeCapabilities: message.runtimeCapabilities
18404
+ })
18405
+ ),
18406
+ goal: threadGoal,
18407
+ todos: stream.todos,
18408
+ pending: liveTaskSummaryPending,
18409
+ running: liveTaskSummaryRunning,
18410
+ agentNames: taskSummaryAgentNames
18411
+ }),
18412
+ [
18413
+ liveTaskSummaryPending,
18414
+ liveTaskSummaryRunning,
18415
+ messages,
18416
+ stream.todos,
18417
+ taskSummaryAgentNames,
18418
+ threadGoal
18419
+ ]
18420
+ );
18421
+ const taskSummary = useTaskSummary({
18422
+ enabled: taskSummaryEnabled,
18423
+ conversationId: taskSummaryConversationId,
18424
+ client: stream.client,
18425
+ live: liveTaskSummary
18426
+ });
18427
+ const navigateToTaskSummaryMessage = React54.useCallback(
18428
+ async (messageId) => {
18429
+ try {
18430
+ let anchor = messageNavigationAnchorsRef.current.get(messageId);
18431
+ let pageCount = 0;
18432
+ while (!anchor && pageCount < 100) {
18433
+ const loaded = await stream.loadMoreConversationMessages();
18434
+ if (!loaded.length) break;
18435
+ pageCount += 1;
18436
+ await new Promise(
18437
+ (resolve) => requestAnimationFrame(() => resolve())
18438
+ );
18439
+ anchor = messageNavigationAnchorsRef.current.get(messageId);
18440
+ }
18441
+ if (!anchor) return;
18442
+ disableAutoFollow();
18443
+ clearQuoteSelection();
18444
+ anchor.scrollIntoView({ behavior: "smooth", block: "center" });
18445
+ } catch (error) {
18446
+ console.warn("Failed to locate task summary message", error);
18447
+ }
18448
+ },
18449
+ [clearQuoteSelection, disableAutoFollow, stream]
18450
+ );
18451
+ const openTaskSummaryResource = React54.useCallback(
18452
+ (resource, messageId, resourceTitle) => {
18453
+ const data = {
18454
+ resource,
18455
+ conversationId: taskSummaryConversationId ?? void 0,
18456
+ messageId,
18457
+ title: resourceTitle
18458
+ };
18459
+ parentMessenger.sendEvent("public_event", [
18460
+ "effect",
18461
+ {
18462
+ name: import_chatkit_types14.CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT,
18463
+ data
18464
+ }
18465
+ ]);
18466
+ },
18467
+ [parentMessenger, taskSummaryConversationId]
18468
+ );
18469
+ React54.useEffect(() => {
17142
18470
  const viewport = viewportRef.current;
17143
18471
  if (!viewport) return;
17144
18472
  previousScrollTopRef.current = viewport.scrollTop;
@@ -17219,14 +18547,14 @@ function Chat({
17219
18547
  window.removeEventListener("pointercancel", stopPointerTracking);
17220
18548
  };
17221
18549
  }, [cancelPendingAutoScroll, disableAutoFollow]);
17222
- React52.useEffect(() => {
18550
+ React54.useEffect(() => {
17223
18551
  shouldAutoScrollRef.current = true;
17224
18552
  forceFollowRef.current = false;
17225
18553
  previousScrollTopRef.current = 0;
17226
18554
  setIsAtBottom(true);
17227
18555
  setHasUpdatesBelow(false);
17228
18556
  }, [stream.threadId]);
17229
- React52.useEffect(() => {
18557
+ React54.useEffect(() => {
17230
18558
  const messageCountChanged = messages.length !== previousMessageCountRef.current;
17231
18559
  previousMessageCountRef.current = messages.length;
17232
18560
  if (isPrependingHistoryMessagesRef.current) {
@@ -17248,7 +18576,7 @@ function Chat({
17248
18576
  const isSubmissionBlocked = hasPendingInteractiveRequest || missingConfig || isHistoryLoading || hasUploadingFiles || isUploadingReferenceImages;
17249
18577
  const isSendDisabled = !trimmedDraft && !hasReferences || isSubmissionBlocked;
17250
18578
  const isPromptEditDisabled = hasPendingInteractiveRequest || missingConfig || isHistoryLoading;
17251
- const resizeComposerInput = React52.useCallback(() => {
18579
+ const resizeComposerInput = React54.useCallback(() => {
17252
18580
  const input = composerInputRef.current;
17253
18581
  if (!input) {
17254
18582
  return;
@@ -17256,7 +18584,7 @@ function Chat({
17256
18584
  input.style.maxHeight = `${COMPOSER_INPUT_MAX_HEIGHT}px`;
17257
18585
  input.style.overflowY = input.scrollHeight > COMPOSER_INPUT_MAX_HEIGHT ? "auto" : "hidden";
17258
18586
  }, []);
17259
- React52.useLayoutEffect(() => {
18587
+ React54.useLayoutEffect(() => {
17260
18588
  composerPartsRef.current = composerParts;
17261
18589
  resizeComposerInput();
17262
18590
  const caretOffset = pendingComposerCaretOffsetRef.current;
@@ -17268,13 +18596,13 @@ function Chat({
17268
18596
  }
17269
18597
  }
17270
18598
  }, [composerDomVersion, composerParts, resizeComposerInput]);
17271
- React52.useEffect(() => {
18599
+ React54.useEffect(() => {
17272
18600
  document.addEventListener("selectionchange", syncQuoteSelection);
17273
18601
  return () => {
17274
18602
  document.removeEventListener("selectionchange", syncQuoteSelection);
17275
18603
  };
17276
18604
  }, [syncQuoteSelection]);
17277
- React52.useEffect(() => {
18605
+ React54.useEffect(() => {
17278
18606
  const viewport = viewportRef.current;
17279
18607
  if (!viewport) {
17280
18608
  return;
@@ -17291,14 +18619,14 @@ function Chat({
17291
18619
  window.removeEventListener("resize", handleViewportScroll);
17292
18620
  };
17293
18621
  }, [clearQuoteSelection]);
17294
- React52.useEffect(() => {
18622
+ React54.useEffect(() => {
17295
18623
  clearQuoteSelection();
17296
18624
  }, [messages.length, stream.threadId, clearQuoteSelection]);
17297
- React52.useEffect(() => {
18625
+ React54.useEffect(() => {
17298
18626
  if (missingConfig) return;
17299
18627
  void refreshThreads();
17300
18628
  }, [missingConfig, refreshThreads]);
17301
- React52.useEffect(() => {
18629
+ React54.useEffect(() => {
17302
18630
  if (missingConfig || !stream.client || !stream.assistantId) {
17303
18631
  setAssistantName(null);
17304
18632
  setAssistantAvatar(null);
@@ -17321,10 +18649,10 @@ function Chat({
17321
18649
  cancelled = true;
17322
18650
  };
17323
18651
  }, [missingConfig, stream.client, stream.assistantId]);
17324
- React52.useEffect(() => {
18652
+ React54.useEffect(() => {
17325
18653
  setThreadGoal(stream.threadGoal);
17326
18654
  }, [stream.threadGoal]);
17327
- React52.useEffect(() => {
18655
+ React54.useEffect(() => {
17328
18656
  const threadId = stream.threadId?.trim();
17329
18657
  if (!threadId || !goalCommandAvailable) {
17330
18658
  setThreadGoal(null);
@@ -17365,7 +18693,7 @@ function Chat({
17365
18693
  return () => controller.abort();
17366
18694
  }, [goalAdapter, goalCommandAvailable, stream.threadId]);
17367
18695
  const uploadedFiles = attachmentState.uploadedFiles;
17368
- const syncComposerInputFromElement = React52.useCallback(
18696
+ const syncComposerInputFromElement = React54.useCallback(
17369
18697
  (input) => {
17370
18698
  const previousCapabilities = getComposerCapabilityPartMap(
17371
18699
  composerPartsRef.current
@@ -17383,25 +18711,25 @@ function Chat({
17383
18711
  },
17384
18712
  [commitComposerParts, updateRuntimeCapabilityPalette]
17385
18713
  );
17386
- const handleComposerInput = React52.useCallback(
18714
+ const handleComposerInput = React54.useCallback(
17387
18715
  (event) => {
17388
18716
  syncComposerInputFromElement(event.currentTarget);
17389
18717
  },
17390
18718
  [syncComposerInputFromElement]
17391
18719
  );
17392
- const handleComposerCompositionEnd = React52.useCallback(
18720
+ const handleComposerCompositionEnd = React54.useCallback(
17393
18721
  (event) => {
17394
18722
  syncComposerInputFromElement(event.currentTarget);
17395
18723
  },
17396
18724
  [syncComposerInputFromElement]
17397
18725
  );
17398
- const handleComposerSelect = React52.useCallback(() => {
18726
+ const handleComposerSelect = React54.useCallback(() => {
17399
18727
  updateRuntimeCapabilityPalette(
17400
18728
  composerPartsRef.current,
17401
18729
  composerInputRef.current ? getComposerSelectionOffset(composerInputRef.current) : void 0
17402
18730
  );
17403
18731
  }, [updateRuntimeCapabilityPalette]);
17404
- const submitDraft = React52.useCallback(
18732
+ const submitDraft = React54.useCallback(
17405
18733
  (submitOptions = {}) => {
17406
18734
  if (isSubmissionBlocked) return;
17407
18735
  const contentToSubmit = (submitOptions.inputText ?? trimmedDraft).trim();
@@ -17507,7 +18835,7 @@ function Chat({
17507
18835
  t
17508
18836
  ]
17509
18837
  );
17510
- const handleGoalCommand = React52.useCallback(
18838
+ const handleGoalCommand = React54.useCallback(
17511
18839
  async ({
17512
18840
  args,
17513
18841
  commandSource,
@@ -17613,7 +18941,7 @@ function Chat({
17613
18941
  t
17614
18942
  ]
17615
18943
  );
17616
- const handleGoalPanelOpenChange = React52.useCallback((open) => {
18944
+ const handleGoalPanelOpenChange = React54.useCallback((open) => {
17617
18945
  setIsGoalPanelOpen(open);
17618
18946
  }, []);
17619
18947
  const {
@@ -17657,7 +18985,7 @@ function Chat({
17657
18985
  plugin: t("composer.slashCommands.empty.loadingCapabilities"),
17658
18986
  subAgent: t("composer.slashCommands.empty.loadingCapabilities")
17659
18987
  };
17660
- React52.useEffect(() => {
18988
+ React54.useEffect(() => {
17661
18989
  if (!runtimeCapabilityPalette) {
17662
18990
  return;
17663
18991
  }
@@ -17676,7 +19004,7 @@ function Chat({
17676
19004
  );
17677
19005
  }
17678
19006
  }, [slashPaletteOptions.length, runtimeCapabilityPalette]);
17679
- React52.useLayoutEffect(() => {
19007
+ React54.useLayoutEffect(() => {
17680
19008
  if (!runtimeCapabilityPalette) {
17681
19009
  return;
17682
19010
  }
@@ -17693,7 +19021,7 @@ function Chat({
17693
19021
  container.scrollTop += optionRect.bottom - containerRect.bottom;
17694
19022
  }
17695
19023
  }, [runtimeCapabilityPalette, slashPaletteOptions.length]);
17696
- const submitGoalModeDraft = React52.useCallback(() => {
19024
+ const submitGoalModeDraft = React54.useCallback(() => {
17697
19025
  const objective = getComposerPlainText(composerPartsRef.current).trim();
17698
19026
  if (!isGoalModeOpen || !goalCommandAvailable || !objective) {
17699
19027
  return false;
@@ -17731,7 +19059,7 @@ function Chat({
17731
19059
  }
17732
19060
  submitDraft();
17733
19061
  };
17734
- const handleEditPendingFollowUp = React52.useCallback(
19062
+ const handleEditPendingFollowUp = React54.useCallback(
17735
19063
  (id) => {
17736
19064
  const item = pendingFollowUps.find(
17737
19065
  (entry) => entry.id === id && entry.mode === "queue"
@@ -17758,7 +19086,7 @@ function Chat({
17758
19086
  },
17759
19087
  [pendingFollowUps, setComposerText, stream]
17760
19088
  );
17761
- const handleQuoteSelection = React52.useCallback(() => {
19089
+ const handleQuoteSelection = React54.useCallback(() => {
17762
19090
  if (!quoteSelection) {
17763
19091
  return;
17764
19092
  }
@@ -17774,7 +19102,7 @@ function Chat({
17774
19102
  const handleAttachmentClick = () => {
17775
19103
  attachmentsRef.current?.openFilePicker();
17776
19104
  };
17777
- const uploadContextFile = React52.useCallback(
19105
+ const uploadContextFile = React54.useCallback(
17778
19106
  (file) => {
17779
19107
  const formData = new FormData();
17780
19108
  formData.append("file", file, file.name || "upload");
@@ -17793,13 +19121,13 @@ function Chat({
17793
19121
  },
17794
19122
  [stream.assistantId, stream.client, stream.threadId]
17795
19123
  );
17796
- const getContextFileStatus = React52.useCallback(
19124
+ const getContextFileStatus = React54.useCallback(
17797
19125
  (fileId) => stream.client.contexts.fetch(`/files/${fileId}/status`, {
17798
19126
  method: "GET"
17799
19127
  }),
17800
19128
  [stream.client]
17801
19129
  );
17802
- const deleteContextFile = React52.useCallback(
19130
+ const deleteContextFile = React54.useCallback(
17803
19131
  (storageFileId) => stream.client.contexts.deleteFile(storageFileId),
17804
19132
  [stream.client]
17805
19133
  );
@@ -17907,7 +19235,7 @@ function Chat({
17907
19235
  }
17908
19236
  submitDraft();
17909
19237
  };
17910
- const handleComposerPaste = React52.useCallback(
19238
+ const handleComposerPaste = React54.useCallback(
17911
19239
  (event) => {
17912
19240
  const clipboardData = event.clipboardData;
17913
19241
  if (!clipboardData) {
@@ -18009,13 +19337,13 @@ function Chat({
18009
19337
  const handleToolSelect = (tool) => {
18010
19338
  setSelectedTool((prev) => prev?.id === tool.id ? null : tool);
18011
19339
  };
18012
- const handlePromptClick = React52.useCallback(
19340
+ const handlePromptClick = React54.useCallback(
18013
19341
  (prompt) => {
18014
19342
  submitDraft({ inputText: prompt, displayText: prompt });
18015
19343
  },
18016
19344
  [submitDraft]
18017
19345
  );
18018
- const handlePromptEdit = React52.useCallback(
19346
+ const handlePromptEdit = React54.useCallback(
18019
19347
  (prompt) => {
18020
19348
  if (isPromptEditDisabled) return;
18021
19349
  setComposerText(prompt, prompt.length);
@@ -18024,7 +19352,7 @@ function Chat({
18024
19352
  },
18025
19353
  [focusComposerAt, isPromptEditDisabled, setComposerText]
18026
19354
  );
18027
- const loadConversationMessages = React52.useCallback(
19355
+ const loadConversationMessages = React54.useCallback(
18028
19356
  async (recordId) => {
18029
19357
  if (missingConfig) {
18030
19358
  setHistoryError(missingConfigShortMessage);
@@ -18045,7 +19373,7 @@ function Chat({
18045
19373
  },
18046
19374
  [missingConfig, missingConfigShortMessage, stream, t]
18047
19375
  );
18048
- const handleLoadMoreMessages = React52.useCallback(async () => {
19376
+ const handleLoadMoreMessages = React54.useCallback(async () => {
18049
19377
  if (!canLoadMoreMessages || isLoadingMoreMessages) {
18050
19378
  return;
18051
19379
  }
@@ -18154,19 +19482,19 @@ function Chat({
18154
19482
  };
18155
19483
  const acceptMimes = composer?.attachments?.accept ? Object.entries(composer.attachments.accept).map(([mime, exts]) => [mime, ...exts.map((e) => `.${e}`)].join(",")).join(",") : void 0;
18156
19484
  const canUploadDroppedFiles = composer?.attachments?.enabled === true && !missingConfig && !isHistoryLoading && !hasPendingInteractiveRequest;
18157
- const handleDroppedFiles = React52.useCallback((files) => {
19485
+ const handleDroppedFiles = React54.useCallback((files) => {
18158
19486
  return attachmentsRef.current?.queueFiles(files) ?? false;
18159
19487
  }, []);
18160
- const currentThread = React52.useMemo(
19488
+ const currentThread = React54.useMemo(
18161
19489
  () => threads.find((item) => item.id === stream.threadId),
18162
19490
  [threads, stream.threadId]
18163
19491
  );
18164
- const assistantStatusText = React52.useMemo(() => {
19492
+ const assistantStatusText = React54.useMemo(() => {
18165
19493
  if (!stream.threadId) return t("chat.statusOnline");
18166
19494
  return currentThread?.title?.trim() || t("chat.statusOnline");
18167
19495
  }, [currentThread?.title, stream.threadId, t]);
18168
19496
  const streamErrorMessage = stream.error instanceof Error ? stream.error.message : void 0;
18169
- const threadErrorMessage = React52.useMemo(() => {
19497
+ const threadErrorMessage = React54.useMemo(() => {
18170
19498
  if (streamErrorMessage?.trim()) return streamErrorMessage.trim();
18171
19499
  if (currentThread?.status !== "error") return void 0;
18172
19500
  const message = currentThread.error?.trim();
@@ -18197,777 +19525,880 @@ function Chat({
18197
19525
  fallbackTitle: t("history.threadFallback")
18198
19526
  });
18199
19527
  const layoutMaxWidth = options?.layout?.maxWidth;
18200
- const chatColumnStyle = React52.useMemo(() => {
19528
+ const chatColumnStyle = React54.useMemo(() => {
18201
19529
  if (layoutMaxWidth === void 0 || layoutMaxWidth === null || layoutMaxWidth === "") {
18202
19530
  return void 0;
18203
19531
  }
18204
19532
  return { maxWidth: layoutMaxWidth };
18205
19533
  }, [layoutMaxWidth]);
18206
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
18207
- UploadDroppedFiles,
19534
+ React54.useLayoutEffect(() => {
19535
+ if (!taskSummaryEnabled) {
19536
+ setTaskSummaryDocked(false);
19537
+ return;
19538
+ }
19539
+ const viewport = viewportRef.current;
19540
+ const chatColumn = chatColumnRef.current;
19541
+ if (!viewport || !chatColumn) {
19542
+ setTaskSummaryDocked(false);
19543
+ return;
19544
+ }
19545
+ const updateDockedState = () => {
19546
+ const viewportRect = viewport.getBoundingClientRect();
19547
+ const chatColumnRect = chatColumn.getBoundingClientRect();
19548
+ const rootFontSize = Number.parseFloat(
19549
+ window.getComputedStyle(document.documentElement).fontSize
19550
+ );
19551
+ const remInPixels = Number.isFinite(rootFontSize) ? rootFontSize : 16;
19552
+ const requiredSideSpace = (TASK_SUMMARY_PANEL_WIDTH_REM + TASK_SUMMARY_PANEL_EDGE_INSET_REM + TASK_SUMMARY_PANEL_SAFE_GAP_REM) * remInPixels;
19553
+ const availableSideSpace = viewportRect.right - chatColumnRect.right;
19554
+ setTaskSummaryDocked(availableSideSpace >= requiredSideSpace);
19555
+ };
19556
+ updateDockedState();
19557
+ window.addEventListener("resize", updateDockedState);
19558
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(updateDockedState) : null;
19559
+ resizeObserver?.observe(viewport);
19560
+ resizeObserver?.observe(chatColumn);
19561
+ return () => {
19562
+ window.removeEventListener("resize", updateDockedState);
19563
+ resizeObserver?.disconnect();
19564
+ };
19565
+ }, [layoutMaxWidth, taskSummaryEnabled]);
19566
+ const taskSummaryAvailable = Boolean(
19567
+ taskSummaryEnabled && stream.threadId && taskSummaryConversationId
19568
+ );
19569
+ const handleTaskSummaryOpenChange = React54.useCallback(
19570
+ (open) => {
19571
+ setTaskSummaryOpen(open);
19572
+ if (!taskSummaryConversationId) return;
19573
+ if (open) {
19574
+ manuallyClosedTaskSummaryConversationIdsRef.current.delete(
19575
+ taskSummaryConversationId
19576
+ );
19577
+ return;
19578
+ }
19579
+ manuallyClosedTaskSummaryConversationIdsRef.current.add(
19580
+ taskSummaryConversationId
19581
+ );
19582
+ },
19583
+ [taskSummaryConversationId]
19584
+ );
19585
+ React54.useEffect(() => {
19586
+ if (!taskSummaryDocked) {
19587
+ setTaskSummaryOpen(false);
19588
+ }
19589
+ }, [taskSummaryDocked]);
19590
+ React54.useEffect(() => {
19591
+ if (!taskSummaryDocked || !taskSummaryAvailable || !taskSummaryConversationId || manuallyClosedTaskSummaryConversationIdsRef.current.has(
19592
+ taskSummaryConversationId
19593
+ )) {
19594
+ return;
19595
+ }
19596
+ setTaskSummaryOpen(true);
19597
+ }, [taskSummaryAvailable, taskSummaryConversationId, taskSummaryDocked]);
19598
+ const taskSummaryProps = {
19599
+ summary: taskSummary.summary,
19600
+ historyError: taskSummary.historyError,
19601
+ loadingSections: taskSummary.loadingSections,
19602
+ loadedSectionCounts: taskSummary.loadedSectionCounts,
19603
+ onRetryHistory: taskSummary.retryHistory,
19604
+ onLoadSection: taskSummary.loadSection,
19605
+ onNavigateMessage: (messageId) => {
19606
+ void navigateToTaskSummaryMessage(messageId);
19607
+ },
19608
+ onFocusComposer: () => focusComposerAt(),
19609
+ onOpenResource: openTaskSummaryResource
19610
+ };
19611
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19612
+ "div",
18208
19613
  {
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
- ),
19614
+ className: "relative flex h-full w-full min-w-0 bg-background",
19615
+ "data-task-summary-layout": taskSummaryDocked ? "docked" : "popover",
18220
19616
  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,
19617
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19618
+ UploadDroppedFiles,
18556
19619
  {
18557
- type: "button",
18558
- size: "icon-sm",
18559
- variant: hasUpdatesBelow ? "default" : "outline",
19620
+ ref: viewportRef,
19621
+ "data-chatkit-root": "",
19622
+ enabled: canUploadDroppedFiles,
19623
+ dropTitle: t("chat.dropFilesTitle"),
19624
+ dropHint: t("chat.dropFilesHint"),
19625
+ activeClassName: "ring-2 ring-primary/40 ring-inset",
19626
+ onFiles: handleDroppedFiles,
18560
19627
  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"
19628
+ "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",
19629
+ className
18563
19630
  ),
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
19631
  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)(
19632
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18644
19633
  "div",
18645
19634
  {
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
- ),
19635
+ ref: chatColumnRef,
19636
+ "data-slot": "chatkit-chat-header",
19637
+ className: "mx-auto flex w-full items-center justify-between border-b p-2 sticky top-0 z-10 bg-background",
19638
+ style: chatColumnStyle,
18650
19639
  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" })
19640
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex min-w-0 items-center gap-3 overflow-hidden", children: [
19641
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "relative shrink-0", children: [
19642
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19643
+ ChatkitAvatar,
19644
+ {
19645
+ avatar: assistantAvatar,
19646
+ className: "h-9 w-9 border border-border/60",
19647
+ label: assistantTitle
19648
+ }
19649
+ ),
19650
+ /* @__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
19651
  ] }),
18666
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18667
- "div",
19652
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0", children: [
19653
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19654
+ "h2",
19655
+ {
19656
+ className: "text-lg font-semibold truncate",
19657
+ title: assistantTitle,
19658
+ children: assistantTitle
19659
+ }
19660
+ ),
19661
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19662
+ "p",
19663
+ {
19664
+ className: "truncate text-xs text-muted-foreground",
19665
+ title: assistantStatusText,
19666
+ children: assistantStatusText
19667
+ }
19668
+ )
19669
+ ] })
19670
+ ] }),
19671
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-1", children: [
19672
+ taskSummaryAvailable && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19673
+ TaskSummaryTrigger,
18668
19674
  {
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
19675
+ ...taskSummaryProps,
19676
+ displayMode: taskSummaryDocked ? "docked" : "popover",
19677
+ open: taskSummaryOpen,
19678
+ onOpenChange: handleTaskSummaryOpenChange
18674
19679
  }
18675
19680
  ),
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,
19681
+ canMinimizeToPet && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
19682
+ /* @__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)(
19683
+ "button",
18684
19684
  {
18685
19685
  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" })
19686
+ onClick: handleMinimizeToPet,
19687
+ className: cn(
19688
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19689
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19690
+ "transition-colors duration-150"
19691
+ ),
19692
+ "aria-label": t("chat.minimizeToPet"),
19693
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Minus, { size: 16 })
18694
19694
  }
18695
- ) }),
18696
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: t("chat.goal.edit") })
19695
+ ) }) }),
19696
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("chat.minimizeToPet") })
18697
19697
  ] }),
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,
19698
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
19699
+ /* @__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)(
19700
+ "button",
18701
19701
  {
18702
19702
  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" })
19703
+ onClick: () => setPetSettingsOpen(true),
19704
+ className: cn(
19705
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19706
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19707
+ "transition-colors duration-150"
19708
+ ),
19709
+ "aria-label": t("settings.open"),
19710
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Settings, { size: 16 })
18716
19711
  }
18717
- ) }),
18718
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
19712
+ ) }) }),
19713
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("settings.open") })
18719
19714
  ] }),
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)(
19715
+ history?.enabled !== false && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
19716
+ /* @__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",
19719
+ {
19720
+ type: "button",
19721
+ onClick: handleNewThread,
19722
+ disabled: missingConfig || isHistoryLoading,
19723
+ className: cn(
19724
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19725
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19726
+ "transition-colors duration-150",
19727
+ "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed"
19728
+ ),
19729
+ "aria-label": t("history.newThread"),
19730
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Pencil, { size: 16 })
19731
+ }
19732
+ ) }) }),
19733
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { side: "bottom", children: t("history.newThread") })
19734
+ ] }),
19735
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19736
+ HistorySidebar,
19737
+ {
19738
+ threads,
19739
+ currentThreadId: stream.threadId ?? void 0,
19740
+ onNewThread: handleNewThread,
19741
+ onSelectThread: handleSelectThread,
19742
+ onDeleteThread: handleDeleteThread,
19743
+ showDelete: history?.showDelete !== false,
19744
+ disabled: missingConfig || isThreadsLoading || isHistoryLoading
19745
+ }
19746
+ )
19747
+ ] })
19748
+ ] })
19749
+ ]
19750
+ }
19751
+ ),
19752
+ showMessageNavigation && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19753
+ MessageNavigator,
19754
+ {
19755
+ items: messageNavigationItems,
19756
+ viewportRef,
19757
+ getAnchor: getMessageNavigationAnchor,
19758
+ onNavigate: handleMessageNavigationNavigate,
19759
+ label: t("message.navigation.label"),
19760
+ tagsOverflowLabel: (count) => t("message.navigation.moreTags", { count })
19761
+ }
19762
+ ),
19763
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19764
+ "div",
19765
+ {
19766
+ "data-slot": "chatkit-chat-content",
19767
+ className: "mx-auto w-full flex-1 p-4",
19768
+ style: chatColumnStyle,
19769
+ children: [
19770
+ 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 }),
19771
+ 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 }),
19772
+ 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 }),
19773
+ 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") }),
19774
+ messages.length === 0 && !canLoadMoreMessages ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19775
+ StartScreen,
19776
+ {
19777
+ startScreen,
19778
+ onPromptClick: handlePromptClick,
19779
+ onPromptEdit: handlePromptEdit,
19780
+ promptSendDisabled: isSubmissionBlocked,
19781
+ promptEditDisabled: isPromptEditDisabled
19782
+ }
19783
+ ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "space-y-4", children: [
19784
+ canLoadMoreMessages && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-3 py-1", children: [
19785
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" }),
19786
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
18722
19787
  Button,
18723
19788
  {
18724
19789
  type: "button",
18725
19790
  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" })
19791
+ size: "sm",
19792
+ onClick: handleLoadMoreMessages,
19793
+ disabled: isLoadingMoreMessages,
19794
+ className: "h-7 px-2 text-xs font-medium text-muted-foreground hover:text-foreground",
19795
+ children: isLoadingMoreMessages ? t("chat.loadingMoreMessages") : t("chat.loadMoreMessages")
18738
19796
  }
18739
- ) }),
18740
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: t("chat.goal.clear") })
19797
+ ),
19798
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "h-px min-w-8 flex-1 bg-border" })
18741
19799
  ] }),
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,
19800
+ messages.map((message, index) => {
19801
+ const messageType = String(message.type);
19802
+ const isAssistantMessage = messageType === "assistant" || messageType === "ai";
19803
+ const isStreamingMessage = stream.isLoading && index === messages.length - 1;
19804
+ const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
18745
19805
  {
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,
19806
+ ...message,
19807
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19808
+ },
19809
+ isStreamingMessage,
19810
+ { now: streamingNow }
19811
+ ) : null;
19812
+ if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
19813
+ return null;
19814
+ }
19815
+ const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
19816
+ const hasPlainRenderableContent = messageContent.trim().length > 0;
19817
+ const humanMessage = message;
19818
+ const humanReferences = humanMessage.references ?? [];
19819
+ const humanAttachments = [
19820
+ ...humanMessage.fileAssets ?? [],
19821
+ ...humanMessage.attachments ?? []
19822
+ ];
19823
+ const humanRuntimeCapabilityOptions = message.type === "human" ? humanMessage.runtimeCapabilityOptions ?? getRuntimeCapabilityOptionsForSelection(
19824
+ getRecommendedRuntimeCapabilitiesSelection(
19825
+ humanMessage.runtimeCapabilities
19826
+ ),
19827
+ runtimeCapabilityOptions
19828
+ ) : [];
19829
+ const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
19830
+ const canQuoteMessage = message.type === "human" || isAssistantMessage;
19831
+ const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
19832
+ const messageNavigationId = getMessageNavigationItemId(
19833
+ message,
19834
+ index
19835
+ );
19836
+ if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanRuntimeCapabilityOptions.length === 0 && humanReferences.length === 0) {
19837
+ return null;
19838
+ }
19839
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19840
+ "div",
19841
+ {
19842
+ ref: (node) => setMessageNavigationAnchor(messageNavigationId, node),
19843
+ "data-message-navigation-id": messageNavigationId,
19844
+ className: cn(
19845
+ "group flex gap-3",
19846
+ message.type === "human" ? "justify-end" : "justify-start -ml-1"
19847
+ // AI messages: slightly closer to left
19848
+ ),
19849
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
19850
+ "div",
18754
19851
  {
18755
19852
  className: cn(
18756
- "size-3 transition-transform",
18757
- isGoalObjectiveExpanded && "rotate-180"
18758
- )
19853
+ "flex flex-col px-3 overflow-hidden",
19854
+ isAssistantMessage && "min-w-0 flex-1"
19855
+ ),
19856
+ children: [
19857
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19858
+ "div",
19859
+ {
19860
+ ...canQuoteMessage ? {
19861
+ "data-quote-message-id": message.id,
19862
+ "data-quote-source": quoteSource
19863
+ } : {},
19864
+ className: cn(
19865
+ "max-w-full rounded-2xl",
19866
+ 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"
19867
+ // AI messages: use chat-specific foreground color
19868
+ ),
19869
+ children: isAssistantMessage ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19870
+ AssistantMessage,
19871
+ {
19872
+ message: {
19873
+ ...message,
19874
+ type: "assistant"
19875
+ },
19876
+ messages: messages.slice(0, index + 1).map(
19877
+ (item) => ({
19878
+ ...item,
19879
+ type: String(item.type) === "ai" ? "assistant" : item.type
19880
+ })
19881
+ ),
19882
+ isStreaming: isStreamingMessage,
19883
+ streamingStatus,
19884
+ isThreadRunning: currentThreadIsRunning,
19885
+ organizationId: stream.organizationId,
19886
+ apiUrl: stream.apiUrl,
19887
+ pet: effectivePet
19888
+ }
19889
+ ) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
19890
+ message.type === "human" && humanRuntimeCapabilityOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19891
+ HumanRuntimeCapabilityChips,
19892
+ {
19893
+ options: humanRuntimeCapabilityOptions
19894
+ }
19895
+ ),
19896
+ 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)(
19897
+ ReferenceChip,
19898
+ {
19899
+ reference,
19900
+ variant: "message"
19901
+ },
19902
+ getReferenceKey(reference)
19903
+ )) }),
19904
+ 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)(
19905
+ "div",
19906
+ {
19907
+ className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
19908
+ children: [
19909
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.FileText, { size: 12 }),
19910
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "max-w-[100px] truncate", children: file.originalName ?? file.id })
19911
+ ]
19912
+ },
19913
+ fileIndex
19914
+ )) }),
19915
+ Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19916
+ "p",
19917
+ {
19918
+ className: "wrap-break-word text-sm leading-relaxed",
19919
+ children: formatMessageContent(part)
19920
+ },
19921
+ `${part.type}-${partIndex}`
19922
+ )) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
19923
+ ] })
19924
+ }
19925
+ ),
19926
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19927
+ MessageActions,
19928
+ {
19929
+ content: messageContent,
19930
+ isAssistant: isAssistantMessage,
19931
+ isStreaming: isStreamingMessage,
19932
+ onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
19933
+ }
19934
+ )
19935
+ ]
18759
19936
  }
18760
19937
  )
19938
+ },
19939
+ message.id ?? `${message.type}-${index}`
19940
+ );
19941
+ }),
19942
+ showLoadingDots && (() => {
19943
+ const lastMessage = messages[messages.length - 1];
19944
+ const lastMessageType = lastMessage ? String(lastMessage.type) : "";
19945
+ const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
19946
+ const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
19947
+ {
19948
+ ...lastMessage,
19949
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19950
+ },
19951
+ stream.isLoading,
19952
+ { now: streamingNow }
19953
+ ) : null;
19954
+ if (lastAssistantStatus) return null;
19955
+ const fallbackStreamingStatus = getAssistantStreamingStatus(
19956
+ {
19957
+ status: void 0,
19958
+ reasoning: void 0,
19959
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19960
+ },
19961
+ stream.isLoading,
19962
+ { now: streamingNow }
19963
+ );
19964
+ 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)(
19965
+ AssistantStreamingIndicator,
19966
+ {
19967
+ status: fallbackStreamingStatus ?? "loading"
18761
19968
  }
18762
- ) }),
18763
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
18764
- ] })
19969
+ ) }) });
19970
+ })()
18765
19971
  ] })
18766
19972
  ]
18767
19973
  }
18768
19974
  ),
18769
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18770
- PendingRuntimeServices,
18771
- {
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,
19975
+ !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)(
19976
+ Button,
18801
19977
  {
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
19978
+ type: "button",
19979
+ size: "icon-sm",
19980
+ variant: hasUpdatesBelow ? "default" : "outline",
19981
+ className: cn(
19982
+ "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)]",
19983
+ hasUpdatesBelow && "animate-bounce"
19984
+ ),
19985
+ onClick: () => scrollToBottom(true, true),
19986
+ "aria-label": t("chat.scrollToBottom"),
19987
+ title: t("chat.scrollToBottom"),
19988
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.ArrowDown, { size: 16 })
18815
19989
  }
18816
- ),
18817
- runtimeCapabilityPalette && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18818
- SlashPalette,
19990
+ ) }),
19991
+ quoteSelection && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
19992
+ "div",
18819
19993
  {
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
19994
+ className: "pointer-events-none fixed z-50",
19995
+ style: {
19996
+ top: `${quoteSelection.top}px`,
19997
+ left: `${quoteSelection.left}px`,
19998
+ transform: "translateX(-50%)"
19999
+ },
20000
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20001
+ Button,
20002
+ {
20003
+ type: "button",
20004
+ size: "sm",
20005
+ variant: "secondary",
20006
+ className: "pointer-events-auto shadow-lg",
20007
+ onMouseDown: (event) => event.preventDefault(),
20008
+ onClick: handleQuoteSelection,
20009
+ "aria-label": t("composer.quoteSelection"),
20010
+ title: t("composer.quoteSelection"),
20011
+ children: [
20012
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Quote, { size: 14 }),
20013
+ t("composer.quoteSelection")
20014
+ ]
20015
+ }
20016
+ )
18829
20017
  }
18830
20018
  ),
18831
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
20019
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18832
20020
  "div",
18833
20021
  {
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
- ),
20022
+ "data-slot": "chatkit-chat-composer",
20023
+ className: "mx-auto w-full p-2 sticky bottom-0 z-10 bg-background",
20024
+ style: chatColumnStyle,
18844
20025
  children: [
18845
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18846
- "div",
20026
+ 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 }),
20027
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20028
+ ChatAttachments,
18847
20029
  {
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"
20030
+ ref: attachmentsRef,
20031
+ accept: acceptMimes,
20032
+ maxCount: composer?.attachments?.maxCount ?? 10,
20033
+ maxSize: composer?.attachments?.maxSize ?? 100 * 1024 * 1024,
20034
+ retryUploadLabel: t("chat.retryUpload"),
20035
+ uploadFile: uploadContextFile,
20036
+ deleteFile: deleteContextFile,
20037
+ getFileStatus: getContextFileStatus,
20038
+ onStateChange: setAttachmentState
20039
+ }
20040
+ ),
20041
+ 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)(
20042
+ ReferenceChip,
20043
+ {
20044
+ reference,
20045
+ variant: "composer",
20046
+ onRemove: () => setReferences(
20047
+ (previous) => previous.filter(
20048
+ (item) => getReferenceKey(item) !== getReferenceKey(reference)
20049
+ )
18865
20050
  ),
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
- )
20051
+ removeLabel: t("composer.removeReference")
18869
20052
  },
18870
- composerDomVersion
20053
+ getReferenceKey(reference)
20054
+ )) }),
20055
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20056
+ DetachedRunRuntimeCapabilities,
20057
+ {
20058
+ options: detachedRunRuntimeCapabilityOptions,
20059
+ runOnlyLabel: t("composer.capabilities.runOnly"),
20060
+ removeLabel: t("composer.capabilities.removeRunCapability"),
20061
+ onRemove: removeRunRuntimeCapability
20062
+ }
18871
20063
  ),
18872
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
20064
+ showGoalStatus && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
18873
20065
  "div",
18874
20066
  {
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",
20067
+ className: cn(
20068
+ "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",
20069
+ isGoalObjectiveExpanded ? "items-start" : "items-center"
20070
+ ),
18877
20071
  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,
20072
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20073
+ import_lucide_react31.Target,
20074
+ {
20075
+ className: cn(
20076
+ "size-4 shrink-0 text-muted-foreground",
20077
+ isGoalObjectiveExpanded && "mt-1"
20078
+ )
20079
+ }
20080
+ ),
20081
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "min-w-0 flex-1", children: [
20082
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex min-w-0 items-center gap-2", children: [
20083
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "font-medium", children: t("chat.goal.label") }),
20084
+ 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}`) }),
20085
+ isGoalLoading && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Loader2, { className: "size-3 animate-spin text-muted-foreground" })
20086
+ ] }),
20087
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20088
+ "div",
18881
20089
  {
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
20090
+ className: cn(
20091
+ "mt-0.5 text-muted-foreground",
20092
+ threadGoal?.objective && !goalError && isGoalObjectiveExpanded ? "whitespace-pre-wrap break-words" : "truncate"
20093
+ ),
20094
+ children: goalError || threadGoal?.objective
18895
20095
  }
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",
20096
+ ),
20097
+ 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", {
20098
+ elapsed: formatGoalElapsed(displayedGoalElapsedSeconds)
20099
+ }) }) })
20100
+ ] }),
20101
+ threadGoal && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
20102
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20103
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20104
+ Button,
18901
20105
  {
18902
20106
  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 })
20107
+ variant: "ghost",
20108
+ size: "icon-xs",
20109
+ disabled: isGoalLoading,
20110
+ onClick: () => {
20111
+ const prefix = "/goal edit ";
20112
+ setComposerText(`${prefix}${threadGoal.objective}`);
20113
+ },
20114
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Pencil, { className: "size-3" })
18906
20115
  }
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 ? [
20116
+ ) }),
20117
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: t("chat.goal.edit") })
20118
+ ] }),
20119
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20120
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20121
+ Button,
18920
20122
  {
18921
- label: t("chat.followUps.queue"),
18922
- keys: "Enter"
20123
+ type: "button",
20124
+ variant: "ghost",
20125
+ size: "icon-xs",
20126
+ disabled: isGoalLoading,
20127
+ onClick: () => void handleGoalCommand({
20128
+ args: threadGoal.status === "paused" ? "resume" : "pause",
20129
+ commandSource: {
20130
+ type: "slash_command",
20131
+ name: "goal",
20132
+ source: "runtime",
20133
+ executionType: "insert_invocation"
20134
+ }
20135
+ }),
20136
+ 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" })
20137
+ }
20138
+ ) }),
20139
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
20140
+ ] }),
20141
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20142
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20143
+ Button,
20144
+ {
20145
+ type: "button",
20146
+ variant: "ghost",
20147
+ size: "icon-xs",
20148
+ disabled: isGoalLoading,
20149
+ onClick: () => void handleGoalCommand({
20150
+ args: "clear",
20151
+ commandSource: {
20152
+ type: "slash_command",
20153
+ name: "goal",
20154
+ source: "runtime",
20155
+ executionType: "insert_invocation"
20156
+ }
20157
+ }),
20158
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.Trash2, { className: "size-3" })
20159
+ }
20160
+ ) }),
20161
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: t("chat.goal.clear") })
20162
+ ] }),
20163
+ threadGoal.objective && !goalError && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip, { children: [
20164
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20165
+ Button,
20166
+ {
20167
+ type: "button",
20168
+ variant: "ghost",
20169
+ size: "icon-xs",
20170
+ "aria-expanded": isGoalObjectiveExpanded,
20171
+ "aria-label": isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective"),
20172
+ onClick: () => setIsGoalObjectiveExpanded((expanded) => !expanded),
20173
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20174
+ import_lucide_react31.ChevronDown,
20175
+ {
20176
+ className: cn(
20177
+ "size-3 transition-transform",
20178
+ isGoalObjectiveExpanded && "rotate-180"
20179
+ )
20180
+ }
20181
+ )
18923
20182
  }
18924
- ] : void 0
20183
+ ) }),
20184
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
20185
+ ] })
20186
+ ] })
20187
+ ]
20188
+ }
20189
+ ),
20190
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20191
+ PendingRuntimeServices,
20192
+ {
20193
+ state: stream.runtimeActivities.sandboxServices,
20194
+ onStopService: (serviceId) => stream.stopRuntimeActivityItem("sandbox-services", serviceId),
20195
+ attachToComposer: !hasPendingTodos && !hasPendingFollowUps,
20196
+ className: hasPendingTodos || hasPendingFollowUps ? "mb-2" : void 0
20197
+ }
20198
+ ),
20199
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20200
+ PendingTodos,
20201
+ {
20202
+ snapshot: stream.todos,
20203
+ attachToComposer: !hasPendingFollowUps,
20204
+ className: hasPendingFollowUps ? "mb-2" : void 0
20205
+ }
20206
+ ),
20207
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20208
+ PendingFollowUps,
20209
+ {
20210
+ items: pendingFollowUps,
20211
+ isLoading: stream.isLoading,
20212
+ onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
20213
+ canSendNow: stream.canSendPendingFollowUpNow,
20214
+ onSendNow: (id) => stream.sendPendingFollowUpNow(id),
20215
+ onEdit: handleEditPendingFollowUp,
20216
+ onRemove: stream.removePendingFollowUp,
20217
+ attachToComposer: true
20218
+ }
20219
+ ),
20220
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20221
+ RequestUserInputPanel,
20222
+ {
20223
+ request: stream.pendingRequestUserInput,
20224
+ onSubmit: stream.submitRequestUserInput,
20225
+ onDismiss: stream.stop,
20226
+ attachToComposer: true
20227
+ }
20228
+ ),
20229
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20230
+ HITLApprovalPanel,
20231
+ {
20232
+ request: stream.pendingHITLRequest,
20233
+ onSubmit: stream.submitHITLDecision,
20234
+ onDismiss: stream.stop,
20235
+ attachToComposer: true
20236
+ }
20237
+ ),
20238
+ runtimeCapabilityPalette && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20239
+ SlashPalette,
20240
+ {
20241
+ palette: runtimeCapabilityPalette,
20242
+ options: slashPaletteOptions,
20243
+ paletteRef: slashPaletteRef,
20244
+ optionRefs: slashPaletteOptionRefs,
20245
+ panelRoundedClass: getPanelRoundedClass(theme.radius),
20246
+ itemRoundedClass: getMenuItemRoundedClass(theme.radius),
20247
+ emptyLabel: slashPaletteEmptyLabel,
20248
+ capabilityEmptyLabels: slashPaletteCapabilityEmptyLabels,
20249
+ onSelect: selectSlashPaletteOption
20250
+ }
20251
+ ),
20252
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20253
+ "div",
20254
+ {
20255
+ "data-slot": "composer-input-shell",
20256
+ "data-layout": isComposerStacked ? "stacked" : "inline",
20257
+ className: cn(
20258
+ "relative flex flex-1 overflow-hidden",
20259
+ "bg-background border border-border shadow-sm",
20260
+ isComposerStacked ? "min-h-[5.5rem] px-1.5 pt-1.5 pb-12" : "min-h-12 px-1.5 py-1",
20261
+ "focus-within:border-muted-foreground/30 focus-within:shadow-md",
20262
+ "transition-[min-height,padding,border-radius,box-shadow,border-color] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
20263
+ composerInputRoundedClass
20264
+ ),
20265
+ children: [
20266
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20267
+ "div",
20268
+ {
20269
+ ref: composerInputRef,
20270
+ role: "textbox",
20271
+ "aria-multiline": "true",
20272
+ "aria-disabled": missingConfig || isHistoryLoading || hasPendingInteractiveRequest,
20273
+ contentEditable: !(missingConfig || isHistoryLoading || hasPendingInteractiveRequest),
20274
+ suppressContentEditableWarning: true,
20275
+ onInput: handleComposerInput,
20276
+ onCompositionEnd: handleComposerCompositionEnd,
20277
+ onSelect: handleComposerSelect,
20278
+ onPaste: handleComposerPaste,
20279
+ onKeyDown: handleComposerKeyDown,
20280
+ "data-placeholder": inputPlaceholder,
20281
+ className: cn(
20282
+ "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)]",
20283
+ isComposerStacked ? "px-2 py-1.5" : "py-1 pr-11 pl-11 mt-1",
20284
+ "empty:before:pointer-events-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
20285
+ (missingConfig || isHistoryLoading || hasPendingInteractiveRequest) && "cursor-not-allowed opacity-50"
20286
+ ),
20287
+ children: renderedComposerParts.map(
20288
+ (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)
20289
+ )
20290
+ },
20291
+ composerDomVersion
20292
+ ),
20293
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
20294
+ "div",
20295
+ {
20296
+ "data-slot": "composer-action-bar",
20297
+ className: "pointer-events-none absolute inset-x-1.5 bottom-1 flex min-h-10 items-center justify-between gap-2",
20298
+ children: [
20299
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "pointer-events-none flex min-w-0 flex-1 items-center gap-1.5", children: [
20300
+ /* @__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)(
20301
+ ComposerMenu,
20302
+ {
20303
+ composer,
20304
+ onAttachmentClick: handleAttachmentClick,
20305
+ onToolSelect: handleToolSelect,
20306
+ selectedTool,
20307
+ planModeEnabled,
20308
+ onPlanModeChange: setPlanModeEnabled,
20309
+ goalCommandAvailable,
20310
+ goalPanelOpen: isGoalModeOpen,
20311
+ onGoalPanelOpenChange: handleGoalPanelOpenChange,
20312
+ runtimeCapabilities: runtimeCapabilitiesReady ? runtimeCapabilities : null,
20313
+ selectedRuntimeCapabilities: effectiveSessionRuntimeCapabilities,
20314
+ onRuntimeCapabilityToggle: handleSessionRuntimeCapabilityToggle,
20315
+ disabled: missingConfig || isHistoryLoading || hasPendingInteractiveRequest
20316
+ }
20317
+ ) }),
20318
+ 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: [
20319
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "truncate", children: selectedTool.shortLabel ?? selectedTool.label }),
20320
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20321
+ "button",
20322
+ {
20323
+ type: "button",
20324
+ onClick: () => setSelectedTool(null),
20325
+ className: "shrink-0 rounded-full p-0.5 text-primary/70 hover:bg-primary/10 hover:text-primary",
20326
+ children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react31.X, { size: 12 })
20327
+ }
20328
+ )
20329
+ ] })
20330
+ ] }),
20331
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "pointer-events-auto shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20332
+ SendButton,
20333
+ {
20334
+ disabled: isSendDisabled,
20335
+ isLoading: stream.isLoading,
20336
+ showStop: stream.isLoading && (!trimmedDraft || hasPendingInteractiveRequest),
20337
+ onStop: () => stream.stop(),
20338
+ stopLabel: t("chat.stop"),
20339
+ sendLabel: t("chat.send"),
20340
+ shortcuts: stream.isLoading && trimmedDraft ? [
20341
+ {
20342
+ label: t("chat.followUps.queue"),
20343
+ keys: "Enter"
20344
+ }
20345
+ ] : void 0
20346
+ }
20347
+ ) })
20348
+ ]
18925
20349
  }
18926
- ) })
20350
+ )
18927
20351
  ]
18928
20352
  }
18929
- )
20353
+ ) }),
20354
+ disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20355
+ "p",
20356
+ {
20357
+ className: cn(
20358
+ "mt-2 text-center text-xs",
20359
+ disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
20360
+ ),
20361
+ children: disclaimer.text
20362
+ }
20363
+ ),
20364
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
20365
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: t("chat.poweredBy") }),
20366
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ContextUsageIndicator, { className: "absolute right-4" })
20367
+ ] })
18930
20368
  ]
18931
20369
  }
18932
- ) }),
18933
- disclaimer?.text && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18934
- "p",
20370
+ ),
20371
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
20372
+ SettingsSheet,
18935
20373
  {
18936
- className: cn(
18937
- "mt-2 text-center text-xs",
18938
- disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
18939
- ),
18940
- children: disclaimer.text
20374
+ open: petSettingsOpen,
20375
+ settings: displayedPetSettings,
20376
+ petRequired,
20377
+ onOpenChange: setPetSettingsOpen,
20378
+ onSave: savePetLocalSettings
18941
20379
  }
18942
20380
  ),
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
- ] })
20381
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(PetBridge, { pet: effectivePet, state: petAutoState })
18947
20382
  ]
18948
20383
  }
18949
20384
  ),
18950
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
18951
- SettingsSheet,
20385
+ 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)(
20386
+ TaskSummaryPanel,
18952
20387
  {
18953
- open: petSettingsOpen,
18954
- settings: displayedPetSettings,
18955
- petRequired,
18956
- onOpenChange: setPetSettingsOpen,
18957
- onSave: savePetLocalSettings
20388
+ ...taskSummaryProps,
20389
+ className: "pointer-events-auto max-h-full"
18958
20390
  }
18959
- ),
18960
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(PetBridge, { pet: effectivePet, state: petAutoState })
20391
+ ) })
18961
20392
  ]
18962
20393
  }
18963
20394
  );
18964
20395
  }
18965
20396
 
18966
20397
  // 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)(
20398
+ var React55 = __toESM(require("react"), 1);
20399
+ var import_jsx_runtime59 = require("react/jsx-runtime");
20400
+ var Separator = React55.forwardRef(
20401
+ ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
18971
20402
  "div",
18972
20403
  {
18973
20404
  ref,