@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.js CHANGED
@@ -1,21 +1,22 @@
1
1
  // src/components/chat.tsx
2
- import * as React52 from "react";
2
+ import * as React54 from "react";
3
3
  import {
4
4
  ArrowDown as ArrowDown2,
5
5
  ChevronDown as ChevronDown5,
6
6
  FileText as FileText5,
7
7
  ImageIcon,
8
- Loader2 as Loader29,
8
+ Loader2 as Loader210,
9
9
  Minus,
10
10
  Pause,
11
11
  Pencil as Pencil4,
12
12
  Play,
13
13
  Quote,
14
14
  Settings as Settings2,
15
- Target as Target2,
15
+ Target as Target3,
16
16
  Trash2 as Trash23,
17
17
  X as X7
18
18
  } from "lucide-react";
19
+ import { CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT } from "@xpert-ai/chatkit-types";
19
20
 
20
21
  // src/lib/utils.ts
21
22
  import { clsx } from "clsx";
@@ -393,6 +394,15 @@ function toLineNumber(value) {
393
394
  function isOptionalNumber(value) {
394
395
  return value === void 0 || Number.isFinite(value);
395
396
  }
397
+ function isElementAttribute(value) {
398
+ if (!isObjectLike(value)) {
399
+ return false;
400
+ }
401
+ return "name" in value && "value" in value && typeof value.name === "string" && typeof value.value === "string";
402
+ }
403
+ function isElementAttributes(value) {
404
+ return Array.isArray(value) && value.every(isElementAttribute);
405
+ }
396
406
  function toOptionalNumber(value, options) {
397
407
  const allowZero = options?.allowZero ?? false;
398
408
  if (!Number.isFinite(value)) {
@@ -428,6 +438,20 @@ function isImageReferenceCandidate(value) {
428
438
  const candidate = value;
429
439
  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);
430
440
  }
441
+ function isElementReferenceCandidate(value) {
442
+ if (!isObjectLike(value)) {
443
+ return false;
444
+ }
445
+ const candidate = value;
446
+ 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);
447
+ }
448
+ function isFileElementReferenceCandidate(value) {
449
+ if (!isObjectLike(value)) {
450
+ return false;
451
+ }
452
+ const candidate = value;
453
+ 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);
454
+ }
431
455
  function toCodeReference(candidate) {
432
456
  return {
433
457
  type: "code",
@@ -472,6 +496,48 @@ function toImageReference(candidate) {
472
496
  ...toOptionalNumber(candidate.height) !== void 0 ? { height: toOptionalNumber(candidate.height) } : {}
473
497
  };
474
498
  }
499
+ function toElementReference(candidate) {
500
+ const id = toOptionalString(candidate.id);
501
+ const label = toOptionalString(candidate.label);
502
+ const pageTitle = toOptionalString(candidate.pageTitle);
503
+ const role = toOptionalString(candidate.role);
504
+ return {
505
+ type: "element",
506
+ ...id ? { id } : {},
507
+ ...label ? { label } : {},
508
+ attributes: candidate.attributes,
509
+ outerHtml: candidate.outerHtml,
510
+ ...pageTitle ? { pageTitle } : {},
511
+ pageUrl: candidate.pageUrl.trim(),
512
+ ...role ? { role } : {},
513
+ selector: candidate.selector,
514
+ serviceId: candidate.serviceId,
515
+ tagName: candidate.tagName,
516
+ text: candidate.text
517
+ };
518
+ }
519
+ function toFileElementReference(candidate) {
520
+ const id = toOptionalString(candidate.id);
521
+ const label = toOptionalString(candidate.label);
522
+ const documentTitle = toOptionalString(candidate.documentTitle);
523
+ const role = toOptionalString(candidate.role);
524
+ return {
525
+ type: "file_element",
526
+ ...id ? { id } : {},
527
+ ...label ? { label } : {},
528
+ attributes: candidate.attributes,
529
+ ...documentTitle ? { documentTitle } : {},
530
+ domPath: candidate.domPath,
531
+ filePath: candidate.filePath,
532
+ outerHtml: candidate.outerHtml,
533
+ ...role ? { role } : {},
534
+ selector: candidate.selector,
535
+ ...toOptionalNumber(candidate.sourceStartLine) !== void 0 ? { sourceStartLine: candidate.sourceStartLine } : {},
536
+ ...toOptionalNumber(candidate.sourceEndLine) !== void 0 ? { sourceEndLine: candidate.sourceEndLine } : {},
537
+ tagName: candidate.tagName,
538
+ text: candidate.text
539
+ };
540
+ }
475
541
  function isLegacyCodeReference(candidate) {
476
542
  return candidate.type === void 0 && isNonEmptyString(candidate.path) && toLineNumber(candidate.startLine) !== null && toLineNumber(candidate.endLine) !== null && toReferenceText(candidate.text) !== null;
477
543
  }
@@ -490,6 +556,12 @@ function normalizeReference(value) {
490
556
  if (isImageReferenceCandidate(candidate)) {
491
557
  return toImageReference(candidate);
492
558
  }
559
+ if (isElementReferenceCandidate(candidate)) {
560
+ return toElementReference(candidate);
561
+ }
562
+ if (isFileElementReferenceCandidate(candidate)) {
563
+ return toFileElementReference(candidate);
564
+ }
493
565
  if (type === void 0 && isLegacyCodeReference(candidate)) {
494
566
  return toCodeReference(candidate);
495
567
  }
@@ -564,6 +636,22 @@ function getReferenceKey(reference) {
564
636
  reference.text
565
637
  ].join(":");
566
638
  }
639
+ if (reference.type === "element") {
640
+ return [
641
+ reference.type,
642
+ reference.serviceId,
643
+ reference.pageUrl,
644
+ reference.selector
645
+ ].join(":");
646
+ }
647
+ if (reference.type === "file_element") {
648
+ return [
649
+ reference.type,
650
+ reference.filePath,
651
+ reference.domPath,
652
+ reference.selector
653
+ ].join(":");
654
+ }
567
655
  return [
568
656
  reference.type,
569
657
  reference.messageId ?? "",
@@ -596,7 +684,13 @@ function getReferenceLabel(reference) {
596
684
  if (reference.type === "image") {
597
685
  return reference.name?.trim() || "Pasted image";
598
686
  }
599
- if (reference.source && reference.source.trim()) {
687
+ if (reference.type === "element") {
688
+ return reference.pageTitle?.trim() || reference.tagName;
689
+ }
690
+ if (reference.type === "file_element") {
691
+ return reference.documentTitle?.trim() || reference.filePath;
692
+ }
693
+ if (reference.type === "quote" && reference.source?.trim()) {
600
694
  return reference.source.trim();
601
695
  }
602
696
  return getQuoteExcerpt(reference);
@@ -609,10 +703,18 @@ function getReferenceMetaLine(reference) {
609
703
  const parts = getImageReferenceMetaParts(reference);
610
704
  return parts.length ? parts.join(" \u2022 ") : null;
611
705
  }
612
- if (reference.source && reference.source.trim()) {
706
+ if (reference.type === "element") {
707
+ return reference.pageUrl;
708
+ }
709
+ if (reference.type === "file_element") {
710
+ const start = reference.sourceStartLine;
711
+ const end = reference.sourceEndLine ?? start;
712
+ return start ? `${reference.filePath}:${start}${end === start ? "" : `-${end}`}` : reference.filePath;
713
+ }
714
+ if (reference.type === "quote" && reference.source?.trim()) {
613
715
  return getQuoteExcerpt(reference);
614
716
  }
615
- if (reference.messageId && reference.messageId.trim()) {
717
+ if (reference.type === "quote" && reference.messageId?.trim()) {
616
718
  return `Message ${reference.messageId.trim()}`;
617
719
  }
618
720
  return null;
@@ -638,6 +740,17 @@ ${reference.text}`;
638
740
  }
639
741
  return titleLines.join("\n");
640
742
  }
743
+ if (reference.type === "element") {
744
+ return `${getReferenceLabel(reference)}
745
+ ${reference.pageUrl}
746
+
747
+ ${reference.text}`;
748
+ }
749
+ if (reference.type === "file_element") {
750
+ return `${getReferenceMetaLine(reference) ?? reference.filePath}
751
+
752
+ ${reference.text}`;
753
+ }
641
754
  const header = reference.label?.trim() || reference.source?.trim() || "Quoted text";
642
755
  return `${header}
643
756
 
@@ -1258,6 +1371,548 @@ function countCompletedTodos(items) {
1258
1371
  return items.filter((item) => item.status === "completed").length;
1259
1372
  }
1260
1373
 
1374
+ // src/lib/task-summary.ts
1375
+ var PLAN_PATTERN = /<proposed_plan>\s*([\s\S]*?)\s*<\/proposed_plan>/i;
1376
+ function isObject(value) {
1377
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1378
+ }
1379
+ function stringValue(value) {
1380
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
1381
+ }
1382
+ function timestamp(value) {
1383
+ const parsed = value ? Date.parse(value) : 0;
1384
+ return Number.isNaN(parsed) ? 0 : parsed;
1385
+ }
1386
+ function contentParts(content) {
1387
+ return Array.isArray(content) ? content.filter((part) => isObject(part)) : [];
1388
+ }
1389
+ function messageText(content) {
1390
+ if (typeof content === "string") return content;
1391
+ return contentParts(content).map(
1392
+ (part) => isObject(part) && "text" in part ? stringValue(part.text) ?? "" : ""
1393
+ ).join("\n");
1394
+ }
1395
+ function normalizeTaskSummaryContribution(value) {
1396
+ if (!isObject(value)) return null;
1397
+ const candidate = value;
1398
+ if (candidate.version !== 1) return null;
1399
+ const plan = normalizePlan(candidate.plan);
1400
+ const todos = normalizeTodos(candidate.todos);
1401
+ const outputs = Array.isArray(candidate.outputs) ? candidate.outputs.flatMap((item) => normalizeOutput(item) ?? []) : [];
1402
+ const sources = Array.isArray(candidate.sources) ? candidate.sources.flatMap((item) => normalizeSource(item) ?? []) : [];
1403
+ return {
1404
+ version: 1,
1405
+ ...plan ? { plan } : {},
1406
+ ...todos ? { todos } : {},
1407
+ ...outputs.length ? { outputs } : {},
1408
+ ...sources.length ? { sources } : {}
1409
+ };
1410
+ }
1411
+ function normalizePlan(value) {
1412
+ if (!isObject(value)) return null;
1413
+ const candidate = value;
1414
+ const title = stringValue(candidate.title);
1415
+ const excerpt = stringValue(candidate.excerpt);
1416
+ return title && excerpt ? {
1417
+ title,
1418
+ excerpt,
1419
+ messageId: stringValue(candidate.messageId),
1420
+ updatedAt: stringValue(candidate.updatedAt)
1421
+ } : null;
1422
+ }
1423
+ function normalizeTodos(value) {
1424
+ if (!isObject(value)) return null;
1425
+ const candidate = value;
1426
+ const componentId = stringValue(candidate.componentId);
1427
+ if (!componentId || !Array.isArray(candidate.items)) return null;
1428
+ const items = candidate.items.flatMap((item) => {
1429
+ if (!isObject(item)) return [];
1430
+ const todo = item;
1431
+ const id = stringValue(todo.id);
1432
+ const content = stringValue(todo.content);
1433
+ const status = todo.status;
1434
+ return id && content && isTodoStatus(status) ? [{ id, content, status }] : [];
1435
+ });
1436
+ return items.length ? {
1437
+ componentId,
1438
+ title: stringValue(candidate.title),
1439
+ items,
1440
+ messageId: stringValue(candidate.messageId),
1441
+ updatedAt: stringValue(candidate.updatedAt)
1442
+ } : null;
1443
+ }
1444
+ function isTodoStatus(value) {
1445
+ return value === "pending" || value === "in_progress" || value === "completed";
1446
+ }
1447
+ function normalizeOutput(value) {
1448
+ if (!isObject(value)) return null;
1449
+ const candidate = value;
1450
+ const id = stringValue(candidate.id);
1451
+ const title = stringValue(candidate.title);
1452
+ const kind = artifactKind(candidate.kind);
1453
+ if (!id || !title || !kind) return null;
1454
+ const status = candidate.status;
1455
+ return {
1456
+ id,
1457
+ kind,
1458
+ title,
1459
+ description: stringValue(candidate.description),
1460
+ status: status === "pending" || status === "running" || status === "success" || status === "error" ? status : void 0,
1461
+ resource: normalizeResource(candidate.resource),
1462
+ messageId: stringValue(candidate.messageId),
1463
+ updatedAt: stringValue(candidate.updatedAt)
1464
+ };
1465
+ }
1466
+ function normalizeSource(value) {
1467
+ if (!isObject(value)) return null;
1468
+ const candidate = value;
1469
+ const id = stringValue(candidate.id);
1470
+ const title = stringValue(candidate.title);
1471
+ if (!id || !title || !isSourceKind(candidate.kind)) return null;
1472
+ return {
1473
+ id,
1474
+ kind: candidate.kind,
1475
+ title,
1476
+ description: stringValue(candidate.description),
1477
+ resource: normalizeResource(candidate.resource),
1478
+ messageId: stringValue(candidate.messageId),
1479
+ updatedAt: stringValue(candidate.updatedAt)
1480
+ };
1481
+ }
1482
+ function normalizeResource(value) {
1483
+ if (!isObject(value)) return void 0;
1484
+ const candidate = value;
1485
+ if (candidate.type === "message") {
1486
+ const messageId = stringValue(candidate.messageId);
1487
+ return messageId ? { type: "message", messageId } : void 0;
1488
+ }
1489
+ if (candidate.type === "workspace_file") {
1490
+ const workspacePath = stringValue(candidate.workspacePath);
1491
+ return workspacePath ? {
1492
+ type: "workspace_file",
1493
+ workspacePath,
1494
+ fileAssetId: stringValue(candidate.fileAssetId),
1495
+ storageFileId: stringValue(candidate.storageFileId)
1496
+ } : void 0;
1497
+ }
1498
+ if (candidate.type === "artifact") {
1499
+ const artifactId = stringValue(candidate.artifactId);
1500
+ return artifactId ? { type: "artifact", artifactId } : void 0;
1501
+ }
1502
+ if (candidate.type === "browser") {
1503
+ const serviceId = stringValue(candidate.serviceId);
1504
+ const url = stringValue(candidate.url);
1505
+ return serviceId || url ? { type: "browser", serviceId, url } : void 0;
1506
+ }
1507
+ if (candidate.type === "url") {
1508
+ const url = stringValue(candidate.url);
1509
+ return url ? { type: "url", url } : void 0;
1510
+ }
1511
+ return void 0;
1512
+ }
1513
+ function isSourceKind(value) {
1514
+ return value === "attachment" || value === "code" || value === "quote" || value === "image" || value === "web_page" || value === "file_element" || value === "knowledge" || value === "skill" || value === "plugin" || value === "sub_agent";
1515
+ }
1516
+ function contributionFromPart(part) {
1517
+ if (part.type !== "component" || !isObject(part.data)) return null;
1518
+ const data = part.data;
1519
+ const direct = normalizeTaskSummaryContribution(data.taskSummary);
1520
+ if (direct) return direct;
1521
+ if (!isObject(data._meta)) return null;
1522
+ return normalizeTaskSummaryContribution(
1523
+ data._meta["xpertai/taskSummary"]
1524
+ );
1525
+ }
1526
+ function extractPlan(message) {
1527
+ const match = PLAN_PATTERN.exec(messageText(message.content));
1528
+ const markdown = match?.[1]?.trim();
1529
+ if (!markdown) return void 0;
1530
+ const title = markdown.split(/\r?\n/).map((line) => line.replace(/^#{1,6}\s+/, "").trim()).find(Boolean);
1531
+ const excerpt = markdown.replace(/\s+/g, " ").trim();
1532
+ return {
1533
+ title: title ?? "Plan",
1534
+ excerpt: excerpt.length <= 160 ? excerpt : `${excerpt.slice(0, 157).trimEnd()}...`,
1535
+ messageId: message.id,
1536
+ updatedAt: message.updatedAt ?? message.createdAt
1537
+ };
1538
+ }
1539
+ function artifactKind(value) {
1540
+ switch (value) {
1541
+ case "file":
1542
+ case "image":
1543
+ case "document":
1544
+ case "spreadsheet":
1545
+ case "presentation":
1546
+ case "site":
1547
+ case "url":
1548
+ case "mcp_app":
1549
+ return value;
1550
+ case "html":
1551
+ return "site";
1552
+ case "markdown":
1553
+ case "pdf":
1554
+ return "document";
1555
+ case "pptx":
1556
+ return "presentation";
1557
+ default:
1558
+ return null;
1559
+ }
1560
+ }
1561
+ function knownPartOutputs(part, message) {
1562
+ const updatedAt = message.updatedAt ?? message.createdAt;
1563
+ if (part.type === "image_url") {
1564
+ const url = stringValue(part.image_url) ?? (isObject(part.image_url) && "url" in part.image_url ? stringValue(part.image_url.url) : void 0);
1565
+ return url ? [
1566
+ {
1567
+ id: `image:${url}`,
1568
+ kind: "image",
1569
+ title: stringValue(part.title) ?? "Image",
1570
+ resource: { type: "url", url },
1571
+ messageId: message.id,
1572
+ updatedAt
1573
+ }
1574
+ ] : [];
1575
+ }
1576
+ if (part.type === "iframe") {
1577
+ const url = stringValue(part.url) ?? (isObject(part.data) ? stringValue(part.data.url) : void 0);
1578
+ return url ? [
1579
+ {
1580
+ id: `url:${url}`,
1581
+ kind: "url",
1582
+ title: stringValue(part.title) ?? url,
1583
+ resource: { type: "url", url },
1584
+ messageId: message.id,
1585
+ updatedAt
1586
+ }
1587
+ ] : [];
1588
+ }
1589
+ if (part.type !== "component" || !isObject(part.data)) return [];
1590
+ const data = part.data;
1591
+ const outputs = [...contributionFromPart(part)?.outputs ?? []];
1592
+ if (data.type === "McpApp") {
1593
+ outputs.push({
1594
+ id: `mcp-app:${stringValue(part.id) ?? message.id ?? "message"}`,
1595
+ kind: "mcp_app",
1596
+ title: stringValue(data.title) ?? "MCP App",
1597
+ resource: message.id ? { type: "message", messageId: message.id } : void 0,
1598
+ messageId: message.id,
1599
+ updatedAt
1600
+ });
1601
+ }
1602
+ if (isObject(data.artifact)) {
1603
+ const artifact = data.artifact;
1604
+ const artifactId = stringValue(artifact.artifactId) ?? stringValue(artifact.id);
1605
+ const workspacePath = stringValue(artifact.workspacePath);
1606
+ const kind = artifactKind(artifact.kind) ?? "file";
1607
+ const id = artifactId ?? stringValue(artifact.fileAssetId) ?? workspacePath;
1608
+ if (kind && id && (artifactId || workspacePath)) {
1609
+ outputs.push({
1610
+ id: `artifact:${id}`,
1611
+ kind,
1612
+ title: stringValue(artifact.title) ?? id,
1613
+ description: stringValue(artifact.description),
1614
+ resource: artifactId ? { type: "artifact", artifactId } : {
1615
+ type: "workspace_file",
1616
+ workspacePath,
1617
+ fileAssetId: stringValue(artifact.fileAssetId),
1618
+ storageFileId: stringValue(artifact.storageFileId)
1619
+ },
1620
+ messageId: message.id,
1621
+ updatedAt
1622
+ });
1623
+ }
1624
+ }
1625
+ for (const value of [data.artifactLink, data.file]) {
1626
+ if (!isObject(value)) continue;
1627
+ const artifact = value;
1628
+ const artifactId = stringValue(artifact.artifactId) ?? stringValue(artifact.id);
1629
+ const workspacePath = stringValue(artifact.workspacePath);
1630
+ const id = artifactId ?? stringValue(artifact.fileAssetId) ?? workspacePath;
1631
+ if (!id || !artifactId && !workspacePath) continue;
1632
+ outputs.push({
1633
+ id: `artifact:${id}`,
1634
+ kind: artifactKind(artifact.kind) ?? "file",
1635
+ title: stringValue(artifact.title) ?? id,
1636
+ description: stringValue(artifact.description),
1637
+ resource: artifactId ? { type: "artifact", artifactId } : {
1638
+ type: "workspace_file",
1639
+ workspacePath,
1640
+ fileAssetId: stringValue(artifact.fileAssetId),
1641
+ storageFileId: stringValue(artifact.storageFileId)
1642
+ },
1643
+ messageId: message.id,
1644
+ updatedAt
1645
+ });
1646
+ }
1647
+ return outputs;
1648
+ }
1649
+ function sourceFromReference(reference, message) {
1650
+ const updatedAt = message.updatedAt ?? message.createdAt;
1651
+ const common = {
1652
+ id: reference.id ?? `${reference.type}:${reference.text}`,
1653
+ title: reference.label?.trim() || reference.text.trim().slice(0, 80),
1654
+ messageId: message.id,
1655
+ updatedAt
1656
+ };
1657
+ if (reference.type === "code") {
1658
+ return {
1659
+ ...common,
1660
+ kind: "code",
1661
+ title: reference.label ?? reference.path,
1662
+ description: `${reference.path}:${reference.startLine}-${reference.endLine}`,
1663
+ resource: message.id ? { type: "message", messageId: message.id } : void 0
1664
+ };
1665
+ }
1666
+ if (reference.type === "image") {
1667
+ return {
1668
+ ...common,
1669
+ kind: "image",
1670
+ title: reference.name ?? common.title,
1671
+ resource: reference.url ? { type: "url", url: reference.url } : void 0
1672
+ };
1673
+ }
1674
+ if (reference.type === "element") {
1675
+ return {
1676
+ ...common,
1677
+ kind: "web_page",
1678
+ title: reference.pageTitle ?? reference.pageUrl,
1679
+ description: reference.pageUrl,
1680
+ resource: {
1681
+ type: "browser",
1682
+ serviceId: reference.serviceId,
1683
+ url: reference.pageUrl
1684
+ }
1685
+ };
1686
+ }
1687
+ if (reference.type === "file_element") {
1688
+ return {
1689
+ ...common,
1690
+ kind: "file_element",
1691
+ title: reference.documentTitle ?? reference.filePath,
1692
+ description: reference.filePath,
1693
+ resource: { type: "workspace_file", workspacePath: reference.filePath }
1694
+ };
1695
+ }
1696
+ return { ...common, kind: "quote", description: reference.source };
1697
+ }
1698
+ function fileSources(files, message) {
1699
+ return (files ?? []).flatMap((file) => {
1700
+ const id = stringValue(file.fileAssetId) ?? stringValue(file.id) ?? stringValue(file.storageFileId);
1701
+ const title = stringValue(file.originalName) ?? stringValue(file.name) ?? stringValue(file.fileName);
1702
+ if (!id || !title) return [];
1703
+ const workspacePath = stringValue(file.workspacePath);
1704
+ return [
1705
+ {
1706
+ id: `attachment:${id}`,
1707
+ kind: "attachment",
1708
+ title,
1709
+ resource: workspacePath ? {
1710
+ type: "workspace_file",
1711
+ workspacePath,
1712
+ fileAssetId: stringValue(file.fileAssetId) ?? stringValue(file.id),
1713
+ storageFileId: stringValue(file.storageFileId)
1714
+ } : message.id ? { type: "message", messageId: message.id } : void 0,
1715
+ messageId: message.id,
1716
+ updatedAt: message.updatedAt ?? message.createdAt
1717
+ }
1718
+ ];
1719
+ });
1720
+ }
1721
+ function capabilitySources(message) {
1722
+ const selection = message.runtimeCapabilities;
1723
+ if (!selection) return [];
1724
+ const updatedAt = message.updatedAt ?? message.createdAt;
1725
+ const common = { messageId: message.id, updatedAt };
1726
+ return [
1727
+ ...selection.skills.ids.map((id) => ({
1728
+ ...common,
1729
+ id: `skill:${id}`,
1730
+ kind: "skill",
1731
+ title: id
1732
+ })),
1733
+ ...selection.plugins.nodeKeys.map((id) => ({
1734
+ ...common,
1735
+ id: `plugin:${id}`,
1736
+ kind: "plugin",
1737
+ title: id
1738
+ }))
1739
+ ];
1740
+ }
1741
+ function collectLiveTaskSummary({
1742
+ messages,
1743
+ goal,
1744
+ todos,
1745
+ pending,
1746
+ running,
1747
+ agentNames
1748
+ }) {
1749
+ const contributions = messages.flatMap((message) => [
1750
+ ...message.taskSummary?.version === 1 ? [message.taskSummary] : [],
1751
+ ...contentParts(message.content).flatMap(
1752
+ (part) => contributionFromPart(part) ?? []
1753
+ )
1754
+ ]);
1755
+ const messagePlans = messages.flatMap(
1756
+ (message) => extractPlan(message) ?? []
1757
+ );
1758
+ const agentRuns = messages.flatMap(
1759
+ (message) => (message.agentRuns ?? []).map((run) => ({
1760
+ id: run.id,
1761
+ parentId: run.parentId,
1762
+ level: agentRunLevel(run, messages),
1763
+ agentKey: run.agentKey,
1764
+ title: (run.agentKey ? agentNames?.get(run.agentKey) : void 0) ?? run.title ?? run.xpertName ?? run.agentKey ?? "Agent",
1765
+ status: taskSummaryAgentStatus(run.status),
1766
+ elapsedTime: run.elapsedTime,
1767
+ error: typeof run.error === "string" ? run.error : void 0,
1768
+ messageId: message.id,
1769
+ updatedAt: run.updatedAt ?? run.endedAt ?? run.startedAt ?? message.updatedAt
1770
+ }))
1771
+ );
1772
+ return {
1773
+ goal,
1774
+ plan: newest([
1775
+ ...contributions.flatMap((item) => item.plan ?? []),
1776
+ ...messagePlans
1777
+ ]),
1778
+ todos: todos ? {
1779
+ componentId: todos.componentId,
1780
+ title: todos.title,
1781
+ items: todos.items,
1782
+ updatedAt: todos.endDate ?? todos.createdDate
1783
+ } : newest(contributions.flatMap((item) => item.todos ?? [])),
1784
+ outputs: mergeLatest([
1785
+ ...contributions.flatMap((item) => item.outputs ?? []),
1786
+ ...messages.flatMap(
1787
+ (message) => contentParts(message.content).flatMap(
1788
+ (part) => knownPartOutputs(part, message)
1789
+ )
1790
+ )
1791
+ ]),
1792
+ sources: mergeLatest([
1793
+ ...contributions.flatMap((item) => item.sources ?? []).filter((source) => source.kind !== "sub_agent"),
1794
+ ...messages.flatMap((message) => [
1795
+ ...(message.references ?? []).map(
1796
+ (reference) => sourceFromReference(reference, message)
1797
+ ),
1798
+ ...fileSources(message.fileAssets, message),
1799
+ ...fileSources(message.attachments, message),
1800
+ ...capabilitySources(message)
1801
+ ])
1802
+ ]),
1803
+ agents: mergeAgents(agentRuns),
1804
+ pending: pending ?? [],
1805
+ running: running ?? []
1806
+ };
1807
+ }
1808
+ function mergeTaskSummary(history, live, historySections) {
1809
+ const outputs = mergeLatest([
1810
+ ...historySections?.outputs ?? history?.outputs.items ?? [],
1811
+ ...live.outputs
1812
+ ]);
1813
+ const sources = mergeLatest([
1814
+ ...historySections?.sources ?? history?.sources.items ?? [],
1815
+ ...live.sources
1816
+ ]);
1817
+ const agents = mergeAgents([
1818
+ ...historySections?.agents ?? history?.agents.items ?? [],
1819
+ ...live.agents
1820
+ ]);
1821
+ const pending = mergePending([
1822
+ ...historySections?.pending ?? history?.pending.items ?? [],
1823
+ ...live.pending
1824
+ ]);
1825
+ return {
1826
+ goal: live.goal ?? history?.task.goal,
1827
+ plan: newest(
1828
+ [history?.task.plan, live.plan].filter(
1829
+ (item) => Boolean(item)
1830
+ )
1831
+ ),
1832
+ todos: newest(
1833
+ [history?.task.todos, live.todos].filter(
1834
+ (item) => Boolean(item)
1835
+ )
1836
+ ),
1837
+ outputs,
1838
+ sources,
1839
+ agents,
1840
+ pending,
1841
+ running: live.running,
1842
+ totals: {
1843
+ outputs: Math.max(history?.outputs.total ?? 0, outputs.length),
1844
+ sources: Math.max(history?.sources.total ?? 0, sources.length),
1845
+ agents: agents.length,
1846
+ pending: Math.max(history?.pending.total ?? 0, pending.length)
1847
+ }
1848
+ };
1849
+ }
1850
+ function mergeLatest(items) {
1851
+ const byId = /* @__PURE__ */ new Map();
1852
+ items.forEach((item) => {
1853
+ const current = byId.get(item.id);
1854
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1855
+ byId.set(item.id, item);
1856
+ }
1857
+ });
1858
+ return [...byId.values()].sort(
1859
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1860
+ );
1861
+ }
1862
+ function mergeAgents(items) {
1863
+ const byAgent = /* @__PURE__ */ new Map();
1864
+ items.forEach((item) => {
1865
+ const key = item.agentKey?.trim() || item.id;
1866
+ const current = byAgent.get(key);
1867
+ if (!current || timestamp(item.updatedAt) >= timestamp(current.updatedAt)) {
1868
+ byAgent.set(key, item);
1869
+ }
1870
+ });
1871
+ return [...byAgent.values()].sort(
1872
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1873
+ );
1874
+ }
1875
+ function mergePending(items) {
1876
+ const byId = new Map(items.map((item) => [item.id, item]));
1877
+ return [...byId.values()].sort(
1878
+ (left, right) => timestamp(right.createdAt) - timestamp(left.createdAt)
1879
+ );
1880
+ }
1881
+ function taskSummaryAgentStatus(status) {
1882
+ switch (status) {
1883
+ case "running":
1884
+ case "success":
1885
+ case "error":
1886
+ case "pending":
1887
+ case "timeout":
1888
+ case "interrupted":
1889
+ return status;
1890
+ default:
1891
+ return void 0;
1892
+ }
1893
+ }
1894
+ function newest(items) {
1895
+ return [...items].sort(
1896
+ (left, right) => timestamp(right.updatedAt) - timestamp(left.updatedAt)
1897
+ )[0];
1898
+ }
1899
+ function agentRunLevel(run, messages) {
1900
+ const byId = new Map(
1901
+ messages.flatMap(
1902
+ (message) => (message.agentRuns ?? []).map((item) => [item.id, item])
1903
+ )
1904
+ );
1905
+ let parentId = run.parentId;
1906
+ let level = 0;
1907
+ const visited = /* @__PURE__ */ new Set();
1908
+ while (parentId && !visited.has(parentId)) {
1909
+ visited.add(parentId);
1910
+ level += 1;
1911
+ parentId = byId.get(parentId)?.parentId;
1912
+ }
1913
+ return level;
1914
+ }
1915
+
1261
1916
  // src/providers/Stream.tsx
1262
1917
  import { jsx as jsx2 } from "react/jsx-runtime";
1263
1918
  var StreamContext = createContext2(void 0);
@@ -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",
@@ -4888,8 +5609,8 @@ function JsonTreeNode({
4888
5609
  depth = 0
4889
5610
  }) {
4890
5611
  const isArray = Array.isArray(value);
4891
- const isObject = isJsonObjectValue(value);
4892
- const isExpandable = isArray || isObject;
5612
+ const isObject2 = isJsonObjectValue(value);
5613
+ const isExpandable = isArray || isObject2;
4893
5614
  const [isExpanded, setIsExpanded] = React18.useState(depth < 2);
4894
5615
  if (!isExpandable) {
4895
5616
  return /* @__PURE__ */ jsxs13("div", { className: "flex min-w-0 gap-2 leading-6", children: [
@@ -5284,7 +6005,7 @@ function HITLApprovalPanel({
5284
6005
  }
5285
6006
  const argsText = currentDraft.argsText ?? formatArgs(currentAction.args);
5286
6007
  const argsJsonValue = toJsonValue(currentAction.args) ?? {};
5287
- const messageText = currentDraft.message ?? "";
6008
+ const messageText2 = currentDraft.message ?? "";
5288
6009
  const isCurrentInvalid = validation.error?.actionIndex === currentActionIndex;
5289
6010
  return /* @__PURE__ */ jsxs14(
5290
6011
  "section",
@@ -5446,7 +6167,7 @@ function HITLApprovalPanel({
5446
6167
  /* @__PURE__ */ jsx22(
5447
6168
  "textarea",
5448
6169
  {
5449
- value: messageText,
6170
+ value: messageText2,
5450
6171
  onChange: (event) => updateCurrentDraft({
5451
6172
  ...currentDraft,
5452
6173
  message: event.target.value
@@ -7880,14 +8601,14 @@ function isComponentContent(content) {
7880
8601
  }
7881
8602
  function parseDateValue(value) {
7882
8603
  if (value instanceof Date) {
7883
- const timestamp2 = value.getTime();
7884
- return Number.isNaN(timestamp2) ? null : timestamp2;
8604
+ const timestamp3 = value.getTime();
8605
+ return Number.isNaN(timestamp3) ? null : timestamp3;
7885
8606
  }
7886
8607
  if (typeof value !== "string") {
7887
8608
  return null;
7888
8609
  }
7889
- const timestamp = Date.parse(value);
7890
- return Number.isNaN(timestamp) ? null : timestamp;
8610
+ const timestamp2 = Date.parse(value);
8611
+ return Number.isNaN(timestamp2) ? null : timestamp2;
7891
8612
  }
7892
8613
  function readContentTitle(content) {
7893
8614
  if (typeof content === "string") return void 0;
@@ -10706,14 +11427,14 @@ function getToolStepData(content) {
10706
11427
  }
10707
11428
  function parseStepDate(value) {
10708
11429
  if (value instanceof Date) {
10709
- const timestamp2 = value.getTime();
10710
- return Number.isNaN(timestamp2) ? null : timestamp2;
11430
+ const timestamp3 = value.getTime();
11431
+ return Number.isNaN(timestamp3) ? null : timestamp3;
10711
11432
  }
10712
11433
  if (typeof value !== "string") {
10713
11434
  return null;
10714
11435
  }
10715
- const timestamp = Date.parse(value);
10716
- return Number.isNaN(timestamp) ? null : timestamp;
11436
+ const timestamp2 = Date.parse(value);
11437
+ return Number.isNaN(timestamp2) ? null : timestamp2;
10717
11438
  }
10718
11439
  function isThreadKnownIdle(isThreadRunning) {
10719
11440
  return isThreadRunning === false;
@@ -12986,14 +13707,14 @@ function MemoryBlock({ content }) {
12986
13707
  }
12987
13708
  function parseStepDate2(value) {
12988
13709
  if (value instanceof Date) {
12989
- const timestamp2 = value.getTime();
12990
- return Number.isNaN(timestamp2) ? null : timestamp2;
13710
+ const timestamp3 = value.getTime();
13711
+ return Number.isNaN(timestamp3) ? null : timestamp3;
12991
13712
  }
12992
13713
  if (typeof value !== "string") {
12993
13714
  return null;
12994
13715
  }
12995
- const timestamp = Date.parse(value);
12996
- return Number.isNaN(timestamp) ? null : timestamp;
13716
+ const timestamp2 = Date.parse(value);
13717
+ return Number.isNaN(timestamp2) ? null : timestamp2;
12997
13718
  }
12998
13719
  function formatStepDuration3(durationMs) {
12999
13720
  if (durationMs < 1e3) {
@@ -13772,9 +14493,9 @@ var getThreadTitle = (threadRecord) => {
13772
14493
  };
13773
14494
  var toDate = (value) => {
13774
14495
  if (!value) return void 0;
13775
- const timestamp = Date.parse(value);
13776
- if (Number.isNaN(timestamp)) return void 0;
13777
- return new Date(timestamp);
14496
+ const timestamp2 = Date.parse(value);
14497
+ if (Number.isNaN(timestamp2)) return void 0;
14498
+ return new Date(timestamp2);
13778
14499
  };
13779
14500
  var getErrorMessage2 = (error) => {
13780
14501
  if (!error) return void 0;
@@ -16533,18 +17254,487 @@ function buildMessageNavigationItems(messages, options) {
16533
17254
  return items;
16534
17255
  }
16535
17256
 
16536
- // src/components/chat.tsx
16537
- import { Fragment as Fragment9, jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
16538
- var defaultApiUrl2 = import.meta.env.VITE_XPERTAI_API_URL;
16539
- var COMPOSER_INPUT_MAX_HEIGHT = 128;
16540
- var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
16541
- var GOAL_RUN_INPUT = "Continue working toward the active goal.";
16542
- function isGoalAdapter(value) {
16543
- return Boolean(value) && typeof value === "object" && typeof value.getGoal === "function" && typeof value.setGoal === "function" && typeof value.updateGoal === "function" && typeof value.clearGoal === "function";
17257
+ // src/hooks/useTaskSummary.ts
17258
+ import * as React52 from "react";
17259
+ function useTaskSummary({
17260
+ enabled,
17261
+ conversationId,
17262
+ client,
17263
+ live
17264
+ }) {
17265
+ const [loaded, setLoaded] = React52.useState(null);
17266
+ const [historySections, setHistorySections] = React52.useState({});
17267
+ const [historySectionsConversationId, setHistorySectionsConversationId] = React52.useState(null);
17268
+ const [loadingSections, setLoadingSections] = React52.useState({});
17269
+ const [error, setError] = React52.useState(null);
17270
+ const [retryVersion, setRetryVersion] = React52.useState(0);
17271
+ const requestVersionRef = React52.useRef(0);
17272
+ const conversationIdRef = React52.useRef(conversationId);
17273
+ const sectionControllersRef = React52.useRef(
17274
+ /* @__PURE__ */ new Map()
17275
+ );
17276
+ conversationIdRef.current = conversationId;
17277
+ const abortSectionRequests = React52.useCallback(() => {
17278
+ sectionControllersRef.current.forEach((controller) => controller.abort());
17279
+ sectionControllersRef.current.clear();
17280
+ }, []);
17281
+ React52.useEffect(() => {
17282
+ abortSectionRequests();
17283
+ setHistorySections({});
17284
+ setHistorySectionsConversationId(conversationId);
17285
+ setLoadingSections({});
17286
+ setError(null);
17287
+ if (!enabled || !conversationId) {
17288
+ setLoaded(null);
17289
+ setHistorySectionsConversationId(null);
17290
+ return;
17291
+ }
17292
+ const controller = new AbortController();
17293
+ const requestVersion = ++requestVersionRef.current;
17294
+ client.conversations.getTaskSummary(conversationId, { signal: controller.signal }).then((snapshot2) => {
17295
+ if (requestVersionRef.current !== requestVersion) return;
17296
+ setLoaded({ conversationId, snapshot: snapshot2 });
17297
+ }).catch((nextError) => {
17298
+ if (controller.signal.aborted || requestVersionRef.current !== requestVersion)
17299
+ return;
17300
+ setLoaded(null);
17301
+ setError(nextError);
17302
+ });
17303
+ return () => {
17304
+ controller.abort();
17305
+ abortSectionRequests();
17306
+ requestVersionRef.current += 1;
17307
+ };
17308
+ }, [abortSectionRequests, client, conversationId, enabled, retryVersion]);
17309
+ const snapshot = loaded?.conversationId === conversationId ? loaded.snapshot : null;
17310
+ const activeHistorySections = React52.useMemo(
17311
+ () => historySectionsConversationId === conversationId ? historySections : {},
17312
+ [conversationId, historySections, historySectionsConversationId]
17313
+ );
17314
+ const loadSection = React52.useCallback(
17315
+ async (section) => {
17316
+ if (!enabled || !conversationId || loadingSections[section]) {
17317
+ return;
17318
+ }
17319
+ const current = activeHistorySections[section]?.length ?? 0;
17320
+ const controller = new AbortController();
17321
+ sectionControllersRef.current.get(section)?.abort();
17322
+ sectionControllersRef.current.set(section, controller);
17323
+ setLoadingSections((state) => ({ ...state, [section]: true }));
17324
+ try {
17325
+ const page = await client.conversations.listTaskSummaryItems(
17326
+ conversationId,
17327
+ section,
17328
+ { offset: current, limit: 50, signal: controller.signal }
17329
+ );
17330
+ if (conversationIdRef.current !== conversationId) return;
17331
+ setHistorySections(
17332
+ (state) => ({
17333
+ ...state,
17334
+ [section]: [...state[section] ?? [], ...page.items]
17335
+ })
17336
+ );
17337
+ } catch (nextError) {
17338
+ if (!controller.signal.aborted) {
17339
+ setError(nextError);
17340
+ }
17341
+ } finally {
17342
+ if (sectionControllersRef.current.get(section) === controller) {
17343
+ sectionControllersRef.current.delete(section);
17344
+ }
17345
+ if (conversationIdRef.current === conversationId) {
17346
+ setLoadingSections((state) => ({ ...state, [section]: false }));
17347
+ }
17348
+ }
17349
+ },
17350
+ [
17351
+ activeHistorySections,
17352
+ client,
17353
+ conversationId,
17354
+ enabled,
17355
+ loadingSections
17356
+ ]
17357
+ );
17358
+ return {
17359
+ summary: mergeTaskSummary(snapshot, live, activeHistorySections),
17360
+ historyError: error,
17361
+ retryHistory: () => setRetryVersion((version) => version + 1),
17362
+ loadSection,
17363
+ loadingSections,
17364
+ loadedSectionCounts: {
17365
+ outputs: activeHistorySections.outputs?.length ?? 0,
17366
+ sources: activeHistorySections.sources?.length ?? 0,
17367
+ agents: activeHistorySections.agents?.length ?? 0,
17368
+ pending: activeHistorySections.pending?.length ?? 0
17369
+ }
17370
+ };
16544
17371
  }
16545
- function formatGoalElapsed(seconds) {
16546
- if (seconds < 60) {
16547
- return `${seconds}s`;
17372
+
17373
+ // src/components/task-summary/TaskSummary.tsx
17374
+ import * as React53 from "react";
17375
+ import {
17376
+ Bot as Bot4,
17377
+ BookOpen as BookOpen3,
17378
+ CheckCircle2 as CheckCircle25,
17379
+ CircleEllipsis,
17380
+ ExternalLink,
17381
+ FileOutput,
17382
+ ListChecks as ListChecks3,
17383
+ Loader2 as Loader29,
17384
+ PlayCircle,
17385
+ Plus as Plus2,
17386
+ RotateCcw,
17387
+ Target as Target2
17388
+ } from "lucide-react";
17389
+ import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
17390
+ var PREVIEW_SIZE = 3;
17391
+ function TaskSummaryTrigger({
17392
+ displayMode = "popover",
17393
+ open: controlledOpen,
17394
+ onOpenChange,
17395
+ ...props
17396
+ }) {
17397
+ const { t } = useChatkitTranslation();
17398
+ const [uncontrolledOpen, setUncontrolledOpen] = React53.useState(false);
17399
+ const open = controlledOpen ?? uncontrolledOpen;
17400
+ const setOpen = React53.useCallback(
17401
+ (nextOpen) => {
17402
+ if (controlledOpen === void 0) {
17403
+ setUncontrolledOpen(nextOpen);
17404
+ }
17405
+ onOpenChange?.(nextOpen);
17406
+ },
17407
+ [controlledOpen, onOpenChange]
17408
+ );
17409
+ const triggerButton = /* @__PURE__ */ jsx57(
17410
+ "button",
17411
+ {
17412
+ type: "button",
17413
+ 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",
17414
+ "aria-label": t("taskSummary.open"),
17415
+ "aria-expanded": open,
17416
+ onClick: displayMode === "docked" ? () => setOpen(!open) : void 0,
17417
+ children: /* @__PURE__ */ jsx57(ListChecks3, { size: 16 })
17418
+ }
17419
+ );
17420
+ if (displayMode === "docked") {
17421
+ return /* @__PURE__ */ jsxs39(Tooltip, { children: [
17422
+ /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: triggerButton }),
17423
+ /* @__PURE__ */ jsx57(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17424
+ ] });
17425
+ }
17426
+ return /* @__PURE__ */ jsxs39(Popover, { open, onOpenChange: setOpen, children: [
17427
+ /* @__PURE__ */ jsxs39(Tooltip, { children: [
17428
+ /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57(PopoverTrigger, { asChild: true, children: triggerButton }) }),
17429
+ /* @__PURE__ */ jsx57(TooltipContent, { side: "bottom", children: t("taskSummary.open") })
17430
+ ] }),
17431
+ /* @__PURE__ */ jsx57(
17432
+ PopoverContent,
17433
+ {
17434
+ align: "end",
17435
+ sideOffset: 8,
17436
+ 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",
17437
+ "aria-label": t("taskSummary.title"),
17438
+ children: /* @__PURE__ */ jsx57(TaskSummaryContent, { ...props })
17439
+ }
17440
+ )
17441
+ ] });
17442
+ }
17443
+ function TaskSummaryPanel({
17444
+ className,
17445
+ ...props
17446
+ }) {
17447
+ const { t } = useChatkitTranslation();
17448
+ return /* @__PURE__ */ jsx57(
17449
+ "aside",
17450
+ {
17451
+ "data-slot": "task-summary-panel",
17452
+ "aria-label": t("taskSummary.title"),
17453
+ className: cn(
17454
+ "h-fit max-h-full overflow-y-auto rounded-2xl border border-border/70 bg-popover text-popover-foreground shadow-lg",
17455
+ className
17456
+ ),
17457
+ children: /* @__PURE__ */ jsx57(TaskSummaryContent, { ...props })
17458
+ }
17459
+ );
17460
+ }
17461
+ function TaskSummaryContent({
17462
+ summary,
17463
+ historyError,
17464
+ loadingSections = {},
17465
+ loadedSectionCounts = { outputs: 0, sources: 0, agents: 0, pending: 0 },
17466
+ onRetryHistory,
17467
+ onLoadSection,
17468
+ onNavigateMessage,
17469
+ onFocusComposer,
17470
+ onOpenResource
17471
+ }) {
17472
+ const { t } = useChatkitTranslation();
17473
+ const [expanded, setExpanded] = React53.useState({});
17474
+ const hasTask = Boolean(
17475
+ summary.goal || summary.plan || summary.todos?.items.length
17476
+ );
17477
+ const toggleSection = (section) => {
17478
+ if (expanded[section]) {
17479
+ setExpanded((state) => ({ ...state, [section]: false }));
17480
+ return;
17481
+ }
17482
+ setExpanded((state) => ({ ...state, [section]: true }));
17483
+ if (loadedSectionCounts[section] === 0) {
17484
+ void onLoadSection(section);
17485
+ }
17486
+ };
17487
+ const sectionItems = (section, items) => expanded[section] ? items : items.slice(0, PREVIEW_SIZE);
17488
+ const openSummaryItem = (resource, messageId, title) => {
17489
+ if (resource?.type === "message") {
17490
+ onNavigateMessage(resource.messageId);
17491
+ return;
17492
+ }
17493
+ if (resource) {
17494
+ onOpenResource(resource, messageId, title);
17495
+ return;
17496
+ }
17497
+ if (messageId) {
17498
+ onNavigateMessage(messageId);
17499
+ }
17500
+ };
17501
+ const sectionAction = (section, total2) => {
17502
+ if (total2 <= PREVIEW_SIZE && !expanded[section]) return null;
17503
+ const loading = loadingSections[section];
17504
+ const canLoadMore = Boolean(expanded[section]) && loadedSectionCounts[section] < total2;
17505
+ return /* @__PURE__ */ jsxs39(
17506
+ "button",
17507
+ {
17508
+ type: "button",
17509
+ 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",
17510
+ disabled: loading,
17511
+ onClick: () => canLoadMore ? void onLoadSection(section) : toggleSection(section),
17512
+ children: [
17513
+ loading && /* @__PURE__ */ jsx57(Loader29, { className: "size-3 animate-spin" }),
17514
+ !loading && /* @__PURE__ */ jsx57(ListChecks3, { className: "size-3.5" }),
17515
+ canLoadMore ? t("taskSummary.loadMore") : expanded[section] ? t("taskSummary.collapse") : t("taskSummary.viewAll", { count: total2 })
17516
+ ]
17517
+ }
17518
+ );
17519
+ };
17520
+ return /* @__PURE__ */ jsxs39("div", { className: "divide-y divide-border/70", children: [
17521
+ Boolean(historyError) && /* @__PURE__ */ jsxs39("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: [
17522
+ /* @__PURE__ */ jsx57("span", { children: t("taskSummary.historyError") }),
17523
+ /* @__PURE__ */ jsxs39(
17524
+ "button",
17525
+ {
17526
+ type: "button",
17527
+ className: "inline-flex shrink-0 items-center gap-1 font-medium hover:underline",
17528
+ onClick: onRetryHistory,
17529
+ children: [
17530
+ /* @__PURE__ */ jsx57(RotateCcw, { className: "size-3" }),
17531
+ t("taskSummary.retry")
17532
+ ]
17533
+ }
17534
+ )
17535
+ ] }),
17536
+ /* @__PURE__ */ jsxs39(
17537
+ SummarySection,
17538
+ {
17539
+ title: t("taskSummary.sections.outputs"),
17540
+ actionLabel: t("taskSummary.addOutput"),
17541
+ onAction: onFocusComposer,
17542
+ children: [
17543
+ summary.outputs.length === 0 ? /* @__PURE__ */ jsx57(SummaryPrompt, { onClick: onFocusComposer, children: t("taskSummary.createOutput") }) : sectionItems("outputs", summary.outputs).map((item) => /* @__PURE__ */ jsx57(
17544
+ SummaryButton,
17545
+ {
17546
+ title: item.title,
17547
+ description: item.description ?? item.status,
17548
+ leading: /* @__PURE__ */ jsx57(FileOutput, { className: "size-4" }),
17549
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ jsx57(ExternalLink, { className: "size-3.5" }) : void 0,
17550
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17551
+ },
17552
+ item.id
17553
+ )),
17554
+ sectionAction("outputs", summary.totals.outputs)
17555
+ ]
17556
+ }
17557
+ ),
17558
+ /* @__PURE__ */ jsxs39(
17559
+ SummarySection,
17560
+ {
17561
+ title: t("taskSummary.sections.sources"),
17562
+ actionLabel: t("taskSummary.addSource"),
17563
+ onAction: onFocusComposer,
17564
+ children: [
17565
+ sectionItems("sources", summary.sources).map((item) => /* @__PURE__ */ jsx57(
17566
+ SummaryButton,
17567
+ {
17568
+ title: item.title,
17569
+ description: item.description,
17570
+ leading: /* @__PURE__ */ jsx57(BookOpen3, { className: "size-4" }),
17571
+ trailing: item.resource && item.resource.type !== "message" ? /* @__PURE__ */ jsx57(ExternalLink, { className: "size-3.5" }) : void 0,
17572
+ onClick: () => openSummaryItem(item.resource, item.messageId, item.title)
17573
+ },
17574
+ item.id
17575
+ )),
17576
+ sectionAction("sources", summary.totals.sources)
17577
+ ]
17578
+ }
17579
+ ),
17580
+ hasTask && /* @__PURE__ */ jsxs39(SummarySection, { title: t("taskSummary.sections.task"), children: [
17581
+ summary.goal && /* @__PURE__ */ jsx57(
17582
+ SummaryButton,
17583
+ {
17584
+ title: summary.goal.objective,
17585
+ description: summary.goal.status,
17586
+ leading: /* @__PURE__ */ jsx57(Target2, { className: "size-4" }),
17587
+ onClick: onFocusComposer
17588
+ }
17589
+ ),
17590
+ summary.plan && /* @__PURE__ */ jsx57(
17591
+ SummaryButton,
17592
+ {
17593
+ title: summary.plan.title,
17594
+ description: summary.plan.excerpt,
17595
+ leading: /* @__PURE__ */ jsx57(ListChecks3, { className: "size-4" }),
17596
+ onClick: () => summary.plan?.messageId ? onNavigateMessage(summary.plan.messageId) : onFocusComposer()
17597
+ }
17598
+ ),
17599
+ (summary.todos?.items ?? []).slice(0, PREVIEW_SIZE).map((todo) => /* @__PURE__ */ jsx57(
17600
+ SummaryButton,
17601
+ {
17602
+ title: todo.content,
17603
+ description: t(`taskSummary.status.${todo.status}`),
17604
+ leading: todo.status === "completed" ? /* @__PURE__ */ jsx57(CheckCircle25, { className: "size-4 text-muted-foreground" }) : /* @__PURE__ */ jsx57(CircleEllipsis, { className: "size-4 text-muted-foreground" }),
17605
+ onClick: () => summary.todos?.messageId ? onNavigateMessage(summary.todos.messageId) : onFocusComposer()
17606
+ },
17607
+ todo.id
17608
+ ))
17609
+ ] }),
17610
+ summary.running.length > 0 && /* @__PURE__ */ jsx57(SummarySection, { title: t("taskSummary.sections.running"), children: summary.running.slice(0, PREVIEW_SIZE).map((item) => /* @__PURE__ */ jsx57(
17611
+ SummaryButton,
17612
+ {
17613
+ title: item.title,
17614
+ description: item.description ?? item.status,
17615
+ leading: /* @__PURE__ */ jsx57(PlayCircle, { className: "size-4" }),
17616
+ trailing: item.resource ? /* @__PURE__ */ jsx57(ExternalLink, { className: "size-3.5" }) : void 0,
17617
+ onClick: () => item.resource && onOpenResource(item.resource, void 0, item.title)
17618
+ },
17619
+ item.id
17620
+ )) }),
17621
+ summary.agents.length > 0 && /* @__PURE__ */ jsxs39(SummarySection, { title: t("taskSummary.sections.agents"), children: [
17622
+ sectionItems("agents", summary.agents).map((item) => /* @__PURE__ */ jsx57(
17623
+ SummaryButton,
17624
+ {
17625
+ title: item.title,
17626
+ description: [item.status, formatElapsed(item.elapsedTime)].filter(Boolean).join(" \xB7 "),
17627
+ leading: /* @__PURE__ */ jsx57(Bot4, { className: "size-4" }),
17628
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17629
+ },
17630
+ item.id
17631
+ )),
17632
+ sectionAction("agents", summary.totals.agents)
17633
+ ] }),
17634
+ summary.pending.length > 0 && /* @__PURE__ */ jsxs39(SummarySection, { title: t("taskSummary.sections.pending"), children: [
17635
+ sectionItems("pending", summary.pending).map((item) => /* @__PURE__ */ jsx57(
17636
+ SummaryButton,
17637
+ {
17638
+ title: item.title,
17639
+ description: item.description,
17640
+ leading: /* @__PURE__ */ jsx57(CircleEllipsis, { className: "size-4" }),
17641
+ onClick: () => item.messageId ? onNavigateMessage(item.messageId) : onFocusComposer()
17642
+ },
17643
+ item.id
17644
+ )),
17645
+ sectionAction("pending", summary.totals.pending)
17646
+ ] })
17647
+ ] });
17648
+ }
17649
+ function SummarySection({
17650
+ title,
17651
+ actionLabel,
17652
+ onAction,
17653
+ children
17654
+ }) {
17655
+ return /* @__PURE__ */ jsxs39("section", { "aria-label": title, className: "px-4 py-3", children: [
17656
+ /* @__PURE__ */ jsxs39("div", { className: "flex min-h-7 items-center justify-between gap-3", children: [
17657
+ /* @__PURE__ */ jsx57("h3", { className: "text-sm font-medium text-muted-foreground", children: title }),
17658
+ onAction && actionLabel && /* @__PURE__ */ jsx57(
17659
+ Button,
17660
+ {
17661
+ type: "button",
17662
+ variant: "ghost",
17663
+ size: "icon-xs",
17664
+ className: "size-7 rounded-lg bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground",
17665
+ "aria-label": actionLabel,
17666
+ onClick: onAction,
17667
+ children: /* @__PURE__ */ jsx57(Plus2, { className: "size-4" })
17668
+ }
17669
+ )
17670
+ ] }),
17671
+ /* @__PURE__ */ jsx57("div", { className: "mt-1 space-y-0.5", children })
17672
+ ] });
17673
+ }
17674
+ function SummaryPrompt({
17675
+ children,
17676
+ onClick
17677
+ }) {
17678
+ return /* @__PURE__ */ jsx57(
17679
+ "button",
17680
+ {
17681
+ type: "button",
17682
+ 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",
17683
+ onClick,
17684
+ children
17685
+ }
17686
+ );
17687
+ }
17688
+ function SummaryButton({
17689
+ title,
17690
+ description,
17691
+ leading,
17692
+ trailing,
17693
+ onClick
17694
+ }) {
17695
+ return /* @__PURE__ */ jsxs39(
17696
+ "button",
17697
+ {
17698
+ type: "button",
17699
+ disabled: !onClick,
17700
+ onClick,
17701
+ className: cn(
17702
+ "flex w-full min-w-0 items-start gap-2.5 rounded-lg px-2 py-1.5 text-left transition-colors",
17703
+ onClick && "hover:bg-muted/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
17704
+ !onClick && "cursor-default"
17705
+ ),
17706
+ children: [
17707
+ leading && /* @__PURE__ */ jsx57("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: leading }),
17708
+ /* @__PURE__ */ jsxs39("span", { className: "min-w-0 flex-1", children: [
17709
+ /* @__PURE__ */ jsx57("span", { className: "block truncate text-sm font-medium leading-5 text-foreground", children: title }),
17710
+ description && /* @__PURE__ */ jsx57("span", { className: "mt-0.5 block line-clamp-2 text-xs text-muted-foreground", children: description })
17711
+ ] }),
17712
+ trailing && /* @__PURE__ */ jsx57("span", { className: "mt-0.5 text-muted-foreground", children: trailing })
17713
+ ]
17714
+ }
17715
+ );
17716
+ }
17717
+ function formatElapsed(value) {
17718
+ if (typeof value !== "number" || !Number.isFinite(value)) return "";
17719
+ if (value < 1e3) return `${Math.round(value)}ms`;
17720
+ return `${(value / 1e3).toFixed(1)}s`;
17721
+ }
17722
+
17723
+ // src/components/chat.tsx
17724
+ import { Fragment as Fragment9, jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
17725
+ var defaultApiUrl2 = import.meta.env.VITE_XPERTAI_API_URL;
17726
+ var COMPOSER_INPUT_MAX_HEIGHT = 128;
17727
+ var LONG_TEXT_REFERENCE_THRESHOLD = 5e3;
17728
+ var GOAL_RUN_INPUT = "Continue working toward the active goal.";
17729
+ var TASK_SUMMARY_PANEL_WIDTH_REM = 20;
17730
+ var TASK_SUMMARY_PANEL_EDGE_INSET_REM = 1.25;
17731
+ var TASK_SUMMARY_PANEL_SAFE_GAP_REM = 0.75;
17732
+ function isGoalAdapter(value) {
17733
+ return Boolean(value) && typeof value === "object" && typeof value.getGoal === "function" && typeof value.setGoal === "function" && typeof value.updateGoal === "function" && typeof value.clearGoal === "function";
17734
+ }
17735
+ function formatGoalElapsed(seconds) {
17736
+ if (seconds < 60) {
17737
+ return `${seconds}s`;
16548
17738
  }
16549
17739
  const minutes = Math.floor(seconds / 60);
16550
17740
  const remainingSeconds = seconds % 60;
@@ -16638,7 +17828,7 @@ function ReferenceChip({
16638
17828
  const metaLine = getReferenceMetaLine(reference);
16639
17829
  const isComposer = variant === "composer";
16640
17830
  const Icon = reference.type === "quote" ? Quote : reference.type === "image" ? ImageIcon : FileText5;
16641
- return /* @__PURE__ */ jsxs39(
17831
+ return /* @__PURE__ */ jsxs40(
16642
17832
  "div",
16643
17833
  {
16644
17834
  className: cn(
@@ -16647,7 +17837,7 @@ function ReferenceChip({
16647
17837
  ),
16648
17838
  title: getReferenceTitle(reference),
16649
17839
  children: [
16650
- /* @__PURE__ */ jsx57(
17840
+ /* @__PURE__ */ jsx58(
16651
17841
  Icon,
16652
17842
  {
16653
17843
  size: isComposer ? 14 : 12,
@@ -16657,8 +17847,8 @@ function ReferenceChip({
16657
17847
  )
16658
17848
  }
16659
17849
  ),
16660
- /* @__PURE__ */ jsxs39("div", { className: "min-w-0 flex-1", children: [
16661
- /* @__PURE__ */ jsx57(
17850
+ /* @__PURE__ */ jsxs40("div", { className: "min-w-0 flex-1", children: [
17851
+ /* @__PURE__ */ jsx58(
16662
17852
  "div",
16663
17853
  {
16664
17854
  className: cn(
@@ -16668,7 +17858,7 @@ function ReferenceChip({
16668
17858
  children: getReferenceLabel(reference)
16669
17859
  }
16670
17860
  ),
16671
- metaLine && /* @__PURE__ */ jsx57(
17861
+ metaLine && /* @__PURE__ */ jsx58(
16672
17862
  "div",
16673
17863
  {
16674
17864
  className: cn(
@@ -16679,7 +17869,7 @@ function ReferenceChip({
16679
17869
  }
16680
17870
  )
16681
17871
  ] }),
16682
- onRemove && removeLabel && /* @__PURE__ */ jsx57(
17872
+ onRemove && removeLabel && /* @__PURE__ */ jsx58(
16683
17873
  "button",
16684
17874
  {
16685
17875
  type: "button",
@@ -16690,7 +17880,7 @@ function ReferenceChip({
16690
17880
  ),
16691
17881
  title: removeLabel,
16692
17882
  "aria-label": removeLabel,
16693
- children: /* @__PURE__ */ jsx57(X7, { size: 12 })
17883
+ children: /* @__PURE__ */ jsx58(X7, { size: 12 })
16694
17884
  }
16695
17885
  )
16696
17886
  ]
@@ -16721,7 +17911,7 @@ function Chat({
16721
17911
  clientSecret: effectiveClientSecret
16722
17912
  });
16723
17913
  const missingConfig = Boolean(missingConfigKind);
16724
- const missingConfigShortMessage = React52.useMemo(() => {
17914
+ const missingConfigShortMessage = React54.useMemo(() => {
16725
17915
  switch (missingConfigKind) {
16726
17916
  case "apiUrl":
16727
17917
  return t("chat.missingApiUrlShort");
@@ -16733,7 +17923,7 @@ function Chat({
16733
17923
  return t("chat.missingConfigShort");
16734
17924
  }
16735
17925
  }, [missingConfigKind, t]);
16736
- const missingConfigDetailMessage = React52.useMemo(() => {
17926
+ const missingConfigDetailMessage = React54.useMemo(() => {
16737
17927
  switch (missingConfigKind) {
16738
17928
  case "apiUrl":
16739
17929
  return t("chat.missingApiUrlDetail");
@@ -16745,26 +17935,26 @@ function Chat({
16745
17935
  return t("chat.missingConfigDetail");
16746
17936
  }
16747
17937
  }, [missingConfigKind, t]);
16748
- const [isHistoryLoading, setIsHistoryLoading] = React52.useState(false);
16749
- const [historyError, setHistoryError] = React52.useState(null);
16750
- const [assistantName, setAssistantName] = React52.useState(null);
16751
- const [assistantAvatar, setAssistantAvatar] = React52.useState(null);
16752
- const [threadGoal, setThreadGoal] = React52.useState(null);
16753
- const [goalError, setGoalError] = React52.useState(null);
16754
- const [isGoalLoading, setIsGoalLoading] = React52.useState(false);
16755
- const [isGoalPanelOpen, setIsGoalPanelOpen] = React52.useState(false);
16756
- const [isGoalObjectiveExpanded, setIsGoalObjectiveExpanded] = React52.useState(false);
16757
- const [goalElapsedStartedAt, setGoalElapsedStartedAt] = React52.useState(null);
17938
+ const [isHistoryLoading, setIsHistoryLoading] = React54.useState(false);
17939
+ const [historyError, setHistoryError] = React54.useState(null);
17940
+ const [assistantName, setAssistantName] = React54.useState(null);
17941
+ const [assistantAvatar, setAssistantAvatar] = React54.useState(null);
17942
+ const [threadGoal, setThreadGoal] = React54.useState(null);
17943
+ const [goalError, setGoalError] = React54.useState(null);
17944
+ const [isGoalLoading, setIsGoalLoading] = React54.useState(false);
17945
+ const [isGoalPanelOpen, setIsGoalPanelOpen] = React54.useState(false);
17946
+ const [isGoalObjectiveExpanded, setIsGoalObjectiveExpanded] = React54.useState(false);
17947
+ const [goalElapsedStartedAt, setGoalElapsedStartedAt] = React54.useState(null);
16758
17948
  const LOADING_DOTS_MIN_DURATION = 800;
16759
17949
  const STREAMING_STATUS_REFRESH_MS = 250;
16760
- const [showLoadingDots, setShowLoadingDots] = React52.useState(false);
16761
- const [streamingNow, setStreamingNow] = React52.useState(() => Date.now());
16762
- const loadingStartTimeRef = React52.useRef(null);
16763
- const lastStreamOutputAtRef = React52.useRef(null);
16764
- React52.useEffect(() => {
17950
+ const [showLoadingDots, setShowLoadingDots] = React54.useState(false);
17951
+ const [streamingNow, setStreamingNow] = React54.useState(() => Date.now());
17952
+ const loadingStartTimeRef = React54.useRef(null);
17953
+ const lastStreamOutputAtRef = React54.useRef(null);
17954
+ React54.useEffect(() => {
16765
17955
  setStream(stream);
16766
17956
  }, [setStream, stream]);
16767
- React52.useEffect(() => {
17957
+ React54.useEffect(() => {
16768
17958
  if (stream.isLoading) {
16769
17959
  if (!loadingStartTimeRef.current) {
16770
17960
  loadingStartTimeRef.current = Date.now();
@@ -16787,7 +17977,7 @@ function Chat({
16787
17977
  }
16788
17978
  }
16789
17979
  }, [stream.isLoading]);
16790
- React52.useEffect(() => {
17980
+ React54.useEffect(() => {
16791
17981
  if (!stream.isLoading) {
16792
17982
  lastStreamOutputAtRef.current = null;
16793
17983
  setStreamingNow(Date.now());
@@ -16797,7 +17987,7 @@ function Chat({
16797
17987
  lastStreamOutputAtRef.current = now;
16798
17988
  setStreamingNow(now);
16799
17989
  }, [stream.messages, stream.isLoading]);
16800
- React52.useEffect(() => {
17990
+ React54.useEffect(() => {
16801
17991
  if (!stream.isLoading) {
16802
17992
  return;
16803
17993
  }
@@ -16806,7 +17996,7 @@ function Chat({
16806
17996
  }, STREAMING_STATUS_REFRESH_MS);
16807
17997
  return () => window.clearInterval(timer);
16808
17998
  }, [stream.isLoading]);
16809
- React52.useEffect(() => {
17999
+ React54.useEffect(() => {
16810
18000
  if (threadGoal?.status === "active" && stream.isLoading) {
16811
18001
  setGoalElapsedStartedAt(Date.now());
16812
18002
  return;
@@ -16818,54 +18008,55 @@ function Chat({
16818
18008
  threadGoal?.id,
16819
18009
  threadGoal?.status
16820
18010
  ]);
16821
- React52.useEffect(() => {
18011
+ React54.useEffect(() => {
16822
18012
  setIsGoalObjectiveExpanded(false);
16823
18013
  }, [threadGoal?.id]);
16824
- const [composerParts, setComposerParts] = React52.useState([]);
16825
- const [renderedComposerParts, setRenderedComposerParts] = React52.useState([]);
16826
- const [composerDomVersion, setComposerDomVersion] = React52.useState(0);
16827
- const [selectedTool, setSelectedTool] = React52.useState(
18014
+ const [composerParts, setComposerParts] = React54.useState([]);
18015
+ const [renderedComposerParts, setRenderedComposerParts] = React54.useState([]);
18016
+ const [composerDomVersion, setComposerDomVersion] = React54.useState(0);
18017
+ const [selectedTool, setSelectedTool] = React54.useState(
16828
18018
  null
16829
18019
  );
16830
- const [planModeEnabled, setPlanModeEnabled] = React52.useState(false);
16831
- const [petSettingsOpen, setPetSettingsOpen] = React52.useState(false);
16832
- const [petLocalSettings, setPetLocalSettings] = React52.useState(() => readPetLocalSettings());
16833
- const [attachmentState, setAttachmentState] = React52.useState({
18020
+ const [planModeEnabled, setPlanModeEnabled] = React54.useState(false);
18021
+ const [petSettingsOpen, setPetSettingsOpen] = React54.useState(false);
18022
+ const [petLocalSettings, setPetLocalSettings] = React54.useState(() => readPetLocalSettings());
18023
+ const [attachmentState, setAttachmentState] = React54.useState({
16834
18024
  uploadedFiles: [],
16835
18025
  hasUploadingFiles: false,
16836
18026
  hasParsingFiles: false
16837
18027
  });
16838
- const [references, setReferences] = React52.useState([]);
16839
- const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React52.useState(false);
16840
- const [quoteSelection, setQuoteSelection] = React52.useState(null);
16841
- const [isAtBottom, setIsAtBottom] = React52.useState(true);
16842
- const [hasUpdatesBelow, setHasUpdatesBelow] = React52.useState(false);
18028
+ const [references, setReferences] = React54.useState([]);
18029
+ const [isUploadingReferenceImages, setIsUploadingReferenceImages] = React54.useState(false);
18030
+ const [quoteSelection, setQuoteSelection] = React54.useState(null);
18031
+ const [isAtBottom, setIsAtBottom] = React54.useState(true);
18032
+ const [hasUpdatesBelow, setHasUpdatesBelow] = React54.useState(false);
16843
18033
  const {
16844
18034
  threads,
16845
18035
  deleteThread,
16846
18036
  refreshThreads,
16847
18037
  isLoading: isThreadsLoading
16848
18038
  } = useThreads();
16849
- const viewportRef = React52.useRef(null);
16850
- const messageNavigationAnchorsRef = React52.useRef(
18039
+ const viewportRef = React54.useRef(null);
18040
+ const chatColumnRef = React54.useRef(null);
18041
+ const messageNavigationAnchorsRef = React54.useRef(
16851
18042
  /* @__PURE__ */ new Map()
16852
18043
  );
16853
- const attachmentsRef = React52.useRef(null);
16854
- const composerInputRef = React52.useRef(null);
16855
- const slashPaletteRef = React52.useRef(null);
16856
- const slashPaletteOptionRefs = React52.useRef(
18044
+ const attachmentsRef = React54.useRef(null);
18045
+ const composerInputRef = React54.useRef(null);
18046
+ const slashPaletteRef = React54.useRef(null);
18047
+ const slashPaletteOptionRefs = React54.useRef(
16857
18048
  []
16858
18049
  );
16859
- const composerPartsRef = React52.useRef([]);
16860
- const pendingComposerCaretOffsetRef = React52.useRef(null);
16861
- const shouldAutoScrollRef = React52.useRef(true);
16862
- const forceFollowRef = React52.useRef(false);
16863
- const previousMessageCountRef = React52.useRef(0);
16864
- const previousScrollTopRef = React52.useRef(0);
16865
- const isPrependingHistoryMessagesRef = React52.useRef(false);
16866
- const autoScrollFrameRef = React52.useRef(null);
16867
- const isPointerDownRef = React52.useRef(false);
16868
- const lastTouchYRef = React52.useRef(null);
18050
+ const composerPartsRef = React54.useRef([]);
18051
+ const pendingComposerCaretOffsetRef = React54.useRef(null);
18052
+ const shouldAutoScrollRef = React54.useRef(true);
18053
+ const forceFollowRef = React54.useRef(false);
18054
+ const previousMessageCountRef = React54.useRef(0);
18055
+ const previousScrollTopRef = React54.useRef(0);
18056
+ const isPrependingHistoryMessagesRef = React54.useRef(false);
18057
+ const autoScrollFrameRef = React54.useRef(null);
18058
+ const isPointerDownRef = React54.useRef(false);
18059
+ const lastTouchYRef = React54.useRef(null);
16869
18060
  const {
16870
18061
  runtimeCapabilities,
16871
18062
  runtimeCapabilitiesReady,
@@ -16894,24 +18085,24 @@ function Chat({
16894
18085
  const resolvedPlaceholder = placeholder ?? t("chat.placeholder");
16895
18086
  const assistantTitle = assistantName || resolvedTitle;
16896
18087
  const petRequired = options?.displayMode === "pet";
16897
- const basePetSettings = React52.useMemo(
18088
+ const basePetSettings = React54.useMemo(
16898
18089
  () => derivePetLocalSettings(options?.pet),
16899
18090
  [options?.pet]
16900
18091
  );
16901
- const displayedPetSettings = React52.useMemo(
18092
+ const displayedPetSettings = React54.useMemo(
16902
18093
  () => ({
16903
18094
  ...petLocalSettings ?? basePetSettings,
16904
18095
  ...petRequired ? { enabled: true } : {}
16905
18096
  }),
16906
18097
  [basePetSettings, petLocalSettings, petRequired]
16907
18098
  );
16908
- const effectivePet = React52.useMemo(() => {
18099
+ const effectivePet = React54.useMemo(() => {
16909
18100
  if (petRequired || petLocalSettings) {
16910
18101
  return buildPetOptionsFromLocalSettings(displayedPetSettings);
16911
18102
  }
16912
18103
  return options?.pet ?? null;
16913
18104
  }, [displayedPetSettings, options?.pet, petLocalSettings, petRequired]);
16914
- const savePetLocalSettings = React52.useCallback(
18105
+ const savePetLocalSettings = React54.useCallback(
16915
18106
  (settings) => {
16916
18107
  const nextSettings = petRequired ? { ...settings, enabled: true } : settings;
16917
18108
  setPetLocalSettings(nextSettings);
@@ -16919,7 +18110,7 @@ function Chat({
16919
18110
  },
16920
18111
  [petRequired]
16921
18112
  );
16922
- const handlePetCommand = React52.useCallback(
18113
+ const handlePetCommand = React54.useCallback(
16923
18114
  (mode) => {
16924
18115
  if (mode === "settings") {
16925
18116
  setPetSettingsOpen(true);
@@ -16941,11 +18132,11 @@ function Chat({
16941
18132
  [displayedPetSettings, effectivePet, petRequired, savePetLocalSettings]
16942
18133
  );
16943
18134
  const inputPlaceholder = selectedTool?.placeholderOverride ?? composer?.placeholder ?? resolvedPlaceholder;
16944
- const messages = React52.useMemo(
18135
+ const messages = React54.useMemo(
16945
18136
  () => stream.messages ?? [],
16946
18137
  [stream.messages]
16947
18138
  );
16948
- const messageNavigationLabels = React52.useMemo(
18139
+ const messageNavigationLabels = React54.useMemo(
16949
18140
  () => ({
16950
18141
  user: t("chat.youLabel"),
16951
18142
  assistant: assistantTitle,
@@ -16964,7 +18155,7 @@ function Chat({
16964
18155
  }),
16965
18156
  [assistantTitle, t]
16966
18157
  );
16967
- const messageNavigationItems = React52.useMemo(
18158
+ const messageNavigationItems = React54.useMemo(
16968
18159
  () => messageNavigationEnabled ? buildMessageNavigationItems(
16969
18160
  messages,
16970
18161
  {
@@ -16987,7 +18178,7 @@ function Chat({
16987
18178
  historyMessagePagination?.isLoadingMore
16988
18179
  );
16989
18180
  const canLoadMoreMessages = Boolean(historyMessagePagination?.hasMore);
16990
- const draft = React52.useMemo(
18181
+ const draft = React54.useMemo(
16991
18182
  () => getComposerPlainText(composerParts),
16992
18183
  [composerParts]
16993
18184
  );
@@ -17001,7 +18192,7 @@ function Chat({
17001
18192
  isEmpty: isComposerInputEmpty,
17002
18193
  isStacked: isComposerStacked
17003
18194
  });
17004
- const pendingFollowUps = React52.useMemo(
18195
+ const pendingFollowUps = React54.useMemo(
17005
18196
  () => sortVisiblePendingFollowUps(stream.pendingFollowUps ?? []),
17006
18197
  [stream.pendingFollowUps]
17007
18198
  );
@@ -17010,7 +18201,7 @@ function Chat({
17010
18201
  const hasPendingHITLRequest = Boolean(stream.pendingHITLRequest);
17011
18202
  const hasPendingInteractiveRequest = hasPendingRequestUserInput || hasPendingHITLRequest;
17012
18203
  const hasPendingTodos = Boolean(stream.todos?.items.length);
17013
- const goalAdapter = React52.useMemo(() => {
18204
+ const goalAdapter = React54.useMemo(() => {
17014
18205
  if (isGoalAdapter(options?.goal)) {
17015
18206
  return options.goal;
17016
18207
  }
@@ -17023,10 +18214,10 @@ function Chat({
17023
18214
  "goal"
17024
18215
  );
17025
18216
  const showGoalStatus = goalCommandAvailable && !hasCompletedGoal && (Boolean(goalError) || threadGoal?.status === "active" && stream.isLoading);
17026
- const clearQuoteSelection = React52.useCallback(() => {
18217
+ const clearQuoteSelection = React54.useCallback(() => {
17027
18218
  setQuoteSelection(null);
17028
18219
  }, []);
17029
- const commitComposerParts = React52.useCallback(
18220
+ const commitComposerParts = React54.useCallback(
17030
18221
  (nextParts, options2) => {
17031
18222
  const normalized = normalizeComposerParts(nextParts);
17032
18223
  const previous = composerPartsRef.current;
@@ -17056,7 +18247,7 @@ function Chat({
17056
18247
  },
17057
18248
  [setRunRuntimeCapabilities]
17058
18249
  );
17059
- const setComposerText = React52.useCallback(
18250
+ const setComposerText = React54.useCallback(
17060
18251
  (text, caretOffset = text.length) => {
17061
18252
  commitComposerParts(createComposerTextParts(text), {
17062
18253
  caretOffset,
@@ -17066,7 +18257,7 @@ function Chat({
17066
18257
  },
17067
18258
  [commitComposerParts]
17068
18259
  );
17069
- const focusComposerAt = React52.useCallback((position) => {
18260
+ const focusComposerAt = React54.useCallback((position) => {
17070
18261
  const nextPosition = position ?? getComposerEditingLength(composerPartsRef.current);
17071
18262
  pendingComposerCaretOffsetRef.current = nextPosition;
17072
18263
  requestAnimationFrame(() => {
@@ -17095,7 +18286,7 @@ function Chat({
17095
18286
  focusComposerAt
17096
18287
  });
17097
18288
  const parentMessenger = useParentMessenger({
17098
- onSetComposerValue: React52.useCallback(
18289
+ onSetComposerValue: React54.useCallback(
17099
18290
  (payload) => {
17100
18291
  if (!payload) {
17101
18292
  return;
@@ -17123,16 +18314,16 @@ function Chat({
17123
18314
  },
17124
18315
  [applyComposerValueRuntimeCapabilities, composer?.tools, setComposerText]
17125
18316
  ),
17126
- onSetRuntimeCapabilities: React52.useCallback(
18317
+ onSetRuntimeCapabilities: React54.useCallback(
17127
18318
  (selection) => {
17128
18319
  applyExternalRuntimeCapabilities(selection);
17129
18320
  },
17130
18321
  [applyExternalRuntimeCapabilities]
17131
18322
  ),
17132
- onFocusComposer: React52.useCallback(() => {
18323
+ onFocusComposer: React54.useCallback(() => {
17133
18324
  composerInputRef.current?.focus();
17134
18325
  }, []),
17135
- onSetPetEnabled: React52.useCallback(
18326
+ onSetPetEnabled: React54.useCallback(
17136
18327
  (enabled) => {
17137
18328
  if (petRequired) {
17138
18329
  return;
@@ -17146,10 +18337,10 @@ function Chat({
17146
18337
  )
17147
18338
  });
17148
18339
  const canMinimizeToPet = parentMessenger?.isParentAvailable === true && isPetEnabled(effectivePet);
17149
- const handleMinimizeToPet = React52.useCallback(() => {
18340
+ const handleMinimizeToPet = React54.useCallback(() => {
17150
18341
  parentMessenger?.sendEvent("chat_minimize_change", { minimized: true });
17151
18342
  }, [parentMessenger]);
17152
- const syncQuoteSelection = React52.useCallback(() => {
18343
+ const syncQuoteSelection = React54.useCallback(() => {
17153
18344
  if (typeof window === "undefined") {
17154
18345
  clearQuoteSelection();
17155
18346
  return;
@@ -17194,23 +18385,23 @@ function Chat({
17194
18385
  left
17195
18386
  });
17196
18387
  }, [clearQuoteSelection]);
17197
- const cancelPendingAutoScroll = React52.useCallback(() => {
18388
+ const cancelPendingAutoScroll = React54.useCallback(() => {
17198
18389
  if (autoScrollFrameRef.current !== null) {
17199
18390
  cancelAnimationFrame(autoScrollFrameRef.current);
17200
18391
  autoScrollFrameRef.current = null;
17201
18392
  }
17202
18393
  }, []);
17203
- const disableAutoFollow = React52.useCallback(() => {
18394
+ const disableAutoFollow = React54.useCallback(() => {
17204
18395
  forceFollowRef.current = false;
17205
18396
  shouldAutoScrollRef.current = false;
17206
18397
  cancelPendingAutoScroll();
17207
18398
  }, [cancelPendingAutoScroll]);
17208
- const enableAutoFollow = React52.useCallback(() => {
18399
+ const enableAutoFollow = React54.useCallback(() => {
17209
18400
  forceFollowRef.current = true;
17210
18401
  shouldAutoScrollRef.current = true;
17211
18402
  setHasUpdatesBelow(false);
17212
18403
  }, []);
17213
- const scrollToBottom = React52.useCallback(
18404
+ const scrollToBottom = React54.useCallback(
17214
18405
  (smooth = false, force = false) => {
17215
18406
  if (force) {
17216
18407
  enableAutoFollow();
@@ -17237,7 +18428,7 @@ function Chat({
17237
18428
  },
17238
18429
  [cancelPendingAutoScroll, enableAutoFollow]
17239
18430
  );
17240
- const setMessageNavigationAnchor = React52.useCallback(
18431
+ const setMessageNavigationAnchor = React54.useCallback(
17241
18432
  (id, node) => {
17242
18433
  if (node) {
17243
18434
  messageNavigationAnchorsRef.current.set(id, node);
@@ -17247,15 +18438,165 @@ function Chat({
17247
18438
  },
17248
18439
  []
17249
18440
  );
17250
- const getMessageNavigationAnchor = React52.useCallback(
18441
+ const getMessageNavigationAnchor = React54.useCallback(
17251
18442
  (item) => messageNavigationAnchorsRef.current.get(item.id) ?? null,
17252
18443
  []
17253
18444
  );
17254
- const handleMessageNavigationNavigate = React52.useCallback(() => {
18445
+ const handleMessageNavigationNavigate = React54.useCallback(() => {
17255
18446
  disableAutoFollow();
17256
18447
  clearQuoteSelection();
17257
18448
  }, [clearQuoteSelection, disableAutoFollow]);
17258
- React52.useEffect(() => {
18449
+ const taskSummaryEnabled = options?.taskSummary?.enabled === true;
18450
+ const taskSummaryConversationId = stream.conversationId ?? null;
18451
+ const [taskSummaryDocked, setTaskSummaryDocked] = React54.useState(false);
18452
+ const [taskSummaryOpen, setTaskSummaryOpen] = React54.useState(false);
18453
+ const manuallyClosedTaskSummaryConversationIdsRef = React54.useRef(
18454
+ /* @__PURE__ */ new Set()
18455
+ );
18456
+ const liveTaskSummaryPending = React54.useMemo(() => {
18457
+ const followUps = pendingFollowUps.map((item) => ({
18458
+ id: `follow-up:${item.id}`,
18459
+ kind: "follow_up",
18460
+ title: item.mode === "steer" ? t("taskSummary.pending.steer") : t("taskSummary.pending.followUp"),
18461
+ messageId: item.clientMessageId,
18462
+ createdAt: new Date(item.createdAt).toISOString()
18463
+ }));
18464
+ const userInput = stream.pendingRequestUserInput ? [
18465
+ {
18466
+ id: `user-input:${stream.pendingRequestUserInput.id}`,
18467
+ kind: "user_input",
18468
+ title: stream.pendingRequestUserInput.params.questions[0]?.header || t("taskSummary.pending.userInput"),
18469
+ createdAt: new Date(
18470
+ stream.pendingRequestUserInput.createdAt
18471
+ ).toISOString()
18472
+ }
18473
+ ] : [];
18474
+ const approvals = stream.pendingHITLRequest ? [
18475
+ {
18476
+ id: `approval:${stream.pendingHITLRequest.id}`,
18477
+ kind: "approval",
18478
+ title: t("taskSummary.pending.approval"),
18479
+ createdAt: new Date(
18480
+ stream.pendingHITLRequest.createdAt
18481
+ ).toISOString()
18482
+ }
18483
+ ] : [];
18484
+ return [...approvals, ...userInput, ...followUps];
18485
+ }, [
18486
+ pendingFollowUps,
18487
+ stream.pendingHITLRequest,
18488
+ stream.pendingRequestUserInput,
18489
+ t
18490
+ ]);
18491
+ const liveTaskSummaryRunning = React54.useMemo(
18492
+ () => stream.runtimeActivities.sandboxServices.services.filter(
18493
+ (service) => service.status === "starting" || service.status === "running" || service.status === "stopping"
18494
+ ).map((service) => ({
18495
+ id: service.id ?? `${service.provider}:${service.name}:${service.actualPort ?? service.requestedPort ?? ""}`,
18496
+ title: service.name,
18497
+ status: service.status,
18498
+ description: service.actualPort || service.requestedPort ? `:${service.actualPort ?? service.requestedPort}` : void 0,
18499
+ resource: {
18500
+ type: "browser",
18501
+ serviceId: service.id,
18502
+ url: service.previewUrl ?? void 0
18503
+ },
18504
+ updatedAt: service.startedAt ?? void 0
18505
+ })),
18506
+ [stream.runtimeActivities.sandboxServices.services]
18507
+ );
18508
+ const taskSummaryAgentNames = React54.useMemo(() => {
18509
+ const names = /* @__PURE__ */ new Map();
18510
+ runtimeCapabilityOptions.forEach((option) => {
18511
+ if (option.type !== "subAgent") return;
18512
+ const name = option.capability.name?.trim();
18513
+ if (!name) return;
18514
+ names.set(option.id, name);
18515
+ const agentKey = option.capability.agentKey?.trim();
18516
+ if (agentKey) names.set(agentKey, name);
18517
+ });
18518
+ return names;
18519
+ }, [runtimeCapabilityOptions]);
18520
+ const liveTaskSummary = React54.useMemo(
18521
+ () => collectLiveTaskSummary({
18522
+ messages: messages.map(
18523
+ (message) => ({
18524
+ id: message.id,
18525
+ content: message.content,
18526
+ createdAt: message.createdAt,
18527
+ updatedAt: message.updatedAt,
18528
+ taskSummary: message.taskSummary,
18529
+ references: message.references,
18530
+ attachments: message.attachments,
18531
+ fileAssets: message.fileAssets,
18532
+ agentRuns: message.agentRuns,
18533
+ runtimeCapabilities: message.runtimeCapabilities
18534
+ })
18535
+ ),
18536
+ goal: threadGoal,
18537
+ todos: stream.todos,
18538
+ pending: liveTaskSummaryPending,
18539
+ running: liveTaskSummaryRunning,
18540
+ agentNames: taskSummaryAgentNames
18541
+ }),
18542
+ [
18543
+ liveTaskSummaryPending,
18544
+ liveTaskSummaryRunning,
18545
+ messages,
18546
+ stream.todos,
18547
+ taskSummaryAgentNames,
18548
+ threadGoal
18549
+ ]
18550
+ );
18551
+ const taskSummary = useTaskSummary({
18552
+ enabled: taskSummaryEnabled,
18553
+ conversationId: taskSummaryConversationId,
18554
+ client: stream.client,
18555
+ live: liveTaskSummary
18556
+ });
18557
+ const navigateToTaskSummaryMessage = React54.useCallback(
18558
+ async (messageId) => {
18559
+ try {
18560
+ let anchor = messageNavigationAnchorsRef.current.get(messageId);
18561
+ let pageCount = 0;
18562
+ while (!anchor && pageCount < 100) {
18563
+ const loaded = await stream.loadMoreConversationMessages();
18564
+ if (!loaded.length) break;
18565
+ pageCount += 1;
18566
+ await new Promise(
18567
+ (resolve) => requestAnimationFrame(() => resolve())
18568
+ );
18569
+ anchor = messageNavigationAnchorsRef.current.get(messageId);
18570
+ }
18571
+ if (!anchor) return;
18572
+ disableAutoFollow();
18573
+ clearQuoteSelection();
18574
+ anchor.scrollIntoView({ behavior: "smooth", block: "center" });
18575
+ } catch (error) {
18576
+ console.warn("Failed to locate task summary message", error);
18577
+ }
18578
+ },
18579
+ [clearQuoteSelection, disableAutoFollow, stream]
18580
+ );
18581
+ const openTaskSummaryResource = React54.useCallback(
18582
+ (resource, messageId, resourceTitle) => {
18583
+ const data = {
18584
+ resource,
18585
+ conversationId: taskSummaryConversationId ?? void 0,
18586
+ messageId,
18587
+ title: resourceTitle
18588
+ };
18589
+ parentMessenger.sendEvent("public_event", [
18590
+ "effect",
18591
+ {
18592
+ name: CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT,
18593
+ data
18594
+ }
18595
+ ]);
18596
+ },
18597
+ [parentMessenger, taskSummaryConversationId]
18598
+ );
18599
+ React54.useEffect(() => {
17259
18600
  const viewport = viewportRef.current;
17260
18601
  if (!viewport) return;
17261
18602
  previousScrollTopRef.current = viewport.scrollTop;
@@ -17336,14 +18677,14 @@ function Chat({
17336
18677
  window.removeEventListener("pointercancel", stopPointerTracking);
17337
18678
  };
17338
18679
  }, [cancelPendingAutoScroll, disableAutoFollow]);
17339
- React52.useEffect(() => {
18680
+ React54.useEffect(() => {
17340
18681
  shouldAutoScrollRef.current = true;
17341
18682
  forceFollowRef.current = false;
17342
18683
  previousScrollTopRef.current = 0;
17343
18684
  setIsAtBottom(true);
17344
18685
  setHasUpdatesBelow(false);
17345
18686
  }, [stream.threadId]);
17346
- React52.useEffect(() => {
18687
+ React54.useEffect(() => {
17347
18688
  const messageCountChanged = messages.length !== previousMessageCountRef.current;
17348
18689
  previousMessageCountRef.current = messages.length;
17349
18690
  if (isPrependingHistoryMessagesRef.current) {
@@ -17365,7 +18706,7 @@ function Chat({
17365
18706
  const isSubmissionBlocked = hasPendingInteractiveRequest || missingConfig || isHistoryLoading || hasUploadingFiles || isUploadingReferenceImages;
17366
18707
  const isSendDisabled = !trimmedDraft && !hasReferences || isSubmissionBlocked;
17367
18708
  const isPromptEditDisabled = hasPendingInteractiveRequest || missingConfig || isHistoryLoading;
17368
- const resizeComposerInput = React52.useCallback(() => {
18709
+ const resizeComposerInput = React54.useCallback(() => {
17369
18710
  const input = composerInputRef.current;
17370
18711
  if (!input) {
17371
18712
  return;
@@ -17373,7 +18714,7 @@ function Chat({
17373
18714
  input.style.maxHeight = `${COMPOSER_INPUT_MAX_HEIGHT}px`;
17374
18715
  input.style.overflowY = input.scrollHeight > COMPOSER_INPUT_MAX_HEIGHT ? "auto" : "hidden";
17375
18716
  }, []);
17376
- React52.useLayoutEffect(() => {
18717
+ React54.useLayoutEffect(() => {
17377
18718
  composerPartsRef.current = composerParts;
17378
18719
  resizeComposerInput();
17379
18720
  const caretOffset = pendingComposerCaretOffsetRef.current;
@@ -17385,13 +18726,13 @@ function Chat({
17385
18726
  }
17386
18727
  }
17387
18728
  }, [composerDomVersion, composerParts, resizeComposerInput]);
17388
- React52.useEffect(() => {
18729
+ React54.useEffect(() => {
17389
18730
  document.addEventListener("selectionchange", syncQuoteSelection);
17390
18731
  return () => {
17391
18732
  document.removeEventListener("selectionchange", syncQuoteSelection);
17392
18733
  };
17393
18734
  }, [syncQuoteSelection]);
17394
- React52.useEffect(() => {
18735
+ React54.useEffect(() => {
17395
18736
  const viewport = viewportRef.current;
17396
18737
  if (!viewport) {
17397
18738
  return;
@@ -17408,14 +18749,14 @@ function Chat({
17408
18749
  window.removeEventListener("resize", handleViewportScroll);
17409
18750
  };
17410
18751
  }, [clearQuoteSelection]);
17411
- React52.useEffect(() => {
18752
+ React54.useEffect(() => {
17412
18753
  clearQuoteSelection();
17413
18754
  }, [messages.length, stream.threadId, clearQuoteSelection]);
17414
- React52.useEffect(() => {
18755
+ React54.useEffect(() => {
17415
18756
  if (missingConfig) return;
17416
18757
  void refreshThreads();
17417
18758
  }, [missingConfig, refreshThreads]);
17418
- React52.useEffect(() => {
18759
+ React54.useEffect(() => {
17419
18760
  if (missingConfig || !stream.client || !stream.assistantId) {
17420
18761
  setAssistantName(null);
17421
18762
  setAssistantAvatar(null);
@@ -17438,10 +18779,10 @@ function Chat({
17438
18779
  cancelled = true;
17439
18780
  };
17440
18781
  }, [missingConfig, stream.client, stream.assistantId]);
17441
- React52.useEffect(() => {
18782
+ React54.useEffect(() => {
17442
18783
  setThreadGoal(stream.threadGoal);
17443
18784
  }, [stream.threadGoal]);
17444
- React52.useEffect(() => {
18785
+ React54.useEffect(() => {
17445
18786
  const threadId = stream.threadId?.trim();
17446
18787
  if (!threadId || !goalCommandAvailable) {
17447
18788
  setThreadGoal(null);
@@ -17482,7 +18823,7 @@ function Chat({
17482
18823
  return () => controller.abort();
17483
18824
  }, [goalAdapter, goalCommandAvailable, stream.threadId]);
17484
18825
  const uploadedFiles = attachmentState.uploadedFiles;
17485
- const syncComposerInputFromElement = React52.useCallback(
18826
+ const syncComposerInputFromElement = React54.useCallback(
17486
18827
  (input) => {
17487
18828
  const previousCapabilities = getComposerCapabilityPartMap(
17488
18829
  composerPartsRef.current
@@ -17500,25 +18841,25 @@ function Chat({
17500
18841
  },
17501
18842
  [commitComposerParts, updateRuntimeCapabilityPalette]
17502
18843
  );
17503
- const handleComposerInput = React52.useCallback(
18844
+ const handleComposerInput = React54.useCallback(
17504
18845
  (event) => {
17505
18846
  syncComposerInputFromElement(event.currentTarget);
17506
18847
  },
17507
18848
  [syncComposerInputFromElement]
17508
18849
  );
17509
- const handleComposerCompositionEnd = React52.useCallback(
18850
+ const handleComposerCompositionEnd = React54.useCallback(
17510
18851
  (event) => {
17511
18852
  syncComposerInputFromElement(event.currentTarget);
17512
18853
  },
17513
18854
  [syncComposerInputFromElement]
17514
18855
  );
17515
- const handleComposerSelect = React52.useCallback(() => {
18856
+ const handleComposerSelect = React54.useCallback(() => {
17516
18857
  updateRuntimeCapabilityPalette(
17517
18858
  composerPartsRef.current,
17518
18859
  composerInputRef.current ? getComposerSelectionOffset(composerInputRef.current) : void 0
17519
18860
  );
17520
18861
  }, [updateRuntimeCapabilityPalette]);
17521
- const submitDraft = React52.useCallback(
18862
+ const submitDraft = React54.useCallback(
17522
18863
  (submitOptions = {}) => {
17523
18864
  if (isSubmissionBlocked) return;
17524
18865
  const contentToSubmit = (submitOptions.inputText ?? trimmedDraft).trim();
@@ -17624,7 +18965,7 @@ function Chat({
17624
18965
  t
17625
18966
  ]
17626
18967
  );
17627
- const handleGoalCommand = React52.useCallback(
18968
+ const handleGoalCommand = React54.useCallback(
17628
18969
  async ({
17629
18970
  args,
17630
18971
  commandSource,
@@ -17730,7 +19071,7 @@ function Chat({
17730
19071
  t
17731
19072
  ]
17732
19073
  );
17733
- const handleGoalPanelOpenChange = React52.useCallback((open) => {
19074
+ const handleGoalPanelOpenChange = React54.useCallback((open) => {
17734
19075
  setIsGoalPanelOpen(open);
17735
19076
  }, []);
17736
19077
  const {
@@ -17774,7 +19115,7 @@ function Chat({
17774
19115
  plugin: t("composer.slashCommands.empty.loadingCapabilities"),
17775
19116
  subAgent: t("composer.slashCommands.empty.loadingCapabilities")
17776
19117
  };
17777
- React52.useEffect(() => {
19118
+ React54.useEffect(() => {
17778
19119
  if (!runtimeCapabilityPalette) {
17779
19120
  return;
17780
19121
  }
@@ -17793,7 +19134,7 @@ function Chat({
17793
19134
  );
17794
19135
  }
17795
19136
  }, [slashPaletteOptions.length, runtimeCapabilityPalette]);
17796
- React52.useLayoutEffect(() => {
19137
+ React54.useLayoutEffect(() => {
17797
19138
  if (!runtimeCapabilityPalette) {
17798
19139
  return;
17799
19140
  }
@@ -17810,7 +19151,7 @@ function Chat({
17810
19151
  container.scrollTop += optionRect.bottom - containerRect.bottom;
17811
19152
  }
17812
19153
  }, [runtimeCapabilityPalette, slashPaletteOptions.length]);
17813
- const submitGoalModeDraft = React52.useCallback(() => {
19154
+ const submitGoalModeDraft = React54.useCallback(() => {
17814
19155
  const objective = getComposerPlainText(composerPartsRef.current).trim();
17815
19156
  if (!isGoalModeOpen || !goalCommandAvailable || !objective) {
17816
19157
  return false;
@@ -17848,7 +19189,7 @@ function Chat({
17848
19189
  }
17849
19190
  submitDraft();
17850
19191
  };
17851
- const handleEditPendingFollowUp = React52.useCallback(
19192
+ const handleEditPendingFollowUp = React54.useCallback(
17852
19193
  (id) => {
17853
19194
  const item = pendingFollowUps.find(
17854
19195
  (entry) => entry.id === id && entry.mode === "queue"
@@ -17875,7 +19216,7 @@ function Chat({
17875
19216
  },
17876
19217
  [pendingFollowUps, setComposerText, stream]
17877
19218
  );
17878
- const handleQuoteSelection = React52.useCallback(() => {
19219
+ const handleQuoteSelection = React54.useCallback(() => {
17879
19220
  if (!quoteSelection) {
17880
19221
  return;
17881
19222
  }
@@ -17891,7 +19232,7 @@ function Chat({
17891
19232
  const handleAttachmentClick = () => {
17892
19233
  attachmentsRef.current?.openFilePicker();
17893
19234
  };
17894
- const uploadContextFile = React52.useCallback(
19235
+ const uploadContextFile = React54.useCallback(
17895
19236
  (file) => {
17896
19237
  const formData = new FormData();
17897
19238
  formData.append("file", file, file.name || "upload");
@@ -17910,13 +19251,13 @@ function Chat({
17910
19251
  },
17911
19252
  [stream.assistantId, stream.client, stream.threadId]
17912
19253
  );
17913
- const getContextFileStatus = React52.useCallback(
19254
+ const getContextFileStatus = React54.useCallback(
17914
19255
  (fileId) => stream.client.contexts.fetch(`/files/${fileId}/status`, {
17915
19256
  method: "GET"
17916
19257
  }),
17917
19258
  [stream.client]
17918
19259
  );
17919
- const deleteContextFile = React52.useCallback(
19260
+ const deleteContextFile = React54.useCallback(
17920
19261
  (storageFileId) => stream.client.contexts.deleteFile(storageFileId),
17921
19262
  [stream.client]
17922
19263
  );
@@ -18024,7 +19365,7 @@ function Chat({
18024
19365
  }
18025
19366
  submitDraft();
18026
19367
  };
18027
- const handleComposerPaste = React52.useCallback(
19368
+ const handleComposerPaste = React54.useCallback(
18028
19369
  (event) => {
18029
19370
  const clipboardData = event.clipboardData;
18030
19371
  if (!clipboardData) {
@@ -18126,13 +19467,13 @@ function Chat({
18126
19467
  const handleToolSelect = (tool) => {
18127
19468
  setSelectedTool((prev) => prev?.id === tool.id ? null : tool);
18128
19469
  };
18129
- const handlePromptClick = React52.useCallback(
19470
+ const handlePromptClick = React54.useCallback(
18130
19471
  (prompt) => {
18131
19472
  submitDraft({ inputText: prompt, displayText: prompt });
18132
19473
  },
18133
19474
  [submitDraft]
18134
19475
  );
18135
- const handlePromptEdit = React52.useCallback(
19476
+ const handlePromptEdit = React54.useCallback(
18136
19477
  (prompt) => {
18137
19478
  if (isPromptEditDisabled) return;
18138
19479
  setComposerText(prompt, prompt.length);
@@ -18141,7 +19482,7 @@ function Chat({
18141
19482
  },
18142
19483
  [focusComposerAt, isPromptEditDisabled, setComposerText]
18143
19484
  );
18144
- const loadConversationMessages = React52.useCallback(
19485
+ const loadConversationMessages = React54.useCallback(
18145
19486
  async (recordId) => {
18146
19487
  if (missingConfig) {
18147
19488
  setHistoryError(missingConfigShortMessage);
@@ -18162,7 +19503,7 @@ function Chat({
18162
19503
  },
18163
19504
  [missingConfig, missingConfigShortMessage, stream, t]
18164
19505
  );
18165
- const handleLoadMoreMessages = React52.useCallback(async () => {
19506
+ const handleLoadMoreMessages = React54.useCallback(async () => {
18166
19507
  if (!canLoadMoreMessages || isLoadingMoreMessages) {
18167
19508
  return;
18168
19509
  }
@@ -18271,19 +19612,19 @@ function Chat({
18271
19612
  };
18272
19613
  const acceptMimes = composer?.attachments?.accept ? Object.entries(composer.attachments.accept).map(([mime, exts]) => [mime, ...exts.map((e) => `.${e}`)].join(",")).join(",") : void 0;
18273
19614
  const canUploadDroppedFiles = composer?.attachments?.enabled === true && !missingConfig && !isHistoryLoading && !hasPendingInteractiveRequest;
18274
- const handleDroppedFiles = React52.useCallback((files) => {
19615
+ const handleDroppedFiles = React54.useCallback((files) => {
18275
19616
  return attachmentsRef.current?.queueFiles(files) ?? false;
18276
19617
  }, []);
18277
- const currentThread = React52.useMemo(
19618
+ const currentThread = React54.useMemo(
18278
19619
  () => threads.find((item) => item.id === stream.threadId),
18279
19620
  [threads, stream.threadId]
18280
19621
  );
18281
- const assistantStatusText = React52.useMemo(() => {
19622
+ const assistantStatusText = React54.useMemo(() => {
18282
19623
  if (!stream.threadId) return t("chat.statusOnline");
18283
19624
  return currentThread?.title?.trim() || t("chat.statusOnline");
18284
19625
  }, [currentThread?.title, stream.threadId, t]);
18285
19626
  const streamErrorMessage = stream.error instanceof Error ? stream.error.message : void 0;
18286
- const threadErrorMessage = React52.useMemo(() => {
19627
+ const threadErrorMessage = React54.useMemo(() => {
18287
19628
  if (streamErrorMessage?.trim()) return streamErrorMessage.trim();
18288
19629
  if (currentThread?.status !== "error") return void 0;
18289
19630
  const message = currentThread.error?.trim();
@@ -18314,777 +19655,880 @@ function Chat({
18314
19655
  fallbackTitle: t("history.threadFallback")
18315
19656
  });
18316
19657
  const layoutMaxWidth = options?.layout?.maxWidth;
18317
- const chatColumnStyle = React52.useMemo(() => {
19658
+ const chatColumnStyle = React54.useMemo(() => {
18318
19659
  if (layoutMaxWidth === void 0 || layoutMaxWidth === null || layoutMaxWidth === "") {
18319
19660
  return void 0;
18320
19661
  }
18321
19662
  return { maxWidth: layoutMaxWidth };
18322
19663
  }, [layoutMaxWidth]);
18323
- return /* @__PURE__ */ jsxs39(
18324
- UploadDroppedFiles,
19664
+ React54.useLayoutEffect(() => {
19665
+ if (!taskSummaryEnabled) {
19666
+ setTaskSummaryDocked(false);
19667
+ return;
19668
+ }
19669
+ const viewport = viewportRef.current;
19670
+ const chatColumn = chatColumnRef.current;
19671
+ if (!viewport || !chatColumn) {
19672
+ setTaskSummaryDocked(false);
19673
+ return;
19674
+ }
19675
+ const updateDockedState = () => {
19676
+ const viewportRect = viewport.getBoundingClientRect();
19677
+ const chatColumnRect = chatColumn.getBoundingClientRect();
19678
+ const rootFontSize = Number.parseFloat(
19679
+ window.getComputedStyle(document.documentElement).fontSize
19680
+ );
19681
+ const remInPixels = Number.isFinite(rootFontSize) ? rootFontSize : 16;
19682
+ const requiredSideSpace = (TASK_SUMMARY_PANEL_WIDTH_REM + TASK_SUMMARY_PANEL_EDGE_INSET_REM + TASK_SUMMARY_PANEL_SAFE_GAP_REM) * remInPixels;
19683
+ const availableSideSpace = viewportRect.right - chatColumnRect.right;
19684
+ setTaskSummaryDocked(availableSideSpace >= requiredSideSpace);
19685
+ };
19686
+ updateDockedState();
19687
+ window.addEventListener("resize", updateDockedState);
19688
+ const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(updateDockedState) : null;
19689
+ resizeObserver?.observe(viewport);
19690
+ resizeObserver?.observe(chatColumn);
19691
+ return () => {
19692
+ window.removeEventListener("resize", updateDockedState);
19693
+ resizeObserver?.disconnect();
19694
+ };
19695
+ }, [layoutMaxWidth, taskSummaryEnabled]);
19696
+ const taskSummaryAvailable = Boolean(
19697
+ taskSummaryEnabled && stream.threadId && taskSummaryConversationId
19698
+ );
19699
+ const handleTaskSummaryOpenChange = React54.useCallback(
19700
+ (open) => {
19701
+ setTaskSummaryOpen(open);
19702
+ if (!taskSummaryConversationId) return;
19703
+ if (open) {
19704
+ manuallyClosedTaskSummaryConversationIdsRef.current.delete(
19705
+ taskSummaryConversationId
19706
+ );
19707
+ return;
19708
+ }
19709
+ manuallyClosedTaskSummaryConversationIdsRef.current.add(
19710
+ taskSummaryConversationId
19711
+ );
19712
+ },
19713
+ [taskSummaryConversationId]
19714
+ );
19715
+ React54.useEffect(() => {
19716
+ if (!taskSummaryDocked) {
19717
+ setTaskSummaryOpen(false);
19718
+ }
19719
+ }, [taskSummaryDocked]);
19720
+ React54.useEffect(() => {
19721
+ if (!taskSummaryDocked || !taskSummaryAvailable || !taskSummaryConversationId || manuallyClosedTaskSummaryConversationIdsRef.current.has(
19722
+ taskSummaryConversationId
19723
+ )) {
19724
+ return;
19725
+ }
19726
+ setTaskSummaryOpen(true);
19727
+ }, [taskSummaryAvailable, taskSummaryConversationId, taskSummaryDocked]);
19728
+ const taskSummaryProps = {
19729
+ summary: taskSummary.summary,
19730
+ historyError: taskSummary.historyError,
19731
+ loadingSections: taskSummary.loadingSections,
19732
+ loadedSectionCounts: taskSummary.loadedSectionCounts,
19733
+ onRetryHistory: taskSummary.retryHistory,
19734
+ onLoadSection: taskSummary.loadSection,
19735
+ onNavigateMessage: (messageId) => {
19736
+ void navigateToTaskSummaryMessage(messageId);
19737
+ },
19738
+ onFocusComposer: () => focusComposerAt(),
19739
+ onOpenResource: openTaskSummaryResource
19740
+ };
19741
+ return /* @__PURE__ */ jsxs40(
19742
+ "div",
18325
19743
  {
18326
- ref: viewportRef,
18327
- "data-chatkit-root": "",
18328
- enabled: canUploadDroppedFiles,
18329
- dropTitle: t("chat.dropFilesTitle"),
18330
- dropHint: t("chat.dropFilesHint"),
18331
- activeClassName: "ring-2 ring-primary/40 ring-inset",
18332
- onFiles: handleDroppedFiles,
18333
- className: cn(
18334
- "relative flex h-full w-full flex-col flex-1 overflow-y-auto bg-background shadow-sm transition-[box-shadow] duration-150",
18335
- className
18336
- ),
19744
+ className: "relative flex h-full w-full min-w-0 bg-background",
19745
+ "data-task-summary-layout": taskSummaryDocked ? "docked" : "popover",
18337
19746
  children: [
18338
- /* @__PURE__ */ jsxs39(
18339
- "div",
19747
+ /* @__PURE__ */ jsxs40(
19748
+ UploadDroppedFiles,
18340
19749
  {
18341
- "data-slot": "chatkit-chat-header",
18342
- className: "mx-auto flex w-full items-center justify-between border-b p-2 sticky top-0 z-10 bg-background",
18343
- style: chatColumnStyle,
19750
+ ref: viewportRef,
19751
+ "data-chatkit-root": "",
19752
+ enabled: canUploadDroppedFiles,
19753
+ dropTitle: t("chat.dropFilesTitle"),
19754
+ dropHint: t("chat.dropFilesHint"),
19755
+ activeClassName: "ring-2 ring-primary/40 ring-inset",
19756
+ onFiles: handleDroppedFiles,
19757
+ className: cn(
19758
+ "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",
19759
+ className
19760
+ ),
18344
19761
  children: [
18345
- /* @__PURE__ */ jsxs39("div", { className: "flex min-w-0 items-center gap-3 overflow-hidden", children: [
18346
- /* @__PURE__ */ jsxs39("div", { className: "relative shrink-0", children: [
18347
- /* @__PURE__ */ jsx57(
18348
- ChatkitAvatar,
18349
- {
18350
- avatar: assistantAvatar,
18351
- className: "h-9 w-9 border border-border/60",
18352
- label: assistantTitle
18353
- }
18354
- ),
18355
- /* @__PURE__ */ jsx57("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
18356
- ] }),
18357
- /* @__PURE__ */ jsxs39("div", { className: "min-w-0", children: [
18358
- /* @__PURE__ */ jsx57(
18359
- "h2",
18360
- {
18361
- className: "text-lg font-semibold truncate",
18362
- title: assistantTitle,
18363
- children: assistantTitle
18364
- }
18365
- ),
18366
- /* @__PURE__ */ jsx57(
18367
- "p",
18368
- {
18369
- className: "truncate text-xs text-muted-foreground",
18370
- title: assistantStatusText,
18371
- children: assistantStatusText
18372
- }
18373
- )
18374
- ] })
18375
- ] }),
18376
- /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-1", children: [
18377
- canMinimizeToPet && /* @__PURE__ */ jsxs39(Tooltip, { children: [
18378
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx57(
18379
- "button",
18380
- {
18381
- type: "button",
18382
- onClick: handleMinimizeToPet,
18383
- className: cn(
18384
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18385
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18386
- "transition-colors duration-150"
18387
- ),
18388
- "aria-label": t("chat.minimizeToPet"),
18389
- children: /* @__PURE__ */ jsx57(Minus, { size: 16 })
18390
- }
18391
- ) }) }),
18392
- /* @__PURE__ */ jsx57(TooltipContent, { side: "bottom", children: t("chat.minimizeToPet") })
18393
- ] }),
18394
- /* @__PURE__ */ jsxs39(Tooltip, { children: [
18395
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx57(
18396
- "button",
18397
- {
18398
- type: "button",
18399
- onClick: () => setPetSettingsOpen(true),
18400
- className: cn(
18401
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18402
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18403
- "transition-colors duration-150"
18404
- ),
18405
- "aria-label": t("settings.open"),
18406
- children: /* @__PURE__ */ jsx57(Settings2, { size: 16 })
18407
- }
18408
- ) }) }),
18409
- /* @__PURE__ */ jsx57(TooltipContent, { side: "bottom", children: t("settings.open") })
18410
- ] }),
18411
- history?.enabled !== false && /* @__PURE__ */ jsxs39(Fragment9, { children: [
18412
- /* @__PURE__ */ jsxs39(Tooltip, { children: [
18413
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx57(
18414
- "button",
18415
- {
18416
- type: "button",
18417
- onClick: handleNewThread,
18418
- disabled: missingConfig || isHistoryLoading,
18419
- className: cn(
18420
- "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
18421
- "text-muted-foreground hover:text-foreground hover:bg-muted",
18422
- "transition-colors duration-150",
18423
- "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed"
19762
+ /* @__PURE__ */ jsxs40(
19763
+ "div",
19764
+ {
19765
+ ref: chatColumnRef,
19766
+ "data-slot": "chatkit-chat-header",
19767
+ className: "mx-auto flex w-full items-center justify-between border-b p-2 sticky top-0 z-10 bg-background",
19768
+ style: chatColumnStyle,
19769
+ children: [
19770
+ /* @__PURE__ */ jsxs40("div", { className: "flex min-w-0 items-center gap-3 overflow-hidden", children: [
19771
+ /* @__PURE__ */ jsxs40("div", { className: "relative shrink-0", children: [
19772
+ /* @__PURE__ */ jsx58(
19773
+ ChatkitAvatar,
19774
+ {
19775
+ avatar: assistantAvatar,
19776
+ className: "h-9 w-9 border border-border/60",
19777
+ label: assistantTitle
19778
+ }
18424
19779
  ),
18425
- "aria-label": t("history.newThread"),
18426
- children: /* @__PURE__ */ jsx57(Pencil4, { size: 16 })
18427
- }
18428
- ) }) }),
18429
- /* @__PURE__ */ jsx57(TooltipContent, { side: "bottom", children: t("history.newThread") })
18430
- ] }),
18431
- /* @__PURE__ */ jsx57(
18432
- HistorySidebar,
18433
- {
18434
- threads,
18435
- currentThreadId: stream.threadId ?? void 0,
18436
- onNewThread: handleNewThread,
18437
- onSelectThread: handleSelectThread,
18438
- onDeleteThread: handleDeleteThread,
18439
- showDelete: history?.showDelete !== false,
18440
- disabled: missingConfig || isThreadsLoading || isHistoryLoading
18441
- }
18442
- )
18443
- ] })
18444
- ] })
18445
- ]
18446
- }
18447
- ),
18448
- showMessageNavigation && /* @__PURE__ */ jsx57(
18449
- MessageNavigator,
18450
- {
18451
- items: messageNavigationItems,
18452
- viewportRef,
18453
- getAnchor: getMessageNavigationAnchor,
18454
- onNavigate: handleMessageNavigationNavigate,
18455
- label: t("message.navigation.label"),
18456
- tagsOverflowLabel: (count) => t("message.navigation.moreTags", { count })
18457
- }
18458
- ),
18459
- /* @__PURE__ */ jsxs39(
18460
- "div",
18461
- {
18462
- "data-slot": "chatkit-chat-content",
18463
- className: "mx-auto w-full flex-1 p-4",
18464
- style: chatColumnStyle,
18465
- children: [
18466
- errorMessage && /* @__PURE__ */ jsx57("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
18467
- historyError && /* @__PURE__ */ jsx57("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: historyError }),
18468
- showMissingConfig && /* @__PURE__ */ jsx57("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: missingConfigDetailMessage }),
18469
- isHistoryLoading && /* @__PURE__ */ jsx57("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
18470
- messages.length === 0 && !canLoadMoreMessages ? /* @__PURE__ */ jsx57(
18471
- StartScreen,
18472
- {
18473
- startScreen,
18474
- onPromptClick: handlePromptClick,
18475
- onPromptEdit: handlePromptEdit,
18476
- promptSendDisabled: isSubmissionBlocked,
18477
- promptEditDisabled: isPromptEditDisabled
18478
- }
18479
- ) : /* @__PURE__ */ jsxs39("div", { className: "space-y-4", children: [
18480
- canLoadMoreMessages && /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-3 py-1", children: [
18481
- /* @__PURE__ */ jsx57("div", { className: "h-px min-w-8 flex-1 bg-border" }),
18482
- /* @__PURE__ */ jsx57(
18483
- Button,
18484
- {
18485
- type: "button",
18486
- variant: "ghost",
18487
- size: "sm",
18488
- onClick: handleLoadMoreMessages,
18489
- disabled: isLoadingMoreMessages,
18490
- className: "h-7 px-2 text-xs font-medium text-muted-foreground hover:text-foreground",
18491
- children: isLoadingMoreMessages ? t("chat.loadingMoreMessages") : t("chat.loadMoreMessages")
18492
- }
18493
- ),
18494
- /* @__PURE__ */ jsx57("div", { className: "h-px min-w-8 flex-1 bg-border" })
18495
- ] }),
18496
- messages.map((message, index) => {
18497
- const messageType = String(message.type);
18498
- const isAssistantMessage = messageType === "assistant" || messageType === "ai";
18499
- const isStreamingMessage = stream.isLoading && index === messages.length - 1;
18500
- const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
18501
- {
18502
- ...message,
18503
- lastStreamOutputAt: lastStreamOutputAtRef.current
18504
- },
18505
- isStreamingMessage,
18506
- { now: streamingNow }
18507
- ) : null;
18508
- if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
18509
- return null;
18510
- }
18511
- const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
18512
- const hasPlainRenderableContent = messageContent.trim().length > 0;
18513
- const humanMessage = message;
18514
- const humanReferences = humanMessage.references ?? [];
18515
- const humanAttachments = [
18516
- ...humanMessage.fileAssets ?? [],
18517
- ...humanMessage.attachments ?? []
18518
- ];
18519
- const humanRuntimeCapabilityOptions = message.type === "human" ? humanMessage.runtimeCapabilityOptions ?? getRuntimeCapabilityOptionsForSelection(
18520
- getRecommendedRuntimeCapabilitiesSelection(
18521
- humanMessage.runtimeCapabilities
18522
- ),
18523
- runtimeCapabilityOptions
18524
- ) : [];
18525
- const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
18526
- const canQuoteMessage = message.type === "human" || isAssistantMessage;
18527
- const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
18528
- const messageNavigationId = getMessageNavigationItemId(
18529
- message,
18530
- index
18531
- );
18532
- if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanRuntimeCapabilityOptions.length === 0 && humanReferences.length === 0) {
18533
- return null;
18534
- }
18535
- return /* @__PURE__ */ jsx57(
18536
- "div",
18537
- {
18538
- ref: (node) => setMessageNavigationAnchor(messageNavigationId, node),
18539
- "data-message-navigation-id": messageNavigationId,
18540
- className: cn(
18541
- "group flex gap-3",
18542
- message.type === "human" ? "justify-end" : "justify-start -ml-1"
18543
- // AI messages: slightly closer to left
18544
- ),
18545
- children: /* @__PURE__ */ jsxs39(
18546
- "div",
19780
+ /* @__PURE__ */ jsx58("span", { className: "absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full border-2 border-background bg-green-500" })
19781
+ ] }),
19782
+ /* @__PURE__ */ jsxs40("div", { className: "min-w-0", children: [
19783
+ /* @__PURE__ */ jsx58(
19784
+ "h2",
19785
+ {
19786
+ className: "text-lg font-semibold truncate",
19787
+ title: assistantTitle,
19788
+ children: assistantTitle
19789
+ }
19790
+ ),
19791
+ /* @__PURE__ */ jsx58(
19792
+ "p",
19793
+ {
19794
+ className: "truncate text-xs text-muted-foreground",
19795
+ title: assistantStatusText,
19796
+ children: assistantStatusText
19797
+ }
19798
+ )
19799
+ ] })
19800
+ ] }),
19801
+ /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-1", children: [
19802
+ taskSummaryAvailable && /* @__PURE__ */ jsx58(
19803
+ TaskSummaryTrigger,
18547
19804
  {
18548
- className: cn(
18549
- "flex flex-col px-3 overflow-hidden",
18550
- isAssistantMessage && "min-w-0 flex-1"
18551
- ),
18552
- children: [
18553
- /* @__PURE__ */ jsx57(
18554
- "div",
18555
- {
18556
- ...canQuoteMessage ? {
18557
- "data-quote-message-id": message.id,
18558
- "data-quote-source": quoteSource
18559
- } : {},
18560
- className: cn(
18561
- "max-w-full rounded-2xl",
18562
- 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"
18563
- // AI messages: use chat-specific foreground color
18564
- ),
18565
- children: isAssistantMessage ? /* @__PURE__ */ jsx57(
18566
- AssistantMessage,
18567
- {
18568
- message: {
18569
- ...message,
18570
- type: "assistant"
18571
- },
18572
- messages: messages.slice(0, index + 1).map(
18573
- (item) => ({
18574
- ...item,
18575
- type: String(item.type) === "ai" ? "assistant" : item.type
18576
- })
18577
- ),
18578
- isStreaming: isStreamingMessage,
18579
- streamingStatus,
18580
- isThreadRunning: currentThreadIsRunning,
18581
- organizationId: stream.organizationId,
18582
- apiUrl: stream.apiUrl,
18583
- pet: effectivePet
18584
- }
18585
- ) : /* @__PURE__ */ jsxs39(Fragment9, { children: [
18586
- message.type === "human" && humanRuntimeCapabilityOptions.length > 0 && /* @__PURE__ */ jsx57(
18587
- HumanRuntimeCapabilityChips,
18588
- {
18589
- options: humanRuntimeCapabilityOptions
18590
- }
18591
- ),
18592
- message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ jsx57("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ jsx57(
18593
- ReferenceChip,
18594
- {
18595
- reference,
18596
- variant: "message"
18597
- },
18598
- getReferenceKey(reference)
18599
- )) }),
18600
- message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ jsx57("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ jsxs39(
18601
- "div",
18602
- {
18603
- className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
18604
- children: [
18605
- /* @__PURE__ */ jsx57(FileText5, { size: 12 }),
18606
- /* @__PURE__ */ jsx57("span", { className: "max-w-[100px] truncate", children: file.originalName ?? file.id })
18607
- ]
18608
- },
18609
- fileIndex
18610
- )) }),
18611
- Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ jsx57(
18612
- "p",
18613
- {
18614
- className: "wrap-break-word text-sm leading-relaxed",
18615
- children: formatMessageContent(part)
18616
- },
18617
- `${part.type}-${partIndex}`
18618
- )) : /* @__PURE__ */ jsx57("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
18619
- ] })
18620
- }
18621
- ),
18622
- /* @__PURE__ */ jsx57(
18623
- MessageActions,
18624
- {
18625
- content: messageContent,
18626
- isAssistant: isAssistantMessage,
18627
- isStreaming: isStreamingMessage,
18628
- onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
18629
- }
18630
- )
18631
- ]
19805
+ ...taskSummaryProps,
19806
+ displayMode: taskSummaryDocked ? "docked" : "popover",
19807
+ open: taskSummaryOpen,
19808
+ onOpenChange: handleTaskSummaryOpenChange
18632
19809
  }
18633
- )
18634
- },
18635
- message.id ?? `${message.type}-${index}`
18636
- );
18637
- }),
18638
- showLoadingDots && (() => {
18639
- const lastMessage = messages[messages.length - 1];
18640
- const lastMessageType = lastMessage ? String(lastMessage.type) : "";
18641
- const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
18642
- const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
18643
- {
18644
- ...lastMessage,
18645
- lastStreamOutputAt: lastStreamOutputAtRef.current
18646
- },
18647
- stream.isLoading,
18648
- { now: streamingNow }
18649
- ) : null;
18650
- if (lastAssistantStatus) return null;
18651
- const fallbackStreamingStatus = getAssistantStreamingStatus(
18652
- {
18653
- status: void 0,
18654
- reasoning: void 0,
18655
- lastStreamOutputAt: lastStreamOutputAtRef.current
18656
- },
18657
- stream.isLoading,
18658
- { now: streamingNow }
18659
- );
18660
- return /* @__PURE__ */ jsx57("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ jsx57("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ jsx57(
18661
- AssistantStreamingIndicator,
18662
- {
18663
- status: fallbackStreamingStatus ?? "loading"
18664
- }
18665
- ) }) });
18666
- })()
18667
- ] })
18668
- ]
18669
- }
18670
- ),
18671
- !isAtBottom && messages.length > 0 && /* @__PURE__ */ jsx57("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ jsx57(
18672
- Button,
18673
- {
18674
- type: "button",
18675
- size: "icon-sm",
18676
- variant: hasUpdatesBelow ? "default" : "outline",
18677
- className: cn(
18678
- "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)]",
18679
- hasUpdatesBelow && "animate-bounce"
18680
- ),
18681
- onClick: () => scrollToBottom(true, true),
18682
- "aria-label": t("chat.scrollToBottom"),
18683
- title: t("chat.scrollToBottom"),
18684
- children: /* @__PURE__ */ jsx57(ArrowDown2, { size: 16 })
18685
- }
18686
- ) }),
18687
- quoteSelection && /* @__PURE__ */ jsx57(
18688
- "div",
18689
- {
18690
- className: "pointer-events-none fixed z-50",
18691
- style: {
18692
- top: `${quoteSelection.top}px`,
18693
- left: `${quoteSelection.left}px`,
18694
- transform: "translateX(-50%)"
18695
- },
18696
- children: /* @__PURE__ */ jsxs39(
18697
- Button,
18698
- {
18699
- type: "button",
18700
- size: "sm",
18701
- variant: "secondary",
18702
- className: "pointer-events-auto shadow-lg",
18703
- onMouseDown: (event) => event.preventDefault(),
18704
- onClick: handleQuoteSelection,
18705
- "aria-label": t("composer.quoteSelection"),
18706
- title: t("composer.quoteSelection"),
18707
- children: [
18708
- /* @__PURE__ */ jsx57(Quote, { size: 14 }),
18709
- t("composer.quoteSelection")
18710
- ]
18711
- }
18712
- )
18713
- }
18714
- ),
18715
- /* @__PURE__ */ jsxs39(
18716
- "div",
18717
- {
18718
- "data-slot": "chatkit-chat-composer",
18719
- className: "mx-auto w-full p-2 sticky bottom-0 z-10 bg-background",
18720
- style: chatColumnStyle,
18721
- children: [
18722
- threadErrorMessage && /* @__PURE__ */ jsx57("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 }),
18723
- /* @__PURE__ */ jsx57(
18724
- ChatAttachments,
18725
- {
18726
- ref: attachmentsRef,
18727
- accept: acceptMimes,
18728
- maxCount: composer?.attachments?.maxCount ?? 10,
18729
- maxSize: composer?.attachments?.maxSize ?? 100 * 1024 * 1024,
18730
- retryUploadLabel: t("chat.retryUpload"),
18731
- uploadFile: uploadContextFile,
18732
- deleteFile: deleteContextFile,
18733
- getFileStatus: getContextFileStatus,
18734
- onStateChange: setAttachmentState
19810
+ ),
19811
+ canMinimizeToPet && /* @__PURE__ */ jsxs40(Tooltip, { children: [
19812
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx58(
19813
+ "button",
19814
+ {
19815
+ type: "button",
19816
+ onClick: handleMinimizeToPet,
19817
+ className: cn(
19818
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19819
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19820
+ "transition-colors duration-150"
19821
+ ),
19822
+ "aria-label": t("chat.minimizeToPet"),
19823
+ children: /* @__PURE__ */ jsx58(Minus, { size: 16 })
19824
+ }
19825
+ ) }) }),
19826
+ /* @__PURE__ */ jsx58(TooltipContent, { side: "bottom", children: t("chat.minimizeToPet") })
19827
+ ] }),
19828
+ /* @__PURE__ */ jsxs40(Tooltip, { children: [
19829
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx58(
19830
+ "button",
19831
+ {
19832
+ type: "button",
19833
+ onClick: () => setPetSettingsOpen(true),
19834
+ className: cn(
19835
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19836
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19837
+ "transition-colors duration-150"
19838
+ ),
19839
+ "aria-label": t("settings.open"),
19840
+ children: /* @__PURE__ */ jsx58(Settings2, { size: 16 })
19841
+ }
19842
+ ) }) }),
19843
+ /* @__PURE__ */ jsx58(TooltipContent, { side: "bottom", children: t("settings.open") })
19844
+ ] }),
19845
+ history?.enabled !== false && /* @__PURE__ */ jsxs40(Fragment9, { children: [
19846
+ /* @__PURE__ */ jsxs40(Tooltip, { children: [
19847
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58("span", { className: "inline-flex h-8 w-8", children: /* @__PURE__ */ jsx58(
19848
+ "button",
19849
+ {
19850
+ type: "button",
19851
+ onClick: handleNewThread,
19852
+ disabled: missingConfig || isHistoryLoading,
19853
+ className: cn(
19854
+ "flex h-8 w-8 cursor-pointer items-center justify-center rounded-md",
19855
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
19856
+ "transition-colors duration-150",
19857
+ "disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed"
19858
+ ),
19859
+ "aria-label": t("history.newThread"),
19860
+ children: /* @__PURE__ */ jsx58(Pencil4, { size: 16 })
19861
+ }
19862
+ ) }) }),
19863
+ /* @__PURE__ */ jsx58(TooltipContent, { side: "bottom", children: t("history.newThread") })
19864
+ ] }),
19865
+ /* @__PURE__ */ jsx58(
19866
+ HistorySidebar,
19867
+ {
19868
+ threads,
19869
+ currentThreadId: stream.threadId ?? void 0,
19870
+ onNewThread: handleNewThread,
19871
+ onSelectThread: handleSelectThread,
19872
+ onDeleteThread: handleDeleteThread,
19873
+ showDelete: history?.showDelete !== false,
19874
+ disabled: missingConfig || isThreadsLoading || isHistoryLoading
19875
+ }
19876
+ )
19877
+ ] })
19878
+ ] })
19879
+ ]
18735
19880
  }
18736
19881
  ),
18737
- references.length > 0 && /* @__PURE__ */ jsx57("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ jsx57(
18738
- ReferenceChip,
18739
- {
18740
- reference,
18741
- variant: "composer",
18742
- onRemove: () => setReferences(
18743
- (previous) => previous.filter(
18744
- (item) => getReferenceKey(item) !== getReferenceKey(reference)
18745
- )
18746
- ),
18747
- removeLabel: t("composer.removeReference")
18748
- },
18749
- getReferenceKey(reference)
18750
- )) }),
18751
- /* @__PURE__ */ jsx57(
18752
- DetachedRunRuntimeCapabilities,
19882
+ showMessageNavigation && /* @__PURE__ */ jsx58(
19883
+ MessageNavigator,
18753
19884
  {
18754
- options: detachedRunRuntimeCapabilityOptions,
18755
- runOnlyLabel: t("composer.capabilities.runOnly"),
18756
- removeLabel: t("composer.capabilities.removeRunCapability"),
18757
- onRemove: removeRunRuntimeCapability
19885
+ items: messageNavigationItems,
19886
+ viewportRef,
19887
+ getAnchor: getMessageNavigationAnchor,
19888
+ onNavigate: handleMessageNavigationNavigate,
19889
+ label: t("message.navigation.label"),
19890
+ tagsOverflowLabel: (count) => t("message.navigation.moreTags", { count })
18758
19891
  }
18759
19892
  ),
18760
- showGoalStatus && /* @__PURE__ */ jsxs39(
19893
+ /* @__PURE__ */ jsxs40(
18761
19894
  "div",
18762
19895
  {
18763
- className: cn(
18764
- "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",
18765
- isGoalObjectiveExpanded ? "items-start" : "items-center"
18766
- ),
19896
+ "data-slot": "chatkit-chat-content",
19897
+ className: "mx-auto w-full flex-1 p-4",
19898
+ style: chatColumnStyle,
18767
19899
  children: [
18768
- /* @__PURE__ */ jsx57(
18769
- Target2,
19900
+ errorMessage && /* @__PURE__ */ jsx58("div", { className: "mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: errorMessage }),
19901
+ historyError && /* @__PURE__ */ jsx58("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: historyError }),
19902
+ showMissingConfig && /* @__PURE__ */ jsx58("div", { className: "mb-4 rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: missingConfigDetailMessage }),
19903
+ isHistoryLoading && /* @__PURE__ */ jsx58("div", { className: "mb-4 rounded-lg border border-muted px-3 py-2 text-sm text-muted-foreground", children: t("chat.loadingThread") }),
19904
+ messages.length === 0 && !canLoadMoreMessages ? /* @__PURE__ */ jsx58(
19905
+ StartScreen,
18770
19906
  {
18771
- className: cn(
18772
- "size-4 shrink-0 text-muted-foreground",
18773
- isGoalObjectiveExpanded && "mt-1"
18774
- )
19907
+ startScreen,
19908
+ onPromptClick: handlePromptClick,
19909
+ onPromptEdit: handlePromptEdit,
19910
+ promptSendDisabled: isSubmissionBlocked,
19911
+ promptEditDisabled: isPromptEditDisabled
18775
19912
  }
18776
- ),
18777
- /* @__PURE__ */ jsxs39("div", { className: "min-w-0 flex-1", children: [
18778
- /* @__PURE__ */ jsxs39("div", { className: "flex min-w-0 items-center gap-2", children: [
18779
- /* @__PURE__ */ jsx57("span", { className: "font-medium", children: t("chat.goal.label") }),
18780
- threadGoal && /* @__PURE__ */ jsx57("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}`) }),
18781
- isGoalLoading && /* @__PURE__ */ jsx57(Loader29, { className: "size-3 animate-spin text-muted-foreground" })
18782
- ] }),
18783
- /* @__PURE__ */ jsx57(
18784
- "div",
18785
- {
18786
- className: cn(
18787
- "mt-0.5 text-muted-foreground",
18788
- threadGoal?.objective && !goalError && isGoalObjectiveExpanded ? "whitespace-pre-wrap break-words" : "truncate"
18789
- ),
18790
- children: goalError || threadGoal?.objective
18791
- }
18792
- ),
18793
- threadGoal && /* @__PURE__ */ jsx57("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: /* @__PURE__ */ jsx57("span", { children: t("chat.goal.elapsed", {
18794
- elapsed: formatGoalElapsed(displayedGoalElapsedSeconds)
18795
- }) }) })
18796
- ] }),
18797
- threadGoal && /* @__PURE__ */ jsxs39("div", { className: "flex shrink-0 items-center gap-1", children: [
18798
- /* @__PURE__ */ jsxs39(Tooltip, { children: [
18799
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57(
19913
+ ) : /* @__PURE__ */ jsxs40("div", { className: "space-y-4", children: [
19914
+ canLoadMoreMessages && /* @__PURE__ */ jsxs40("div", { className: "flex items-center gap-3 py-1", children: [
19915
+ /* @__PURE__ */ jsx58("div", { className: "h-px min-w-8 flex-1 bg-border" }),
19916
+ /* @__PURE__ */ jsx58(
18800
19917
  Button,
18801
19918
  {
18802
19919
  type: "button",
18803
19920
  variant: "ghost",
18804
- size: "icon-xs",
18805
- disabled: isGoalLoading,
18806
- onClick: () => {
18807
- const prefix = "/goal edit ";
18808
- setComposerText(`${prefix}${threadGoal.objective}`);
18809
- },
18810
- children: /* @__PURE__ */ jsx57(Pencil4, { className: "size-3" })
19921
+ size: "sm",
19922
+ onClick: handleLoadMoreMessages,
19923
+ disabled: isLoadingMoreMessages,
19924
+ className: "h-7 px-2 text-xs font-medium text-muted-foreground hover:text-foreground",
19925
+ children: isLoadingMoreMessages ? t("chat.loadingMoreMessages") : t("chat.loadMoreMessages")
18811
19926
  }
18812
- ) }),
18813
- /* @__PURE__ */ jsx57(TooltipContent, { children: t("chat.goal.edit") })
18814
- ] }),
18815
- /* @__PURE__ */ jsxs39(Tooltip, { children: [
18816
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57(
18817
- Button,
18818
- {
18819
- type: "button",
18820
- variant: "ghost",
18821
- size: "icon-xs",
18822
- disabled: isGoalLoading,
18823
- onClick: () => void handleGoalCommand({
18824
- args: threadGoal.status === "paused" ? "resume" : "pause",
18825
- commandSource: {
18826
- type: "slash_command",
18827
- name: "goal",
18828
- source: "runtime",
18829
- executionType: "insert_invocation"
18830
- }
18831
- }),
18832
- children: threadGoal.status === "paused" ? /* @__PURE__ */ jsx57(Play, { className: "size-3" }) : /* @__PURE__ */ jsx57(Pause, { className: "size-3" })
18833
- }
18834
- ) }),
18835
- /* @__PURE__ */ jsx57(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
19927
+ ),
19928
+ /* @__PURE__ */ jsx58("div", { className: "h-px min-w-8 flex-1 bg-border" })
18836
19929
  ] }),
18837
- /* @__PURE__ */ jsxs39(Tooltip, { children: [
18838
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57(
18839
- Button,
19930
+ messages.map((message, index) => {
19931
+ const messageType = String(message.type);
19932
+ const isAssistantMessage = messageType === "assistant" || messageType === "ai";
19933
+ const isStreamingMessage = stream.isLoading && index === messages.length - 1;
19934
+ const streamingStatus = isAssistantMessage ? getAssistantStreamingStatus(
18840
19935
  {
18841
- type: "button",
18842
- variant: "ghost",
18843
- size: "icon-xs",
18844
- disabled: isGoalLoading,
18845
- onClick: () => void handleGoalCommand({
18846
- args: "clear",
18847
- commandSource: {
18848
- type: "slash_command",
18849
- name: "goal",
18850
- source: "runtime",
18851
- executionType: "insert_invocation"
18852
- }
18853
- }),
18854
- children: /* @__PURE__ */ jsx57(Trash23, { className: "size-3" })
18855
- }
18856
- ) }),
18857
- /* @__PURE__ */ jsx57(TooltipContent, { children: t("chat.goal.clear") })
18858
- ] }),
18859
- threadGoal.objective && !goalError && /* @__PURE__ */ jsxs39(Tooltip, { children: [
18860
- /* @__PURE__ */ jsx57(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx57(
18861
- Button,
19936
+ ...message,
19937
+ lastStreamOutputAt: lastStreamOutputAtRef.current
19938
+ },
19939
+ isStreamingMessage,
19940
+ { now: streamingNow }
19941
+ ) : null;
19942
+ if (isAssistantMessage && !hasRenderableAssistantMessage(message) && !streamingStatus) {
19943
+ return null;
19944
+ }
19945
+ const messageContent = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.map((part) => formatMessageContent(part)).join("") : formatMessageContent(message.content);
19946
+ const hasPlainRenderableContent = messageContent.trim().length > 0;
19947
+ const humanMessage = message;
19948
+ const humanReferences = humanMessage.references ?? [];
19949
+ const humanAttachments = [
19950
+ ...humanMessage.fileAssets ?? [],
19951
+ ...humanMessage.attachments ?? []
19952
+ ];
19953
+ const humanRuntimeCapabilityOptions = message.type === "human" ? humanMessage.runtimeCapabilityOptions ?? getRuntimeCapabilityOptionsForSelection(
19954
+ getRecommendedRuntimeCapabilitiesSelection(
19955
+ humanMessage.runtimeCapabilities
19956
+ ),
19957
+ runtimeCapabilityOptions
19958
+ ) : [];
19959
+ const hasHumanAttachments = message.type === "human" && humanAttachments.length > 0;
19960
+ const canQuoteMessage = message.type === "human" || isAssistantMessage;
19961
+ const quoteSource = message.type === "human" ? t("chat.youLabel") : assistantTitle;
19962
+ const messageNavigationId = getMessageNavigationItemId(
19963
+ message,
19964
+ index
19965
+ );
19966
+ if (!isAssistantMessage && !hasPlainRenderableContent && !hasHumanAttachments && humanRuntimeCapabilityOptions.length === 0 && humanReferences.length === 0) {
19967
+ return null;
19968
+ }
19969
+ return /* @__PURE__ */ jsx58(
19970
+ "div",
18862
19971
  {
18863
- type: "button",
18864
- variant: "ghost",
18865
- size: "icon-xs",
18866
- "aria-expanded": isGoalObjectiveExpanded,
18867
- "aria-label": isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective"),
18868
- onClick: () => setIsGoalObjectiveExpanded((expanded) => !expanded),
18869
- children: /* @__PURE__ */ jsx57(
18870
- ChevronDown5,
19972
+ ref: (node) => setMessageNavigationAnchor(messageNavigationId, node),
19973
+ "data-message-navigation-id": messageNavigationId,
19974
+ className: cn(
19975
+ "group flex gap-3",
19976
+ message.type === "human" ? "justify-end" : "justify-start -ml-1"
19977
+ // AI messages: slightly closer to left
19978
+ ),
19979
+ children: /* @__PURE__ */ jsxs40(
19980
+ "div",
18871
19981
  {
18872
19982
  className: cn(
18873
- "size-3 transition-transform",
18874
- isGoalObjectiveExpanded && "rotate-180"
18875
- )
19983
+ "flex flex-col px-3 overflow-hidden",
19984
+ isAssistantMessage && "min-w-0 flex-1"
19985
+ ),
19986
+ children: [
19987
+ /* @__PURE__ */ jsx58(
19988
+ "div",
19989
+ {
19990
+ ...canQuoteMessage ? {
19991
+ "data-quote-message-id": message.id,
19992
+ "data-quote-source": quoteSource
19993
+ } : {},
19994
+ className: cn(
19995
+ "max-w-full rounded-2xl",
19996
+ 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"
19997
+ // AI messages: use chat-specific foreground color
19998
+ ),
19999
+ children: isAssistantMessage ? /* @__PURE__ */ jsx58(
20000
+ AssistantMessage,
20001
+ {
20002
+ message: {
20003
+ ...message,
20004
+ type: "assistant"
20005
+ },
20006
+ messages: messages.slice(0, index + 1).map(
20007
+ (item) => ({
20008
+ ...item,
20009
+ type: String(item.type) === "ai" ? "assistant" : item.type
20010
+ })
20011
+ ),
20012
+ isStreaming: isStreamingMessage,
20013
+ streamingStatus,
20014
+ isThreadRunning: currentThreadIsRunning,
20015
+ organizationId: stream.organizationId,
20016
+ apiUrl: stream.apiUrl,
20017
+ pet: effectivePet
20018
+ }
20019
+ ) : /* @__PURE__ */ jsxs40(Fragment9, { children: [
20020
+ message.type === "human" && humanRuntimeCapabilityOptions.length > 0 && /* @__PURE__ */ jsx58(
20021
+ HumanRuntimeCapabilityChips,
20022
+ {
20023
+ options: humanRuntimeCapabilityOptions
20024
+ }
20025
+ ),
20026
+ message.type === "human" && humanReferences.length > 0 && /* @__PURE__ */ jsx58("div", { className: "mb-2 flex flex-wrap gap-1.5", children: humanReferences.map((reference) => /* @__PURE__ */ jsx58(
20027
+ ReferenceChip,
20028
+ {
20029
+ reference,
20030
+ variant: "message"
20031
+ },
20032
+ getReferenceKey(reference)
20033
+ )) }),
20034
+ message.type === "human" && humanAttachments.length > 0 && /* @__PURE__ */ jsx58("div", { className: "flex flex-wrap gap-1.5 mb-2", children: humanAttachments.map((file, fileIndex) => /* @__PURE__ */ jsxs40(
20035
+ "div",
20036
+ {
20037
+ className: "flex items-center gap-1.5 rounded-md bg-primary-foreground/20 px-2 py-1 text-xs",
20038
+ children: [
20039
+ /* @__PURE__ */ jsx58(FileText5, { size: 12 }),
20040
+ /* @__PURE__ */ jsx58("span", { className: "max-w-[100px] truncate", children: file.originalName ?? file.id })
20041
+ ]
20042
+ },
20043
+ fileIndex
20044
+ )) }),
20045
+ Array.isArray(message.content) ? message.content.map((part, partIndex) => /* @__PURE__ */ jsx58(
20046
+ "p",
20047
+ {
20048
+ className: "wrap-break-word text-sm leading-relaxed",
20049
+ children: formatMessageContent(part)
20050
+ },
20051
+ `${part.type}-${partIndex}`
20052
+ )) : /* @__PURE__ */ jsx58("span", { className: "wrap-break-word text-sm leading-relaxed", children: formatMessageContent(message.content) })
20053
+ ] })
20054
+ }
20055
+ ),
20056
+ /* @__PURE__ */ jsx58(
20057
+ MessageActions,
20058
+ {
20059
+ content: messageContent,
20060
+ isAssistant: isAssistantMessage,
20061
+ isStreaming: isStreamingMessage,
20062
+ onRetry: isAssistantMessage && !stream.isLoading && index === messages.length - 1 ? () => handleRetry(index) : void 0
20063
+ }
20064
+ )
20065
+ ]
18876
20066
  }
18877
20067
  )
20068
+ },
20069
+ message.id ?? `${message.type}-${index}`
20070
+ );
20071
+ }),
20072
+ showLoadingDots && (() => {
20073
+ const lastMessage = messages[messages.length - 1];
20074
+ const lastMessageType = lastMessage ? String(lastMessage.type) : "";
20075
+ const isLastMessageFromAI = lastMessageType === "ai" || lastMessageType === "assistant";
20076
+ const lastAssistantStatus = isLastMessageFromAI ? getAssistantStreamingStatus(
20077
+ {
20078
+ ...lastMessage,
20079
+ lastStreamOutputAt: lastStreamOutputAtRef.current
20080
+ },
20081
+ stream.isLoading,
20082
+ { now: streamingNow }
20083
+ ) : null;
20084
+ if (lastAssistantStatus) return null;
20085
+ const fallbackStreamingStatus = getAssistantStreamingStatus(
20086
+ {
20087
+ status: void 0,
20088
+ reasoning: void 0,
20089
+ lastStreamOutputAt: lastStreamOutputAtRef.current
20090
+ },
20091
+ stream.isLoading,
20092
+ { now: streamingNow }
20093
+ );
20094
+ return /* @__PURE__ */ jsx58("div", { className: "flex justify-start gap-3 -ml-2", children: /* @__PURE__ */ jsx58("div", { className: "max-w-full rounded-2xl py-2.5", children: /* @__PURE__ */ jsx58(
20095
+ AssistantStreamingIndicator,
20096
+ {
20097
+ status: fallbackStreamingStatus ?? "loading"
18878
20098
  }
18879
- ) }),
18880
- /* @__PURE__ */ jsx57(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
18881
- ] })
20099
+ ) }) });
20100
+ })()
18882
20101
  ] })
18883
20102
  ]
18884
20103
  }
18885
20104
  ),
18886
- /* @__PURE__ */ jsx57(
18887
- PendingRuntimeServices,
18888
- {
18889
- state: stream.runtimeActivities.sandboxServices,
18890
- onStopService: (serviceId) => stream.stopRuntimeActivityItem("sandbox-services", serviceId),
18891
- attachToComposer: !hasPendingTodos && !hasPendingFollowUps,
18892
- className: hasPendingTodos || hasPendingFollowUps ? "mb-2" : void 0
18893
- }
18894
- ),
18895
- /* @__PURE__ */ jsx57(
18896
- PendingTodos,
18897
- {
18898
- snapshot: stream.todos,
18899
- attachToComposer: !hasPendingFollowUps,
18900
- className: hasPendingFollowUps ? "mb-2" : void 0
18901
- }
18902
- ),
18903
- /* @__PURE__ */ jsx57(
18904
- PendingFollowUps,
20105
+ !isAtBottom && messages.length > 0 && /* @__PURE__ */ jsx58("div", { className: "sticky bottom-20 z-20 flex justify-center px-4 pointer-events-none", children: /* @__PURE__ */ jsx58(
20106
+ Button,
18905
20107
  {
18906
- items: pendingFollowUps,
18907
- isLoading: stream.isLoading,
18908
- onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
18909
- canSendNow: stream.canSendPendingFollowUpNow,
18910
- onSendNow: (id) => stream.sendPendingFollowUpNow(id),
18911
- onEdit: handleEditPendingFollowUp,
18912
- onRemove: stream.removePendingFollowUp,
18913
- attachToComposer: true
18914
- }
18915
- ),
18916
- /* @__PURE__ */ jsx57(
18917
- RequestUserInputPanel,
18918
- {
18919
- request: stream.pendingRequestUserInput,
18920
- onSubmit: stream.submitRequestUserInput,
18921
- onDismiss: stream.stop,
18922
- attachToComposer: true
18923
- }
18924
- ),
18925
- /* @__PURE__ */ jsx57(
18926
- HITLApprovalPanel,
18927
- {
18928
- request: stream.pendingHITLRequest,
18929
- onSubmit: stream.submitHITLDecision,
18930
- onDismiss: stream.stop,
18931
- attachToComposer: true
20108
+ type: "button",
20109
+ size: "icon-sm",
20110
+ variant: hasUpdatesBelow ? "default" : "outline",
20111
+ className: cn(
20112
+ "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)]",
20113
+ hasUpdatesBelow && "animate-bounce"
20114
+ ),
20115
+ onClick: () => scrollToBottom(true, true),
20116
+ "aria-label": t("chat.scrollToBottom"),
20117
+ title: t("chat.scrollToBottom"),
20118
+ children: /* @__PURE__ */ jsx58(ArrowDown2, { size: 16 })
18932
20119
  }
18933
- ),
18934
- runtimeCapabilityPalette && /* @__PURE__ */ jsx57(
18935
- SlashPalette,
20120
+ ) }),
20121
+ quoteSelection && /* @__PURE__ */ jsx58(
20122
+ "div",
18936
20123
  {
18937
- palette: runtimeCapabilityPalette,
18938
- options: slashPaletteOptions,
18939
- paletteRef: slashPaletteRef,
18940
- optionRefs: slashPaletteOptionRefs,
18941
- panelRoundedClass: getPanelRoundedClass(theme.radius),
18942
- itemRoundedClass: getMenuItemRoundedClass(theme.radius),
18943
- emptyLabel: slashPaletteEmptyLabel,
18944
- capabilityEmptyLabels: slashPaletteCapabilityEmptyLabels,
18945
- onSelect: selectSlashPaletteOption
20124
+ className: "pointer-events-none fixed z-50",
20125
+ style: {
20126
+ top: `${quoteSelection.top}px`,
20127
+ left: `${quoteSelection.left}px`,
20128
+ transform: "translateX(-50%)"
20129
+ },
20130
+ children: /* @__PURE__ */ jsxs40(
20131
+ Button,
20132
+ {
20133
+ type: "button",
20134
+ size: "sm",
20135
+ variant: "secondary",
20136
+ className: "pointer-events-auto shadow-lg",
20137
+ onMouseDown: (event) => event.preventDefault(),
20138
+ onClick: handleQuoteSelection,
20139
+ "aria-label": t("composer.quoteSelection"),
20140
+ title: t("composer.quoteSelection"),
20141
+ children: [
20142
+ /* @__PURE__ */ jsx58(Quote, { size: 14 }),
20143
+ t("composer.quoteSelection")
20144
+ ]
20145
+ }
20146
+ )
18946
20147
  }
18947
20148
  ),
18948
- /* @__PURE__ */ jsx57("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs39(
20149
+ /* @__PURE__ */ jsxs40(
18949
20150
  "div",
18950
20151
  {
18951
- "data-slot": "composer-input-shell",
18952
- "data-layout": isComposerStacked ? "stacked" : "inline",
18953
- className: cn(
18954
- "relative flex flex-1 overflow-hidden",
18955
- "bg-background border border-border shadow-sm",
18956
- isComposerStacked ? "min-h-[5.5rem] px-1.5 pt-1.5 pb-12" : "min-h-12 px-1.5 py-1",
18957
- "focus-within:border-muted-foreground/30 focus-within:shadow-md",
18958
- "transition-[min-height,padding,border-radius,box-shadow,border-color] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
18959
- composerInputRoundedClass
18960
- ),
20152
+ "data-slot": "chatkit-chat-composer",
20153
+ className: "mx-auto w-full p-2 sticky bottom-0 z-10 bg-background",
20154
+ style: chatColumnStyle,
18961
20155
  children: [
18962
- /* @__PURE__ */ jsx57(
18963
- "div",
20156
+ threadErrorMessage && /* @__PURE__ */ jsx58("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 }),
20157
+ /* @__PURE__ */ jsx58(
20158
+ ChatAttachments,
18964
20159
  {
18965
- ref: composerInputRef,
18966
- role: "textbox",
18967
- "aria-multiline": "true",
18968
- "aria-disabled": missingConfig || isHistoryLoading || hasPendingInteractiveRequest,
18969
- contentEditable: !(missingConfig || isHistoryLoading || hasPendingInteractiveRequest),
18970
- suppressContentEditableWarning: true,
18971
- onInput: handleComposerInput,
18972
- onCompositionEnd: handleComposerCompositionEnd,
18973
- onSelect: handleComposerSelect,
18974
- onPaste: handleComposerPaste,
18975
- onKeyDown: handleComposerKeyDown,
18976
- "data-placeholder": inputPlaceholder,
18977
- className: cn(
18978
- "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)]",
18979
- isComposerStacked ? "px-2 py-1.5" : "py-1 pr-11 pl-11 mt-1",
18980
- "empty:before:pointer-events-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
18981
- (missingConfig || isHistoryLoading || hasPendingInteractiveRequest) && "cursor-not-allowed opacity-50"
20160
+ ref: attachmentsRef,
20161
+ accept: acceptMimes,
20162
+ maxCount: composer?.attachments?.maxCount ?? 10,
20163
+ maxSize: composer?.attachments?.maxSize ?? 100 * 1024 * 1024,
20164
+ retryUploadLabel: t("chat.retryUpload"),
20165
+ uploadFile: uploadContextFile,
20166
+ deleteFile: deleteContextFile,
20167
+ getFileStatus: getContextFileStatus,
20168
+ onStateChange: setAttachmentState
20169
+ }
20170
+ ),
20171
+ references.length > 0 && /* @__PURE__ */ jsx58("div", { className: "mb-3 flex flex-wrap gap-2", children: references.map((reference) => /* @__PURE__ */ jsx58(
20172
+ ReferenceChip,
20173
+ {
20174
+ reference,
20175
+ variant: "composer",
20176
+ onRemove: () => setReferences(
20177
+ (previous) => previous.filter(
20178
+ (item) => getReferenceKey(item) !== getReferenceKey(reference)
20179
+ )
18982
20180
  ),
18983
- children: renderedComposerParts.map(
18984
- (part, index) => part.type === "text" ? /* @__PURE__ */ jsx57(React52.Fragment, { children: part.text }, `text-${index}`) : /* @__PURE__ */ jsx57(ComposerCapabilityToken, { part }, part.key)
18985
- )
20181
+ removeLabel: t("composer.removeReference")
18986
20182
  },
18987
- composerDomVersion
20183
+ getReferenceKey(reference)
20184
+ )) }),
20185
+ /* @__PURE__ */ jsx58(
20186
+ DetachedRunRuntimeCapabilities,
20187
+ {
20188
+ options: detachedRunRuntimeCapabilityOptions,
20189
+ runOnlyLabel: t("composer.capabilities.runOnly"),
20190
+ removeLabel: t("composer.capabilities.removeRunCapability"),
20191
+ onRemove: removeRunRuntimeCapability
20192
+ }
18988
20193
  ),
18989
- /* @__PURE__ */ jsxs39(
20194
+ showGoalStatus && /* @__PURE__ */ jsxs40(
18990
20195
  "div",
18991
20196
  {
18992
- "data-slot": "composer-action-bar",
18993
- className: "pointer-events-none absolute inset-x-1.5 bottom-1 flex min-h-10 items-center justify-between gap-2",
20197
+ className: cn(
20198
+ "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",
20199
+ isGoalObjectiveExpanded ? "items-start" : "items-center"
20200
+ ),
18994
20201
  children: [
18995
- /* @__PURE__ */ jsxs39("div", { className: "pointer-events-none flex min-w-0 flex-1 items-center gap-1.5", children: [
18996
- /* @__PURE__ */ jsx57("div", { className: "pointer-events-auto flex shrink-0 items-center gap-1.5", children: /* @__PURE__ */ jsx57(
18997
- ComposerMenu,
20202
+ /* @__PURE__ */ jsx58(
20203
+ Target3,
20204
+ {
20205
+ className: cn(
20206
+ "size-4 shrink-0 text-muted-foreground",
20207
+ isGoalObjectiveExpanded && "mt-1"
20208
+ )
20209
+ }
20210
+ ),
20211
+ /* @__PURE__ */ jsxs40("div", { className: "min-w-0 flex-1", children: [
20212
+ /* @__PURE__ */ jsxs40("div", { className: "flex min-w-0 items-center gap-2", children: [
20213
+ /* @__PURE__ */ jsx58("span", { className: "font-medium", children: t("chat.goal.label") }),
20214
+ threadGoal && /* @__PURE__ */ jsx58("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}`) }),
20215
+ isGoalLoading && /* @__PURE__ */ jsx58(Loader210, { className: "size-3 animate-spin text-muted-foreground" })
20216
+ ] }),
20217
+ /* @__PURE__ */ jsx58(
20218
+ "div",
18998
20219
  {
18999
- composer,
19000
- onAttachmentClick: handleAttachmentClick,
19001
- onToolSelect: handleToolSelect,
19002
- selectedTool,
19003
- planModeEnabled,
19004
- onPlanModeChange: setPlanModeEnabled,
19005
- goalCommandAvailable,
19006
- goalPanelOpen: isGoalModeOpen,
19007
- onGoalPanelOpenChange: handleGoalPanelOpenChange,
19008
- runtimeCapabilities: runtimeCapabilitiesReady ? runtimeCapabilities : null,
19009
- selectedRuntimeCapabilities: effectiveSessionRuntimeCapabilities,
19010
- onRuntimeCapabilityToggle: handleSessionRuntimeCapabilityToggle,
19011
- disabled: missingConfig || isHistoryLoading || hasPendingInteractiveRequest
20220
+ className: cn(
20221
+ "mt-0.5 text-muted-foreground",
20222
+ threadGoal?.objective && !goalError && isGoalObjectiveExpanded ? "whitespace-pre-wrap break-words" : "truncate"
20223
+ ),
20224
+ children: goalError || threadGoal?.objective
19012
20225
  }
19013
- ) }),
19014
- selectedTool && /* @__PURE__ */ jsxs39("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: [
19015
- /* @__PURE__ */ jsx57("span", { className: "truncate", children: selectedTool.shortLabel ?? selectedTool.label }),
19016
- /* @__PURE__ */ jsx57(
19017
- "button",
20226
+ ),
20227
+ threadGoal && /* @__PURE__ */ jsx58("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground", children: /* @__PURE__ */ jsx58("span", { children: t("chat.goal.elapsed", {
20228
+ elapsed: formatGoalElapsed(displayedGoalElapsedSeconds)
20229
+ }) }) })
20230
+ ] }),
20231
+ threadGoal && /* @__PURE__ */ jsxs40("div", { className: "flex shrink-0 items-center gap-1", children: [
20232
+ /* @__PURE__ */ jsxs40(Tooltip, { children: [
20233
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58(
20234
+ Button,
19018
20235
  {
19019
20236
  type: "button",
19020
- onClick: () => setSelectedTool(null),
19021
- className: "shrink-0 rounded-full p-0.5 text-primary/70 hover:bg-primary/10 hover:text-primary",
19022
- children: /* @__PURE__ */ jsx57(X7, { size: 12 })
20237
+ variant: "ghost",
20238
+ size: "icon-xs",
20239
+ disabled: isGoalLoading,
20240
+ onClick: () => {
20241
+ const prefix = "/goal edit ";
20242
+ setComposerText(`${prefix}${threadGoal.objective}`);
20243
+ },
20244
+ children: /* @__PURE__ */ jsx58(Pencil4, { className: "size-3" })
19023
20245
  }
19024
- )
19025
- ] })
19026
- ] }),
19027
- /* @__PURE__ */ jsx57("div", { className: "pointer-events-auto shrink-0", children: /* @__PURE__ */ jsx57(
19028
- SendButton,
19029
- {
19030
- disabled: isSendDisabled,
19031
- isLoading: stream.isLoading,
19032
- showStop: stream.isLoading && (!trimmedDraft || hasPendingInteractiveRequest),
19033
- onStop: () => stream.stop(),
19034
- stopLabel: t("chat.stop"),
19035
- sendLabel: t("chat.send"),
19036
- shortcuts: stream.isLoading && trimmedDraft ? [
20246
+ ) }),
20247
+ /* @__PURE__ */ jsx58(TooltipContent, { children: t("chat.goal.edit") })
20248
+ ] }),
20249
+ /* @__PURE__ */ jsxs40(Tooltip, { children: [
20250
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58(
20251
+ Button,
20252
+ {
20253
+ type: "button",
20254
+ variant: "ghost",
20255
+ size: "icon-xs",
20256
+ disabled: isGoalLoading,
20257
+ onClick: () => void handleGoalCommand({
20258
+ args: threadGoal.status === "paused" ? "resume" : "pause",
20259
+ commandSource: {
20260
+ type: "slash_command",
20261
+ name: "goal",
20262
+ source: "runtime",
20263
+ executionType: "insert_invocation"
20264
+ }
20265
+ }),
20266
+ children: threadGoal.status === "paused" ? /* @__PURE__ */ jsx58(Play, { className: "size-3" }) : /* @__PURE__ */ jsx58(Pause, { className: "size-3" })
20267
+ }
20268
+ ) }),
20269
+ /* @__PURE__ */ jsx58(TooltipContent, { children: threadGoal.status === "paused" ? t("chat.goal.resume") : t("chat.goal.pause") })
20270
+ ] }),
20271
+ /* @__PURE__ */ jsxs40(Tooltip, { children: [
20272
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58(
20273
+ Button,
19037
20274
  {
19038
- label: t("chat.followUps.queue"),
19039
- keys: "Enter"
20275
+ type: "button",
20276
+ variant: "ghost",
20277
+ size: "icon-xs",
20278
+ disabled: isGoalLoading,
20279
+ onClick: () => void handleGoalCommand({
20280
+ args: "clear",
20281
+ commandSource: {
20282
+ type: "slash_command",
20283
+ name: "goal",
20284
+ source: "runtime",
20285
+ executionType: "insert_invocation"
20286
+ }
20287
+ }),
20288
+ children: /* @__PURE__ */ jsx58(Trash23, { className: "size-3" })
19040
20289
  }
19041
- ] : void 0
20290
+ ) }),
20291
+ /* @__PURE__ */ jsx58(TooltipContent, { children: t("chat.goal.clear") })
20292
+ ] }),
20293
+ threadGoal.objective && !goalError && /* @__PURE__ */ jsxs40(Tooltip, { children: [
20294
+ /* @__PURE__ */ jsx58(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx58(
20295
+ Button,
20296
+ {
20297
+ type: "button",
20298
+ variant: "ghost",
20299
+ size: "icon-xs",
20300
+ "aria-expanded": isGoalObjectiveExpanded,
20301
+ "aria-label": isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective"),
20302
+ onClick: () => setIsGoalObjectiveExpanded((expanded) => !expanded),
20303
+ children: /* @__PURE__ */ jsx58(
20304
+ ChevronDown5,
20305
+ {
20306
+ className: cn(
20307
+ "size-3 transition-transform",
20308
+ isGoalObjectiveExpanded && "rotate-180"
20309
+ )
20310
+ }
20311
+ )
20312
+ }
20313
+ ) }),
20314
+ /* @__PURE__ */ jsx58(TooltipContent, { children: isGoalObjectiveExpanded ? t("chat.goal.collapseObjective") : t("chat.goal.expandObjective") })
20315
+ ] })
20316
+ ] })
20317
+ ]
20318
+ }
20319
+ ),
20320
+ /* @__PURE__ */ jsx58(
20321
+ PendingRuntimeServices,
20322
+ {
20323
+ state: stream.runtimeActivities.sandboxServices,
20324
+ onStopService: (serviceId) => stream.stopRuntimeActivityItem("sandbox-services", serviceId),
20325
+ attachToComposer: !hasPendingTodos && !hasPendingFollowUps,
20326
+ className: hasPendingTodos || hasPendingFollowUps ? "mb-2" : void 0
20327
+ }
20328
+ ),
20329
+ /* @__PURE__ */ jsx58(
20330
+ PendingTodos,
20331
+ {
20332
+ snapshot: stream.todos,
20333
+ attachToComposer: !hasPendingFollowUps,
20334
+ className: hasPendingFollowUps ? "mb-2" : void 0
20335
+ }
20336
+ ),
20337
+ /* @__PURE__ */ jsx58(
20338
+ PendingFollowUps,
20339
+ {
20340
+ items: pendingFollowUps,
20341
+ isLoading: stream.isLoading,
20342
+ onPromoteToSteer: (id) => stream.promotePendingFollowUpToSteer(id),
20343
+ canSendNow: stream.canSendPendingFollowUpNow,
20344
+ onSendNow: (id) => stream.sendPendingFollowUpNow(id),
20345
+ onEdit: handleEditPendingFollowUp,
20346
+ onRemove: stream.removePendingFollowUp,
20347
+ attachToComposer: true
20348
+ }
20349
+ ),
20350
+ /* @__PURE__ */ jsx58(
20351
+ RequestUserInputPanel,
20352
+ {
20353
+ request: stream.pendingRequestUserInput,
20354
+ onSubmit: stream.submitRequestUserInput,
20355
+ onDismiss: stream.stop,
20356
+ attachToComposer: true
20357
+ }
20358
+ ),
20359
+ /* @__PURE__ */ jsx58(
20360
+ HITLApprovalPanel,
20361
+ {
20362
+ request: stream.pendingHITLRequest,
20363
+ onSubmit: stream.submitHITLDecision,
20364
+ onDismiss: stream.stop,
20365
+ attachToComposer: true
20366
+ }
20367
+ ),
20368
+ runtimeCapabilityPalette && /* @__PURE__ */ jsx58(
20369
+ SlashPalette,
20370
+ {
20371
+ palette: runtimeCapabilityPalette,
20372
+ options: slashPaletteOptions,
20373
+ paletteRef: slashPaletteRef,
20374
+ optionRefs: slashPaletteOptionRefs,
20375
+ panelRoundedClass: getPanelRoundedClass(theme.radius),
20376
+ itemRoundedClass: getMenuItemRoundedClass(theme.radius),
20377
+ emptyLabel: slashPaletteEmptyLabel,
20378
+ capabilityEmptyLabels: slashPaletteCapabilityEmptyLabels,
20379
+ onSelect: selectSlashPaletteOption
20380
+ }
20381
+ ),
20382
+ /* @__PURE__ */ jsx58("form", { className: "flex items-end", onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs40(
20383
+ "div",
20384
+ {
20385
+ "data-slot": "composer-input-shell",
20386
+ "data-layout": isComposerStacked ? "stacked" : "inline",
20387
+ className: cn(
20388
+ "relative flex flex-1 overflow-hidden",
20389
+ "bg-background border border-border shadow-sm",
20390
+ isComposerStacked ? "min-h-[5.5rem] px-1.5 pt-1.5 pb-12" : "min-h-12 px-1.5 py-1",
20391
+ "focus-within:border-muted-foreground/30 focus-within:shadow-md",
20392
+ "transition-[min-height,padding,border-radius,box-shadow,border-color] duration-300 ease-[cubic-bezier(0.2,0.8,0.2,1)]",
20393
+ composerInputRoundedClass
20394
+ ),
20395
+ children: [
20396
+ /* @__PURE__ */ jsx58(
20397
+ "div",
20398
+ {
20399
+ ref: composerInputRef,
20400
+ role: "textbox",
20401
+ "aria-multiline": "true",
20402
+ "aria-disabled": missingConfig || isHistoryLoading || hasPendingInteractiveRequest,
20403
+ contentEditable: !(missingConfig || isHistoryLoading || hasPendingInteractiveRequest),
20404
+ suppressContentEditableWarning: true,
20405
+ onInput: handleComposerInput,
20406
+ onCompositionEnd: handleComposerCompositionEnd,
20407
+ onSelect: handleComposerSelect,
20408
+ onPaste: handleComposerPaste,
20409
+ onKeyDown: handleComposerKeyDown,
20410
+ "data-placeholder": inputPlaceholder,
20411
+ className: cn(
20412
+ "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)]",
20413
+ isComposerStacked ? "px-2 py-1.5" : "py-1 pr-11 pl-11 mt-1",
20414
+ "empty:before:pointer-events-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
20415
+ (missingConfig || isHistoryLoading || hasPendingInteractiveRequest) && "cursor-not-allowed opacity-50"
20416
+ ),
20417
+ children: renderedComposerParts.map(
20418
+ (part, index) => part.type === "text" ? /* @__PURE__ */ jsx58(React54.Fragment, { children: part.text }, `text-${index}`) : /* @__PURE__ */ jsx58(ComposerCapabilityToken, { part }, part.key)
20419
+ )
20420
+ },
20421
+ composerDomVersion
20422
+ ),
20423
+ /* @__PURE__ */ jsxs40(
20424
+ "div",
20425
+ {
20426
+ "data-slot": "composer-action-bar",
20427
+ className: "pointer-events-none absolute inset-x-1.5 bottom-1 flex min-h-10 items-center justify-between gap-2",
20428
+ children: [
20429
+ /* @__PURE__ */ jsxs40("div", { className: "pointer-events-none flex min-w-0 flex-1 items-center gap-1.5", children: [
20430
+ /* @__PURE__ */ jsx58("div", { className: "pointer-events-auto flex shrink-0 items-center gap-1.5", children: /* @__PURE__ */ jsx58(
20431
+ ComposerMenu,
20432
+ {
20433
+ composer,
20434
+ onAttachmentClick: handleAttachmentClick,
20435
+ onToolSelect: handleToolSelect,
20436
+ selectedTool,
20437
+ planModeEnabled,
20438
+ onPlanModeChange: setPlanModeEnabled,
20439
+ goalCommandAvailable,
20440
+ goalPanelOpen: isGoalModeOpen,
20441
+ onGoalPanelOpenChange: handleGoalPanelOpenChange,
20442
+ runtimeCapabilities: runtimeCapabilitiesReady ? runtimeCapabilities : null,
20443
+ selectedRuntimeCapabilities: effectiveSessionRuntimeCapabilities,
20444
+ onRuntimeCapabilityToggle: handleSessionRuntimeCapabilityToggle,
20445
+ disabled: missingConfig || isHistoryLoading || hasPendingInteractiveRequest
20446
+ }
20447
+ ) }),
20448
+ selectedTool && /* @__PURE__ */ jsxs40("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: [
20449
+ /* @__PURE__ */ jsx58("span", { className: "truncate", children: selectedTool.shortLabel ?? selectedTool.label }),
20450
+ /* @__PURE__ */ jsx58(
20451
+ "button",
20452
+ {
20453
+ type: "button",
20454
+ onClick: () => setSelectedTool(null),
20455
+ className: "shrink-0 rounded-full p-0.5 text-primary/70 hover:bg-primary/10 hover:text-primary",
20456
+ children: /* @__PURE__ */ jsx58(X7, { size: 12 })
20457
+ }
20458
+ )
20459
+ ] })
20460
+ ] }),
20461
+ /* @__PURE__ */ jsx58("div", { className: "pointer-events-auto shrink-0", children: /* @__PURE__ */ jsx58(
20462
+ SendButton,
20463
+ {
20464
+ disabled: isSendDisabled,
20465
+ isLoading: stream.isLoading,
20466
+ showStop: stream.isLoading && (!trimmedDraft || hasPendingInteractiveRequest),
20467
+ onStop: () => stream.stop(),
20468
+ stopLabel: t("chat.stop"),
20469
+ sendLabel: t("chat.send"),
20470
+ shortcuts: stream.isLoading && trimmedDraft ? [
20471
+ {
20472
+ label: t("chat.followUps.queue"),
20473
+ keys: "Enter"
20474
+ }
20475
+ ] : void 0
20476
+ }
20477
+ ) })
20478
+ ]
19042
20479
  }
19043
- ) })
20480
+ )
19044
20481
  ]
19045
20482
  }
19046
- )
20483
+ ) }),
20484
+ disclaimer?.text && /* @__PURE__ */ jsx58(
20485
+ "p",
20486
+ {
20487
+ className: cn(
20488
+ "mt-2 text-center text-xs",
20489
+ disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
20490
+ ),
20491
+ children: disclaimer.text
20492
+ }
20493
+ ),
20494
+ /* @__PURE__ */ jsxs40("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
20495
+ /* @__PURE__ */ jsx58("span", { children: t("chat.poweredBy") }),
20496
+ /* @__PURE__ */ jsx58(ContextUsageIndicator, { className: "absolute right-4" })
20497
+ ] })
19047
20498
  ]
19048
20499
  }
19049
- ) }),
19050
- disclaimer?.text && /* @__PURE__ */ jsx57(
19051
- "p",
20500
+ ),
20501
+ /* @__PURE__ */ jsx58(
20502
+ SettingsSheet,
19052
20503
  {
19053
- className: cn(
19054
- "mt-2 text-center text-xs",
19055
- disclaimer.highContrast ? "text-foreground" : "text-muted-foreground"
19056
- ),
19057
- children: disclaimer.text
20504
+ open: petSettingsOpen,
20505
+ settings: displayedPetSettings,
20506
+ petRequired,
20507
+ onOpenChange: setPetSettingsOpen,
20508
+ onSave: savePetLocalSettings
19058
20509
  }
19059
20510
  ),
19060
- /* @__PURE__ */ jsxs39("div", { className: "mt-2 flex items-center justify-center gap-2 text-xs text-muted-foreground", children: [
19061
- /* @__PURE__ */ jsx57("span", { children: t("chat.poweredBy") }),
19062
- /* @__PURE__ */ jsx57(ContextUsageIndicator, { className: "absolute right-4" })
19063
- ] })
20511
+ /* @__PURE__ */ jsx58(PetBridge, { pet: effectivePet, state: petAutoState })
19064
20512
  ]
19065
20513
  }
19066
20514
  ),
19067
- /* @__PURE__ */ jsx57(
19068
- SettingsSheet,
20515
+ taskSummaryAvailable && taskSummaryDocked && taskSummaryOpen && /* @__PURE__ */ jsx58("div", { className: "pointer-events-none absolute right-5 top-3 z-20 max-h-[calc(100%-1.5rem)] w-80", children: /* @__PURE__ */ jsx58(
20516
+ TaskSummaryPanel,
19069
20517
  {
19070
- open: petSettingsOpen,
19071
- settings: displayedPetSettings,
19072
- petRequired,
19073
- onOpenChange: setPetSettingsOpen,
19074
- onSave: savePetLocalSettings
20518
+ ...taskSummaryProps,
20519
+ className: "pointer-events-auto max-h-full"
19075
20520
  }
19076
- ),
19077
- /* @__PURE__ */ jsx57(PetBridge, { pet: effectivePet, state: petAutoState })
20521
+ ) })
19078
20522
  ]
19079
20523
  }
19080
20524
  );
19081
20525
  }
19082
20526
 
19083
20527
  // src/components/ui/separator.tsx
19084
- import * as React53 from "react";
19085
- import { jsx as jsx58 } from "react/jsx-runtime";
19086
- var Separator = React53.forwardRef(
19087
- ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ jsx58(
20528
+ import * as React55 from "react";
20529
+ import { jsx as jsx59 } from "react/jsx-runtime";
20530
+ var Separator = React55.forwardRef(
20531
+ ({ className, orientation = "horizontal", ...props }, ref) => /* @__PURE__ */ jsx59(
19088
20532
  "div",
19089
20533
  {
19090
20534
  ref,