@sinm/kai 1.10.11 → 1.10.12

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 (130) hide show
  1. package/RELEASE_NOTES.md +33 -0
  2. package/dist-cli/kai-cli.js +7039 -5545
  3. package/dist-electron/renderer/assets/{_baseUniq-CuYKmvg2.js → _baseUniq-Cd6KMhyP.js} +1 -1
  4. package/dist-electron/renderer/assets/_baseUniq-Cd6KMhyP.js.gz +0 -0
  5. package/dist-electron/renderer/assets/{arc-wbF5WnQV.js → arc-BeDNmpya.js} +1 -1
  6. package/dist-electron/renderer/assets/arc-BeDNmpya.js.gz +0 -0
  7. package/dist-electron/renderer/assets/{architectureDiagram-Q4EWVU46-hlZU-AYP.js → architectureDiagram-Q4EWVU46-CnWU5PnR.js} +5 -5
  8. package/dist-electron/renderer/assets/architectureDiagram-Q4EWVU46-CnWU5PnR.js.gz +0 -0
  9. package/dist-electron/renderer/assets/{blockDiagram-DXYQGD6D-BUWOFiwr.js → blockDiagram-DXYQGD6D-B9rNlDVj.js} +6 -6
  10. package/dist-electron/renderer/assets/blockDiagram-DXYQGD6D-B9rNlDVj.js.gz +0 -0
  11. package/dist-electron/renderer/assets/{c4Diagram-AHTNJAMY-DMdJwQt_.js → c4Diagram-AHTNJAMY-DTgNP3Iw.js} +2 -2
  12. package/dist-electron/renderer/assets/c4Diagram-AHTNJAMY-DTgNP3Iw.js.gz +0 -0
  13. package/dist-electron/renderer/assets/{channel-D3joe8D2.js → channel-BfZUuPdo.js} +1 -1
  14. package/dist-electron/renderer/assets/{chunk-4BX2VUAB-B-lkn6Ra.js → chunk-4BX2VUAB-l5bA-Sjq.js} +1 -1
  15. package/dist-electron/renderer/assets/{chunk-4TB4RGXK-CvsgJjGn.js → chunk-4TB4RGXK-CdlbWYt_.js} +5 -5
  16. package/dist-electron/renderer/assets/chunk-4TB4RGXK-CdlbWYt_.js.gz +0 -0
  17. package/dist-electron/renderer/assets/{chunk-55IACEB6-iojbbU_5.js → chunk-55IACEB6-DoWfU52U.js} +1 -1
  18. package/dist-electron/renderer/assets/{chunk-EDXVE4YY-4OVSdmJJ.js → chunk-EDXVE4YY-BzNNBO_8.js} +1 -1
  19. package/dist-electron/renderer/assets/chunk-EDXVE4YY-BzNNBO_8.js.gz +0 -0
  20. package/dist-electron/renderer/assets/{chunk-FMBD7UC4-BIhRhPTv.js → chunk-FMBD7UC4-kZ24-i_g.js} +1 -1
  21. package/dist-electron/renderer/assets/{chunk-OYMX7WX6-Bc0TINts.js → chunk-OYMX7WX6-BcAHPOyy.js} +3 -3
  22. package/dist-electron/renderer/assets/chunk-OYMX7WX6-BcAHPOyy.js.gz +0 -0
  23. package/dist-electron/renderer/assets/{chunk-QZHKN3VN-AghpssW7.js → chunk-QZHKN3VN-CAHKGd6k.js} +1 -1
  24. package/dist-electron/renderer/assets/{chunk-YZCP3GAM-BjXXEobK.js → chunk-YZCP3GAM-bwnLI33o.js} +1 -1
  25. package/dist-electron/renderer/assets/chunk-YZCP3GAM-bwnLI33o.js.gz +0 -0
  26. package/dist-electron/renderer/assets/{classDiagram-6PBFFD2Q-CO01xt-j.js → classDiagram-6PBFFD2Q-CUB864F9.js} +6 -6
  27. package/dist-electron/renderer/assets/{classDiagram-v2-HSJHXN6E-CO01xt-j.js → classDiagram-v2-HSJHXN6E-CUB864F9.js} +6 -6
  28. package/dist-electron/renderer/assets/{clone-Dgq5O-yi.js → clone-xmHKp1sq.js} +1 -1
  29. package/dist-electron/renderer/assets/{cose-bilkent-S5V4N54A-CJLnhbhw.js → cose-bilkent-S5V4N54A-ByOVyfu_.js} +1 -1
  30. package/dist-electron/renderer/assets/cose-bilkent-S5V4N54A-ByOVyfu_.js.gz +0 -0
  31. package/dist-electron/renderer/assets/{dagre-KV5264BT-DdUSLopE.js → dagre-KV5264BT-Cg9YT1xz.js} +6 -6
  32. package/dist-electron/renderer/assets/dagre-KV5264BT-Cg9YT1xz.js.gz +0 -0
  33. package/dist-electron/renderer/assets/{diagram-5BDNPKRD-DQC5xE5U.js → diagram-5BDNPKRD-N-r5wCxr.js} +6 -6
  34. package/dist-electron/renderer/assets/diagram-5BDNPKRD-N-r5wCxr.js.gz +0 -0
  35. package/dist-electron/renderer/assets/{diagram-G4DWMVQ6-CCPlHnyE.js → diagram-G4DWMVQ6-BA5GZndq.js} +6 -6
  36. package/dist-electron/renderer/assets/diagram-G4DWMVQ6-BA5GZndq.js.gz +0 -0
  37. package/dist-electron/renderer/assets/{diagram-MMDJMWI5-DBdIw1TA.js → diagram-MMDJMWI5-DBG89SrK.js} +5 -5
  38. package/dist-electron/renderer/assets/diagram-MMDJMWI5-DBG89SrK.js.gz +0 -0
  39. package/dist-electron/renderer/assets/{diagram-TYMM5635-Cli41wXP.js → diagram-TYMM5635-Saa7LkSc.js} +5 -5
  40. package/dist-electron/renderer/assets/diagram-TYMM5635-Saa7LkSc.js.gz +0 -0
  41. package/dist-electron/renderer/assets/{erDiagram-SMLLAGMA-CavyaE_R.js → erDiagram-SMLLAGMA-CCvyAUKF.js} +4 -4
  42. package/dist-electron/renderer/assets/erDiagram-SMLLAGMA-CCvyAUKF.js.gz +0 -0
  43. package/dist-electron/renderer/assets/{flowDiagram-DWJPFMVM-DrbYlj9H.js → flowDiagram-DWJPFMVM-CNAySAhx.js} +6 -6
  44. package/dist-electron/renderer/assets/flowDiagram-DWJPFMVM-CNAySAhx.js.gz +0 -0
  45. package/dist-electron/renderer/assets/{ganttDiagram-T4ZO3ILL-zGFcXLvx.js → ganttDiagram-T4ZO3ILL-CecC2wHb.js} +1 -1
  46. package/dist-electron/renderer/assets/ganttDiagram-T4ZO3ILL-CecC2wHb.js.gz +0 -0
  47. package/dist-electron/renderer/assets/{gitGraphDiagram-UUTBAWPF-DZlVbvmi.js → gitGraphDiagram-UUTBAWPF-DfYql5OI.js} +6 -6
  48. package/dist-electron/renderer/assets/gitGraphDiagram-UUTBAWPF-DfYql5OI.js.gz +0 -0
  49. package/dist-electron/renderer/assets/{graph-DrxVWiWl.js → graph-DU-V9gO6.js} +2 -2
  50. package/dist-electron/renderer/assets/graph-DU-V9gO6.js.gz +0 -0
  51. package/dist-electron/renderer/assets/{index-DMYFeXxm.css → index-Bg2KVBzU.css} +538 -332
  52. package/dist-electron/renderer/assets/index-Bg2KVBzU.css.gz +0 -0
  53. package/dist-electron/renderer/assets/{index-dANVauHS.js → index-Ct9Hwvus.js} +1209 -438
  54. package/dist-electron/renderer/assets/index-Ct9Hwvus.js.gz +0 -0
  55. package/dist-electron/renderer/assets/{infoDiagram-42DDH7IO-DVzQqzB-.js → infoDiagram-42DDH7IO-PPLbRW-4.js} +4 -4
  56. package/dist-electron/renderer/assets/{ishikawaDiagram-UXIWVN3A-fNeI-iIw.js → ishikawaDiagram-UXIWVN3A-BJYqQjNN.js} +1 -1
  57. package/dist-electron/renderer/assets/ishikawaDiagram-UXIWVN3A-BJYqQjNN.js.gz +0 -0
  58. package/dist-electron/renderer/assets/{journeyDiagram-VCZTEJTY-BfNIUZcQ.js → journeyDiagram-VCZTEJTY-DsWKbkeD.js} +4 -4
  59. package/dist-electron/renderer/assets/journeyDiagram-VCZTEJTY-DsWKbkeD.js.gz +0 -0
  60. package/dist-electron/renderer/assets/{kanban-definition-6JOO6SKY-C7CUToPz.js → kanban-definition-6JOO6SKY-CDxJLRZA.js} +2 -2
  61. package/dist-electron/renderer/assets/kanban-definition-6JOO6SKY-CDxJLRZA.js.gz +0 -0
  62. package/dist-electron/renderer/assets/{layout-CHg8GOVl.js → layout-DWL1fnIc.js} +4 -4
  63. package/dist-electron/renderer/assets/layout-DWL1fnIc.js.gz +0 -0
  64. package/dist-electron/renderer/assets/{min-DMOXbVDI.js → min-CH5IMQz3.js} +2 -2
  65. package/dist-electron/renderer/assets/min-CH5IMQz3.js.gz +0 -0
  66. package/dist-electron/renderer/assets/{mindmap-definition-QFDTVHPH-CehXyJEp.js → mindmap-definition-QFDTVHPH-CqllRxov.js} +3 -3
  67. package/dist-electron/renderer/assets/mindmap-definition-QFDTVHPH-CqllRxov.js.gz +0 -0
  68. package/dist-electron/renderer/assets/{pieDiagram-DEJITSTG-D9DSsmFY.js → pieDiagram-DEJITSTG-CbcGJHeL.js} +6 -6
  69. package/dist-electron/renderer/assets/pieDiagram-DEJITSTG-CbcGJHeL.js.gz +0 -0
  70. package/dist-electron/renderer/assets/{quadrantDiagram-34T5L4WZ-C6LACI_u.js → quadrantDiagram-34T5L4WZ-qCo_ja2B.js} +1 -1
  71. package/dist-electron/renderer/assets/quadrantDiagram-34T5L4WZ-qCo_ja2B.js.gz +0 -0
  72. package/dist-electron/renderer/assets/{requirementDiagram-MS252O5E-Cw79fNU0.js → requirementDiagram-MS252O5E-B2Pe66uY.js} +3 -3
  73. package/dist-electron/renderer/assets/requirementDiagram-MS252O5E-B2Pe66uY.js.gz +0 -0
  74. package/dist-electron/renderer/assets/{sankeyDiagram-XADWPNL6-D8qlDZqR.js → sankeyDiagram-XADWPNL6-CzWD-MNf.js} +1 -1
  75. package/dist-electron/renderer/assets/sankeyDiagram-XADWPNL6-CzWD-MNf.js.gz +0 -0
  76. package/dist-electron/renderer/assets/{sequenceDiagram-FGHM5R23-D4pctSQZ.js → sequenceDiagram-FGHM5R23-BZRIOGYF.js} +3 -3
  77. package/dist-electron/renderer/assets/sequenceDiagram-FGHM5R23-BZRIOGYF.js.gz +0 -0
  78. package/dist-electron/renderer/assets/{stateDiagram-FHFEXIEX-DxS1AKAn.js → stateDiagram-FHFEXIEX-CHLPdfbn.js} +8 -8
  79. package/dist-electron/renderer/assets/stateDiagram-FHFEXIEX-CHLPdfbn.js.gz +0 -0
  80. package/dist-electron/renderer/assets/{stateDiagram-v2-QKLJ7IA2-DyH8dH7m.js → stateDiagram-v2-QKLJ7IA2-8iBltSQD.js} +4 -4
  81. package/dist-electron/renderer/assets/{timeline-definition-GMOUNBTQ-CSy9zDBK.js → timeline-definition-GMOUNBTQ-BTKekCiN.js} +2 -2
  82. package/dist-electron/renderer/assets/timeline-definition-GMOUNBTQ-BTKekCiN.js.gz +0 -0
  83. package/dist-electron/renderer/assets/{vennDiagram-DHZGUBPP-r13CGS2k.js → vennDiagram-DHZGUBPP-Ccbx5Aye.js} +1 -1
  84. package/dist-electron/renderer/assets/vennDiagram-DHZGUBPP-Ccbx5Aye.js.gz +0 -0
  85. package/dist-electron/renderer/assets/{wardley-RL74JXVD-DURh8ybw.js → wardley-RL74JXVD-B3wNqgCA.js} +3 -3
  86. package/dist-electron/renderer/assets/wardley-RL74JXVD-B3wNqgCA.js.gz +0 -0
  87. package/dist-electron/renderer/assets/{wardleyDiagram-NUSXRM2D-QMLW6W2D.js → wardleyDiagram-NUSXRM2D-Cw5dzdVm.js} +5 -5
  88. package/dist-electron/renderer/assets/wardleyDiagram-NUSXRM2D-Cw5dzdVm.js.gz +0 -0
  89. package/dist-electron/renderer/assets/{xychartDiagram-5P7HB3ND-B6rq-ItR.js → xychartDiagram-5P7HB3ND-qtorfk-Q.js} +1 -1
  90. package/dist-electron/renderer/assets/{xychartDiagram-5P7HB3ND-B6rq-ItR.js.gz → xychartDiagram-5P7HB3ND-qtorfk-Q.js.gz} +0 -0
  91. package/dist-electron/renderer/index.html +2 -2
  92. package/package.json +1 -1
  93. package/dist-electron/renderer/assets/_baseUniq-CuYKmvg2.js.gz +0 -0
  94. package/dist-electron/renderer/assets/arc-wbF5WnQV.js.gz +0 -0
  95. package/dist-electron/renderer/assets/architectureDiagram-Q4EWVU46-hlZU-AYP.js.gz +0 -0
  96. package/dist-electron/renderer/assets/blockDiagram-DXYQGD6D-BUWOFiwr.js.gz +0 -0
  97. package/dist-electron/renderer/assets/c4Diagram-AHTNJAMY-DMdJwQt_.js.gz +0 -0
  98. package/dist-electron/renderer/assets/chunk-4TB4RGXK-CvsgJjGn.js.gz +0 -0
  99. package/dist-electron/renderer/assets/chunk-EDXVE4YY-4OVSdmJJ.js.gz +0 -0
  100. package/dist-electron/renderer/assets/chunk-OYMX7WX6-Bc0TINts.js.gz +0 -0
  101. package/dist-electron/renderer/assets/chunk-YZCP3GAM-BjXXEobK.js.gz +0 -0
  102. package/dist-electron/renderer/assets/cose-bilkent-S5V4N54A-CJLnhbhw.js.gz +0 -0
  103. package/dist-electron/renderer/assets/dagre-KV5264BT-DdUSLopE.js.gz +0 -0
  104. package/dist-electron/renderer/assets/diagram-5BDNPKRD-DQC5xE5U.js.gz +0 -0
  105. package/dist-electron/renderer/assets/diagram-G4DWMVQ6-CCPlHnyE.js.gz +0 -0
  106. package/dist-electron/renderer/assets/diagram-MMDJMWI5-DBdIw1TA.js.gz +0 -0
  107. package/dist-electron/renderer/assets/diagram-TYMM5635-Cli41wXP.js.gz +0 -0
  108. package/dist-electron/renderer/assets/erDiagram-SMLLAGMA-CavyaE_R.js.gz +0 -0
  109. package/dist-electron/renderer/assets/flowDiagram-DWJPFMVM-DrbYlj9H.js.gz +0 -0
  110. package/dist-electron/renderer/assets/ganttDiagram-T4ZO3ILL-zGFcXLvx.js.gz +0 -0
  111. package/dist-electron/renderer/assets/gitGraphDiagram-UUTBAWPF-DZlVbvmi.js.gz +0 -0
  112. package/dist-electron/renderer/assets/graph-DrxVWiWl.js.gz +0 -0
  113. package/dist-electron/renderer/assets/index-DMYFeXxm.css.gz +0 -0
  114. package/dist-electron/renderer/assets/index-dANVauHS.js.gz +0 -0
  115. package/dist-electron/renderer/assets/ishikawaDiagram-UXIWVN3A-fNeI-iIw.js.gz +0 -0
  116. package/dist-electron/renderer/assets/journeyDiagram-VCZTEJTY-BfNIUZcQ.js.gz +0 -0
  117. package/dist-electron/renderer/assets/kanban-definition-6JOO6SKY-C7CUToPz.js.gz +0 -0
  118. package/dist-electron/renderer/assets/layout-CHg8GOVl.js.gz +0 -0
  119. package/dist-electron/renderer/assets/min-DMOXbVDI.js.gz +0 -0
  120. package/dist-electron/renderer/assets/mindmap-definition-QFDTVHPH-CehXyJEp.js.gz +0 -0
  121. package/dist-electron/renderer/assets/pieDiagram-DEJITSTG-D9DSsmFY.js.gz +0 -0
  122. package/dist-electron/renderer/assets/quadrantDiagram-34T5L4WZ-C6LACI_u.js.gz +0 -0
  123. package/dist-electron/renderer/assets/requirementDiagram-MS252O5E-Cw79fNU0.js.gz +0 -0
  124. package/dist-electron/renderer/assets/sankeyDiagram-XADWPNL6-D8qlDZqR.js.gz +0 -0
  125. package/dist-electron/renderer/assets/sequenceDiagram-FGHM5R23-D4pctSQZ.js.gz +0 -0
  126. package/dist-electron/renderer/assets/stateDiagram-FHFEXIEX-DxS1AKAn.js.gz +0 -0
  127. package/dist-electron/renderer/assets/timeline-definition-GMOUNBTQ-CSy9zDBK.js.gz +0 -0
  128. package/dist-electron/renderer/assets/vennDiagram-DHZGUBPP-r13CGS2k.js.gz +0 -0
  129. package/dist-electron/renderer/assets/wardley-RL74JXVD-DURh8ybw.js.gz +0 -0
  130. package/dist-electron/renderer/assets/wardleyDiagram-NUSXRM2D-QMLW6W2D.js.gz +0 -0
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./dagre-KV5264BT-DdUSLopE.js","./graph-DrxVWiWl.js","./_baseUniq-CuYKmvg2.js","./layout-CHg8GOVl.js","./min-DMOXbVDI.js","./clone-Dgq5O-yi.js","./cose-bilkent-S5V4N54A-CJLnhbhw.js","./cytoscape.esm-D6E6cAed.js","./c4Diagram-AHTNJAMY-DMdJwQt_.js","./chunk-YZCP3GAM-BjXXEobK.js","./flowDiagram-DWJPFMVM-DrbYlj9H.js","./chunk-FMBD7UC4-BIhRhPTv.js","./chunk-55IACEB6-iojbbU_5.js","./chunk-EDXVE4YY-4OVSdmJJ.js","./channel-D3joe8D2.js","./erDiagram-SMLLAGMA-CavyaE_R.js","./gitGraphDiagram-UUTBAWPF-DZlVbvmi.js","./chunk-4BX2VUAB-B-lkn6Ra.js","./chunk-QZHKN3VN-AghpssW7.js","./wardley-RL74JXVD-DURh8ybw.js","./infoDiagram-42DDH7IO-DVzQqzB-.js","./pieDiagram-DEJITSTG-D9DSsmFY.js","./arc-wbF5WnQV.js","./requirementDiagram-MS252O5E-Cw79fNU0.js","./sequenceDiagram-FGHM5R23-D4pctSQZ.js","./classDiagram-6PBFFD2Q-CO01xt-j.js","./chunk-4TB4RGXK-CvsgJjGn.js","./classDiagram-v2-HSJHXN6E-CO01xt-j.js","./stateDiagram-FHFEXIEX-DxS1AKAn.js","./chunk-OYMX7WX6-Bc0TINts.js","./stateDiagram-v2-QKLJ7IA2-DyH8dH7m.js","./journeyDiagram-VCZTEJTY-BfNIUZcQ.js","./timeline-definition-GMOUNBTQ-CSy9zDBK.js","./mindmap-definition-QFDTVHPH-CehXyJEp.js","./kanban-definition-6JOO6SKY-C7CUToPz.js","./diagram-TYMM5635-Cli41wXP.js","./diagram-MMDJMWI5-DBdIw1TA.js","./blockDiagram-DXYQGD6D-BUWOFiwr.js","./diagram-5BDNPKRD-DQC5xE5U.js","./architectureDiagram-Q4EWVU46-hlZU-AYP.js","./diagram-G4DWMVQ6-CCPlHnyE.js","./wardleyDiagram-NUSXRM2D-QMLW6W2D.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./dagre-KV5264BT-Cg9YT1xz.js","./graph-DU-V9gO6.js","./_baseUniq-Cd6KMhyP.js","./layout-DWL1fnIc.js","./min-CH5IMQz3.js","./clone-xmHKp1sq.js","./cose-bilkent-S5V4N54A-ByOVyfu_.js","./cytoscape.esm-D6E6cAed.js","./c4Diagram-AHTNJAMY-DTgNP3Iw.js","./chunk-YZCP3GAM-bwnLI33o.js","./flowDiagram-DWJPFMVM-CNAySAhx.js","./chunk-FMBD7UC4-kZ24-i_g.js","./chunk-55IACEB6-DoWfU52U.js","./chunk-EDXVE4YY-BzNNBO_8.js","./channel-BfZUuPdo.js","./erDiagram-SMLLAGMA-CCvyAUKF.js","./gitGraphDiagram-UUTBAWPF-DfYql5OI.js","./chunk-4BX2VUAB-l5bA-Sjq.js","./chunk-QZHKN3VN-CAHKGd6k.js","./wardley-RL74JXVD-B3wNqgCA.js","./infoDiagram-42DDH7IO-PPLbRW-4.js","./pieDiagram-DEJITSTG-CbcGJHeL.js","./arc-BeDNmpya.js","./requirementDiagram-MS252O5E-B2Pe66uY.js","./sequenceDiagram-FGHM5R23-BZRIOGYF.js","./classDiagram-6PBFFD2Q-CUB864F9.js","./chunk-4TB4RGXK-CdlbWYt_.js","./classDiagram-v2-HSJHXN6E-CUB864F9.js","./stateDiagram-FHFEXIEX-CHLPdfbn.js","./chunk-OYMX7WX6-BcAHPOyy.js","./stateDiagram-v2-QKLJ7IA2-8iBltSQD.js","./journeyDiagram-VCZTEJTY-DsWKbkeD.js","./timeline-definition-GMOUNBTQ-BTKekCiN.js","./mindmap-definition-QFDTVHPH-CqllRxov.js","./kanban-definition-6JOO6SKY-CDxJLRZA.js","./diagram-TYMM5635-Saa7LkSc.js","./diagram-MMDJMWI5-DBG89SrK.js","./blockDiagram-DXYQGD6D-B9rNlDVj.js","./diagram-5BDNPKRD-N-r5wCxr.js","./architectureDiagram-Q4EWVU46-CnWU5PnR.js","./diagram-G4DWMVQ6-BA5GZndq.js","./wardleyDiagram-NUSXRM2D-Cw5dzdVm.js"])))=>i.map(i=>d[i]);
2
2
  function _mergeNamespaces(n2, m2) {
3
3
  for (var i2 = 0; i2 < m2.length; i2++) {
4
4
  const e3 = m2[i2];
@@ -17340,6 +17340,35 @@ function patchBroadcastResponse(blocks, broadcastId, agentId, patch2) {
17340
17340
  };
17341
17341
  return nextBlocks;
17342
17342
  }
17343
+ function upsertGuidanceBlock(blocks, guidanceBlock2) {
17344
+ const guidanceBlockId = getGuidanceBlockId(guidanceBlock2);
17345
+ const index2 = blocks.findIndex(
17346
+ (block) => block.type === "guidance" && getGuidanceBlockId(block) === guidanceBlockId
17347
+ );
17348
+ if (index2 !== -1) {
17349
+ const nextBlocks = [...blocks];
17350
+ nextBlocks[index2] = guidanceBlock2;
17351
+ return nextBlocks;
17352
+ }
17353
+ const insertionIndex = findGuidanceInsertionIndex(blocks);
17354
+ return [
17355
+ ...blocks.slice(0, insertionIndex),
17356
+ guidanceBlock2,
17357
+ ...blocks.slice(insertionIndex)
17358
+ ];
17359
+ }
17360
+ function getGuidanceBlockId(block) {
17361
+ return block.id ?? block.guidance.id;
17362
+ }
17363
+ function findGuidanceInsertionIndex(blocks) {
17364
+ const lastGuidanceIndex = blocks.findLastIndex((block) => block.type === "guidance");
17365
+ if (lastGuidanceIndex !== -1) return lastGuidanceIndex + 1;
17366
+ const firstAssistantOutputIndex = blocks.findIndex(isAssistantOutputBlock);
17367
+ return firstAssistantOutputIndex === -1 ? 0 : firstAssistantOutputIndex;
17368
+ }
17369
+ function isAssistantOutputBlock(block) {
17370
+ return block.type !== "guidance" && block.type !== "reasoning";
17371
+ }
17343
17372
  function deriveMessageStatus(message2) {
17344
17373
  if (message2.senderRole !== "agent") return "completed";
17345
17374
  if (message2.status) return message2.status;
@@ -17664,17 +17693,8 @@ function applyMergeByIdBlockUpdate(blocks, block, pending2) {
17664
17693
  return [...blocks, withBlockPending(block, pending2)];
17665
17694
  }
17666
17695
  function applyGuidanceBlockUpdate(blocks, block, pending2) {
17667
- const blockId = block.id ?? block.guidance.id;
17668
17696
  const nextBlock = withBlockPending({ ...block, id: block.id ?? block.guidance.id }, pending2);
17669
- const existingIndex = blocks.findIndex(
17670
- (current) => current.type === "guidance" && (current.id ?? current.guidance.id) === blockId
17671
- );
17672
- if (existingIndex === -1) {
17673
- return [...blocks, nextBlock];
17674
- }
17675
- const nextBlocks = [...blocks];
17676
- nextBlocks[existingIndex] = nextBlock;
17677
- return nextBlocks;
17697
+ return upsertGuidanceBlock(blocks, nextBlock);
17678
17698
  }
17679
17699
  function applyToolBlockUpdate(blocks, block, pending2) {
17680
17700
  const existingToolIndex = blocks.findIndex(
@@ -17947,7 +17967,12 @@ function projectSnapshot(event, messagesMap, state2) {
17947
17967
  const cid = event.sessionId;
17948
17968
  const current = messagesMap.get(cid) ?? /* @__PURE__ */ new Map();
17949
17969
  const activeRun = event.runtime?.activeRun;
17950
- const msgMap = mergeSnapshotMessages(current, event.messages, activeRun);
17970
+ const msgMap = mergeSnapshotMessages(
17971
+ current,
17972
+ event.messages,
17973
+ activeRun,
17974
+ event.runtime?.guidanceRequests
17975
+ );
17951
17976
  const activeRunId = activeRun?.runId ?? event.queue.activeRunId;
17952
17977
  const existingMetrics = state2.runMetricsMap.get(cid);
17953
17978
  const runMetricsMap = /* @__PURE__ */ new Map();
@@ -18002,10 +18027,9 @@ function clearGuidanceUiState(sessionState, keepSourceMessageIds = /* @__PURE__
18002
18027
  let changed = false;
18003
18028
  for (const [messageId, uiState] of sessionState) {
18004
18029
  if (keepSourceMessageIds.has(messageId)) continue;
18005
- if (!uiState.guidanceRequest && uiState.hiddenByGuidance === void 0) continue;
18030
+ if (!uiState.guidanceRequest) continue;
18006
18031
  const nextState = { ...uiState };
18007
18032
  delete nextState.guidanceRequest;
18008
- delete nextState.hiddenByGuidance;
18009
18033
  if (Object.keys(nextState).length === 0) {
18010
18034
  sessionState.delete(messageId);
18011
18035
  } else {
@@ -18018,12 +18042,14 @@ function clearGuidanceUiState(sessionState, keepSourceMessageIds = /* @__PURE__
18018
18042
  function projectGuidanceRequestUiState(previous2, request) {
18019
18043
  return {
18020
18044
  ...previous2,
18021
- guidanceRequest: request,
18022
- hiddenByGuidance: request.status === "pending" || request.status === "consumed"
18045
+ guidanceRequest: request
18023
18046
  };
18024
18047
  }
18025
- function mergeSnapshotMessages(current, incomingMessages, activeRun) {
18026
- const normalizedMessages = incomingMessages.map((message2) => normalizeSnapshotMessage(message2, activeRun));
18048
+ function mergeSnapshotMessages(current, incomingMessages, activeRun, guidanceRequests) {
18049
+ const guidanceByTargetMessageId = groupSnapshotGuidanceByTargetMessageId(guidanceRequests);
18050
+ const normalizedMessages = incomingMessages.map(
18051
+ (message2) => normalizeSnapshotMessage(withSnapshotGuidanceBlocks(message2, guidanceByTargetMessageId), activeRun)
18052
+ );
18027
18053
  const merged = mergeMessageMaps(current, normalizedMessages);
18028
18054
  for (const message2 of normalizedMessages) {
18029
18055
  const existing = current.get(message2.id);
@@ -18037,8 +18063,56 @@ function mergeSnapshotMessages(current, incomingMessages, activeRun) {
18037
18063
  updatedAt: Math.max(existing.updatedAt, message2.updatedAt)
18038
18064
  });
18039
18065
  }
18066
+ for (const [messageId, requests] of guidanceByTargetMessageId) {
18067
+ const message2 = merged.get(messageId);
18068
+ if (!message2) continue;
18069
+ const blocks = mergeSnapshotGuidanceBlocks(message2.blocks, requests.map(snapshotGuidanceRequestToBlock));
18070
+ if (blocks === message2.blocks) continue;
18071
+ merged.set(messageId, { ...message2, blocks });
18072
+ }
18040
18073
  return merged;
18041
18074
  }
18075
+ function groupSnapshotGuidanceByTargetMessageId(requests) {
18076
+ const grouped = /* @__PURE__ */ new Map();
18077
+ if (!requests || !Array.isArray(requests) || requests.length === 0) return grouped;
18078
+ for (const request of requests) {
18079
+ const existing = grouped.get(request.targetMessageId) ?? [];
18080
+ existing.push(request);
18081
+ grouped.set(request.targetMessageId, existing);
18082
+ }
18083
+ for (const groupedRequests of grouped.values()) {
18084
+ groupedRequests.sort((a2, b2) => a2.markedAt - b2.markedAt);
18085
+ }
18086
+ return grouped;
18087
+ }
18088
+ function withSnapshotGuidanceBlocks(message2, guidanceByTargetMessageId) {
18089
+ const requests = guidanceByTargetMessageId.get(message2.id);
18090
+ if (!requests || requests.length === 0) return message2;
18091
+ const blocks = mergeSnapshotGuidanceBlocks(message2.blocks, requests.map(snapshotGuidanceRequestToBlock));
18092
+ return blocks === message2.blocks ? message2 : { ...message2, blocks };
18093
+ }
18094
+ function mergeSnapshotGuidanceBlocks(blocks, guidanceBlocks) {
18095
+ let nextBlocks = blocks;
18096
+ for (const guidanceBlock2 of guidanceBlocks) {
18097
+ const next2 = upsertGuidanceBlock(nextBlocks, guidanceBlock2);
18098
+ if (next2 !== nextBlocks) nextBlocks = next2;
18099
+ }
18100
+ return nextBlocks;
18101
+ }
18102
+ function snapshotGuidanceRequestToBlock(request) {
18103
+ return {
18104
+ type: "guidance",
18105
+ id: request.id,
18106
+ guidance: {
18107
+ id: request.id,
18108
+ sourceMessageId: request.sourceMessageId,
18109
+ targetRunId: request.targetRunId,
18110
+ content: request.content,
18111
+ status: request.status,
18112
+ markedAt: request.markedAt
18113
+ }
18114
+ };
18115
+ }
18042
18116
  function normalizeSnapshotMessage(message2, activeRun) {
18043
18117
  if (!activeRun || message2.id !== activeRun.messageId) {
18044
18118
  return normalizeSettledSnapshotMessage(message2);
@@ -18293,7 +18367,16 @@ function projectRunRetrying(event, messagesMap, state2) {
18293
18367
  newMetricsMap.set(cid, { startedAt: Date.now() });
18294
18368
  return {
18295
18369
  messagesMap: /* @__PURE__ */ new Map([[cid, current]]),
18296
- retryingMap: /* @__PURE__ */ new Map([[cid, { attempt: event.attempt, maxAttempts: event.maxAttempts }]]),
18370
+ retryingMap: /* @__PURE__ */ new Map([[cid, {
18371
+ attempt: event.attempt,
18372
+ maxAttempts: event.maxAttempts,
18373
+ reason: event.reason,
18374
+ delayMs: event.delayMs,
18375
+ model: event.model,
18376
+ channelId: event.channelId,
18377
+ messageId: event.messageId,
18378
+ runId: event.runId
18379
+ }]]),
18297
18380
  runMetricsMap: newMetricsMap
18298
18381
  };
18299
18382
  }
@@ -18315,6 +18398,12 @@ function projectRunTerminal(event, messagesMap, state2) {
18315
18398
  ..."durationMs" in event && event.durationMs !== void 0 ? { durationMs: event.durationMs } : {},
18316
18399
  ..."model" in event && event.model !== void 0 ? { model: event.model } : {},
18317
18400
  ..."fallback" in event && event.fallback !== void 0 ? { fallback: event.fallback } : {},
18401
+ ...event.type === "run.completed" && event.fallbackTransition !== void 0 ? {
18402
+ metadata: {
18403
+ ...previous2.metadata,
18404
+ fallbackTransition: event.fallbackTransition
18405
+ }
18406
+ } : {},
18318
18407
  updatedAt: Date.now()
18319
18408
  }, status2));
18320
18409
  }
@@ -18944,6 +19033,8 @@ function mapBroadcastStatus(status2) {
18944
19033
  return "streaming";
18945
19034
  case "done":
18946
19035
  return "done";
19036
+ case "cancelled":
19037
+ return "idle";
18947
19038
  default:
18948
19039
  return "idle";
18949
19040
  }
@@ -19719,6 +19810,9 @@ const DEFAULT_AGENT_ID = "default";
19719
19810
  function getFallbackKey(channelId, model) {
19720
19811
  return `${channelId}:${model ?? ""}`;
19721
19812
  }
19813
+ function shouldHideSourceMessageByGuidance(request) {
19814
+ return request?.status === "pending" || request?.status === "consumed";
19815
+ }
19722
19816
  const container$l = "_container_kw9ug_3";
19723
19817
  const icon$8 = "_icon_kw9ug_12";
19724
19818
  const title$h = "_title_kw9ug_18";
@@ -19994,12 +20088,13 @@ function EmptySessionGuide({
19994
20088
  const BOTTOM_THRESHOLD = 10;
19995
20089
  const FORCE_SCROLL_RAF_COUNT = 2;
19996
20090
  function useScrollAnchor(opts, loadMore) {
19997
- const { messageCount, streamVersion, bottomContentVersion, loadingMore: loadingMore2, resetKey } = opts;
20091
+ const { messageCount, tailMessageKey, streamVersion, bottomContentVersion, loadingMore: loadingMore2, resetKey } = opts;
19998
20092
  const containerRef = reactExports.useRef(null);
19999
20093
  const [isAtBottom, setIsAtBottom] = reactExports.useState(true);
20000
20094
  const [showNewMessageHint, setShowNewMessageHint] = reactExports.useState(false);
20001
20095
  const [showScrollToBottom, setShowScrollToBottom] = reactExports.useState(false);
20002
20096
  const prevMessageCountRef = reactExports.useRef(0);
20097
+ const prevTailMessageKeyRef = reactExports.useRef(void 0);
20003
20098
  const isInitialMountRef = reactExports.useRef(true);
20004
20099
  const preserveScrollRef = reactExports.useRef(null);
20005
20100
  const preserveRafRef = reactExports.useRef(null);
@@ -20026,6 +20121,11 @@ function useScrollAnchor(opts, loadMore) {
20026
20121
  preserveRafRef.current = null;
20027
20122
  }
20028
20123
  }, []);
20124
+ const markCurrentTailObserved = reactExports.useCallback(() => {
20125
+ isInitialMountRef.current = false;
20126
+ prevMessageCountRef.current = messageCount;
20127
+ prevTailMessageKeyRef.current = tailMessageKey;
20128
+ }, [messageCount, tailMessageKey]);
20029
20129
  const handleScroll = reactExports.useCallback(() => {
20030
20130
  const container2 = containerRef.current;
20031
20131
  if (!container2) return;
@@ -20049,6 +20149,7 @@ function useScrollAnchor(opts, loadMore) {
20049
20149
  const wheel = event;
20050
20150
  if (wheel && "deltaY" in wheel && wheel.deltaY < 0) {
20051
20151
  stickyBottomRef.current = false;
20152
+ markCurrentTailObserved();
20052
20153
  setIsAtBottom(false);
20053
20154
  setShowScrollToBottom(true);
20054
20155
  setShowNewMessageHint(false);
@@ -20056,31 +20157,35 @@ function useScrollAnchor(opts, loadMore) {
20056
20157
  }
20057
20158
  if (checkIsAtBottom(container2)) return;
20058
20159
  stickyBottomRef.current = false;
20160
+ markCurrentTailObserved();
20059
20161
  setIsAtBottom(false);
20060
20162
  setShowScrollToBottom(true);
20061
- }, [checkIsAtBottom]);
20163
+ }, [checkIsAtBottom, markCurrentTailObserved]);
20062
20164
  const leaveStickyBottom = reactExports.useCallback(() => {
20063
20165
  stickyBottomRef.current = false;
20064
20166
  setIsAtBottom(false);
20065
20167
  setShowScrollToBottom(true);
20066
20168
  setShowNewMessageHint(false);
20067
- }, []);
20169
+ markCurrentTailObserved();
20170
+ }, [markCurrentTailObserved]);
20068
20171
  const scrollToTop = reactExports.useCallback(() => {
20069
20172
  containerRef.current?.scrollTo({ top: 0, behavior: "smooth" });
20070
20173
  }, []);
20071
20174
  const scrollToBottom2 = reactExports.useCallback(() => {
20072
20175
  const el = containerRef.current;
20073
20176
  if (!el) return;
20177
+ markCurrentTailObserved();
20074
20178
  setScrollTop(el, el.scrollHeight);
20075
20179
  stickyBottomRef.current = true;
20076
20180
  setIsAtBottom(true);
20077
20181
  setShowNewMessageHint(false);
20078
20182
  setShowScrollToBottom(false);
20079
- }, [setScrollTop]);
20183
+ }, [markCurrentTailObserved, setScrollTop]);
20080
20184
  const forceScrollToBottom = reactExports.useCallback(() => {
20081
20185
  const el = containerRef.current;
20082
20186
  if (!el) return;
20083
20187
  cancelForceScroll();
20188
+ markCurrentTailObserved();
20084
20189
  stickyBottomRef.current = true;
20085
20190
  setIsAtBottom(true);
20086
20191
  setShowNewMessageHint(false);
@@ -20098,24 +20203,26 @@ function useScrollAnchor(opts, loadMore) {
20098
20203
  }
20099
20204
  };
20100
20205
  forceScrollRafRef.current = requestAnimationFrame(scrollAfterPaint);
20101
- }, [cancelForceScroll, setScrollTop]);
20206
+ }, [cancelForceScroll, markCurrentTailObserved, setScrollTop]);
20102
20207
  const handleNewMessageClick = reactExports.useCallback(() => {
20103
20208
  const container2 = containerRef.current;
20104
20209
  if (!container2) return;
20210
+ markCurrentTailObserved();
20105
20211
  setScrollTop(container2, container2.scrollHeight);
20106
20212
  stickyBottomRef.current = true;
20107
20213
  setIsAtBottom(true);
20108
20214
  setShowNewMessageHint(false);
20109
20215
  setShowScrollToBottom(false);
20110
- }, [setScrollTop]);
20216
+ }, [markCurrentTailObserved, setScrollTop]);
20111
20217
  const handleScrollToBottomClick = reactExports.useCallback(() => {
20112
20218
  const container2 = containerRef.current;
20113
20219
  if (!container2) return;
20220
+ markCurrentTailObserved();
20114
20221
  setScrollTop(container2, container2.scrollHeight);
20115
20222
  stickyBottomRef.current = true;
20116
20223
  setIsAtBottom(true);
20117
20224
  setShowScrollToBottom(false);
20118
- }, [setScrollTop]);
20225
+ }, [markCurrentTailObserved, setScrollTop]);
20119
20226
  const handleLoadMoreClick = reactExports.useCallback(() => {
20120
20227
  const container2 = containerRef.current;
20121
20228
  if (!container2) return;
@@ -20136,6 +20243,7 @@ function useScrollAnchor(opts, loadMore) {
20136
20243
  setIsAtBottom(true);
20137
20244
  setShowScrollToBottom(false);
20138
20245
  prevMessageCountRef.current = 0;
20246
+ prevTailMessageKeyRef.current = void 0;
20139
20247
  lastScrollTopRef.current = 0;
20140
20248
  preserveScrollRef.current = null;
20141
20249
  }, [cancelForceScroll, cancelPreserveScroll, resetKey]);
@@ -20155,29 +20263,35 @@ function useScrollAnchor(opts, loadMore) {
20155
20263
  if (!container2) return;
20156
20264
  const prevCount = prevMessageCountRef.current;
20157
20265
  const nextCount = messageCount;
20266
+ const prevTailMessageKey = prevTailMessageKeyRef.current;
20267
+ const nextTailMessageKey = tailMessageKey;
20268
+ const tailChanged = nextCount > 0 && prevCount > 0 && nextCount === prevCount && prevTailMessageKey !== void 0 && nextTailMessageKey !== void 0 && nextTailMessageKey !== prevTailMessageKey;
20158
20269
  if (isInitialMountRef.current && nextCount > 0) {
20159
20270
  scrollToBottomAction();
20160
20271
  const rafId = requestAnimationFrame(() => {
20161
20272
  scrollToBottomAction();
20162
20273
  isInitialMountRef.current = false;
20163
20274
  prevMessageCountRef.current = nextCount;
20275
+ prevTailMessageKeyRef.current = nextTailMessageKey;
20164
20276
  });
20165
20277
  return () => cancelAnimationFrame(rafId);
20166
20278
  }
20167
- if (nextCount > prevCount) {
20279
+ if (nextCount > prevCount || tailChanged) {
20168
20280
  if (stickyBottomRef.current && !preserveScrollRef.current) {
20169
20281
  scrollToBottomAction();
20170
20282
  const rafId = requestAnimationFrame(() => {
20171
20283
  scrollToBottomAction();
20172
20284
  });
20173
20285
  prevMessageCountRef.current = nextCount;
20286
+ prevTailMessageKeyRef.current = nextTailMessageKey;
20174
20287
  return () => cancelAnimationFrame(rafId);
20175
20288
  } else {
20176
20289
  setShowNewMessageHint(true);
20177
20290
  }
20178
20291
  }
20179
20292
  prevMessageCountRef.current = nextCount;
20180
- }, [messageCount]);
20293
+ prevTailMessageKeyRef.current = nextTailMessageKey;
20294
+ }, [messageCount, tailMessageKey]);
20181
20295
  reactExports.useLayoutEffect(() => {
20182
20296
  const container2 = containerRef.current;
20183
20297
  const preserve = preserveScrollRef.current;
@@ -71670,12 +71784,12 @@ var registerDefaultLayoutLoaders = /* @__PURE__ */ __name(() => {
71670
71784
  registerLayoutLoaders([
71671
71785
  {
71672
71786
  name: "dagre",
71673
- loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-KV5264BT-DdUSLopE.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0, import.meta.url), "loader")
71787
+ loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-KV5264BT-Cg9YT1xz.js"), true ? __vite__mapDeps([0,1,2,3,4,5]) : void 0, import.meta.url), "loader")
71674
71788
  },
71675
71789
  ...[
71676
71790
  {
71677
71791
  name: "cose-bilkent",
71678
- loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./cose-bilkent-S5V4N54A-CJLnhbhw.js"), true ? __vite__mapDeps([6,7]) : void 0, import.meta.url), "loader")
71792
+ loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./cose-bilkent-S5V4N54A-ByOVyfu_.js"), true ? __vite__mapDeps([6,7]) : void 0, import.meta.url), "loader")
71679
71793
  }
71680
71794
  ]
71681
71795
  ]);
@@ -72131,7 +72245,7 @@ var detector = /* @__PURE__ */ __name((txt) => {
72131
72245
  }, "detector");
72132
72246
  var loader = /* @__PURE__ */ __name(async () => {
72133
72247
  const { diagram: diagram2 } = await __vitePreload(async () => {
72134
- const { diagram: diagram22 } = await import("./c4Diagram-AHTNJAMY-DMdJwQt_.js");
72248
+ const { diagram: diagram22 } = await import("./c4Diagram-AHTNJAMY-DTgNP3Iw.js");
72135
72249
  return { diagram: diagram22 };
72136
72250
  }, true ? __vite__mapDeps([8,9]) : void 0, import.meta.url);
72137
72251
  return { id, diagram: diagram2 };
@@ -72151,7 +72265,7 @@ var detector2 = /* @__PURE__ */ __name((txt, config2) => {
72151
72265
  }, "detector");
72152
72266
  var loader2 = /* @__PURE__ */ __name(async () => {
72153
72267
  const { diagram: diagram2 } = await __vitePreload(async () => {
72154
- const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-DrbYlj9H.js");
72268
+ const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-CNAySAhx.js");
72155
72269
  return { diagram: diagram22 };
72156
72270
  }, true ? __vite__mapDeps([10,11,9,12,13,14]) : void 0, import.meta.url);
72157
72271
  return { id: id2, diagram: diagram2 };
@@ -72177,7 +72291,7 @@ var detector3 = /* @__PURE__ */ __name((txt, config2) => {
72177
72291
  }, "detector");
72178
72292
  var loader3 = /* @__PURE__ */ __name(async () => {
72179
72293
  const { diagram: diagram2 } = await __vitePreload(async () => {
72180
- const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-DrbYlj9H.js");
72294
+ const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-CNAySAhx.js");
72181
72295
  return { diagram: diagram22 };
72182
72296
  }, true ? __vite__mapDeps([10,11,9,12,13,14]) : void 0, import.meta.url);
72183
72297
  return { id: id3, diagram: diagram2 };
@@ -72194,7 +72308,7 @@ var detector4 = /* @__PURE__ */ __name((txt) => {
72194
72308
  }, "detector");
72195
72309
  var loader4 = /* @__PURE__ */ __name(async () => {
72196
72310
  const { diagram: diagram2 } = await __vitePreload(async () => {
72197
- const { diagram: diagram22 } = await import("./erDiagram-SMLLAGMA-CavyaE_R.js");
72311
+ const { diagram: diagram22 } = await import("./erDiagram-SMLLAGMA-CCvyAUKF.js");
72198
72312
  return { diagram: diagram22 };
72199
72313
  }, true ? __vite__mapDeps([15,12,13,14]) : void 0, import.meta.url);
72200
72314
  return { id: id4, diagram: diagram2 };
@@ -72211,7 +72325,7 @@ var detector5 = /* @__PURE__ */ __name((txt) => {
72211
72325
  }, "detector");
72212
72326
  var loader5 = /* @__PURE__ */ __name(async () => {
72213
72327
  const { diagram: diagram2 } = await __vitePreload(async () => {
72214
- const { diagram: diagram22 } = await import("./gitGraphDiagram-UUTBAWPF-DZlVbvmi.js");
72328
+ const { diagram: diagram22 } = await import("./gitGraphDiagram-UUTBAWPF-DfYql5OI.js");
72215
72329
  return { diagram: diagram22 };
72216
72330
  }, true ? __vite__mapDeps([16,17,18,19,4,2]) : void 0, import.meta.url);
72217
72331
  return { id: id5, diagram: diagram2 };
@@ -72228,7 +72342,7 @@ var detector6 = /* @__PURE__ */ __name((txt) => {
72228
72342
  }, "detector");
72229
72343
  var loader6 = /* @__PURE__ */ __name(async () => {
72230
72344
  const { diagram: diagram2 } = await __vitePreload(async () => {
72231
- const { diagram: diagram22 } = await import("./ganttDiagram-T4ZO3ILL-zGFcXLvx.js");
72345
+ const { diagram: diagram22 } = await import("./ganttDiagram-T4ZO3ILL-CecC2wHb.js");
72232
72346
  return { diagram: diagram22 };
72233
72347
  }, true ? [] : void 0, import.meta.url);
72234
72348
  return { id: id6, diagram: diagram2 };
@@ -72245,7 +72359,7 @@ var detector7 = /* @__PURE__ */ __name((txt) => {
72245
72359
  }, "detector");
72246
72360
  var loader7 = /* @__PURE__ */ __name(async () => {
72247
72361
  const { diagram: diagram2 } = await __vitePreload(async () => {
72248
- const { diagram: diagram22 } = await import("./infoDiagram-42DDH7IO-DVzQqzB-.js");
72362
+ const { diagram: diagram22 } = await import("./infoDiagram-42DDH7IO-PPLbRW-4.js");
72249
72363
  return { diagram: diagram22 };
72250
72364
  }, true ? __vite__mapDeps([20,19,4,2]) : void 0, import.meta.url);
72251
72365
  return { id: id7, diagram: diagram2 };
@@ -72261,7 +72375,7 @@ var detector8 = /* @__PURE__ */ __name((txt) => {
72261
72375
  }, "detector");
72262
72376
  var loader8 = /* @__PURE__ */ __name(async () => {
72263
72377
  const { diagram: diagram2 } = await __vitePreload(async () => {
72264
- const { diagram: diagram22 } = await import("./pieDiagram-DEJITSTG-D9DSsmFY.js");
72378
+ const { diagram: diagram22 } = await import("./pieDiagram-DEJITSTG-CbcGJHeL.js");
72265
72379
  return { diagram: diagram22 };
72266
72380
  }, true ? __vite__mapDeps([21,17,19,4,2,22]) : void 0, import.meta.url);
72267
72381
  return { id: id8, diagram: diagram2 };
@@ -72277,7 +72391,7 @@ var detector9 = /* @__PURE__ */ __name((txt) => {
72277
72391
  }, "detector");
72278
72392
  var loader9 = /* @__PURE__ */ __name(async () => {
72279
72393
  const { diagram: diagram2 } = await __vitePreload(async () => {
72280
- const { diagram: diagram22 } = await import("./quadrantDiagram-34T5L4WZ-C6LACI_u.js");
72394
+ const { diagram: diagram22 } = await import("./quadrantDiagram-34T5L4WZ-qCo_ja2B.js");
72281
72395
  return { diagram: diagram22 };
72282
72396
  }, true ? [] : void 0, import.meta.url);
72283
72397
  return { id: id9, diagram: diagram2 };
@@ -72294,7 +72408,7 @@ var detector10 = /* @__PURE__ */ __name((txt) => {
72294
72408
  }, "detector");
72295
72409
  var loader10 = /* @__PURE__ */ __name(async () => {
72296
72410
  const { diagram: diagram2 } = await __vitePreload(async () => {
72297
- const { diagram: diagram22 } = await import("./xychartDiagram-5P7HB3ND-B6rq-ItR.js");
72411
+ const { diagram: diagram22 } = await import("./xychartDiagram-5P7HB3ND-qtorfk-Q.js");
72298
72412
  return { diagram: diagram22 };
72299
72413
  }, true ? [] : void 0, import.meta.url);
72300
72414
  return { id: id10, diagram: diagram2 };
@@ -72311,7 +72425,7 @@ var detector11 = /* @__PURE__ */ __name((txt) => {
72311
72425
  }, "detector");
72312
72426
  var loader11 = /* @__PURE__ */ __name(async () => {
72313
72427
  const { diagram: diagram2 } = await __vitePreload(async () => {
72314
- const { diagram: diagram22 } = await import("./requirementDiagram-MS252O5E-Cw79fNU0.js");
72428
+ const { diagram: diagram22 } = await import("./requirementDiagram-MS252O5E-B2Pe66uY.js");
72315
72429
  return { diagram: diagram22 };
72316
72430
  }, true ? __vite__mapDeps([23,12,13]) : void 0, import.meta.url);
72317
72431
  return { id: id11, diagram: diagram2 };
@@ -72328,7 +72442,7 @@ var detector12 = /* @__PURE__ */ __name((txt) => {
72328
72442
  }, "detector");
72329
72443
  var loader12 = /* @__PURE__ */ __name(async () => {
72330
72444
  const { diagram: diagram2 } = await __vitePreload(async () => {
72331
- const { diagram: diagram22 } = await import("./sequenceDiagram-FGHM5R23-D4pctSQZ.js");
72445
+ const { diagram: diagram22 } = await import("./sequenceDiagram-FGHM5R23-BZRIOGYF.js");
72332
72446
  return { diagram: diagram22 };
72333
72447
  }, true ? __vite__mapDeps([24,9,18]) : void 0, import.meta.url);
72334
72448
  return { id: id12, diagram: diagram2 };
@@ -72348,7 +72462,7 @@ var detector13 = /* @__PURE__ */ __name((txt, config2) => {
72348
72462
  }, "detector");
72349
72463
  var loader13 = /* @__PURE__ */ __name(async () => {
72350
72464
  const { diagram: diagram2 } = await __vitePreload(async () => {
72351
- const { diagram: diagram22 } = await import("./classDiagram-6PBFFD2Q-CO01xt-j.js");
72465
+ const { diagram: diagram22 } = await import("./classDiagram-6PBFFD2Q-CUB864F9.js");
72352
72466
  return { diagram: diagram22 };
72353
72467
  }, true ? __vite__mapDeps([25,26,11,9,12,13]) : void 0, import.meta.url);
72354
72468
  return { id: id13, diagram: diagram2 };
@@ -72368,7 +72482,7 @@ var detector14 = /* @__PURE__ */ __name((txt, config2) => {
72368
72482
  }, "detector");
72369
72483
  var loader14 = /* @__PURE__ */ __name(async () => {
72370
72484
  const { diagram: diagram2 } = await __vitePreload(async () => {
72371
- const { diagram: diagram22 } = await import("./classDiagram-v2-HSJHXN6E-CO01xt-j.js");
72485
+ const { diagram: diagram22 } = await import("./classDiagram-v2-HSJHXN6E-CUB864F9.js");
72372
72486
  return { diagram: diagram22 };
72373
72487
  }, true ? __vite__mapDeps([27,26,11,9,12,13]) : void 0, import.meta.url);
72374
72488
  return { id: id14, diagram: diagram2 };
@@ -72388,7 +72502,7 @@ var detector15 = /* @__PURE__ */ __name((txt, config2) => {
72388
72502
  }, "detector");
72389
72503
  var loader15 = /* @__PURE__ */ __name(async () => {
72390
72504
  const { diagram: diagram2 } = await __vitePreload(async () => {
72391
- const { diagram: diagram22 } = await import("./stateDiagram-FHFEXIEX-DxS1AKAn.js");
72505
+ const { diagram: diagram22 } = await import("./stateDiagram-FHFEXIEX-CHLPdfbn.js");
72392
72506
  return { diagram: diagram22 };
72393
72507
  }, true ? __vite__mapDeps([28,29,12,13,1,2,3,4]) : void 0, import.meta.url);
72394
72508
  return { id: id15, diagram: diagram2 };
@@ -72411,7 +72525,7 @@ var detector16 = /* @__PURE__ */ __name((txt, config2) => {
72411
72525
  }, "detector");
72412
72526
  var loader16 = /* @__PURE__ */ __name(async () => {
72413
72527
  const { diagram: diagram2 } = await __vitePreload(async () => {
72414
- const { diagram: diagram22 } = await import("./stateDiagram-v2-QKLJ7IA2-DyH8dH7m.js");
72528
+ const { diagram: diagram22 } = await import("./stateDiagram-v2-QKLJ7IA2-8iBltSQD.js");
72415
72529
  return { diagram: diagram22 };
72416
72530
  }, true ? __vite__mapDeps([30,29,12,13]) : void 0, import.meta.url);
72417
72531
  return { id: id16, diagram: diagram2 };
@@ -72428,7 +72542,7 @@ var detector17 = /* @__PURE__ */ __name((txt) => {
72428
72542
  }, "detector");
72429
72543
  var loader17 = /* @__PURE__ */ __name(async () => {
72430
72544
  const { diagram: diagram2 } = await __vitePreload(async () => {
72431
- const { diagram: diagram22 } = await import("./journeyDiagram-VCZTEJTY-BfNIUZcQ.js");
72545
+ const { diagram: diagram22 } = await import("./journeyDiagram-VCZTEJTY-DsWKbkeD.js");
72432
72546
  return { diagram: diagram22 };
72433
72547
  }, true ? __vite__mapDeps([31,11,9,22]) : void 0, import.meta.url);
72434
72548
  return { id: id17, diagram: diagram2 };
@@ -72498,7 +72612,7 @@ var detector18 = /* @__PURE__ */ __name((txt, config2 = {}) => {
72498
72612
  }, "detector");
72499
72613
  var loader18 = /* @__PURE__ */ __name(async () => {
72500
72614
  const { diagram: diagram2 } = await __vitePreload(async () => {
72501
- const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-DrbYlj9H.js");
72615
+ const { diagram: diagram22 } = await import("./flowDiagram-DWJPFMVM-CNAySAhx.js");
72502
72616
  return { diagram: diagram22 };
72503
72617
  }, true ? __vite__mapDeps([10,11,9,12,13,14]) : void 0, import.meta.url);
72504
72618
  return { id: id18, diagram: diagram2 };
@@ -72515,7 +72629,7 @@ var detector19 = /* @__PURE__ */ __name((txt) => {
72515
72629
  }, "detector");
72516
72630
  var loader19 = /* @__PURE__ */ __name(async () => {
72517
72631
  const { diagram: diagram2 } = await __vitePreload(async () => {
72518
- const { diagram: diagram22 } = await import("./timeline-definition-GMOUNBTQ-CSy9zDBK.js");
72632
+ const { diagram: diagram22 } = await import("./timeline-definition-GMOUNBTQ-BTKekCiN.js");
72519
72633
  return { diagram: diagram22 };
72520
72634
  }, true ? __vite__mapDeps([32,22]) : void 0, import.meta.url);
72521
72635
  return { id: id19, diagram: diagram2 };
@@ -72532,7 +72646,7 @@ var detector20 = /* @__PURE__ */ __name((txt) => {
72532
72646
  }, "detector");
72533
72647
  var loader20 = /* @__PURE__ */ __name(async () => {
72534
72648
  const { diagram: diagram2 } = await __vitePreload(async () => {
72535
- const { diagram: diagram22 } = await import("./mindmap-definition-QFDTVHPH-CehXyJEp.js");
72649
+ const { diagram: diagram22 } = await import("./mindmap-definition-QFDTVHPH-CqllRxov.js");
72536
72650
  return { diagram: diagram22 };
72537
72651
  }, true ? __vite__mapDeps([33,12,13]) : void 0, import.meta.url);
72538
72652
  return { id: id20, diagram: diagram2 };
@@ -72549,7 +72663,7 @@ var detector21 = /* @__PURE__ */ __name((txt) => {
72549
72663
  }, "detector");
72550
72664
  var loader21 = /* @__PURE__ */ __name(async () => {
72551
72665
  const { diagram: diagram2 } = await __vitePreload(async () => {
72552
- const { diagram: diagram22 } = await import("./kanban-definition-6JOO6SKY-C7CUToPz.js");
72666
+ const { diagram: diagram22 } = await import("./kanban-definition-6JOO6SKY-CDxJLRZA.js");
72553
72667
  return { diagram: diagram22 };
72554
72668
  }, true ? __vite__mapDeps([34,11]) : void 0, import.meta.url);
72555
72669
  return { id: id21, diagram: diagram2 };
@@ -72566,7 +72680,7 @@ var detector22 = /* @__PURE__ */ __name((txt) => {
72566
72680
  }, "detector");
72567
72681
  var loader22 = /* @__PURE__ */ __name(async () => {
72568
72682
  const { diagram: diagram2 } = await __vitePreload(async () => {
72569
- const { diagram: diagram22 } = await import("./sankeyDiagram-XADWPNL6-D8qlDZqR.js");
72683
+ const { diagram: diagram22 } = await import("./sankeyDiagram-XADWPNL6-CzWD-MNf.js");
72570
72684
  return { diagram: diagram22 };
72571
72685
  }, true ? [] : void 0, import.meta.url);
72572
72686
  return { id: id22, diagram: diagram2 };
@@ -72583,7 +72697,7 @@ var detector23 = /* @__PURE__ */ __name((txt) => {
72583
72697
  }, "detector");
72584
72698
  var loader23 = /* @__PURE__ */ __name(async () => {
72585
72699
  const { diagram: diagram2 } = await __vitePreload(async () => {
72586
- const { diagram: diagram22 } = await import("./diagram-TYMM5635-Cli41wXP.js");
72700
+ const { diagram: diagram22 } = await import("./diagram-TYMM5635-Saa7LkSc.js");
72587
72701
  return { diagram: diagram22 };
72588
72702
  }, true ? __vite__mapDeps([35,17,19,4,2]) : void 0, import.meta.url);
72589
72703
  return { id: id23, diagram: diagram2 };
@@ -72599,7 +72713,7 @@ var detector24 = /* @__PURE__ */ __name((txt) => {
72599
72713
  }, "detector");
72600
72714
  var loader24 = /* @__PURE__ */ __name(async () => {
72601
72715
  const { diagram: diagram2 } = await __vitePreload(async () => {
72602
- const { diagram: diagram22 } = await import("./diagram-MMDJMWI5-DBdIw1TA.js");
72716
+ const { diagram: diagram22 } = await import("./diagram-MMDJMWI5-DBG89SrK.js");
72603
72717
  return { diagram: diagram22 };
72604
72718
  }, true ? __vite__mapDeps([36,17,19,4,2]) : void 0, import.meta.url);
72605
72719
  return { id: id24, diagram: diagram2 };
@@ -72615,7 +72729,7 @@ var detector25 = /* @__PURE__ */ __name((txt) => {
72615
72729
  }, "detector");
72616
72730
  var loader25 = /* @__PURE__ */ __name(async () => {
72617
72731
  const { diagram: diagram2 } = await __vitePreload(async () => {
72618
- const { diagram: diagram22 } = await import("./blockDiagram-DXYQGD6D-BUWOFiwr.js");
72732
+ const { diagram: diagram22 } = await import("./blockDiagram-DXYQGD6D-B9rNlDVj.js");
72619
72733
  return { diagram: diagram22 };
72620
72734
  }, true ? __vite__mapDeps([37,11,5,1,2,14]) : void 0, import.meta.url);
72621
72735
  return { id: id25, diagram: diagram2 };
@@ -72632,7 +72746,7 @@ var detector26 = /* @__PURE__ */ __name((txt) => {
72632
72746
  }, "detector");
72633
72747
  var loader26 = /* @__PURE__ */ __name(async () => {
72634
72748
  const { diagram: diagram2 } = await __vitePreload(async () => {
72635
- const { diagram: diagram22 } = await import("./diagram-5BDNPKRD-DQC5xE5U.js");
72749
+ const { diagram: diagram22 } = await import("./diagram-5BDNPKRD-N-r5wCxr.js");
72636
72750
  return { diagram: diagram22 };
72637
72751
  }, true ? __vite__mapDeps([38,17,18,19,4,2]) : void 0, import.meta.url);
72638
72752
  return { id: id26, diagram: diagram2 };
@@ -72649,7 +72763,7 @@ var detector27 = /* @__PURE__ */ __name((txt) => {
72649
72763
  }, "detector");
72650
72764
  var loader27 = /* @__PURE__ */ __name(async () => {
72651
72765
  const { diagram: diagram2 } = await __vitePreload(async () => {
72652
- const { diagram: diagram22 } = await import("./architectureDiagram-Q4EWVU46-hlZU-AYP.js");
72766
+ const { diagram: diagram22 } = await import("./architectureDiagram-Q4EWVU46-CnWU5PnR.js");
72653
72767
  return { diagram: diagram22 };
72654
72768
  }, true ? __vite__mapDeps([39,17,19,4,2,7]) : void 0, import.meta.url);
72655
72769
  return { id: id27, diagram: diagram2 };
@@ -72666,7 +72780,7 @@ var detector28 = /* @__PURE__ */ __name((txt) => {
72666
72780
  }, "detector");
72667
72781
  var loader28 = /* @__PURE__ */ __name(async () => {
72668
72782
  const { diagram: diagram2 } = await __vitePreload(async () => {
72669
- const { diagram: diagram22 } = await import("./ishikawaDiagram-UXIWVN3A-fNeI-iIw.js");
72783
+ const { diagram: diagram22 } = await import("./ishikawaDiagram-UXIWVN3A-BJYqQjNN.js");
72670
72784
  return { diagram: diagram22 };
72671
72785
  }, true ? [] : void 0, import.meta.url);
72672
72786
  return { id: id28, diagram: diagram2 };
@@ -72682,7 +72796,7 @@ var detector29 = /* @__PURE__ */ __name((txt) => {
72682
72796
  }, "detector");
72683
72797
  var loader29 = /* @__PURE__ */ __name(async () => {
72684
72798
  const { diagram: diagram2 } = await __vitePreload(async () => {
72685
- const { diagram: diagram22 } = await import("./vennDiagram-DHZGUBPP-r13CGS2k.js");
72799
+ const { diagram: diagram22 } = await import("./vennDiagram-DHZGUBPP-Ccbx5Aye.js");
72686
72800
  return { diagram: diagram22 };
72687
72801
  }, true ? [] : void 0, import.meta.url);
72688
72802
  return { id: id29, diagram: diagram2 };
@@ -72699,7 +72813,7 @@ var detector30 = /* @__PURE__ */ __name((txt) => {
72699
72813
  }, "detector");
72700
72814
  var loader30 = /* @__PURE__ */ __name(async () => {
72701
72815
  const { diagram: diagram2 } = await __vitePreload(async () => {
72702
- const { diagram: diagram22 } = await import("./diagram-G4DWMVQ6-CCPlHnyE.js");
72816
+ const { diagram: diagram22 } = await import("./diagram-G4DWMVQ6-BA5GZndq.js");
72703
72817
  return { diagram: diagram22 };
72704
72818
  }, true ? __vite__mapDeps([40,13,17,19,4,2]) : void 0, import.meta.url);
72705
72819
  return { id: id30, diagram: diagram2 };
@@ -72715,7 +72829,7 @@ var detector31 = /* @__PURE__ */ __name((text2) => {
72715
72829
  }, "detector");
72716
72830
  var loader31 = /* @__PURE__ */ __name(async () => {
72717
72831
  const { diagram: diagram2 } = await __vitePreload(async () => {
72718
- const { diagram: diagram22 } = await import("./wardleyDiagram-NUSXRM2D-QMLW6W2D.js");
72832
+ const { diagram: diagram22 } = await import("./wardleyDiagram-NUSXRM2D-Cw5dzdVm.js");
72719
72833
  return { diagram: diagram22 };
72720
72834
  }, true ? __vite__mapDeps([41,17,19,4,2]) : void 0, import.meta.url);
72721
72835
  return { id: id31, diagram: diagram2 };
@@ -82695,7 +82809,60 @@ async function copyToClipboard(text2) {
82695
82809
  document.body.removeChild(textarea2);
82696
82810
  }
82697
82811
  }
82812
+ const EMPTY_MESSAGE_SEARCH_STATE = {
82813
+ query: "",
82814
+ matches: [],
82815
+ currentIndex: -1
82816
+ };
82817
+ function normalizeSearchText(value2) {
82818
+ return value2.toLowerCase().replace(/\s+/g, " ").trim();
82819
+ }
82820
+ function getSearchTerms(query) {
82821
+ const terms = normalizeSearchText(query).split(" ").filter(Boolean);
82822
+ return Array.from(new Set(terms));
82823
+ }
82824
+ function collectSearchRanges(text2, terms) {
82825
+ const lowerText = text2.toLowerCase();
82826
+ const ranges = [];
82827
+ for (const term of terms) {
82828
+ let fromIndex = 0;
82829
+ while (fromIndex < lowerText.length) {
82830
+ const start2 = lowerText.indexOf(term, fromIndex);
82831
+ if (start2 === -1) break;
82832
+ ranges.push([start2, start2 + term.length]);
82833
+ fromIndex = start2 + Math.max(term.length, 1);
82834
+ }
82835
+ }
82836
+ return ranges.sort((a2, b2) => a2[0] - b2[0] || a2[1] - b2[1]);
82837
+ }
82838
+ function getMessageSearchText(message2) {
82839
+ return getBlocksTextContent(message2.blocks);
82840
+ }
82841
+ function searchMessages(messages, query) {
82842
+ const terms = getSearchTerms(query);
82843
+ if (terms.length === 0) return [];
82844
+ const matches = [];
82845
+ messages.forEach((message2, messageIndex) => {
82846
+ const messageText = getMessageSearchText(message2);
82847
+ const normalizedText = normalizeSearchText(messageText);
82848
+ if (!terms.every((term) => normalizedText.includes(term))) return;
82849
+ message2.blocks.forEach((block, blockIndex) => {
82850
+ if (block.type !== "text") return;
82851
+ const ranges = collectSearchRanges(block.text, terms);
82852
+ ranges.forEach((range3) => {
82853
+ matches.push({
82854
+ messageId: message2.id,
82855
+ messageIndex,
82856
+ blockIndex,
82857
+ range: range3
82858
+ });
82859
+ });
82860
+ });
82861
+ });
82862
+ return matches;
82863
+ }
82698
82864
  const log$n = createLogger("MarkdownMessage");
82865
+ const SEARCH_SKIPPED_TAGS = /* @__PURE__ */ new Set(["code", "pre"]);
82699
82866
  const POSIX_ABSOLUTE_PATH_PATTERN = /^\/(?:[^\s/]+\/)*[^\s/]+\.[A-Za-z0-9][A-Za-z0-9._-]*$/;
82700
82867
  const HOME_RELATIVE_PATH_PATTERN = /^~\/(?:[^\s/]+\/)*[^\s/]+\.[A-Za-z0-9][A-Za-z0-9._-]*$/;
82701
82868
  const CURRENT_RELATIVE_PATH_PATTERN = /^\.\/(?:[^\s/]+\/)*[^\s/]+\.[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -82747,7 +82914,7 @@ function isHtmlLanguage(language) {
82747
82914
  return language.toLowerCase() === "html" || language.toLowerCase() === "htm";
82748
82915
  }
82749
82916
  function markdownPropsEqual(prev2, next2) {
82750
- return prev2.content === next2.content && prev2.className === next2.className && prev2.agentId === next2.agentId && prev2.enableBlockCopy === next2.enableBlockCopy && prev2.isStreaming === next2.isStreaming;
82917
+ return prev2.content === next2.content && prev2.className === next2.className && prev2.agentId === next2.agentId && prev2.enableBlockCopy === next2.enableBlockCopy && prev2.isStreaming === next2.isStreaming && prev2.searchTerms === next2.searchTerms && prev2.activeSearchRange === next2.activeSearchRange;
82751
82918
  }
82752
82919
  const MarkdownMessage = reactExports.memo(function MarkdownMessage2({
82753
82920
  content: content2,
@@ -82755,7 +82922,9 @@ const MarkdownMessage = reactExports.memo(function MarkdownMessage2({
82755
82922
  agentId = DEFAULT_AGENT_ID,
82756
82923
  basePath,
82757
82924
  enableBlockCopy = false,
82758
- isStreaming = false
82925
+ isStreaming = false,
82926
+ searchTerms,
82927
+ activeSearchRange
82759
82928
  }) {
82760
82929
  const { theme } = useTheme();
82761
82930
  const { t: t2 } = useTranslation();
@@ -82764,6 +82933,7 @@ const MarkdownMessage = reactExports.memo(function MarkdownMessage2({
82764
82933
  const [viewerImage, setViewerImage] = reactExports.useState(null);
82765
82934
  const codeStyle = theme === "dark" ? atomOneDark : githubGist;
82766
82935
  const processedContent = content2.replace(/sandbox:\/mnt\/data\/([^\s)]+)/g, "$1");
82936
+ const searchHighlightPlugin = createSearchHighlightPlugin(searchTerms, activeSearchRange);
82767
82937
  const normalizedBlockText = processedContent.trim();
82768
82938
  const estimatedLineCount = normalizedBlockText ? normalizedBlockText.split(/\r?\n/).length : 0;
82769
82939
  const shouldShowBlockCopy = enableBlockCopy && normalizedBlockText.length > 0 && estimatedLineCount > 3;
@@ -82857,10 +83027,11 @@ const MarkdownMessage = reactExports.memo(function MarkdownMessage2({
82857
83027
  Markdown,
82858
83028
  {
82859
83029
  remarkPlugins: [remarkGfm],
83030
+ rehypePlugins: searchHighlightPlugin ? [searchHighlightPlugin] : void 0,
82860
83031
  components: {
82861
83032
  img: LocalImage,
82862
83033
  a: ({ href, children: children2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: resolveMarkdownLinkHref(href, agentId, basePath), onClick: handleLinkClick, children: children2 }),
82863
- text: ({ children: children2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: parseColorInChildren(children2) }),
83034
+ mark: ({ children: children2, node: node2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("mark", { "data-active-search-match": node2?.properties?.["data-active-search-match"], children: parseColorInChildren(children2) }),
82864
83035
  td: ({ children: children2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("td", { children: parseColorInChildren(children2) }),
82865
83036
  th: ({ children: children2 }) => /* @__PURE__ */ jsxRuntimeExports.jsx("th", { children: parseColorInChildren(children2) }),
82866
83037
  code({ className: inlineClassName, children: children2, ...props }) {
@@ -82957,6 +83128,48 @@ const MarkdownMessage = reactExports.memo(function MarkdownMessage2({
82957
83128
  )
82958
83129
  ] });
82959
83130
  }, markdownPropsEqual);
83131
+ function isSearchHighlightSkippedParent(parent) {
83132
+ return "tagName" in parent && typeof parent.tagName === "string" && SEARCH_SKIPPED_TAGS.has(parent.tagName);
83133
+ }
83134
+ function createSearchHighlightPlugin(terms, activeRange) {
83135
+ if (!terms?.length) return void 0;
83136
+ return function rehypeSearchHighlight() {
83137
+ return (tree) => {
83138
+ visit(tree, "text", (node2, index2, parent) => {
83139
+ const sourceOffset = node2.position?.start.offset;
83140
+ if (index2 === void 0 || !parent || sourceOffset === void 0) return;
83141
+ if (isSearchHighlightSkippedParent(parent)) return;
83142
+ const text2 = String(node2.value);
83143
+ const ranges = collectSearchRanges(text2, terms);
83144
+ if (!ranges.length) return;
83145
+ const children2 = [];
83146
+ let cursor = 0;
83147
+ ranges.forEach(([start2, end]) => {
83148
+ if (end <= cursor || start2 >= text2.length) return;
83149
+ const safeStart = Math.max(start2, cursor);
83150
+ const safeEnd = Math.min(end, text2.length);
83151
+ if (safeStart > cursor) {
83152
+ children2.push({ type: "text", value: text2.slice(cursor, safeStart) });
83153
+ }
83154
+ const absoluteStart = sourceOffset + safeStart;
83155
+ const absoluteEnd = sourceOffset + safeEnd;
83156
+ const active2 = activeRange?.[0] === absoluteStart && activeRange[1] === absoluteEnd;
83157
+ children2.push({
83158
+ type: "element",
83159
+ tagName: "mark",
83160
+ properties: active2 ? { "data-active-search-match": "true" } : {},
83161
+ children: [{ type: "text", value: text2.slice(safeStart, safeEnd) }]
83162
+ });
83163
+ cursor = safeEnd;
83164
+ });
83165
+ if (cursor < text2.length) {
83166
+ children2.push({ type: "text", value: text2.slice(cursor) });
83167
+ }
83168
+ parent.children.splice(index2, 1, ...children2);
83169
+ });
83170
+ };
83171
+ };
83172
+ }
82960
83173
  const header$k = "_header_3tatz_1";
82961
83174
  const chevron$4 = "_chevron_3tatz_24";
82962
83175
  const content$b = "_content_3tatz_29";
@@ -83732,36 +83945,37 @@ function useElapsedTime({
83732
83945
  function useRuntimeMetricsVisibility() {
83733
83946
  return !useIsMobile();
83734
83947
  }
83735
- const card$5 = "_card_1t93f_1";
83736
- const embedded$1 = "_embedded_1t93f_9";
83737
- const collapse$1 = "_collapse_1t93f_16";
83738
- const toolIcon = "_toolIcon_1t93f_20";
83739
- const toolName$1 = "_toolName_1t93f_25";
83740
- const argSummaryWrap = "_argSummaryWrap_1t93f_32";
83741
- const argSummary = "_argSummary_1t93f_32";
83742
- const argSummaryClickable = "_argSummaryClickable_1t93f_56";
83743
- const copyPathButton = "_copyPathButton_1t93f_72";
83744
- const spacer$1 = "_spacer_1t93f_108";
83745
- const duration$2 = "_duration_1t93f_112";
83746
- const status$3 = "_status_1t93f_120";
83747
- const pending$1 = "_pending_1t93f_130";
83748
- const success = "_success_1t93f_134";
83749
- const error$8 = "_error_1t93f_138";
83750
- const section$3 = "_section_1t93f_146";
83751
- const label$6 = "_label_1t93f_154";
83752
- const errorResult = "_errorResult_1t93f_162";
83753
- const plainResult = "_plainResult_1t93f_172";
83754
- const diffToggleBar = "_diffToggleBar_1t93f_180";
83755
- const diffButton = "_diffButton_1t93f_184";
83756
- const diffSection = "_diffSection_1t93f_204";
83757
- const taskIdList = "_taskIdList_1t93f_208";
83758
- const spinning$2 = "_spinning_1t93f_214";
83759
- const spin$3 = "_spin_1t93f_214";
83760
- const generatedImage = "_generatedImage_1t93f_225";
83761
- const generatedImageThumb = "_generatedImageThumb_1t93f_233";
83762
- const brokenImage = "_brokenImage_1t93f_241";
83763
- const generatedImageLabel = "_generatedImageLabel_1t93f_253";
83764
- const tooltipContent = "_tooltipContent_1t93f_259";
83948
+ const card$5 = "_card_64fh5_1";
83949
+ const embedded$1 = "_embedded_64fh5_9";
83950
+ const collapse$1 = "_collapse_64fh5_16";
83951
+ const toolIcon = "_toolIcon_64fh5_20";
83952
+ const toolName$1 = "_toolName_64fh5_25";
83953
+ const argSummaryWrap = "_argSummaryWrap_64fh5_32";
83954
+ const argSummary = "_argSummary_64fh5_32";
83955
+ const argSummaryClickable = "_argSummaryClickable_64fh5_56";
83956
+ const copyPathButton = "_copyPathButton_64fh5_72";
83957
+ const spacer$1 = "_spacer_64fh5_108";
83958
+ const duration$2 = "_duration_64fh5_112";
83959
+ const status$3 = "_status_64fh5_120";
83960
+ const pending$1 = "_pending_64fh5_130";
83961
+ const success = "_success_64fh5_134";
83962
+ const error$8 = "_error_64fh5_138";
83963
+ const section$3 = "_section_64fh5_146";
83964
+ const label$6 = "_label_64fh5_154";
83965
+ const errorResult = "_errorResult_64fh5_162";
83966
+ const plainResult = "_plainResult_64fh5_172";
83967
+ const diffToggleBar = "_diffToggleBar_64fh5_180";
83968
+ const diffButton = "_diffButton_64fh5_184";
83969
+ const diffSection = "_diffSection_64fh5_204";
83970
+ const readFileContent = "_readFileContent_64fh5_208";
83971
+ const taskIdList = "_taskIdList_64fh5_214";
83972
+ const spinning$2 = "_spinning_64fh5_220";
83973
+ const spin$3 = "_spin_64fh5_220";
83974
+ const generatedImage = "_generatedImage_64fh5_231";
83975
+ const generatedImageThumb = "_generatedImageThumb_64fh5_239";
83976
+ const brokenImage = "_brokenImage_64fh5_247";
83977
+ const generatedImageLabel = "_generatedImageLabel_64fh5_259";
83978
+ const tooltipContent = "_tooltipContent_64fh5_265";
83765
83979
  const styles$Z = {
83766
83980
  card: card$5,
83767
83981
  embedded: embedded$1,
@@ -83785,6 +83999,7 @@ const styles$Z = {
83785
83999
  diffToggleBar,
83786
84000
  diffButton,
83787
84001
  diffSection,
84002
+ readFileContent,
83788
84003
  taskIdList,
83789
84004
  spinning: spinning$2,
83790
84005
  spin: spin$3,
@@ -84319,7 +84534,8 @@ const ToolCallCard = reactExports.memo(function ToolCallCard2({ toolCall, varian
84319
84534
  ) : readContent ? /* @__PURE__ */ jsxRuntimeExports.jsx(
84320
84535
  "div",
84321
84536
  {
84322
- className: styles$Z.diffSection,
84537
+ className: clsx(styles$Z.diffSection, styles$Z.readFileContent),
84538
+ "data-testid": "read-file-content-scroll",
84323
84539
  "data-tool-file-quote-content": toolQuoteFilePath ? true : void 0,
84324
84540
  "data-quote-file-path": toolQuoteFilePath,
84325
84541
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -84951,24 +85167,26 @@ const HandoffCard = reactExports.memo(function HandoffCard2({ handoff }) {
84951
85167
  }
84952
85168
  );
84953
85169
  });
84954
- const broadcastBody = "_broadcastBody_1ho0j_9";
84955
- const headerAction = "_headerAction_1ho0j_19";
84956
- const tabsBar = "_tabsBar_1ho0j_26";
84957
- const tab$4 = "_tab_1ho0j_26";
84958
- const tabActive$4 = "_tabActive_1ho0j_58";
84959
- const tabName = "_tabName_1ho0j_65";
84960
- const tabDot = "_tabDot_1ho0j_71";
84961
- const dot_pending = "_dot_pending_1ho0j_78";
84962
- const dot_thinking = "_dot_thinking_1ho0j_79";
84963
- const dot_streaming = "_dot_streaming_1ho0j_83";
84964
- const dotPulse = "_dotPulse_1ho0j_1";
84965
- const dot_done = "_dot_done_1ho0j_89";
84966
- const dot_failed = "_dot_failed_1ho0j_94";
84967
- const tabContent$1 = "_tabContent_1ho0j_112";
84968
- const tabBlocksViewport = "_tabBlocksViewport_1ho0j_122";
84969
- const tabBlockItem = "_tabBlockItem_1ho0j_126";
84970
- const placeholder = "_placeholder_1ho0j_132";
84971
- const errorText$2 = "_errorText_1ho0j_138";
85170
+ const broadcastBody = "_broadcastBody_13xq3_9";
85171
+ const headerAction = "_headerAction_13xq3_19";
85172
+ const tabsBar = "_tabsBar_13xq3_26";
85173
+ const tab$4 = "_tab_13xq3_26";
85174
+ const tabActive$4 = "_tabActive_13xq3_61";
85175
+ const tabName = "_tabName_13xq3_68";
85176
+ const tabDot = "_tabDot_13xq3_74";
85177
+ const dot_pending = "_dot_pending_13xq3_81";
85178
+ const dot_thinking = "_dot_thinking_13xq3_82";
85179
+ const dot_streaming = "_dot_streaming_13xq3_86";
85180
+ const dotPulse = "_dotPulse_13xq3_1";
85181
+ const dot_done = "_dot_done_13xq3_92";
85182
+ const dot_failed = "_dot_failed_13xq3_97";
85183
+ const dot_cancelled = "_dot_cancelled_13xq3_101";
85184
+ const tabContent$1 = "_tabContent_13xq3_120";
85185
+ const tabBlocksViewport = "_tabBlocksViewport_13xq3_130";
85186
+ const tabBlockItem = "_tabBlockItem_13xq3_134";
85187
+ const placeholder = "_placeholder_13xq3_140";
85188
+ const errorText$2 = "_errorText_13xq3_146";
85189
+ const cancelledText = "_cancelledText_13xq3_151";
84972
85190
  const styles$T = {
84973
85191
  broadcastBody,
84974
85192
  headerAction,
@@ -84983,30 +85201,55 @@ const styles$T = {
84983
85201
  dotPulse,
84984
85202
  dot_done,
84985
85203
  dot_failed,
85204
+ dot_cancelled,
84986
85205
  tabContent: tabContent$1,
84987
85206
  tabBlocksViewport,
84988
85207
  tabBlockItem,
84989
85208
  placeholder,
84990
- errorText: errorText$2
85209
+ errorText: errorText$2,
85210
+ cancelledText
84991
85211
  };
84992
- function getBadge(responses, status2) {
85212
+ function getBadge(responses, status2, t2) {
84993
85213
  const doneCount = responses.filter((r2) => r2.status === "done").length;
84994
85214
  const failedCount = responses.filter((r2) => r2.status === "failed").length;
85215
+ const cancelledCount = responses.filter((r2) => r2.status === "cancelled").length;
84995
85216
  const total = responses.length;
84996
- if (status2 === "done" || doneCount + failedCount === total) {
85217
+ if (status2 === "done" || doneCount + failedCount + cancelledCount === total) {
84997
85218
  if (failedCount === total) {
84998
- return { text: `${total} 条回答失败`, variant: "failed" };
85219
+ return { text: t2("message.broadcastBadgeFailed", { count: total }), variant: "failed" };
85220
+ }
85221
+ if (cancelledCount > 0) {
85222
+ return {
85223
+ text: failedCount > 0 ? t2("message.broadcastBadgeStoppedWithFailures", { completed: doneCount, total, failed: failedCount }) : t2("message.broadcastBadgeStopped", { completed: doneCount, total }),
85224
+ variant: failedCount > 0 ? "failed" : "idle"
85225
+ };
84999
85226
  }
85000
85227
  if (failedCount > 0) {
85001
- return { text: `${doneCount}/${total} 条回答`, variant: "completed" };
85228
+ return { text: t2("message.broadcastBadgeAnsweredWithFailures", { completed: doneCount, total, failed: failedCount }), variant: "failed" };
85002
85229
  }
85003
- return { text: `${total} 条回答`, variant: "completed" };
85230
+ return { text: t2("message.broadcastBadgeAllAnswered", { total }), variant: "completed" };
85004
85231
  }
85005
- if (status2 === "running" || responses.some((r2) => r2.status === "streaming")) {
85006
- return { text: `${doneCount}/${total} 条回答`, variant: "running" };
85232
+ if (status2 === "running" || responses.some((r2) => r2.status === "streaming" || r2.status === "thinking")) {
85233
+ return { text: t2("message.broadcastBadgeAnswered", { completed: doneCount, total }), variant: "running" };
85007
85234
  }
85008
85235
  return void 0;
85009
85236
  }
85237
+ function getResponseStatusLabel(status2, t2) {
85238
+ switch (status2) {
85239
+ case "pending":
85240
+ return t2("message.broadcastStatusPending");
85241
+ case "thinking":
85242
+ return t2("message.broadcastStatusThinking");
85243
+ case "streaming":
85244
+ return t2("message.broadcastStatusStreaming");
85245
+ case "done":
85246
+ return t2("message.broadcastStatusDone");
85247
+ case "failed":
85248
+ return t2("message.broadcastStatusFailed");
85249
+ case "cancelled":
85250
+ return t2("message.broadcastStatusCancelled");
85251
+ }
85252
+ }
85010
85253
  const BroadcastCard = reactExports.memo(function BroadcastCard2({ broadcast }) {
85011
85254
  const { t: t2 } = useTranslation();
85012
85255
  const { responses, status: status2 } = broadcast;
@@ -85026,7 +85269,7 @@ const BroadcastCard = reactExports.memo(function BroadcastCard2({ broadcast }) {
85026
85269
  contentRef.current?.scrollTo({ top: 0 });
85027
85270
  }, []);
85028
85271
  const activeResponse = responses.find((r2) => r2.agentId === activeTabId) ?? responses[0];
85029
- const badge2 = getBadge(responses, status2);
85272
+ const badge2 = getBadge(responses, status2, t2);
85030
85273
  const total = responses.length;
85031
85274
  const runningElapsedMs = useElapsedTime({
85032
85275
  startedAt: broadcast.startedAt,
@@ -85034,18 +85277,14 @@ const BroadcastCard = reactExports.memo(function BroadcastCard2({ broadcast }) {
85034
85277
  intervalMs: 1e3
85035
85278
  });
85036
85279
  const displayDurationMs = status2 === "running" && showRuntimeMetrics ? runningElapsedMs : void 0;
85037
- const summary2 = `广播咨询:向 ${total} 位成员征求意见`;
85280
+ const summary2 = t2("message.broadcastSummary", { total });
85038
85281
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
85039
85282
  CollaborationShell,
85040
85283
  {
85041
85284
  header: {
85042
85285
  type: "broadcast",
85043
- participants: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.headerAction, children: "广播咨询" }),
85044
- action: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: styles$T.headerAction, children: [
85045
- "向 ",
85046
- total,
85047
- " 位成员征求意见"
85048
- ] }),
85286
+ participants: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.headerAction, children: t2("message.broadcastHeader") }),
85287
+ action: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.headerAction, children: t2("message.broadcastAction", { total }) }),
85049
85288
  tooltip: summary2,
85050
85289
  badge: badge2,
85051
85290
  meta: displayDurationMs != null ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatDurationMs(displayDurationMs) }) : void 0,
@@ -85053,29 +85292,50 @@ const BroadcastCard = reactExports.memo(function BroadcastCard2({ broadcast }) {
85053
85292
  onToggle: () => setExpanded((prev2) => !prev2)
85054
85293
  },
85055
85294
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$T.broadcastBody, children: [
85056
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$T.tabsBar, children: responses.map((response) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
85057
- "button",
85058
- {
85059
- className: clsx(styles$T.tab, response.agentId === activeTabId ? styles$T.tabActive : ""),
85060
- onClick: () => handleTabClick(response.agentId),
85061
- type: "button",
85062
- children: [
85063
- /* @__PURE__ */ jsxRuntimeExports.jsx(
85064
- AgentAvatar,
85065
- {
85066
- agent: { id: response.agentId, name: response.agentName, avatar: response.avatar },
85067
- size: 18
85068
- }
85069
- ),
85070
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.tabName, children: response.agentName }),
85071
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx(styles$T.tabDot, styles$T[`dot_${response.status}`]) })
85072
- ]
85073
- },
85074
- response.agentId
85295
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$T.tabsBar, children: responses.map((response) => (
85296
+ // title gives mouse users the same status that screen readers get from aria-label.
85297
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
85298
+ "button",
85299
+ {
85300
+ className: clsx(styles$T.tab, response.agentId === activeTabId ? styles$T.tabActive : ""),
85301
+ onClick: () => handleTabClick(response.agentId),
85302
+ type: "button",
85303
+ title: `${response.agentName} · ${getResponseStatusLabel(response.status, t2)}`,
85304
+ "aria-label": `${response.agentName} · ${getResponseStatusLabel(response.status, t2)}`,
85305
+ children: [
85306
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
85307
+ AgentAvatar,
85308
+ {
85309
+ agent: { id: response.agentId, name: response.agentName, avatar: response.avatar },
85310
+ size: 18
85311
+ }
85312
+ ),
85313
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.tabName, children: response.agentName }),
85314
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
85315
+ "span",
85316
+ {
85317
+ className: clsx(styles$T.tabDot, styles$T[`dot_${response.status}`]),
85318
+ "aria-hidden": "true"
85319
+ }
85320
+ )
85321
+ ]
85322
+ },
85323
+ response.agentId
85324
+ )
85075
85325
  )) }),
85076
85326
  activeResponse && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$T.tabContent, ref: contentRef, children: [
85077
85327
  activeResponse.status === "pending" && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.placeholder, children: t2("message.broadcastWaiting") }),
85078
85328
  (activeResponse.status === "streaming" || activeResponse.status === "done") && /* @__PURE__ */ jsxRuntimeExports.jsx(TabBlocksRenderer, { blocks: activeResponse.blocks, agentId: activeResponse.agentId }),
85329
+ activeResponse.status === "cancelled" && (activeResponse.blocks.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
85330
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
85331
+ TabBlocksRenderer,
85332
+ {
85333
+ blocks: activeResponse.blocks,
85334
+ agentId: activeResponse.agentId
85335
+ }
85336
+ ),
85337
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.cancelledText, children: t2("message.broadcastCancelled") })
85338
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$T.cancelledText, children: t2("message.broadcastCancelled") })),
85079
85339
  activeResponse.status === "failed" && (activeResponse.blocks.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
85080
85340
  TabBlocksRenderer,
85081
85341
  {
@@ -85113,74 +85373,75 @@ function TabBlocksRenderer({
85113
85373
  }
85114
85374
  );
85115
85375
  }
85116
- const message$4 = "_message_kvj0m_1";
85117
- const fullWidth = "_fullWidth_kvj0m_8";
85118
- const user = "_user_kvj0m_12";
85119
- const agent$2 = "_agent_kvj0m_17";
85120
- const collapsedMessage = "_collapsedMessage_kvj0m_22";
85121
- const groupLayout = "_groupLayout_kvj0m_30";
85122
- const agentShellCompact = "_agentShellCompact_kvj0m_38";
85123
- const avatarCol$1 = "_avatarCol_kvj0m_43";
85124
- const senderHeader = "_senderHeader_kvj0m_57";
85125
- const contentCol = "_contentCol_kvj0m_63";
85126
- const senderLabel = "_senderLabel_kvj0m_84";
85127
- const senderName = "_senderName_kvj0m_101";
85128
- const bubble = "_bubble_kvj0m_107";
85129
- const collapsedBubble = "_collapsedBubble_kvj0m_133";
85130
- const hasUsage = "_hasUsage_kvj0m_137";
85131
- const embeddedBubble = "_embeddedBubble_kvj0m_141";
85132
- const textBubble = "_textBubble_kvj0m_147";
85133
- const textSection = "_textSection_kvj0m_163";
85134
- const embeddedBubbleContent = "_embeddedBubbleContent_kvj0m_182";
85135
- const content$9 = "_content_kvj0m_63";
85136
- const messageFooter = "_messageFooter_kvj0m_208";
85137
- const groupMetaFooter = "_groupMetaFooter_kvj0m_216";
85138
- const messageFooterActions = "_messageFooterActions_kvj0m_242";
85139
- const timestamp = "_timestamp_kvj0m_266";
85140
- const copyButton$1 = "_copyButton_kvj0m_277";
85141
- const errorBlock = "_errorBlock_kvj0m_306";
85142
- const errorHeader = "_errorHeader_kvj0m_314";
85143
- const errorType = "_errorType_kvj0m_322";
85144
- const errorMessage$1 = "_errorMessage_kvj0m_327";
85145
- const errorDetails = "_errorDetails_kvj0m_333";
85146
- const errorDetailsSummary = "_errorDetailsSummary_kvj0m_339";
85147
- const errorDetailsSummaryRow = "_errorDetailsSummaryRow_kvj0m_347";
85148
- const errorDetailsCopyButton = "_errorDetailsCopyButton_kvj0m_354";
85149
- const errorDetailsContent = "_errorDetailsContent_kvj0m_376";
85150
- const collapsedContent = "_collapsedContent_kvj0m_389";
85151
- const virtualCollapsedBlocks = "_virtualCollapsedBlocks_kvj0m_407";
85152
- const expandedContent = "_expandedContent_kvj0m_415";
85153
- const conclusionStrip = "_conclusionStrip_kvj0m_420";
85154
- const conclusionLabel = "_conclusionLabel_kvj0m_434";
85155
- const conclusionText = "_conclusionText_kvj0m_442";
85156
- const expandButton$1 = "_expandButton_kvj0m_448";
85157
- const messageMetrics = "_messageMetrics_kvj0m_475";
85158
- const embeddedMessageMetrics = "_embeddedMessageMetrics_kvj0m_490";
85159
- const fallbackTransitionBanner = "_fallbackTransitionBanner_kvj0m_503";
85160
- const messageMetricsPrimary = "_messageMetricsPrimary_kvj0m_507";
85161
- const embeddedMessageMetricsPrimary = "_embeddedMessageMetricsPrimary_kvj0m_515";
85162
- const messageMetricsMeta = "_messageMetricsMeta_kvj0m_520";
85163
- const metricsStreaming = "_metricsStreaming_kvj0m_548";
85164
- const fallbackTransitionIcon = "_fallbackTransitionIcon_kvj0m_580";
85165
- const fallbackTransitionText = "_fallbackTransitionText_kvj0m_585";
85166
- const tokenUsage = "_tokenUsage_kvj0m_602";
85167
- const duration = "_duration_kvj0m_611";
85168
- const modelLabel = "_modelLabel_kvj0m_621";
85169
- const modelLabelFallback = "_modelLabelFallback_kvj0m_631";
85170
- const system = "_system_kvj0m_643";
85171
- const systemBubble = "_systemBubble_kvj0m_650";
85172
- const systemContent = "_systemContent_kvj0m_662";
85173
- const loadingSpinner = "_loadingSpinner_kvj0m_669";
85174
- const supervisorTag = "_supervisorTag_kvj0m_685";
85175
- const memoryWriteButton = "_memoryWriteButton_kvj0m_724";
85176
- const statusArea = "_statusArea_kvj0m_731";
85177
- const statusDot$1 = "_statusDot_kvj0m_739";
85178
- const dot$2 = "_dot_kvj0m_748";
85179
- const dotSending = "_dotSending_kvj0m_756";
85180
- const dotError = "_dotError_kvj0m_760";
85181
- const retryButton = "_retryButton_kvj0m_765";
85182
- const recallButton = "_recallButton_kvj0m_775";
85183
- const guidanceStatus = "_guidanceStatus_kvj0m_795";
85376
+ const message$4 = "_message_18ic3_1";
85377
+ const fullWidth = "_fullWidth_18ic3_8";
85378
+ const user = "_user_18ic3_12";
85379
+ const agent$2 = "_agent_18ic3_17";
85380
+ const collapsedMessage = "_collapsedMessage_18ic3_22";
85381
+ const groupLayout = "_groupLayout_18ic3_30";
85382
+ const agentShellCompact = "_agentShellCompact_18ic3_38";
85383
+ const avatarCol$1 = "_avatarCol_18ic3_43";
85384
+ const senderHeader = "_senderHeader_18ic3_57";
85385
+ const contentCol = "_contentCol_18ic3_63";
85386
+ const senderLabel = "_senderLabel_18ic3_84";
85387
+ const senderName = "_senderName_18ic3_101";
85388
+ const bubble = "_bubble_18ic3_107";
85389
+ const textBubble = "_textBubble_18ic3_120";
85390
+ const content$9 = "_content_18ic3_63";
85391
+ const activeSearchMatch = "_activeSearchMatch_18ic3_135";
85392
+ const collapsedBubble = "_collapsedBubble_18ic3_153";
85393
+ const hasUsage = "_hasUsage_18ic3_157";
85394
+ const embeddedBubble = "_embeddedBubble_18ic3_161";
85395
+ const textSection = "_textSection_18ic3_183";
85396
+ const embeddedBubbleContent = "_embeddedBubbleContent_18ic3_202";
85397
+ const messageFooter = "_messageFooter_18ic3_228";
85398
+ const groupMetaFooter = "_groupMetaFooter_18ic3_236";
85399
+ const messageFooterActions = "_messageFooterActions_18ic3_262";
85400
+ const timestamp = "_timestamp_18ic3_286";
85401
+ const copyButton$1 = "_copyButton_18ic3_297";
85402
+ const errorBlock = "_errorBlock_18ic3_326";
85403
+ const errorHeader = "_errorHeader_18ic3_334";
85404
+ const errorType = "_errorType_18ic3_342";
85405
+ const errorMessage$1 = "_errorMessage_18ic3_347";
85406
+ const errorDetails = "_errorDetails_18ic3_353";
85407
+ const errorDetailsSummary = "_errorDetailsSummary_18ic3_359";
85408
+ const errorDetailsSummaryRow = "_errorDetailsSummaryRow_18ic3_367";
85409
+ const errorDetailsCopyButton = "_errorDetailsCopyButton_18ic3_374";
85410
+ const errorDetailsContent = "_errorDetailsContent_18ic3_396";
85411
+ const collapsedContent = "_collapsedContent_18ic3_409";
85412
+ const virtualCollapsedBlocks = "_virtualCollapsedBlocks_18ic3_427";
85413
+ const expandedContent = "_expandedContent_18ic3_435";
85414
+ const conclusionStrip = "_conclusionStrip_18ic3_440";
85415
+ const conclusionLabel = "_conclusionLabel_18ic3_454";
85416
+ const conclusionText = "_conclusionText_18ic3_462";
85417
+ const expandButton$1 = "_expandButton_18ic3_468";
85418
+ const messageMetrics = "_messageMetrics_18ic3_495";
85419
+ const embeddedMessageMetrics = "_embeddedMessageMetrics_18ic3_510";
85420
+ const fallbackTransitionBanner = "_fallbackTransitionBanner_18ic3_523";
85421
+ const messageMetricsPrimary = "_messageMetricsPrimary_18ic3_527";
85422
+ const embeddedMessageMetricsPrimary = "_embeddedMessageMetricsPrimary_18ic3_535";
85423
+ const messageMetricsMeta = "_messageMetricsMeta_18ic3_540";
85424
+ const metricsStreaming = "_metricsStreaming_18ic3_568";
85425
+ const fallbackTransitionIcon = "_fallbackTransitionIcon_18ic3_600";
85426
+ const fallbackTransitionText = "_fallbackTransitionText_18ic3_605";
85427
+ const tokenUsage = "_tokenUsage_18ic3_622";
85428
+ const duration = "_duration_18ic3_631";
85429
+ const modelLabel = "_modelLabel_18ic3_641";
85430
+ const modelLabelFallback = "_modelLabelFallback_18ic3_651";
85431
+ const system = "_system_18ic3_663";
85432
+ const systemBubble = "_systemBubble_18ic3_670";
85433
+ const systemContent = "_systemContent_18ic3_682";
85434
+ const loadingSpinner = "_loadingSpinner_18ic3_689";
85435
+ const supervisorTag = "_supervisorTag_18ic3_705";
85436
+ const memoryWriteButton = "_memoryWriteButton_18ic3_744";
85437
+ const statusArea = "_statusArea_18ic3_751";
85438
+ const statusDot$1 = "_statusDot_18ic3_759";
85439
+ const dot$2 = "_dot_18ic3_768";
85440
+ const dotSending = "_dotSending_18ic3_776";
85441
+ const dotError = "_dotError_18ic3_780";
85442
+ const retryButton = "_retryButton_18ic3_785";
85443
+ const recallButton = "_recallButton_18ic3_795";
85444
+ const guidanceStatus = "_guidanceStatus_18ic3_815";
85184
85445
  const styles$S = {
85185
85446
  message: message$4,
85186
85447
  fullWidth,
@@ -85195,13 +85456,14 @@ const styles$S = {
85195
85456
  senderLabel,
85196
85457
  senderName,
85197
85458
  bubble,
85459
+ textBubble,
85460
+ content: content$9,
85461
+ activeSearchMatch,
85198
85462
  collapsedBubble,
85199
85463
  hasUsage,
85200
85464
  embeddedBubble,
85201
- textBubble,
85202
85465
  textSection,
85203
85466
  embeddedBubbleContent,
85204
- content: content$9,
85205
85467
  messageFooter,
85206
85468
  groupMetaFooter,
85207
85469
  messageFooterActions,
@@ -85402,11 +85664,11 @@ function renderNonTextBlock(block, index2, context, variant, onCancelGuidance) {
85402
85664
  return null;
85403
85665
  }
85404
85666
  }
85405
- function renderUserTextLegacy(text2) {
85667
+ function renderUserTextLegacy(text2, searchTerms, activeSearchRange) {
85406
85668
  const parts = parseAttachmentsInText(text2);
85407
85669
  return parts.map((part, i2) => {
85408
85670
  if (part.type === "text") {
85409
- return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm leading-relaxed", children: part.content }, `text-${i2}`);
85671
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm leading-relaxed", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SearchHighlightedText, { text: part.content, terms: searchTerms, activeRange: activeSearchRange }) }, `text-${i2}`);
85410
85672
  }
85411
85673
  return /* @__PURE__ */ jsxRuntimeExports.jsx(AttachmentDisplay, { attachment: part.content }, `attachment-${i2}`);
85412
85674
  });
@@ -85425,8 +85687,9 @@ function isRenderableBlock(block) {
85425
85687
  case "task":
85426
85688
  case "handoff":
85427
85689
  case "broadcast":
85428
- case "guidance":
85429
85690
  return true;
85691
+ case "guidance":
85692
+ return block.guidance.status === "pending";
85430
85693
  default:
85431
85694
  return false;
85432
85695
  }
@@ -85463,7 +85726,7 @@ function groupBlocks(blocks) {
85463
85726
  }
85464
85727
  return groups;
85465
85728
  }
85466
- function renderAgentBlockGroup(group2, context, variant, onCancelGuidance) {
85729
+ function renderAgentBlockGroup(group2, context, variant, onCancelGuidance, searchMatch, searchTerms) {
85467
85730
  const { message: message2 } = context;
85468
85731
  if (group2.type === "text") {
85469
85732
  const textBlocks = group2.blocks.filter(
@@ -85482,7 +85745,9 @@ function renderAgentBlockGroup(group2, context, variant, onCancelGuidance) {
85482
85745
  content: block.text,
85483
85746
  agentId: message2.senderId,
85484
85747
  enableBlockCopy: true,
85485
- isStreaming: isBlockPending(block)
85748
+ isStreaming: isBlockPending(block),
85749
+ searchTerms,
85750
+ activeSearchRange: searchMatch?.blockIndex === group2.startIndex + j2 ? searchMatch.range : void 0
85486
85751
  },
85487
85752
  `text-${group2.startIndex + j2}`
85488
85753
  ))
@@ -85527,7 +85792,9 @@ const BlockRenderer = reactExports.memo(function BlockRenderer2({
85527
85792
  blocks,
85528
85793
  context,
85529
85794
  variant = "default",
85530
- onCancelGuidance
85795
+ onCancelGuidance,
85796
+ searchMatch,
85797
+ searchTerms
85531
85798
  }) {
85532
85799
  const { message: message2, isUser } = context;
85533
85800
  if (isUser) {
@@ -85535,15 +85802,26 @@ const BlockRenderer = reactExports.memo(function BlockRenderer2({
85535
85802
  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: blocks.map((block, i2) => {
85536
85803
  if (block.type === "text") {
85537
85804
  if (hasAttachmentsBlock) {
85538
- return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm leading-relaxed", children: block.text }, `text-${i2}`);
85805
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm leading-relaxed", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
85806
+ SearchHighlightedText,
85807
+ {
85808
+ text: block.text,
85809
+ terms: searchTerms,
85810
+ activeRange: searchMatch?.blockIndex === i2 ? searchMatch.range : void 0
85811
+ }
85812
+ ) }, `text-${i2}`);
85539
85813
  }
85540
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: renderUserTextLegacy(block.text) }, `text-${i2}`);
85814
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: renderUserTextLegacy(
85815
+ block.text,
85816
+ searchTerms,
85817
+ searchMatch?.blockIndex === i2 ? searchMatch.range : void 0
85818
+ ) }, `text-${i2}`);
85541
85819
  }
85542
85820
  return /* @__PURE__ */ jsxRuntimeExports.jsx(BlockErrorBoundary, { children: renderNonTextBlock(block, i2, context, variant, onCancelGuidance) }, `eb-${i2}`);
85543
85821
  }) });
85544
85822
  }
85545
85823
  const groups = groupBlocks(blocks).filter(isRenderableBlockGroup);
85546
- return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: groups.map((group2) => renderAgentBlockGroup(group2, context, variant, onCancelGuidance)) });
85824
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: groups.map((group2) => renderAgentBlockGroup(group2, context, variant, onCancelGuidance, searchMatch, searchTerms)) });
85547
85825
  });
85548
85826
  const VirtualizedBlockRenderer = reactExports.memo(function VirtualizedBlockRenderer2({
85549
85827
  blocks,
@@ -85554,10 +85832,12 @@ const VirtualizedBlockRenderer = reactExports.memo(function VirtualizedBlockRend
85554
85832
  itemClassName,
85555
85833
  itemGap = 0,
85556
85834
  increaseViewportBy = DEFAULT_VIRTUAL_INCREASE_VIEWPORT_BY,
85557
- onCancelGuidance
85835
+ onCancelGuidance,
85836
+ searchMatch,
85837
+ searchTerms
85558
85838
  }) {
85559
85839
  if (context.isUser) {
85560
- return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className, style: { height }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(BlockRenderer, { blocks, context, variant, onCancelGuidance }) });
85840
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className, style: { height }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(BlockRenderer, { blocks, context, variant, onCancelGuidance, searchMatch, searchTerms }) });
85561
85841
  }
85562
85842
  const groups = groupBlocks(blocks).filter(isRenderableBlockGroup);
85563
85843
  if (groups.length === 0) {
@@ -85578,12 +85858,35 @@ const VirtualizedBlockRenderer = reactExports.memo(function VirtualizedBlockRend
85578
85858
  minHeight: 1,
85579
85859
  ...index2 < groups.length - 1 && itemGap > 0 ? { marginBottom: itemGap } : null
85580
85860
  },
85581
- children: renderAgentBlockGroup(group2, context, variant, onCancelGuidance)
85861
+ children: renderAgentBlockGroup(group2, context, variant, onCancelGuidance, searchMatch, searchTerms)
85582
85862
  }
85583
85863
  )
85584
85864
  }
85585
85865
  );
85586
85866
  });
85867
+ function SearchHighlightedText({
85868
+ text: text2,
85869
+ terms,
85870
+ activeRange
85871
+ }) {
85872
+ const ranges = terms?.length ? collectSearchRanges(text2, terms) : [];
85873
+ if (!ranges.length) return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: text2 });
85874
+ const parts = [];
85875
+ let cursor = 0;
85876
+ ranges.forEach(([start2, end], index2) => {
85877
+ if (end <= cursor || start2 >= text2.length) return;
85878
+ const safeStart = Math.max(start2, cursor);
85879
+ const safeEnd = Math.min(end, text2.length);
85880
+ if (safeStart > cursor) parts.push(text2.slice(cursor, safeStart));
85881
+ const active2 = activeRange?.[0] === safeStart && activeRange[1] === safeEnd;
85882
+ parts.push(
85883
+ /* @__PURE__ */ jsxRuntimeExports.jsx("mark", { "data-active-search-match": active2 ? "true" : void 0, children: text2.slice(safeStart, safeEnd) }, `${safeStart}-${safeEnd}-${index2}`)
85884
+ );
85885
+ cursor = safeEnd;
85886
+ });
85887
+ if (cursor < text2.length) parts.push(text2.slice(cursor));
85888
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: parts });
85889
+ }
85587
85890
  const container$f = "_container_189qy_1";
85588
85891
  const inline = "_inline_189qy_7";
85589
85892
  const status = "_status_189qy_12";
@@ -85749,8 +86052,13 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85749
86052
  textContent,
85750
86053
  variant = "default",
85751
86054
  embedRuntimeStatusInBubble = false,
86055
+ retryInfo,
85752
86056
  onCancelGuidance,
85753
- onExpandChange
86057
+ onExpandChange,
86058
+ forceExpanded = false,
86059
+ searchMatch,
86060
+ searchTerms,
86061
+ isActiveSearchMatch = false
85754
86062
  }, ref) {
85755
86063
  const showRuntimeMetrics = useRuntimeMetricsVisibility();
85756
86064
  const [isExpanded, setIsExpanded] = reactExports.useState(false);
@@ -85785,7 +86093,7 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85785
86093
  observer.disconnect();
85786
86094
  };
85787
86095
  }, [autoCollapsed, isUser, blocks]);
85788
- const isCollapsed = autoCollapsed && !isUser && needsCollapse && !isExpanded;
86096
+ const isCollapsed = autoCollapsed && !isUser && needsCollapse && !isExpanded && !forceExpanded;
85789
86097
  const contentClass = isCollapsed ? styles$S.collapsedContent : styles$S.expandedContent;
85790
86098
  const useVirtualCollapsedRenderer = isCollapsed && !isUser && !messageStreaming && !messageFailed && blocks.length >= VIRTUAL_COLLAPSED_BLOCK_THRESHOLD;
85791
86099
  const conclusion = reactExports.useMemo(() => {
@@ -85824,9 +86132,10 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85824
86132
  const displayModel = runMetrics?.model ?? message2.model;
85825
86133
  const displayUsage = runMetrics?.usage ?? message2.usage;
85826
86134
  const fallbackTransition = messageStreaming ? runMetrics?.fallbackTransition : void 0;
86135
+ const messageRetryInfo = messageStreaming && retryInfo?.messageId === message2.id ? retryInfo : null;
85827
86136
  const displayDurationMs = messageStreaming && runMetrics ? elapsedMs : message2.durationMs;
85828
86137
  const hasMetrics = showRuntimeMetrics && !!(displayModel || displayUsage || displayDurationMs != null && !isNaN(displayDurationMs));
85829
- const embeddedRuntimeStatusVisible = embedRuntimeStatusInBubble && (showToolLoading || !!fallbackTransition);
86138
+ const embeddedRuntimeStatusVisible = embedRuntimeStatusInBubble && (showToolLoading || !!fallbackTransition || !!messageRetryInfo);
85830
86139
  const bubbleHasMetrics = !isEmbedded ? hasMetrics : embeddedRuntimeStatusVisible;
85831
86140
  const showFooter = isEmbedded ? embeddedRuntimeStatusVisible : true;
85832
86141
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -85836,7 +86145,8 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85836
86145
  styles$S.bubble,
85837
86146
  bubbleHasMetrics ? styles$S.hasUsage : "",
85838
86147
  isEmbedded && styles$S.embeddedBubble,
85839
- isCollapsed && styles$S.collapsedBubble
86148
+ isCollapsed && styles$S.collapsedBubble,
86149
+ isActiveSearchMatch && styles$S.activeSearchMatch
85840
86150
  ),
85841
86151
  "data-message-content": true,
85842
86152
  "data-message-id": message2.id,
@@ -85856,7 +86166,9 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85856
86166
  className: styles$S.virtualCollapsedBlocks,
85857
86167
  itemClassName: styles$S.virtualBlockItem,
85858
86168
  itemGap: 6,
85859
- onCancelGuidance
86169
+ onCancelGuidance,
86170
+ searchMatch,
86171
+ searchTerms
85860
86172
  }
85861
86173
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
85862
86174
  BlockRenderer,
@@ -85864,7 +86176,9 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85864
86176
  blocks,
85865
86177
  context: blockContext,
85866
86178
  variant: blockVariant,
85867
- onCancelGuidance
86179
+ onCancelGuidance,
86180
+ searchMatch,
86181
+ searchTerms
85868
86182
  }
85869
86183
  ),
85870
86184
  messageFailed && message2.error && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageErrorBlock, { error: message2.error })
@@ -85889,6 +86203,7 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85889
86203
  {
85890
86204
  loading: showToolLoading,
85891
86205
  fallbackTransition,
86206
+ retryInfo: messageRetryInfo,
85892
86207
  variant: isEmbedded ? "embedded" : "default"
85893
86208
  }
85894
86209
  ),
@@ -85897,7 +86212,7 @@ const MessageBubble = reactExports.memo(reactExports.forwardRef(function Message
85897
86212
  }
85898
86213
  );
85899
86214
  }));
85900
- function MessageRuntimeStatus({ fallbackTransition, loading: loading2, variant = "default" }) {
86215
+ function MessageRuntimeStatus({ fallbackTransition, retryInfo, loading: loading2, variant = "default" }) {
85901
86216
  const isEmbedded = variant === "embedded";
85902
86217
  const transitionKey = fallbackTransition ? `${fallbackTransition.fromModel}->${fallbackTransition.toModel}:${fallbackTransition.reason}` : null;
85903
86218
  const [visibleTransitionKey, setVisibleTransitionKey] = reactExports.useState(transitionKey);
@@ -85913,13 +86228,26 @@ function MessageRuntimeStatus({ fallbackTransition, loading: loading2, variant =
85913
86228
  return () => window.clearTimeout(timer2);
85914
86229
  }, [transitionKey]);
85915
86230
  const showFallbackTransition = Boolean(fallbackTransition && visibleTransitionKey === transitionKey);
85916
- if (!loading2 && !showFallbackTransition) return null;
86231
+ if (!loading2 && !showFallbackTransition && !retryInfo) return null;
85917
86232
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx(styles$S.messageMetrics, isEmbedded && styles$S.embeddedMessageMetrics), children: [
86233
+ retryInfo && /* @__PURE__ */ jsxRuntimeExports.jsx(RetryStatusBanner, { retryInfo }),
85918
86234
  showFallbackTransition && fallbackTransition && /* @__PURE__ */ jsxRuntimeExports.jsx(FallbackTransitionBanner, { transition: fallbackTransition }),
85919
86235
  loading2 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(styles$S.messageMetricsPrimary, isEmbedded && styles$S.embeddedMessageMetricsPrimary), children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$S.metricsStreaming, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingDots, { inline: true, variant: "status" }) }) })
85920
86236
  ] });
85921
86237
  }
85922
- function MessageMetrics({ usage, durationMs, model, fallback: fallback2, loading: loading2, variant = "default" }) {
86238
+ function RetryStatusBanner({ retryInfo }) {
86239
+ const { t: t2 } = useTranslation();
86240
+ const seconds = Math.max(1, Math.round((retryInfo.delayMs ?? 0) / 1e3));
86241
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$S.fallbackTransitionBanner, role: "status", "aria-live": "polite", children: [
86242
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 11, className: styles$S.fallbackTransitionIcon, "aria-hidden": "true" }),
86243
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$S.fallbackTransitionText, children: t2("message.retry.rateLimitScheduled", {
86244
+ seconds,
86245
+ attempt: retryInfo.attempt,
86246
+ maxAttempts: retryInfo.maxAttempts
86247
+ }) })
86248
+ ] });
86249
+ }
86250
+ function MessageMetrics({ usage, durationMs, model, fallback: fallback2, fallbackTransition, loading: loading2, variant = "default" }) {
85923
86251
  const showRuntimeMetrics = useRuntimeMetricsVisibility();
85924
86252
  const hasDuration = durationMs != null && !isNaN(durationMs);
85925
86253
  const isEmbedded = variant === "embedded";
@@ -85928,7 +86256,7 @@ function MessageMetrics({ usage, durationMs, model, fallback: fallback2, loading
85928
86256
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx(styles$S.messageMetrics, isEmbedded && styles$S.embeddedMessageMetrics), children: [
85929
86257
  loading2 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(styles$S.messageMetricsPrimary, isEmbedded && styles$S.embeddedMessageMetricsPrimary), children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$S.metricsStreaming, children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoadingDots, { inline: true, variant: "status" }) }) }),
85930
86258
  hasMeta && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$S.messageMetricsMeta, children: [
85931
- model && /* @__PURE__ */ jsxRuntimeExports.jsx(ModelLabel, { model, fallback: fallback2 }),
86259
+ model && /* @__PURE__ */ jsxRuntimeExports.jsx(ModelLabel, { model, fallback: fallback2, fallbackTransition }),
85932
86260
  usage && /* @__PURE__ */ jsxRuntimeExports.jsx(TokenUsage, { usage }),
85933
86261
  hasDuration && /* @__PURE__ */ jsxRuntimeExports.jsx(Duration, { durationMs })
85934
86262
  ] })
@@ -85959,9 +86287,20 @@ function getFallbackReasonText(reason) {
85959
86287
  function shortModelName(model) {
85960
86288
  return model.split("/").pop() || model;
85961
86289
  }
85962
- function ModelLabel({ model, fallback: fallback2 }) {
86290
+ function ModelLabel({
86291
+ model,
86292
+ fallback: fallback2,
86293
+ fallbackTransition
86294
+ }) {
86295
+ const { t: t2 } = useTranslation();
85963
86296
  const shortName = shortModelName(model);
85964
- return /* @__PURE__ */ jsxRuntimeExports.jsx(AppTooltip, { content: model, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx(styles$S.modelLabel, fallback2 ? styles$S.modelLabelFallback : ""), children: shortName }) });
86297
+ const reasonText = fallbackTransition ? t2(getFallbackReasonText(fallbackTransition.reason)) : void 0;
86298
+ const tooltip = fallbackTransition ? t2("message.fallback.usedTooltip", {
86299
+ from: shortModelName(fallbackTransition.fromModel),
86300
+ to: shortModelName(fallbackTransition.toModel),
86301
+ reason: reasonText
86302
+ }) : model;
86303
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(AppTooltip, { content: tooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx(styles$S.modelLabel, fallback2 ? styles$S.modelLabelFallback : ""), children: fallback2 ? t2("message.fallback.usedLabel", { model: shortName }) : shortName }) });
85965
86304
  }
85966
86305
  function formatTokenCount(n2) {
85967
86306
  if (!n2) return "0";
@@ -86121,6 +86460,10 @@ const MessageItem = reactExports.memo(function MessageItem2({
86121
86460
  isGroupChat,
86122
86461
  isLastAgentMessage = false,
86123
86462
  autoCollapsed = false,
86463
+ forceExpanded = false,
86464
+ searchMatch,
86465
+ searchTerms,
86466
+ isActiveSearchMatch = false,
86124
86467
  scrollContainerRef,
86125
86468
  onLeaveStickyBottom,
86126
86469
  onAgentClick,
@@ -86198,6 +86541,10 @@ const MessageItem = reactExports.memo(function MessageItem2({
86198
86541
  textContent,
86199
86542
  isLastAgentMessage,
86200
86543
  autoCollapsed,
86544
+ forceExpanded,
86545
+ searchMatch,
86546
+ searchTerms,
86547
+ isActiveSearchMatch,
86201
86548
  sending,
86202
86549
  displaySenderId,
86203
86550
  senderName: senderName2 ?? void 0,
@@ -86228,6 +86575,8 @@ const MessageItem = reactExports.memo(function MessageItem2({
86228
86575
  isUser,
86229
86576
  isLastAgentMessage: false,
86230
86577
  autoCollapsed: false,
86578
+ searchMatch,
86579
+ isActiveSearchMatch,
86231
86580
  sending,
86232
86581
  textContent
86233
86582
  }
@@ -86281,6 +86630,10 @@ function AgentBlockMessage({
86281
86630
  textContent,
86282
86631
  isLastAgentMessage,
86283
86632
  autoCollapsed,
86633
+ forceExpanded,
86634
+ searchMatch,
86635
+ searchTerms,
86636
+ isActiveSearchMatch,
86284
86637
  sending,
86285
86638
  displaySenderId,
86286
86639
  senderName: senderName2,
@@ -86306,6 +86659,9 @@ function AgentBlockMessage({
86306
86659
  return s2.runMetricsMap.get(message2.sessionId);
86307
86660
  }, [message2.runId, message2.sessionId])
86308
86661
  );
86662
+ const retryInfo = useMessageStore(
86663
+ reactExports.useMemo(() => (s2) => s2.retryingMap.get(message2.sessionId) ?? null, [message2.sessionId])
86664
+ );
86309
86665
  const isActiveRun = useMessageStore(
86310
86666
  reactExports.useMemo(() => (s2) => !!message2.runId && s2.activeRunIdMap.get(message2.sessionId) === message2.runId, [message2.runId, message2.sessionId])
86311
86667
  );
@@ -86329,8 +86685,8 @@ function AgentBlockMessage({
86329
86685
  const displayDurationMs = messageStreaming && runMetrics ? elapsedMs : message2.durationMs;
86330
86686
  const showFooterMetrics = showRuntimeMetrics && !!(displayModel || displayUsage || displayDurationMs != null && !isNaN(displayDurationMs));
86331
86687
  const [manuallyExpanded, setManuallyExpanded] = reactExports.useState(false);
86332
- const isExpanded = !autoCollapsed || manuallyExpanded;
86333
- const isCollapsed = autoCollapsed && !manuallyExpanded;
86688
+ const isExpanded = !autoCollapsed || manuallyExpanded || forceExpanded;
86689
+ const isCollapsed = autoCollapsed && !manuallyExpanded && !forceExpanded;
86334
86690
  reactExports.useEffect(() => {
86335
86691
  setManuallyExpanded(false);
86336
86692
  }, [autoCollapsed]);
@@ -86427,10 +86783,15 @@ function AgentBlockMessage({
86427
86783
  isUser: false,
86428
86784
  isLastAgentMessage,
86429
86785
  autoCollapsed,
86786
+ forceExpanded,
86787
+ searchMatch,
86788
+ searchTerms,
86789
+ isActiveSearchMatch,
86430
86790
  sending,
86431
86791
  textContent: getBlocksTextContent(blocks),
86432
86792
  variant: "embedded",
86433
86793
  embedRuntimeStatusInBubble: true,
86794
+ retryInfo,
86434
86795
  onCancelGuidance: (guidanceId) => {
86435
86796
  void useMessageStore.getState().cancelGuidance(guidanceId);
86436
86797
  },
@@ -86445,6 +86806,7 @@ function AgentBlockMessage({
86445
86806
  durationMs: displayDurationMs,
86446
86807
  model: displayModel,
86447
86808
  fallback: displayFallback,
86809
+ fallbackTransition: runMetrics?.fallbackTransition ?? message2.metadata?.fallbackTransition,
86448
86810
  variant: "embedded"
86449
86811
  }
86450
86812
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
@@ -86531,29 +86893,37 @@ function GuideQueuedMessageButton({
86531
86893
  }
86532
86894
  ) });
86533
86895
  }
86534
- const container$e = "_container_1mfpt_1";
86535
- const loadMoreButton = "_loadMoreButton_1mfpt_8";
86536
- const messageWrapper = "_messageWrapper_1mfpt_25";
86537
- const contextStatusRow = "_contextStatusRow_1mfpt_32";
86538
- const maintenanceRow = "_maintenanceRow_1mfpt_41";
86539
- const loadingMore = "_loadingMore_1mfpt_45";
86540
- const noMoreMessages$2 = "_noMoreMessages_1mfpt_46";
86541
- const centerState = "_centerState_1mfpt_47";
86542
- const newMessageHint = "_newMessageHint_1mfpt_61";
86543
- const scrollToBottom$2 = "_scrollToBottom_1mfpt_81";
86544
- const quoteSelectionButton = "_quoteSelectionButton_1mfpt_108";
86896
+ const container$e = "_container_1nc3n_1";
86897
+ const loadMoreButton = "_loadMoreButton_1nc3n_8";
86898
+ const searchButton = "_searchButton_1nc3n_29";
86899
+ const newMessageHint = "_newMessageHint_1nc3n_30";
86900
+ const scrollToBottom$2 = "_scrollToBottom_1nc3n_31";
86901
+ const quoteSelectionButton = "_quoteSelectionButton_1nc3n_32";
86902
+ const messageWrapper = "_messageWrapper_1nc3n_37";
86903
+ const searchBar = "_searchBar_1nc3n_44";
86904
+ const searchInput$6 = "_searchInput_1nc3n_60";
86905
+ const searchCount$1 = "_searchCount_1nc3n_81";
86906
+ const contextStatusRow = "_contextStatusRow_1nc3n_113";
86907
+ const maintenanceRow = "_maintenanceRow_1nc3n_122";
86908
+ const loadingMore = "_loadingMore_1nc3n_126";
86909
+ const noMoreMessages$2 = "_noMoreMessages_1nc3n_127";
86910
+ const centerState = "_centerState_1nc3n_128";
86545
86911
  const styles$P = {
86546
86912
  container: container$e,
86547
86913
  loadMoreButton,
86914
+ searchButton,
86915
+ newMessageHint,
86916
+ scrollToBottom: scrollToBottom$2,
86917
+ quoteSelectionButton,
86548
86918
  messageWrapper,
86919
+ searchBar,
86920
+ searchInput: searchInput$6,
86921
+ searchCount: searchCount$1,
86549
86922
  contextStatusRow,
86550
86923
  maintenanceRow,
86551
86924
  loadingMore,
86552
86925
  noMoreMessages: noMoreMessages$2,
86553
- centerState,
86554
- newMessageHint,
86555
- scrollToBottom: scrollToBottom$2,
86556
- quoteSelectionButton
86926
+ centerState
86557
86927
  };
86558
86928
  function getAutoCollapsedMessageIds(messages) {
86559
86929
  const collapsibleAgentMessageIds = [];
@@ -86620,6 +86990,10 @@ function MessageListRowItem({ row: row2, ...props }) {
86620
86990
  isGroupChat,
86621
86991
  lastAgentMessageId,
86622
86992
  autoCollapsedMessageIds,
86993
+ searchMatchByMessageId,
86994
+ searchTerms,
86995
+ activeSearchMessageId,
86996
+ searchExpandedMessageIds,
86623
86997
  scroll,
86624
86998
  onAgentClick,
86625
86999
  onWriteMemory,
@@ -86642,6 +87016,10 @@ function MessageListRowItem({ row: row2, ...props }) {
86642
87016
  isLastMessage: row2.isLastMessage,
86643
87017
  isLastAgentMessage: row2.message.id === lastAgentMessageId,
86644
87018
  autoCollapsed: autoCollapsedMessageIds.has(row2.message.id),
87019
+ forceExpanded: searchExpandedMessageIds?.has(row2.message.id) ?? false,
87020
+ searchMatch: searchMatchByMessageId?.get(row2.message.id),
87021
+ searchTerms,
87022
+ isActiveSearchMatch: activeSearchMessageId === row2.message.id,
86645
87023
  scrollContainerRef: scroll.containerRef,
86646
87024
  onLeaveStickyBottom: scroll.leaveStickyBottom,
86647
87025
  onAgentClick,
@@ -86665,8 +87043,11 @@ function QuoteSelectionButton({ selection: selection2, onQuote, className }) {
86665
87043
  top: selection2.position.top,
86666
87044
  left: selection2.position.left
86667
87045
  },
87046
+ "data-quote-selection-button": "true",
86668
87047
  "aria-label": label2,
86669
87048
  onMouseDown: (event) => event.preventDefault(),
87049
+ onMouseUp: (event) => event.stopPropagation(),
87050
+ onTouchEnd: (event) => event.stopPropagation(),
86670
87051
  onClick: () => onQuote(selection2),
86671
87052
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Quote, { size: 15, "aria-hidden": "true" })
86672
87053
  }
@@ -86676,6 +87057,7 @@ const MIN_QUOTE_SELECTION_LENGTH = 2;
86676
87057
  const BUTTON_WIDTH = 36;
86677
87058
  const BUTTON_HEIGHT = 32;
86678
87059
  const VIEWPORT_MARGIN = 8;
87060
+ const QUOTE_SELECTION_BUTTON_SELECTOR = '[data-quote-selection-button="true"]';
86679
87061
  function isEditableElement(node2) {
86680
87062
  const element2 = node2 instanceof Element ? node2 : node2?.parentElement;
86681
87063
  if (!element2) return false;
@@ -86715,6 +87097,9 @@ function getButtonPosition(rect2) {
86715
87097
  function isCoarsePointer() {
86716
87098
  return typeof window.matchMedia === "function" && window.matchMedia("(pointer: coarse)").matches;
86717
87099
  }
87100
+ function isQuoteSelectionButtonEvent(event) {
87101
+ return event.target instanceof Element && Boolean(event.target.closest(QUOTE_SELECTION_BUTTON_SELECTOR));
87102
+ }
86718
87103
  function readQuoteSelection(root2, options) {
86719
87104
  if (!root2 || isCoarsePointer()) return null;
86720
87105
  const selection2 = window.getSelection();
@@ -86745,32 +87130,63 @@ function areSelectionsEqual(a2, b2) {
86745
87130
  function useTextSelectionQuote(rootRef, options) {
86746
87131
  const [selection2, setSelection] = reactExports.useState(null);
86747
87132
  const latestSelectionRef = reactExports.useRef(null);
87133
+ const updateTimerRef = reactExports.useRef(null);
87134
+ const isSelectionSettlingRef = reactExports.useRef(false);
87135
+ const cancelScheduledUpdate = reactExports.useCallback(() => {
87136
+ if (updateTimerRef.current === null) return;
87137
+ window.clearTimeout(updateTimerRef.current);
87138
+ updateTimerRef.current = null;
87139
+ isSelectionSettlingRef.current = false;
87140
+ }, []);
86748
87141
  const updateSelection = reactExports.useCallback(() => {
86749
87142
  const next2 = readQuoteSelection(rootRef.current, options);
86750
87143
  if (areSelectionsEqual(latestSelectionRef.current, next2)) return;
86751
87144
  latestSelectionRef.current = next2;
86752
87145
  setSelection(next2);
86753
87146
  }, [options, rootRef]);
87147
+ const updateSelectionAfterGesture = reactExports.useCallback((event) => {
87148
+ if (isQuoteSelectionButtonEvent(event)) return;
87149
+ cancelScheduledUpdate();
87150
+ isSelectionSettlingRef.current = true;
87151
+ updateTimerRef.current = window.setTimeout(() => {
87152
+ updateTimerRef.current = null;
87153
+ isSelectionSettlingRef.current = false;
87154
+ updateSelection();
87155
+ }, 0);
87156
+ }, [cancelScheduledUpdate, updateSelection]);
86754
87157
  const clearSelection = reactExports.useCallback(() => {
87158
+ cancelScheduledUpdate();
86755
87159
  latestSelectionRef.current = null;
86756
87160
  setSelection(null);
86757
87161
  window.getSelection()?.removeAllRanges();
86758
- }, []);
87162
+ }, [cancelScheduledUpdate]);
86759
87163
  const hideSelection = reactExports.useCallback(() => {
87164
+ cancelScheduledUpdate();
86760
87165
  latestSelectionRef.current = null;
86761
87166
  setSelection(null);
86762
- }, []);
87167
+ }, [cancelScheduledUpdate]);
87168
+ const hideSelectionOnChange = reactExports.useCallback(() => {
87169
+ if (isSelectionSettlingRef.current) return;
87170
+ hideSelection();
87171
+ }, [hideSelection]);
86763
87172
  reactExports.useEffect(() => {
86764
- document.addEventListener("selectionchange", updateSelection);
87173
+ document.addEventListener("selectionchange", hideSelectionOnChange);
87174
+ document.addEventListener("mouseup", updateSelectionAfterGesture);
87175
+ document.addEventListener("keyup", updateSelectionAfterGesture);
87176
+ document.addEventListener("touchend", updateSelectionAfterGesture);
86765
87177
  window.addEventListener("resize", hideSelection);
86766
87178
  const scrollRoot = rootRef.current;
86767
87179
  scrollRoot?.addEventListener("scroll", hideSelection, { passive: true });
86768
87180
  return () => {
86769
- document.removeEventListener("selectionchange", updateSelection);
87181
+ cancelScheduledUpdate();
87182
+ document.removeEventListener("selectionchange", hideSelectionOnChange);
87183
+ document.removeEventListener("mouseup", updateSelectionAfterGesture);
87184
+ document.removeEventListener("keyup", updateSelectionAfterGesture);
87185
+ document.removeEventListener("touchend", updateSelectionAfterGesture);
86770
87186
  window.removeEventListener("resize", hideSelection);
86771
87187
  scrollRoot?.removeEventListener("scroll", hideSelection);
86772
87188
  };
86773
- }, [hideSelection, rootRef, updateSelection]);
87189
+ }, [cancelScheduledUpdate, hideSelection, hideSelectionOnChange, rootRef, updateSelectionAfterGesture]);
86774
87190
  return {
86775
87191
  selection: selection2,
86776
87192
  clearSelection,
@@ -86796,13 +87212,24 @@ function useMessageTextSelectionQuote(rootRef) {
86796
87212
  hideSelection: quote.hideSelection
86797
87213
  };
86798
87214
  }
87215
+ const SEARCH_MATCH_SCROLL_OFFSET = 96;
86799
87216
  function getSortedMessages(msgMap) {
86800
87217
  if (!msgMap) return [];
86801
87218
  return Array.from(msgMap.values()).sort((a2, b2) => a2.createdAt - b2.createdAt);
86802
87219
  }
87220
+ function shouldIgnoreFindShortcut(event) {
87221
+ const target2 = event.target;
87222
+ if (!(target2 instanceof HTMLElement)) return false;
87223
+ if (target2.closest("[data-message-search]")) return false;
87224
+ return Boolean(target2.closest("[data-browser-find-scope]"));
87225
+ }
86803
87226
  const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, sending, onAgentClick, onWriteMemory, onQuoteText, maintenanceEvent, sessionInfo }, ref) {
86804
87227
  const { t: t2 } = useTranslation();
86805
87228
  const { agents } = useAgentStore();
87229
+ const [searchOpen, setSearchOpen] = reactExports.useState(false);
87230
+ const [searchState, setSearchState] = reactExports.useState(EMPTY_MESSAGE_SEARCH_STATE);
87231
+ const [searchExpandedMessageIds, setSearchExpandedMessageIds] = reactExports.useState(() => /* @__PURE__ */ new Set());
87232
+ const searchInputRef = reactExports.useRef(null);
86806
87233
  const msgMap = useMessageStore((s2) => s2.messagesMap.get(sessionId));
86807
87234
  const loading2 = useMessageStore(
86808
87235
  reactExports.useMemo(() => (s2) => s2.loadingMap.get(sessionId) ?? false, [sessionId])
@@ -86823,9 +87250,13 @@ const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, s
86823
87250
  reactExports.useMemo(() => (s2) => s2.messageUiStateMap.get(sessionId), [sessionId])
86824
87251
  );
86825
87252
  const messages = reactExports.useMemo(
86826
- () => getSortedMessages(msgMap).filter((message2) => !messageUiStateMap?.get(message2.id)?.hiddenByGuidance),
87253
+ () => getSortedMessages(msgMap).filter(
87254
+ (message2) => !shouldHideSourceMessageByGuidance(messageUiStateMap?.get(message2.id)?.guidanceRequest)
87255
+ ),
86827
87256
  [msgMap, messageUiStateMap]
86828
87257
  );
87258
+ const lastMessage = messages[messages.length - 1];
87259
+ const tailMessageKey = lastMessage ? `${lastMessage.id}:${lastMessage.updatedAt}:${lastMessage.status ?? ""}` : void 0;
86829
87260
  const streamRevision = useMessageStore(
86830
87261
  reactExports.useMemo(() => (s2) => s2.streamRevisionMap.get(sessionId) ?? 0, [sessionId])
86831
87262
  );
@@ -86859,6 +87290,7 @@ const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, s
86859
87290
  const scroll = useScrollAnchor(
86860
87291
  {
86861
87292
  messageCount: messages.length,
87293
+ tailMessageKey,
86862
87294
  streamVersion: streamRevision,
86863
87295
  bottomContentVersion: `${sending ? 1 : 0}:${activeRunId ?? ""}`,
86864
87296
  loadingMore: loadingMore2,
@@ -86867,6 +87299,104 @@ const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, s
86867
87299
  loadMoreMessages
86868
87300
  );
86869
87301
  const quoteSelection = useMessageTextSelectionQuote(scroll.containerRef);
87302
+ const searchMatchByMessageId = reactExports.useMemo(() => {
87303
+ const matchByMessageId = /* @__PURE__ */ new Map();
87304
+ searchState.matches.forEach((match, index2) => {
87305
+ if (index2 === searchState.currentIndex || !matchByMessageId.has(match.messageId)) {
87306
+ matchByMessageId.set(match.messageId, match);
87307
+ }
87308
+ });
87309
+ return matchByMessageId;
87310
+ }, [searchState.currentIndex, searchState.matches]);
87311
+ const searchTerms = reactExports.useMemo(() => getSearchTerms(searchState.query), [searchState.query]);
87312
+ const activeSearchMatch2 = searchState.currentIndex >= 0 ? searchState.matches[searchState.currentIndex] : void 0;
87313
+ const scrollToSearchMatch = reactExports.useCallback((messageId) => {
87314
+ const messageEl = document.getElementById(`msg-${messageId}`) ?? scroll.containerRef.current?.querySelector(`[data-message-id="${CSS.escape(messageId)}"]`);
87315
+ const activeMark = messageEl?.querySelector('mark[data-active-search-match="true"]');
87316
+ const targetEl = activeMark ?? messageEl;
87317
+ const container2 = scroll.containerRef.current;
87318
+ scroll.leaveStickyBottom();
87319
+ if (targetEl && container2 && typeof container2.scrollTo === "function") {
87320
+ const containerRect = container2.getBoundingClientRect();
87321
+ const targetRect = targetEl.getBoundingClientRect();
87322
+ const targetTop = targetRect.top - containerRect.top + container2.scrollTop;
87323
+ container2.scrollTo({ top: Math.max(0, targetTop - SEARCH_MATCH_SCROLL_OFFSET), behavior: "smooth" });
87324
+ return;
87325
+ }
87326
+ if (targetEl && typeof targetEl.scrollIntoView === "function") {
87327
+ targetEl.scrollIntoView({ behavior: "smooth", block: "center" });
87328
+ }
87329
+ }, [scroll]);
87330
+ const navigateToSearchIndex = reactExports.useCallback((nextIndex) => {
87331
+ setSearchState((current) => {
87332
+ if (current.matches.length === 0) return current;
87333
+ const normalizedIndex = (nextIndex + current.matches.length) % current.matches.length;
87334
+ const match = current.matches[normalizedIndex];
87335
+ if (autoCollapsedMessageIds.has(match.messageId)) {
87336
+ setSearchExpandedMessageIds((prev2) => {
87337
+ if (prev2.has(match.messageId)) return prev2;
87338
+ const next2 = new Set(prev2);
87339
+ next2.add(match.messageId);
87340
+ return next2;
87341
+ });
87342
+ }
87343
+ return { ...current, currentIndex: normalizedIndex };
87344
+ });
87345
+ }, [autoCollapsedMessageIds]);
87346
+ const closeSearch = reactExports.useCallback(() => {
87347
+ setSearchOpen(false);
87348
+ setSearchState(EMPTY_MESSAGE_SEARCH_STATE);
87349
+ setSearchExpandedMessageIds(/* @__PURE__ */ new Set());
87350
+ }, []);
87351
+ const updateSearchQuery = reactExports.useCallback((query) => {
87352
+ const matches = searchMessages(messages, query);
87353
+ setSearchExpandedMessageIds(/* @__PURE__ */ new Set());
87354
+ setSearchState({
87355
+ query,
87356
+ matches,
87357
+ currentIndex: matches.length > 0 ? 0 : -1
87358
+ });
87359
+ }, [messages]);
87360
+ reactExports.useEffect(() => {
87361
+ if (!searchOpen) return;
87362
+ const nextMatches = searchMessages(messages, searchState.query);
87363
+ setSearchState((current) => ({
87364
+ ...current,
87365
+ matches: nextMatches,
87366
+ currentIndex: nextMatches.length === 0 ? -1 : Math.min(Math.max(current.currentIndex, 0), nextMatches.length - 1)
87367
+ }));
87368
+ }, [messages, searchOpen, searchState.query]);
87369
+ reactExports.useEffect(() => {
87370
+ const handleKeyDown = (event) => {
87371
+ const mod = event.metaKey || event.ctrlKey;
87372
+ if (mod && event.key.toLowerCase() === "f" && !shouldIgnoreFindShortcut(event)) {
87373
+ event.preventDefault();
87374
+ setSearchOpen(true);
87375
+ window.requestAnimationFrame(() => searchInputRef.current?.focus());
87376
+ return;
87377
+ }
87378
+ if (!searchOpen) return;
87379
+ if (event.key === "Escape") {
87380
+ event.preventDefault();
87381
+ closeSearch();
87382
+ }
87383
+ };
87384
+ window.addEventListener("keydown", handleKeyDown);
87385
+ return () => window.removeEventListener("keydown", handleKeyDown);
87386
+ }, [closeSearch, searchOpen]);
87387
+ reactExports.useEffect(() => {
87388
+ if (!searchOpen || !activeSearchMatch2) return;
87389
+ if (autoCollapsedMessageIds.has(activeSearchMatch2.messageId)) {
87390
+ setSearchExpandedMessageIds((prev2) => {
87391
+ if (prev2.has(activeSearchMatch2.messageId)) return prev2;
87392
+ const next2 = new Set(prev2);
87393
+ next2.add(activeSearchMatch2.messageId);
87394
+ return next2;
87395
+ });
87396
+ }
87397
+ const raf = window.requestAnimationFrame(() => scrollToSearchMatch(activeSearchMatch2.messageId));
87398
+ return () => window.cancelAnimationFrame(raf);
87399
+ }, [activeSearchMatch2, autoCollapsedMessageIds, scrollToSearchMatch, searchOpen]);
86870
87400
  reactExports.useImperativeHandle(ref, () => ({
86871
87401
  scrollToTop: scroll.scrollToTop,
86872
87402
  scrollToBottom: scroll.scrollToBottom,
@@ -86897,6 +87427,58 @@ const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, s
86897
87427
  onWheel: scroll.handleUserScrollIntent,
86898
87428
  onTouchMove: scroll.handleUserScrollIntent,
86899
87429
  children: [
87430
+ searchOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$P.searchBar, "data-message-search": true, children: [
87431
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
87432
+ "input",
87433
+ {
87434
+ ref: searchInputRef,
87435
+ className: styles$P.searchInput,
87436
+ value: searchState.query,
87437
+ onChange: (event) => updateSearchQuery(event.target.value),
87438
+ onKeyDown: (event) => {
87439
+ if (event.key === "Enter") {
87440
+ event.preventDefault();
87441
+ navigateToSearchIndex(searchState.currentIndex + (event.shiftKey ? -1 : 1));
87442
+ }
87443
+ },
87444
+ placeholder: t2("messageSearch.placeholder"),
87445
+ "aria-label": t2("messageSearch.placeholder")
87446
+ }
87447
+ ),
87448
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$P.searchCount, children: searchState.matches.length > 0 ? `${searchState.currentIndex + 1} / ${searchState.matches.length}` : searchState.query.trim() ? "0 / 0" : t2("messageSearch.emptyHint") }),
87449
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
87450
+ "button",
87451
+ {
87452
+ type: "button",
87453
+ className: styles$P.searchButton,
87454
+ onClick: () => navigateToSearchIndex(searchState.currentIndex - 1),
87455
+ disabled: searchState.matches.length === 0,
87456
+ "aria-label": t2("messageSearch.previousResult"),
87457
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { size: 14 })
87458
+ }
87459
+ ),
87460
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
87461
+ "button",
87462
+ {
87463
+ type: "button",
87464
+ className: styles$P.searchButton,
87465
+ onClick: () => navigateToSearchIndex(searchState.currentIndex + 1),
87466
+ disabled: searchState.matches.length === 0,
87467
+ "aria-label": t2("messageSearch.nextResult"),
87468
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { size: 14 })
87469
+ }
87470
+ ),
87471
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
87472
+ "button",
87473
+ {
87474
+ type: "button",
87475
+ className: styles$P.searchButton,
87476
+ onClick: closeSearch,
87477
+ "aria-label": t2("messageSearch.close"),
87478
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$2, { size: 14 })
87479
+ }
87480
+ )
87481
+ ] }),
86900
87482
  /* @__PURE__ */ jsxRuntimeExports.jsx(
86901
87483
  MessageListRows,
86902
87484
  {
@@ -86905,6 +87487,10 @@ const MessageList = reactExports.forwardRef(function MessageList2({ sessionId, s
86905
87487
  isGroupChat,
86906
87488
  lastAgentMessageId,
86907
87489
  autoCollapsedMessageIds,
87490
+ searchMatchByMessageId,
87491
+ searchTerms,
87492
+ activeSearchMessageId: activeSearchMatch2?.messageId ?? null,
87493
+ searchExpandedMessageIds,
86908
87494
  scroll,
86909
87495
  onAgentClick,
86910
87496
  onWriteMemory,
@@ -91825,13 +92411,13 @@ const onboarding$1 = { "title": "为智能体注入灵魂", "description": "只
91825
92411
  const channelGuide$1 = { "title": "为智能体注入灵魂", "description": "连接 AI 模型,智能体才能思考和回答", "configure": "连接 AI", "dismiss": "跳过" };
91826
92412
  const agentChannelCheck$1 = { "title": "智能体还没有灵魂", "description": "连接 AI 模型后才能开始对话", "configure": "连接 AI", "skip": "仍要创建" };
91827
92413
  const welcome$1 = { "description": "选择一个智能体开始对话,或叫上所有人一起讨论", "title": "开启一段思考", "subtitle": "从左侧选择一位伙伴开始对话", "or": "或", "createGroup": "叫上所有人一起讨论" };
91828
- const settings$1 = { "title": "设置", "nav": { "app": "应用", "capabilities": "能力", "automation": "自动化", "agents": "Agent", "connection": "连接" }, "tabs": { "llm": "模型通道", "agent": "智能体", "skill": "Skills", "appearance": "外观设置", "remote": "远程访问", "mcp": "MCP 服务", "search": "搜索引擎", "integration": "Bot接入", "about": "关于", "usage": "使用统计" }, "panels": { "integration": { "title": "外部接入", "description": "连接外部平台,让 Agent 通过这些接入与你对话", "addNew": "接入新平台", "empty": "还没有连接任何外部平台。绑定后,Agent 可以在对应平台接收和回复消息。", "connected": "已连接", "disconnected": "未连接", "connecting": "连接中", "reconnecting": "重连中", "authFailed": "鉴权失败", "testConnection": "测试连接", "disconnect": "断开", "reconnect": "重新连接", "bind": { "step1Title": "获取凭证", "step2Title": "选择绑定目标", "step3Title": "验证连接", "botId": "Bot ID", "botIdPlaceholder": "输入企业微信机器人 Bot ID", "secret": "Secret", "secretPlaceholder": "输入机器人 Secret", "targetAgent": "Agent", "targetAgentDesc": "Bot 作为 Agent 的化身", "targetThread": "群组 Session", "targetThreadDesc": "Bot 接入群组的某个 Session", "selectAgent": "选择 Agent", "selectGroup": "选择群组", "selectThread": "选择 Session", "next": "下一步", "prev": "上一步", "cancel": "取消", "done": "完成", "testSuccess": "连接成功!WebSocket 通道已建立。", "testFailed": "连接失败", "summaryPlatform": "平台", "summaryBotId": "Bot ID", "summaryTarget": "绑定目标" }, "confirmUnbind": "确定断开此接入?", "unbindTitle": "断开接入", "hint": "外部接入仅在应用运行时可用。关闭应用后,Bot 将自动离线。", "wecomBot": "企业微信", "methodQrcode": "扫码绑定", "methodQrcodeDesc": "用企业微信扫描二维码,自动获取凭证", "methodManual": "手动输入", "methodManualDesc": "输入 Bot ID 和 Secret", "qrLoading": "正在获取二维码...", "qrHint": "请打开企业微信,扫描上方二维码", "qrTimeout": "扫码超时(5 分钟),请重试" }, "appearance": { "title": "外观", "description": "自定义主题、语言与界面显示方式" }, "channel": { "title": "模型通道", "description": "管理用于连接 AI 服务的模型通道与默认模型" }, "multimodal": { "title": "多模态能力", "description": "配置图片、视频、语音等多模态能力的分析与生成" }, "mcp": { "title": "扩展服务", "description": "配置 MCP 服务以扩展 Agent 能力" }, "skill": { "title": "技能", "description": "管理 Agent 可使用的技能模块" }, "search": { "title": "搜索", "description": "配置联网搜索引擎与默认搜索行为" }, "remote": { "title": "远程访问", "description": "开启后可通过手机浏览器访问 KAi,所有连接使用加密 token 认证" }, "agent": { "title": "Agents", "description": "创建和管理自定义 Agent" }, "memoryGrowth": { "title": "记忆成长", "description": "配置记忆如何随着时间自动更新与整理" }, "scheduler": { "title": "定时任务", "description": "创建和管理定时执行的自动化任务" }, "about": { "title": "关于 KAi", "description": "多 AI Agent 协作桌面应用" }, "usage": { "title": "使用统计", "description": "查看本机 AI 工作、Token、群聊、模型和工具使用情况。" } }, "channel": { "title": "模型通道", "add": "添加通道", "addTitle": "添加通道", "editTitle": "编辑通道", "name": "通道名称", "namePlaceholder": "例如:OpenAI、Azure", "apiType": "接口类型", "apiTypeOpenai": "OpenAI Compatible", "apiTypeOfficialOpenai": "OpenAI", "apiTypeAnthropic": "Anthropic", "apiTypeGoogle": "Google Gemini", "apiTypeAuto": "自动检测", "baseUrl": "Base URL", "apiKey": "API Key", "defaultModel": "默认模型", "selectModel": "选择模型...", "enterUrlAndKey": "请先填写 Base URL 和 API Key", "loadingModels": "加载模型中...", "searchOrType": "搜索或输入模型名称…", "useCustom": "自定义", "isDefault": "默认通道", "setAsDefault": "设为默认通道", "default": "默认", "setDefault": "设为默认", "edit": "编辑", "delete": "删除", "confirmDelete": "确定删除此通道?", "deleteTitle": "删除通道", "showApiKey": "显示 API Key", "hideApiKey": "隐藏 API Key", "empty": "暂无通道,点击下方按钮创建", "deleted": "通道已删除", "setDefaultDone": "已将「{{name}}」设为默认通道", "actions": "「{{name}}」操作", "confirmDeleteMm": "此通道正用于多模态图片分析(analyzeImage 工具),删除后该功能将停用。确定删除「{{name}}」?", "tabChannels": "通道", "tabMultimodal": "多模态" }, "llm": { "title": "LLM 配置", "model": "模型名称", "modelPreset": "模型预设", "customModel": "自定义模型", "apiKey": "API Key", "baseUrl": "Base URL", "temperature": "温度", "maxTokens": "最大令牌数", "topP": "Top P", "loadingModels": "加载模型中...", "errors": { "network_error": "无法连接到 API 服务器,请检查 Base URL 和网络连接", "auth_failed": "API Key 验证失败,请检查您的密钥", "api_error": "API 请求失败,请检查服务器状态" } }, "remote": { "title": "远程访问", "description": "开启后可通过手机浏览器访问 KAi。\n所有连接使用加密 token 认证。", "on": "开启", "off": "关闭", "copyLink": "复制链接", "rotateLink": "重新生成链接", "stopLink": "停止远程访问", "rotateSuccess": "已生成新链接,旧链接已失效", "linkTitle": "稳定访问链接", "linkDescription": "链接会在下次启动时自动恢复,除非你手动停止或重新生成。", "restoreMode": "启动恢复", "restoreEnabled": "自动恢复", "restoreDisabled": "不自动恢复", "lastGenerated": "最近生成时间", "notGeneratedYet": "尚未生成", "restoreFailedTitle": "恢复失败", "status": { "disabled": "未开启", "enabling": "开启中", "enabled": "已开启", "restoring": "恢复中", "rotating": "生成新链接中", "stopping": "停止中", "error": "恢复失败" }, "qrCodeAlt": "远程访问二维码", "tokenPending": "正在等待访问 token...", "portValue": "端口: {{port}}", "connectionsValue": "连接: {{current}}/{{max}}", "addresses": "可用地址", "connectedClients": "已连接设备", "errors": { "toggleFailed": "更新远程访问状态失败", "copyFailed": "复制远程访问链接失败", "rotateFailed": "重新生成远程访问链接失败" } }, "search": { "engines": "搜索引擎列表", "builtIn": "内置", "default": "默认", "setDefault": "设为默认", "addCustom": "添加自定义引擎", "addEngine": "添加搜索引擎", "editEngine": "编辑搜索引擎", "name": "引擎名称", "namePlaceholder": "例如:Google Scholar", "urlTemplate": "URL 模板", "urlTemplateHint": "使用 {query} 作为搜索关键词占位符", "urlTemplateError": "URL 模板必须包含 {query} 占位符", "showWindow": "显示搜索窗口(调试用)", "confirmDelete": "确定删除此搜索引擎?", "deleteTitle": "删除搜索引擎", "delete": "删除" }, "language": "语言", "appearance": { "theme": "主题", "themeLight": "亮色", "themeDark": "暗色", "themeSystem": "跟随系统" }, "save": "保存", "cancel": "取消", "saveFailed": "保存设置失败,请重试", "saveSuccess": "保存成功", "mcp": { "title": "MCP 服务", "add": "添加服务", "addServer": "添加服务", "addTitle": "添加服务", "editTitle": "编辑服务", "empty": "暂无 MCP 服务", "confirmDelete": "确定要删除此服务吗?", "deleteTitle": "删除服务", "serverName": "服务名称", "serverType": "类型", "command": "命令", "args": "参数", "url": "WebSocket 地址", "enabled": "启用", "testConnection": "测试连接", "connected": "已连接", "disconnected": "未连接", "error": "连接错误", "edit": "编辑", "delete": "删除", "typeStdio": "Stdio", "typeCommand": "命令", "typeStreamableHttp": "Streamable HTTP", "typeWebsocket": "WebSocket", "toolCount": "工具数量", "testing": "测试中...", "testSuccess": "连接成功", "testFailed": "连接失败", "applyToAgent": "应用到 Agent", "appliedToAgents": "已应用到 {{count}} 个 Agent", "notAppliedToAnyAgent": "未应用到任何 Agent", "globallyDisabled": "全局停用", "selectedCount": "已选择 {{count}} 个", "searchAgent": "搜索 Agent", "noMatchingAgents": "未找到匹配的 Agent", "drawerDisabledWarning": "此 MCP 服务当前全局停用,Agent 无法实际使用", "filteredCount": "找到 {{count}} 个 Agent", "selectAll": "全选", "clearAll": "清空", "selectFiltered": "选中当前结果", "clearFiltered": "清空当前结果" }, "about": { "releaseNotes": "更新日志", "versionCopied": "已复制", "autoCheckForUpdates": "每天自动检查更新", "checkForUpdates": "检查更新", "checking": "正在检查更新", "goDownload": "前往下载", "newVersion": "发现新版本", "updateHighlights": "本次更新", "viewFullReleaseNotes": "查看完整更新日志", "retry": "重新检查", "upToDate": "当前已是最新版本", "updateError": "检查更新失败", "feedback": { "title": "反馈", "placeholder": "告诉我们在想什么...", "bug": "Bug", "feature": "功能建议", "other": "其他", "submit": "提交反馈", "showContact": "留下联系方式", "contactPlaceholder": "邮箱或其他联系方式", "success": "感谢反馈!", "error": "提交失败,请稍后再试。" } }, "multimodal": { "saved": "多模态配置已保存", "saveFailed": "保存失败", "saving": "保存中…", "noChannels": "暂无可用通道,请先在模型通道中添加", "goToChannels": "前往模型通道", "tabImageAnalysis": "图片分析", "tabImageGeneration": "图片生成", "tabVideo": "视频能力", "tabVoice": "语音能力", "comingSoon": "即将推出", "badgeOn": "ON", "badgeOff": "OFF", "analysis": { "title": "图片分析", "summary": "{channel} · {model} · {size}px", "summaryDefault": "未配置", "hint": "启用后,Agent 可使用 analyzeImage 工具识别和理解图片内容", "channel": "通道", "selectChannel": "请选择通道", "modelLabel": "指定模型(可选)", "modelHint": "留空使用通道默认模型", "maxImageEdge": "最大图片长边", "maxImageEdgeHint": "超出时自动缩放,越小成本越低", "inactive": "已关闭", "channelDeleted": "通道已失效", "incomplete": "未完成配置 · 请选择通道" }, "generation": { "title": "图片生成", "summary": "{channel} · {model} · {size}", "summaryDefault": "未配置", "hint": "启用后,Agent 可使用 generateImage 工具根据文字描述生成图片", "channel": "通道", "selectChannel": "请选择通道", "modelLabel": "指定模型(可选)", "modelHint": "留空使用通道默认模型", "defaultSize": "默认尺寸(可选)", "modelDefaultSize": "使用模型默认尺寸", "inactive": "已关闭", "channelDeleted": "通道已失效", "incomplete": "未完成配置 · 请选择通道" }, "fallback": { "title": "备用模型", "add": "添加备用", "remove": "删除", "selectChannel": "选择通道", "hint": "主模型失败时,按顺序依次尝试备用模型" } }, "integration": { "title": "外部接入", "description": "连接外部平台,让 Agent 通过这些接入与你对话", "addNew": "接入新平台", "empty": "还没有连接任何外部平台。绑定后,Agent 可以在对应平台接收和回复消息。", "connected": "已连接", "disconnected": "未连接", "connecting": "连接中", "reconnecting": "重连中", "authFailed": "鉴权失败", "testConnection": "测试连接", "editTarget": "编辑", "editTargetTitle": "修改绑定目标", "editTargetSuccess": "绑定目标已更新", "disconnect": "断开", "reconnect": "重新连接", "createdAt": "创建于 {{time}}", "bind": { "step0Title": "选择平台", "stepMethodTitle": "接入方式", "step1Title": "获取凭证", "step2Title": "选择绑定目标", "step3Title": "验证连接", "botId": "Bot ID", "botIdPlaceholder": "输入企业微信机器人 Bot ID", "secret": "Secret", "secretPlaceholder": "输入机器人 Secret", "targetAgent": "Agent", "targetAgentDesc": "Bot 作为 Agent 的化身", "targetThread": "群组 Session", "targetThreadDesc": "Bot 接入群组的某个 Session", "selectAgent": "选择 Agent", "selectGroup": "选择群组", "selectThread": "选择 Session", "next": "下一步", "prev": "上一步", "cancel": "取消", "done": "完成", "testSuccess": "连接成功!WebSocket 通道已建立。", "testFailed": "连接失败", "summaryPlatform": "平台", "summaryBotId": "Bot ID", "summaryTarget": "绑定目标" }, "confirmUnbind": "确定断开此接入?", "unbindTitle": "断开接入", "hint": "外部接入仅在应用运行时可用。关闭应用后,Bot 将自动离线。", "wecomBot": "企业微信", "wecomBotDesc": "通过企业微信 Bot 接入,需要 Bot ID 和 Secret", "wechatPersonal": "微信", "wechatPersonalDesc": "通过微信个人 Bot(ClawBot)接入,扫码登录即可", "methodQrcode": "扫码绑定", "methodQrcodeDesc": "用企业微信扫描二维码,自动获取凭证", "methodManual": "手动输入", "methodManualDesc": "输入 Bot ID 和 Secret", "qrLoading": "正在获取二维码...", "qrHint": "请打开企业微信,扫描上方二维码", "wpQrHint": "请打开微信,扫描上方二维码登录 Bot", "qrTimeout": "扫码超时(5 分钟),请重试" }, "usage": { "trustLine": "使用统计仅保存在本机,不记录对话内容,可随时清空。", "clearConfirm": "确定清空全部使用统计吗?这个操作不可恢复。", "empty": "还没有使用统计。开始一次对话后,这里会显示你的 AI 使用情况。", "filters": { "range": "时间范围", "scope": "统计范围" }, "range": { "today": "今天", "week": "本周", "month": "本月" }, "scope": { "all": "全部", "direct": "单聊", "group": "群聊" }, "metrics": { "work": "AI 工作次数", "tokens": "Token 用量", "tools": "工具调用", "messages": "消息数" }, "insights": "洞察", "noInsights": "数据还不够,继续使用后会出现洞察。", "trend": "每日 Token 用量", "sections": { "models": "模型用量", "agents": "Agent 用量", "groups": "群聊用量", "tools": "工具使用", "sessions": "高消耗 Session", "phrases": "常用话术" }, "phrases": { "empty": "暂无足够高频的话术记录(至少出现 3 次)", "count": "出现 {{count}} 次", "alreadyExists": "已存在相同内容的快捷回复", "added": "已加入快捷回复", "addFailed": "添加失败", "addToQuickReply": "加入快捷回复" }, "retention": "默认保留最近 90 天。", "clear": "清空统计", "loadError": "无法读取使用统计", "sessionLabel": "会话 {{index}}", "sessionFallback": "未知会话 {{index}}", "callsValue": "{{count}} 次", "insight": { "groupTokenShare": "本周期 {{rate}}% 的 Token 来自群聊协作。", "unfinishedCallRate": "{{rate}}% 的模型或工具调用未完成。", "topTool": "{{name}} 是最常用工具,共调用 {{count}} 次。", "topGroup": "{{name}} 是最活跃群聊,产生 {{count}} 次 AI 工作。" } } };
92414
+ const settings$1 = /* @__PURE__ */ JSON.parse('{"title":"设置","nav":{"app":"应用","capabilities":"能力","automation":"自动化","agents":"Agent","connection":"连接"},"tabs":{"llm":"模型通道","agent":"智能体","skill":"Skills","appearance":"外观设置","remote":"远程访问","mcp":"MCP 服务","search":"搜索引擎","integration":"Bot接入","about":"关于","usage":"使用统计"},"panels":{"integration":{"title":"外部接入","description":"连接外部平台,让 Agent 通过这些接入与你对话","addNew":"接入新平台","empty":"还没有连接任何外部平台。绑定后,Agent 可以在对应平台接收和回复消息。","connected":"已连接","disconnected":"未连接","connecting":"连接中","reconnecting":"重连中","authFailed":"鉴权失败","testConnection":"测试连接","disconnect":"断开","reconnect":"重新连接","bind":{"step1Title":"获取凭证","step2Title":"选择绑定目标","step3Title":"验证连接","botId":"Bot ID","botIdPlaceholder":"输入企业微信机器人 Bot ID","secret":"Secret","secretPlaceholder":"输入机器人 Secret","targetAgent":"Agent","targetAgentDesc":"Bot 作为 Agent 的化身","targetThread":"群组 Session","targetThreadDesc":"Bot 接入群组的某个 Session","selectAgent":"选择 Agent","selectGroup":"选择群组","selectThread":"选择 Session","next":"下一步","prev":"上一步","cancel":"取消","done":"完成","testSuccess":"连接成功!WebSocket 通道已建立。","testFailed":"连接失败","summaryPlatform":"平台","summaryBotId":"Bot ID","summaryTarget":"绑定目标"},"confirmUnbind":"确定断开此接入?","unbindTitle":"断开接入","hint":"外部接入仅在应用运行时可用。关闭应用后,Bot 将自动离线。","wecomBot":"企业微信","methodQrcode":"扫码绑定","methodQrcodeDesc":"用企业微信扫描二维码,自动获取凭证","methodManual":"手动输入","methodManualDesc":"输入 Bot ID 和 Secret","qrLoading":"正在获取二维码...","qrHint":"请打开企业微信,扫描上方二维码","qrTimeout":"扫码超时(5 分钟),请重试"},"appearance":{"title":"外观","description":"自定义主题、语言与界面显示方式"},"channel":{"title":"模型通道","description":"管理用于连接 AI 服务的模型通道与默认模型"},"multimodal":{"title":"多模态能力","description":"配置图片、视频、语音等多模态能力的分析与生成"},"mcp":{"title":"扩展服务","description":"配置 MCP 服务以扩展 Agent 能力"},"skill":{"title":"技能","description":"管理 Agent 可使用的技能模块"},"search":{"title":"搜索","description":"配置联网搜索引擎与默认搜索行为"},"remote":{"title":"远程访问","description":"开启后可通过手机浏览器访问 KAi,所有连接使用加密 token 认证"},"agent":{"title":"Agents","description":"创建和管理自定义 Agent"},"memoryGrowth":{"title":"记忆成长","description":"配置记忆如何随着时间自动更新与整理"},"scheduler":{"title":"定时任务","description":"创建和管理定时执行的自动化任务"},"about":{"title":"关于 KAi","description":"多 AI Agent 协作桌面应用"},"usage":{"title":"使用统计","description":"查看本机 AI 工作、Token、群聊、模型和工具使用情况。"}},"channel":{"title":"模型通道","add":"添加通道","addTitle":"添加通道","editTitle":"编辑通道","name":"通道名称","namePlaceholder":"例如:OpenAI、Azure","apiType":"接口类型","apiTypeOpenai":"OpenAI Compatible","apiTypeOfficialOpenai":"OpenAI","apiTypeAnthropic":"Anthropic","apiTypeGoogle":"Google Gemini","apiTypeAuto":"自动检测","baseUrl":"Base URL","apiKey":"API Key","defaultModel":"默认模型","selectModel":"选择模型...","enterUrlAndKey":"请先填写 Base URL 和 API Key","loadingModels":"加载模型中...","searchOrType":"搜索或输入模型名称…","useCustom":"自定义","isDefault":"默认通道","setAsDefault":"设为默认通道","default":"默认","setDefault":"设为默认","edit":"编辑","delete":"删除","confirmDelete":"确定删除此通道?","deleteTitle":"删除通道","showApiKey":"显示 API Key","hideApiKey":"隐藏 API Key","empty":"暂无通道,点击下方按钮创建","deleted":"通道已删除","setDefaultDone":"已将「{{name}}」设为默认通道","actions":"「{{name}}」操作","confirmDeleteMm":"此通道正用于多模态图片分析(analyzeImage 工具),删除后该功能将停用。确定删除「{{name}}」?","tabChannels":"通道","tabMultimodal":"多模态"},"llm":{"title":"LLM 配置","model":"模型名称","modelPreset":"模型预设","customModel":"自定义模型","apiKey":"API Key","baseUrl":"Base URL","temperature":"温度","maxTokens":"最大令牌数","topP":"Top P","loadingModels":"加载模型中...","errors":{"network_error":"无法连接到 API 服务器,请检查 Base URL 和网络连接","auth_failed":"API Key 验证失败,请检查您的密钥","api_error":"API 请求失败,请检查服务器状态"}},"remote":{"title":"远程访问","description":"开启后可通过手机浏览器访问 KAi。\\n所有连接使用加密 token 认证。","on":"开启","off":"关闭","copyLink":"复制链接","rotateLink":"重新生成链接","stopLink":"停止远程访问","rotateSuccess":"已生成新链接,旧链接已失效","linkTitle":"稳定访问链接","linkDescription":"链接会在下次启动时自动恢复,除非你手动停止或重新生成。","restoreMode":"启动恢复","restoreEnabled":"自动恢复","restoreDisabled":"不自动恢复","lastGenerated":"最近生成时间","notGeneratedYet":"尚未生成","restoreFailedTitle":"恢复失败","status":{"disabled":"未开启","enabling":"开启中","enabled":"已开启","restoring":"恢复中","rotating":"生成新链接中","stopping":"停止中","error":"恢复失败"},"qrCodeAlt":"远程访问二维码","tokenPending":"正在等待访问 token...","portValue":"端口: {{port}}","connectionsValue":"连接: {{current}}/{{max}}","addresses":"可用地址","connectedClients":"已连接设备","errors":{"toggleFailed":"更新远程访问状态失败","copyFailed":"复制远程访问链接失败","rotateFailed":"重新生成远程访问链接失败"}},"search":{"engines":"搜索引擎列表","builtIn":"内置","default":"默认","setDefault":"设为默认","addCustom":"添加自定义引擎","addEngine":"添加搜索引擎","editEngine":"编辑搜索引擎","name":"引擎名称","namePlaceholder":"例如:Google Scholar","urlTemplate":"URL 模板","urlTemplateHint":"使用 {query} 作为搜索关键词占位符","urlTemplateError":"URL 模板必须包含 {query} 占位符","showWindow":"显示搜索窗口(调试用)","confirmDelete":"确定删除此搜索引擎?","deleteTitle":"删除搜索引擎","delete":"删除"},"language":"语言","appearance":{"theme":"主题","themeLight":"亮色","themeDark":"暗色","themeSystem":"跟随系统"},"save":"保存","cancel":"取消","saveFailed":"保存设置失败,请重试","saveSuccess":"保存成功","mcp":{"title":"MCP 服务","add":"添加服务","addServer":"添加服务","addTitle":"添加服务","editTitle":"编辑服务","empty":"暂无 MCP 服务","confirmDelete":"确定要删除此服务吗?","deleteTitle":"删除服务","serverName":"服务名称","serverType":"类型","command":"命令","args":"参数","url":"WebSocket 地址","enabled":"启用","testConnection":"测试连接","connected":"已连接","disconnected":"未连接","error":"连接错误","edit":"编辑","delete":"删除","typeStdio":"Stdio","typeCommand":"命令","typeStreamableHttp":"Streamable HTTP","typeWebsocket":"WebSocket","toolCount":"工具数量","testing":"测试中...","testSuccess":"连接成功","testFailed":"连接失败","applyToAgent":"应用到 Agent","appliedToAgents":"已应用到 {{count}} 个 Agent","notAppliedToAnyAgent":"未应用到任何 Agent","globallyDisabled":"全局停用","selectedCount":"已选择 {{count}} 个","searchAgent":"搜索 Agent","noMatchingAgents":"未找到匹配的 Agent","drawerDisabledWarning":"此 MCP 服务当前全局停用,Agent 无法实际使用","filteredCount":"找到 {{count}} 个 Agent","selectAll":"全选","clearAll":"清空","selectFiltered":"选中当前结果","clearFiltered":"清空当前结果"},"about":{"releaseNotes":"更新日志","versionCopied":"已复制","autoCheckForUpdates":"每天自动检查更新","checkForUpdates":"检查更新","checking":"正在检查更新","goDownload":"前往下载","newVersion":"发现新版本","updateHighlights":"本次更新","viewFullReleaseNotes":"查看完整更新日志","retry":"重新检查","upToDate":"当前已是最新版本","updateError":"检查更新失败","feedback":{"title":"反馈","placeholder":"告诉我们在想什么...","bug":"Bug","feature":"功能建议","other":"其他","submit":"提交反馈","showContact":"留下联系方式","contactPlaceholder":"邮箱或其他联系方式","success":"感谢反馈!","error":"提交失败,请稍后再试。"}},"multimodal":{"saved":"多模态配置已保存","saveFailed":"保存失败","saving":"保存中…","noChannels":"暂无可用通道,请先在模型通道中添加","goToChannels":"前往模型通道","tabImageAnalysis":"图片分析","tabImageGeneration":"图片生成","tabVideo":"视频能力","tabVoice":"语音能力","comingSoon":"即将推出","badgeOn":"ON","badgeOff":"OFF","analysis":{"title":"图片分析","summary":"{channel} · {model} · {size}px","summaryDefault":"未配置","hint":"启用后,Agent 可使用 analyzeImage 工具识别和理解图片内容","channel":"通道","selectChannel":"请选择通道","modelLabel":"指定模型(可选)","modelHint":"留空使用通道默认模型","maxImageEdge":"最大图片长边","maxImageEdgeHint":"超出时自动缩放,越小成本越低","inactive":"已关闭","channelDeleted":"通道已失效","incomplete":"未完成配置 · 请选择通道"},"generation":{"title":"图片生成","summary":"{channel} · {model} · {size}","summaryDefault":"未配置","hint":"启用后,Agent 可使用 generateImage 工具根据文字描述生成图片","channel":"通道","selectChannel":"请选择通道","modelLabel":"指定模型(可选)","modelHint":"留空使用通道默认模型","defaultSize":"默认尺寸(可选)","modelDefaultSize":"使用模型默认尺寸","inactive":"已关闭","channelDeleted":"通道已失效","incomplete":"未完成配置 · 请选择通道"},"fallback":{"title":"备用模型","add":"添加备用","remove":"删除","selectChannel":"选择通道","hint":"主模型失败时,按顺序依次尝试备用模型"}},"integration":{"title":"外部接入","description":"连接外部平台,让 Agent 通过这些接入与你对话","addNew":"接入新平台","empty":"还没有连接任何外部平台。绑定后,Agent 可以在对应平台接收和回复消息。","connected":"已连接","disconnected":"未连接","connecting":"连接中","reconnecting":"重连中","authFailed":"鉴权失败","testConnection":"测试连接","editTarget":"编辑","editTargetTitle":"修改绑定目标","editTargetSuccess":"绑定目标已更新","disconnect":"断开","reconnect":"重新连接","createdAt":"创建于 {{time}}","bind":{"step0Title":"选择平台","stepMethodTitle":"接入方式","step1Title":"获取凭证","step2Title":"选择绑定目标","step3Title":"验证连接","botId":"Bot ID","botIdPlaceholder":"输入企业微信机器人 Bot ID","secret":"Secret","secretPlaceholder":"输入机器人 Secret","targetAgent":"Agent","targetAgentDesc":"Bot 作为 Agent 的化身","targetThread":"群组","targetThreadDesc":"Bot 接入群组,再选择固定 Session 或自动分流","targetAutoSession":"按外部会话自动分流","targetAutoSessionDesc":"每个企业微信会话进入独立 Session","selectAgent":"选择 Agent","selectAgentSession":"选择 Agent Session","defaultSession":"使用 Agent 默认 Session","agentSessionHint":"不选择时,消息会发送到该 Agent 的默认会话。","selectGroup":"选择群组","selectThread":"选择 Session","selectAutoGroup":"自动 Session 所属群组","autoSessionHint":"每个企业微信外部会话会在该群组下创建 1 个 Session,后续消息继续进入同一个 Session。","autoSessionAgentHint":"每个企业微信外部会话会在所选 Agent 下创建 1 个 Direct Session;之后同一外部会话的消息会继续进入这个 Session。","autoSessionCardHint":"每个外部会话一个 Session","routingMode":"会话处理方式","routingFixed":"固定到指定 Session","routingAuto":"按外部会话自动分流","routingAutoLabel":"按外部会话自动分流","bindAndTest":"绑定并测试","next":"下一步","prev":"上一步","cancel":"取消","done":"完成","testSuccess":"连接成功!WebSocket 通道已建立。","testFailed":"连接失败","summaryPlatform":"平台","summaryBotId":"Bot ID","summaryTarget":"绑定目标"},"confirmUnbind":"确定断开此接入?","unbindTitle":"断开接入","hint":"外部接入仅在应用运行时可用。关闭应用后,Bot 将自动离线。","wecomBot":"企业微信","wecomBotDesc":"通过企业微信 Bot 接入,需要 Bot ID 和 Secret","wechatPersonal":"微信","wechatPersonalDesc":"通过微信个人 Bot(ClawBot)接入,扫码登录即可","methodQrcode":"扫码绑定","methodQrcodeDesc":"用企业微信扫描二维码,自动获取凭证","methodManual":"手动输入","methodManualDesc":"输入 Bot ID 和 Secret","qrLoading":"正在获取二维码...","qrHint":"请打开企业微信,扫描上方二维码","wpQrHint":"请打开微信,扫描上方二维码登录 Bot","qrTimeout":"扫码超时(5 分钟),请重试"},"usage":{"trustLine":"使用统计仅保存在本机,不记录对话内容,可随时清空。","clearConfirm":"确定清空全部使用统计吗?这个操作不可恢复。","empty":"还没有使用统计。开始一次对话后,这里会显示你的 AI 使用情况。","filters":{"range":"时间范围","scope":"统计范围"},"range":{"today":"今天","week":"本周","month":"本月"},"scope":{"all":"全部","direct":"单聊","group":"群聊"},"metrics":{"work":"AI 工作次数","tokens":"Token 用量","tools":"工具调用","messages":"消息数"},"insights":"洞察","noInsights":"数据还不够,继续使用后会出现洞察。","trend":"每日 Token 用量","sections":{"models":"模型用量","agents":"Agent 用量","groups":"群聊用量","tools":"工具使用","sessions":"高消耗 Session","phrases":"常用话术"},"phrases":{"empty":"暂无足够高频的话术记录(至少出现 3 次)","count":"出现 {{count}} 次","alreadyExists":"已存在相同内容的快捷回复","added":"已加入快捷回复","addFailed":"添加失败","addToQuickReply":"加入快捷回复"},"retention":"默认保留最近 90 天。","clear":"清空统计","loadError":"无法读取使用统计","sessionLabel":"会话 {{index}}","sessionFallback":"未知会话 {{index}}","callsValue":"{{count}} 次","insight":{"groupTokenShare":"本周期 {{rate}}% 的 Token 来自群聊协作。","unfinishedCallRate":"{{rate}}% 的模型或工具调用未完成。","unfinishedCallRateLessThan":"少于 {{rate}}% 的模型或工具调用未完成。","topTool":"{{name}} 是最常用工具,共调用 {{count}} 次。","topGroup":"{{name}} 是最活跃群聊,产生 {{count}} 次 AI 工作。"}}}');
91829
92415
  const agent$1 = { "name": "名称", "namePlaceholder": "例如:代码助手", "channel": "通道", "model": "模型", "description": "描述", "descriptionPlaceholder": "描述智能体的能力和用途...", "temperature": "Temperature", "temperature.description": "控制输出随机性,值越高越随机 (0-2,默认 0.7)", "topP": "Top P", "topP.description": "核采样阈值,控制词汇多样性 (0-1,默认 1)", "maxTokens": "最大 Token 数", "maxTokens.description": "单次响应的最大输出长度,留空则不限", "maxTokens.unlimited": "不限制", "enableThinking": "启用思考模式", "enableThinking.description": "开启后 AI 会进行深度思考,提供更准确的回答(部分模型支持)", "notifyOnDegraded": "通道异常时通知我", "notifyOnDegraded.description": "当通道响应变慢或不可用时,显示提示", "autoFallback": "自动切换到备用通道", "autoFallback.description": "通道故障时自动尝试备用通道,无需确认(谨慎开启)", "optimizeDescription": "AI 优化描述", "optimizeFailed": "优化失败,请稍后重试", "create": "创建 Agent", "editTitle": "编辑 Agent", "confirmDelete": "确定删除此 Agent?", "deleteTitle": "删除 Agent", "emptyTitle": "还没有 Agent", "emptyDesc": "创建第一个 Agent,把模型和能力组合成一个角色", "createFirst": "创建你的第一个 Agent", "searchPlaceholder": "搜索 Agent", "noDescription": "暂无描述", "noResults": "未找到匹配「{{query}}」的 Agent,按 Esc 清空搜索", "discardTitle": "放弃修改?", "discardMessage": "你有未保存的修改,离开后将丢失这些修改。", "configured": "已配置", "incomplete": "待完善", "unconfigured": "未配置", "noModel": "未选择模型", "justNow": "刚刚", "minutesAgo": "{{count}}分钟前", "hoursAgo": "{{count}}小时前", "daysAgo": "{{count}}天前", "updatedAt": "更新于 {{time}}", "templateCopied": "已从模板「{{name}}」创建", "templateSystemPrefix": "你是{{name}}。", "edit": "编辑", "delete": "删除", "add": "添加", "update": "更新", "advanced": "高级功能", "configure": "配置智能体", "avatar": { "label": "Agent 头像", "hint": "点击头像上传或移除自定义头像" }, "summarizeConversation": "总结本次对话", "updateMemory": "整理长期记忆", "writeToMemory": "写入记忆", "writingMemory": "写入中...", "memoryWritten": "已写入", "summarizePrompt": "请对本次对话做结构化总结。只输出以下四个部分:关键结论、已做决策、待办事项、未决问题。即使某部分为空,也写“暂无”。不要更新任何 workspace 文件。", "primary": "主要", "healthy": "正常", "degraded": "缓慢", "unhealthy": "离线", "unknown": "未知", "advancedConfig": "高级配置", "reasoningEffort": "推理强度", "reasoningEffortLevels": { "off": "关闭", "low": "低", "medium": "中", "high": "高" }, "reasoningEffort.description": "控制模型在回答前投入的推理强度。级别越高,通常更稳,但也可能更慢。", "selected": "已选", "tab": { "basic": "基础", "identity": "身份", "model": "模型", "brain": "模型", "capabilities": "能力", "workspace": "工作空间", "memory": "记忆" }, "summary": { "model": "模型", "skills": "Skills", "mcp": "MCP", "thinking": "Thinking" }, "notSelected": "未选择", "mention": { "placeholder": "选择智能体...", "noAgents": "暂无智能体配置", "allDesc": "通知所有成员" }, "skill": { "title": "Skills", "empty": "暂无 Skill。请在 ~/.kai/skills/ 目录手动创建。", "back": "返回" }, "mcpServers": { "title": "MCP 服务", "empty": "暂无已启用的 MCP 服务,请先在「MCP 服务」中配置", "connected": "已连接", "disconnected": "未连接", "tools": " 个工具" }, "toolLimit": { "title": "内置工具权限", "summaryNone": "未限制", "summaryCount": "已禁用 {{count}} 项", "summaryCountWithCritical": "已禁用 {{count}} 项,含关键工具 {{tool}}", "groupFile": "文件", "groupSystem": "系统", "groupNetwork": "网络", "groupData": "数据", "groupAux": "辅助", "disabled": "已禁用", "hint": "关闭工具后,该 Agent 将无法在运行时调用对应能力。谨慎禁用读写文件、编辑文件或 Shell 等关键工具。", "warningCritical": "已禁用关键工具 {{tool}},Agent 可能无法{{consequence}}。", "warningNearAll": "当前仅剩 {{count}} 项工具可用,Agent 可能几乎无法执行实际任务。", "warningCriticalTools": { "readFile": "读取工作区内容", "writeFile": "写入文件", "editFile": "修改现有文件", "shell": "执行命令或验证结果" }, "toolDesc": { "readFile": "读取本地文件或目录内容", "writeFile": "创建或覆盖写入本地文件", "editFile": "对文件做精确文本替换", "shell": "执行终端命令", "webFetch": "抓取指定网页或接口内容", "webSearch": "联网搜索实时信息", "sqlQuery": "执行只读 SQL 查询", "analyzeImage": "分析图片内容或提取文字", "generateImage": "根据文字描述生成图片", "skill": "加载并使用预定义 Skill", "createCronJob": "创建定时任务", "listCronJobs": "查看定时任务列表", "updateCronJob": "更新定时任务", "deleteCronJob": "删除定时任务" } }, "workspace": { "hide": "隐藏", "edit": "编辑", "openDir": "打开目录" }, "errors": { "duplicateName": "已存在同名智能体,请使用其他名称", "nameRequired": "智能体名称不能为空" }, "initMessage": { "greeting": "你好!我是你的创建者。", "instruction": "请根据以下信息完善你的身份文件:", "name": "名称", "description": "功能描述", "tasks": "请执行以下任务:", "task1": "阅读 IDENTITY.md 和 SOUL.md 的模板内容", "task2": "根据你的名称和功能描述,为自己设计一个合适的身份:", "task2a": "在 IDENTITY.md 中填写你的名字、类型、气质和 Emoji", "task2b": "在 SOUL.md 中根据你的功能定位,调整你的核心真理、边界和风格", "task3": "完成后简要告诉我你是谁,以及你能做什么", "reminder": "记住:这是你的第一次对话,也是你定义自己的机会。" } };
91830
92416
  const skill$1 = { "title": "Skills", "empty": "暂无 Skills", "add": "添加 Skill", "edit": "编辑", "delete": "删除", "back": "返回", "name": "Skill 名称", "namePlaceholder": "例如:pdf-processing", "description": "描述", "descriptionPlaceholder": "简要描述此 Skill 的用途", "content": "内容(Markdown)", "contentPlaceholder": "用 Markdown 编写 Skill 的详细指令...", "deleteConfirm": "确定删除此 Skill?", "nameInvalid": "名称只能包含小写字母、数字和连字符,不能以连字符开头/结尾,不能有连续连字符,最多 64 字符", "selectTitle": "选择 Skills", "permissionHint": "为该 Agent 选择可用 Skills。未选择任何 Skill = 不授予 Skill 权限。", "noSkills": "暂无可用 Skills", "noSkillsSelected": "未选择任何 Skill", "manageSkills": "管理", "searchPlaceholder": "搜索 Skill", "noMatchingSkills": "未找到匹配的 Skill", "selectedCount": "已选择 {{count}} 个", "done": "完成", "remove": "移除", "notAppliedToAnyAgent": "未应用到任何 Agent", "appliedToAgents": "已应用到 {{count}} 个 Agent", "globallyDisabled": "已全局停用", "applyToAgent": "应用到 Agent", "searchAgent": "搜索 Agent", "noMatchingInstalledSkills": "未找到匹配的 Skill", "noMatchingAgents": "未找到匹配的 Agent", "drawerDisabledWarning": "此 Skill 当前全局停用,Agent 无法实际使用", "filteredCount": "找到 {{count}} 个 Agent", "selectAll": "全选", "clearAll": "清空", "tabInstalled": "已安装", "tabDiscover": "发现", "tabSources": "来源", "refreshInstalled": "刷新", "checkInstalledUpdates": "检查更新", "sourceLocal": "本地安装", "globalEnabled": "全局启用", "globalDisabled": "全局禁用", "assignToAgent": "分配给 Agent", "viewDetails": "查看详情", "viewUpdates": "查看更新", "status": "状态", "globalStatus": "全局状态", "agentAssignment": "Agent 分配", "source": "来源", "allowedTools": "允许工具", "installLocation": "安装位置", "discoverComingSoon": "发现页将在下一阶段接入", "discoverComingSoonDesc": "先完成已安装页重构,再接来源管理和远程搜索。", "sourcesComingSoon": "来源管理将在下一阶段接入", "sourcesComingSoonDesc": "这里之后用于配置和测试 Skill Hub Source。", "sourcesTitle": "Skill 来源", "sourcesDesc": "配置可用于发现和安装远程 Skill 的来源。已安装 Skill 不受删除来源影响。", "addSource": "添加来源", "editSource": "编辑来源", "deleteSource": "删除来源", "deleteSourceConfirm": "确定删除来源「{{name}}」?", "deleteSourceHint": "这只会删除来源配置,不会删除本地已安装的 Skill。", "sourceName": "来源名称", "sourceType": "来源类别", "sourceTypes": { "skillhub": "Skill Hub", "static-index": "静态索引", "github-repo": "GitHub 仓库" }, "sourceTypeHints": { "skillhub": "适用于提供搜索、详情和包下载 API 的 Skill Registry。", "static-index": "适用于一个静态 JSON 索引文件,索引中声明 Skill 包和下载地址。", "github-repo": "适用于以 GitHub 仓库组织的 SKILL.md 集合。" }, "sourceBaseUrl": "Base URL", "sourceAuthHint": "当前阶段仅支持无认证来源;Bearer token 将在安全存储接入后开放。", "sourceEnabled": "已启用", "sourceDisabled": "已停用", "authNone": "无认证", "authBearer": "Bearer 认证", "testSource": "测试连接", "testingSource": "测试中", "testSourceSuccess": "连接成功", "testSourceFailed": "连接失败", "noSources": "还没有 Skill 来源。添加来源后,可在发现页搜索远程 Skill。", "sourceStatus": { "connected": "已连接", "unreachable": "无法连接", "auth_failed": "认证失败", "incompatible": "协议不兼容", "disabled": "已停用", "unknown": "未测试" }, "discoverSearchPlaceholder": "搜索远程 Skill,输入 partial / empty / fail 可预览状态", "searchCatalog": "搜索", "discoverNoSources": "还没有启用的来源。请先在“来源”页添加并启用 Skill Source。", "discoverInitial": "输入关键词,从已启用来源中发现可安装的 Skill。", "discoverNoResults": "没有找到匹配的 Skill。", "searchSuccess": "找到 {{count}} 个结果。", "searchPartialFailed": "{{succeeded}} 个来源成功,{{failed}} 个来源失败。", "searchAllFailed": "所有来源都搜索失败。", "installSkill": "安装", "installingSkill": "安装中", "installConfirm": "确定从「{{source}}」安装 Skill「{{name}}」?", "installSuccess": "已安装 Skill「{{name}}」", "installFailed": "安装失败", "installedState": "已安装", "openWebDetail": "网页详情", "loadCatalogDetailFailed": "加载 Skill 详情失败", "incompatibleSkill": "名称不兼容", "checkingInstalledUpdates": "检查中", "updateAvailableCount": "{{count}} 个更新可用", "noInstalledUpdates": "已安装 Skill 均为最新版本", "checkInstalledUpdatesFailed": "检查更新失败", "updateInstalledSkill": "更新", "updatingInstalledSkill": "更新中", "updateInstalledSkillSuccess": "已更新 Skill「{{name}}」", "updateInstalledSkillFailed": "更新失败", "updateVersionBadge": "{{current}} → {{latest}}", "latestVersion": "最新版本", "changelog": "更新说明", "riskHigh": "高风险", "riskFlags": "风险能力", "catalogInfo": "Catalog 信息", "version": "版本", "license": "许可证", "risk": { "shell": "Shell", "write_file": "写文件", "network": "网络访问", "dynamic_command": "动态命令" } };
91831
92417
  const session$1 = { "openDir": "打开目录" };
91832
92418
  const error$6 = { "network": "网络错误,请检查您的连接。", "rate_limit": "请求频率超限,请稍后再试。", "api_error": "API 错误,请检查您的设置。", "unknown": "发生错误,请重试。", "retry": "重试", "boundary": { "title": "出错了", "message": "应用遇到了一个错误", "reload": "重新加载", "report": "报告问题", "copyError": "复制错误", "errorCopied": "已复制" }, "descriptionRequired": "描述不能为空", "noDefaultChannel": "未配置默认 LLM 通道", "channelNeedsBaseUrl": "通道必须配置 baseUrl", "agentNotInConversation": "Agent {{agentId}} 不在当前对话中", "contentTooLong": "内容超过 3000 字符限制", "tooManyConcurrentSearches": "搜索请求过多,请稍后重试", "invalidUrl": "无效或不安全的 URL", "noCustomEngines": "未找到自定义搜索引擎", "commandRequired": "命令行 MCP 服务需要 command 参数", "clientNotConnected": "客户端未连接", "agentExecutionNotImplemented": "Agent 执行功能尚未实现", "agentIdRequired": "agent_review 任务需要 agentId", "invalidCiphertext": "密文格式无效:需要 3 个部分", "emptySummary": "摘要响应为空" };
91833
92419
  const network$1 = { "offline": "无网络连接" };
91834
- const message$3 = { "copy": "复制", "copied": "已复制", "errorDetails": "错误详情", "edit": "编辑", "regenerate": "重新生成", "delete": "删除", "confirmDelete": "确定删除此消息及之后的所有消息?", "contextCleared": "上下文已清理", "contextCompacted": "上下文已压缩", "imageLoadFailed": "图片加载失败", "openImageViewerHint": "点击打开图片查看器", "imageViewerHint": "双击图片切换大小,Ctrl/⌘ + 滚轮缩放,Esc 关闭", "imageLoadError": "图片加载失败", "copyImage": "复制图片", "imageCopied": "图片已复制", "imageCopyFailed": "图片复制失败", "closeImageViewer": "关闭图片查看器", "zoomInImage": "放大 (+)", "zoomOutImage": "缩小 (-)", "resetImageZoom": "适配窗口", "switchToCode": "切换到代码", "switchToPreview": "切换到预览", "preview": "预览", "previewHtml": "预览 HTML", "htmlPreviewTitle": "HTML 预览", "error": { "network": "网络错误", "rate_limit": "请求频率限制", "api_error": "API 错误", "unknown": "未知错误" }, "errorMessage": { "network": "网络连接出了点问题,请检查连接后再试。", "rateLimit": "系统现在有点忙,请稍后再试。", "rateLimitConcurrency": "系统现在有点忙,正在同时处理较多请求,请稍后再试。", "apiError": "模型服务暂时不可用,请稍后再试。", "unknown": "出了点问题,请稍后再试。" }, "fallback": { "transition": "当前模型繁忙,正在切换备用模型…", "tooltip": "{{from}} → {{to}} · {{reason}}", "reason": { "rateLimit": "请求繁忙", "timeout": "响应超时", "apiError": "服务暂时不可用", "contextOverflow": "上下文过长", "unknown": "未知原因" } }, "handoff": "协作转交", "broadcast": "协作咨询", "expand": "展开", "collapse": "收起", "lines": "行", "userMessage": "用户消息", "agentMessage": "{{name}} 的回复", "generating": "生成中", "sending": "发送中", "waiting": "等待处理", "sendFailed": "发送失败", "retrySend": "重试", "recall": "撤回", "resend": "重发", "resendConfirmTitle": "确认重发这条消息?", "resendConfirmMessage": "确认后会立即重新发送:{{content}}", "tokenUsage": "输入:{{input}} | 输出:{{output}}", "tokenUsageWithCache": "输入:{{input}} | 输出:{{output}} | 缓存命中:{{cached}}", "tokens": "tokens", "kTokens": "{{count}}K tokens", "mTokens": "{{count}}M tokens", "broadcastProgress": "完成 {{completed}}/{{total}}", "broadcastStatusPending": "等待中", "broadcastStatusThinking": "思考中", "broadcastStatusStreaming": "回复中", "broadcastStatusDone": "已完成", "broadcastStatusFailed": "失败", "broadcastWaiting": "等待响应…", "broadcastNoContent": "无内容", "broadcastFailed": "响应失败", "broadcastComplete": "协作咨询已结束", "broadcastAllReplied": "所有成员都已回复", "taskAssign": "已发起协作任务", "taskAssignedTo": "已交给 {{name}} 处理", "taskDetail": "查看执行过程", "taskDetailCollapse": "收起执行过程", "taskEmpty": "暂无执行内容", "taskQueued": "排队中", "taskRunning": "进行中", "taskCompleted": "已完成", "taskFailed": "执行失败", "taskKilled": "已结束", "taskBackgroundQueued": "后台排队中", "taskBackgroundRunning": "后台运行中", "taskBackgroundCompleted": "后台完成", "taskBackgroundFailed": "后台失败", "taskBackgroundKilled": "后台结束", "broadcastWaitingMembers": "还有 {{count}} 位成员待回复" };
92420
+ const message$3 = { "copy": "复制", "copied": "已复制", "errorDetails": "错误详情", "edit": "编辑", "regenerate": "重新生成", "delete": "删除", "confirmDelete": "确定删除此消息及之后的所有消息?", "contextCleared": "上下文已清理", "contextCompacted": "上下文已压缩", "imageLoadFailed": "图片加载失败", "openImageViewerHint": "点击打开图片查看器", "imageViewerHint": "双击图片切换大小,Ctrl/⌘ + 滚轮缩放,Esc 关闭", "imageLoadError": "图片加载失败", "copyImage": "复制图片", "imageCopied": "图片已复制", "imageCopyFailed": "图片复制失败", "closeImageViewer": "关闭图片查看器", "zoomInImage": "放大 (+)", "zoomOutImage": "缩小 (-)", "resetImageZoom": "适配窗口", "switchToCode": "切换到代码", "switchToPreview": "切换到预览", "preview": "预览", "previewHtml": "预览 HTML", "htmlPreviewTitle": "HTML 预览", "error": { "network": "网络错误", "rate_limit": "请求频率限制", "api_error": "API 错误", "unknown": "未知错误" }, "errorMessage": { "network": "网络连接出了点问题,请检查连接后再试。", "rateLimit": "系统现在有点忙,请稍后再试。", "rateLimitConcurrency": "系统现在有点忙,正在同时处理较多请求,请稍后再试。", "apiError": "模型服务暂时不可用,请稍后再试。", "unknown": "出了点问题,请稍后再试。" }, "fallback": { "transition": "主模型暂时不可用,已切换备用模型继续执行", "tooltip": "{{from}} → {{to}} · {{reason}}", "usedLabel": "已使用备用模型 {{model}}", "usedTooltip": "{{from}} → {{to}} · {{reason}}", "reason": { "rateLimit": "请求繁忙", "timeout": "响应超时", "apiError": "服务暂时不可用", "contextOverflow": "上下文过长", "unknown": "未知原因" } }, "retry": { "rateLimitScheduled": "当前模型繁忙,{{seconds}} 秒后自动重试 · {{attempt}}/{{maxAttempts}}" }, "handoff": "协作转交", "broadcast": "协作咨询", "expand": "展开", "collapse": "收起", "lines": "行", "userMessage": "用户消息", "agentMessage": "{{name}} 的回复", "generating": "生成中", "sending": "发送中", "waiting": "等待处理", "sendFailed": "发送失败", "retrySend": "重试", "recall": "撤回", "resend": "重发", "resendConfirmTitle": "确认重发这条消息?", "resendConfirmMessage": "确认后会立即重新发送:{{content}}", "tokenUsage": "输入:{{input}} | 输出:{{output}}", "tokenUsageWithCache": "输入:{{input}} | 输出:{{output}} | 缓存命中:{{cached}}", "tokens": "tokens", "kTokens": "{{count}}K tokens", "mTokens": "{{count}}M tokens", "broadcastProgress": "完成 {{completed}}/{{total}}", "broadcastStatusPending": "等待中", "broadcastStatusThinking": "思考中", "broadcastStatusStreaming": "回复中", "broadcastStatusDone": "已完成", "broadcastStatusFailed": "失败", "broadcastStatusCancelled": "已停止", "broadcastWaiting": "等待响应…", "broadcastCancelled": "已停止", "broadcastNoContent": "无内容", "broadcastFailed": "响应失败", "broadcastComplete": "协作咨询已结束", "broadcastAllReplied": "所有成员都已回复", "broadcastSummary": "广播咨询:向 {{total}} 位成员征求意见", "broadcastHeader": "广播咨询", "broadcastAction": "向 {{total}} 位成员征求意见", "broadcastBadgeAnswered": "已回答 {{completed}}/{{total}}", "broadcastBadgeAllAnswered": "已回答 {{total}}/{{total}}", "broadcastBadgeStopped": "已停止 · 已回答 {{completed}}/{{total}}", "broadcastBadgeStoppedWithFailures": "已停止 · 已回答 {{completed}}/{{total}} · 失败 {{failed}}", "broadcastBadgeAnsweredWithFailures": "已回答 {{completed}}/{{total}} · 失败 {{failed}}", "broadcastBadgeFailed": "失败 {{count}}/{{count}}", "taskAssign": "已发起协作任务", "taskAssignedTo": "已交给 {{name}} 处理", "taskDetail": "查看执行过程", "taskDetailCollapse": "收起执行过程", "taskEmpty": "暂无执行内容", "taskQueued": "排队中", "taskRunning": "进行中", "taskCompleted": "已完成", "taskFailed": "执行失败", "taskKilled": "已结束", "taskBackgroundQueued": "后台排队中", "taskBackgroundRunning": "后台运行中", "taskBackgroundCompleted": "后台完成", "taskBackgroundFailed": "后台失败", "taskBackgroundKilled": "后台结束", "broadcastWaitingMembers": "还有 {{count}} 位成员待回复" };
91835
92421
  const channel$1 = { "primary": "主要", "healthy": "正常", "degraded": "缓慢", "unhealthy": "离线", "unknown": "未知", "switch": "切换到 {{name}}", "slow": "响应缓慢", "error": "连接异常", "viewStatus": "查看通道状态", "alertDegraded": "{{channel}} 响应缓慢", "alertUnhealthy": "{{channel}} 连接异常", "unknownChannel": "未知通道", "fallback": "备用模型", "fallbackSummary": "已配置 {{count}} 个", "fallbackEmpty": "暂无备用模型", "addFallback": "添加备用通道" };
91836
92422
  const thread$1 = { "tabs": { "label": "讨论线程", "newThread": "新建讨论", "streaming": "回复中…", "completed": "回复完成", "paused": "已暂停", "archive": "归档讨论", "renameHint": "双击重命名" }, "context": { "discussion": "讨论" }, "createTitle": "新建讨论", "createSubtitle": "在「{{groupName}}」中创建新讨论", "members": "参与成员:", "memberCount": "{{count}} 位成员将参与", "memberCountShort": "{{count}} 位成员将参与", "titlePlaceholder": "讨论主题(必填)", "titleTooLong": "标题不能超过 100 个字符", "createHint": "群组成员将自动加入此讨论。建完后发送第一条消息开始", "create": "创建", "inGroup": "在「{{groupName}}」中发起的讨论", "sendFirst": "发送第一条消息开始讨论", "placeholder": { "default": "在「{{group}}」中跟 {{speaker}} 讨论…", "thread": "跟 {{speaker}} 讨论 {{title}}…" }, "badge": { "tooltip": "{{count}} 个活跃讨论" }, "archiveToast": "讨论已归档", "archiveUndo": "撤销", "archiveConfirm": "归档此讨论?", "archiveTitle": "归档讨论" };
91837
92423
  const mention$1 = { "allDesc": "通知所有成员" };
@@ -91863,6 +92449,7 @@ const scheduler$1 = { "title": "定时任务", "createTask": "创建任务", "ed
91863
92449
  const memoryGrowth$1 = { "title": "记忆成长", "nightly": { "title": "夜间整理", "description": "每天在固定时间整理长期记忆,可能更新 Agent 或群组的记忆文件;不会清理或压缩当前聊天。", "timeLabel": "执行时间", "scopeLabel": "整理范围", "scopeAll": "所有 Agent", "scopeAgent": "指定 Agent", "scopeAllGroups": "所有群组", "scopeGroup": "指定群组", "scopeNone": "未选择整理范围", "scopeAgentValue": "指定 Agent · {{agentName}}", "agentMemoryTitle": "Agent 记忆", "agentMemoryDescription": "整理每个 Agent 对用户、项目和长期经验的记忆。", "groupMemoryTitle": "群记忆", "groupMemoryDescription": "整理群聊中的决策、项目事实和协作规则。", "executionOrderHint": "将先整理群记忆,再整理 Agent 记忆,确保 Agent 能吸收最新群结论。", "agentLabel": "选择 Agent", "selectAgent": "请选择 Agent", "selectAgentFirst": "请先选择要整理的 Agent", "selectScopeFirst": "请至少选择一种要整理的记忆范围", "groupLabel": "选择群组", "selectGroup": "请选择群组", "selectGroupFirst": "请先选择要整理的群组", "saved": "夜间整理已更新", "runNow": "立即整理记忆", "runNowDone": "记忆更新完成:{{succeeded}}/{{total}} 个对象成功", "runNowFailed": "记忆更新失败", "runningProgress": "正在整理记忆", "nextMode": "自动模式", "enabledAt": "已启用 · 每天 {{time}} 执行", "disabled": "未启用", "lastRun": "上次运行", "neverRun": "从未运行", "memoryFiles": "记忆文件", "topicFiles": "专题文件入口", "topicFilesDescription": "这些细节已下沉到专题文件,长期记忆只保留摘要和入口。", "noRecentFiles": "最近没有文件变更", "openMemoryDir": "打开记忆目录", "openMemoryDirHint": "先选择一个 Agent,才能直接打开它的记忆目录。", "openAllGroupsDirHint": "所有群组没有单一目录;请选择指定群组后打开。", "openMemoryDirUnavailable": "当前未选择 Agent,无法打开记忆目录", "recentExecutions": "最近整理记录", "noExecutions": "暂无执行历史", "unknownTime": "未知时间", "executionRunning": "记忆更新进行中", "executionFailed": "执行失败", "executionFinished": "执行完成", "executionSummary": "记录结果:{{succeeded}}/{{total}} 个智能体成功", "executionSummaryCompact": "{{succeeded}}/{{total}} 个 Agent", "groupExecutionSummary": "群组 {{groupName}}:更新 {{changedFiles}} 个文件", "groupExecutionSummaryCompact": "{{changedFiles}} 个文件", "groupBatchExecutionSummary": "群组整理结果:{{succeeded}}/{{total}} 个群组成功", "groupBatchExecutionSummaryCompact": "{{succeeded}}/{{total}} 个群组", "noChanges": "无新内容", "candidates": "候选结果", "candidateDisposition": { "promoted": "已晋升", "duplicate": "重复", "deferred": "待定", "skipped": "已跳过" }, "candidateSource": { "direct": "对话", "group": "群摘要" }, "candidateTarget": { "memory": "长期记忆", "user": "用户画像", "group": "群记忆", "tools": "工具配置", "topic": "专题文件", "dailyOnly": "每日记录" }, "budgetStatus": "长期记忆预算", "budget": { "healthy": "健康", "warning": "接近上限", "over": "已超限" }, "budgetPolicy": { "conservative": "保守晋升", "overBudget": "超限保护" }, "enableConfirmTitle": "开启夜间整理?", "enableConfirmMessage": "开启后,系统将在每天指定时间整理长期记忆,可能更新 Agent 或群组的记忆文件;不会清理或压缩当前聊天。\n\n你可以随时关闭,也可以查看每次整理的详细记录。", "enableConfirmAction": "开启", "executionStatus": { "running": "运行中", "success": "成功", "failed": "失败", "no-changes": "无变更" }, "autoTitle": "自动整理记忆", "autoEnableConfirmTitle": "开启自动整理记忆?", "autoEnableConfirmMessage": "开启后,系统将在每天指定时间整理长期记忆,可能更新 Agent 或群组的记忆文件;不会清理或压缩当前聊天。\n\n你可以随时关闭,也可以查看每次整理的详细记录。", "configChanged": "设置已修改,保存后生效。", "advancedDetails": "高级详情", "sources": "来源", "sourcesEmpty": "无可用来源", "sourceDirect": "{{count}} 个对话 · {{messages}} 条消息", "sourceGroupDigest": "{{count}} 个群摘要", "groupSources": "Group 输入 / 输出", "groupSourcesRead": "读取", "groupSourcesWritten": "写入", "truncated": "已截断", "sourceBudgetExhausted": "读取预算已耗尽,结果只基于已读取内容。", "fileOperation": { "create": "创建", "update": "更新" }, "consolidation": "Stage2 consolidation", "consolidationMode": { "fallback": "fallback:沿用现有 daily 整理", "extraction-driven": "extraction-driven:使用 Stage1 extraction", "skipped-locked": "已跳过:另一个整理正在运行", "skipped-cooldown": "已跳过:冷却中" }, "extractionCount": "extractions {{count}}", "decisionCount": "decisions {{count}}", "consolidationDecision": { "promoted": "已写入", "merged": "已合并", "discarded": "已丢弃", "deferred": "候选保留", "needs_review": "需人工确认" }, "moreItems": "还有 {{count}} 项未展开。", "reflectionSignals": "Reflection signals", "staleSignals": "stale {{count}}", "contradictionSignals": "contradiction {{count}}", "needsReview": "needs_review {{count}}", "procedureCandidates": "procedure {{count}}", "skillCandidates": "skill {{count}}", "reviewOnlyNotice": "这些是需要确认的信号;系统不会在这里自动删除或改写长期记忆。", "promotionCandidates": "Procedure / skill candidates", "promotionCandidateCount": "候选 {{count}}", "promotionReviewOnlyNotice": "这里只展示候选 artifact;不会自动创建正式 skill、workflow 或 Agent 指令。" } };
91864
92450
  const clear$1 = { "confirmTitle": "清理上下文?", "confirmDesc": "当前对话消息会保留,只会清理后续回复使用的上下文。", "confirmBtn": "清理" };
91865
92451
  const filePreview$1 = { "source": "源码", "preview": "预览", "nonTextTitle": "非文本文件", "nonTextDesc": "此文件无法以文本方式预览。", "openWithSystem": "用系统应用打开", "loadError": "加载失败", "tooLargeTitle": "文件过大", "tooLargeDesc": "文件大小 {{size}},超出预览限制。请用系统应用打开。", "showInFolder": "在文件夹中显示", "download": "下载", "close": "关闭", "searchPlaceholder": "查找…", "matchCase": "区分大小写", "previousMatch": "上一个匹配", "nextMatch": "下一个匹配", "closeSearch": "关闭搜索" };
92452
+ const messageSearch$1 = { "placeholder": "搜索当前 Session 消息", "emptyHint": "输入关键词", "previousResult": "上一个结果", "nextResult": "下一个结果", "close": "关闭搜索" };
91866
92453
  const cancel$1 = "取消";
91867
92454
  const contextSuggestion$1 = { "title": "建议整理上下文", "description": "这段会话有点长了。整理后会保留重点,让后续回复更连贯。聊天记录不会删除。", "accept": "整理上下文", "dismiss": "本会话不再提示", "remindLater": "稍后再说", "close": "关闭", "running": "正在整理会话…", "completed": "会话已整理,后续回复会参考整理后的关键内容。", "failed": "暂时无法整理会话,请稍后再试。" };
91868
92455
  const zh = {
@@ -91912,6 +92499,7 @@ const zh = {
91912
92499
  memoryGrowth: memoryGrowth$1,
91913
92500
  clear: clear$1,
91914
92501
  filePreview: filePreview$1,
92502
+ messageSearch: messageSearch$1,
91915
92503
  cancel: cancel$1,
91916
92504
  contextSuggestion: contextSuggestion$1
91917
92505
  };
@@ -91923,13 +92511,13 @@ const onboarding = { "title": "Bring Your Agents to Life", "description": "One s
91923
92511
  const channelGuide = { "title": "Bring Your Agents to Life", "description": "Connect an AI model so agents can think and respond", "configure": "Connect AI", "dismiss": "Skip" };
91924
92512
  const agentChannelCheck = { "title": "This agent needs a spark", "description": "Connect an AI model before starting a conversation", "configure": "Connect AI", "skip": "Create anyway" };
91925
92513
  const welcome = { "description": "Chat with an agent or bring everyone together", "title": "Start a conversation", "subtitle": "Pick a partner from the sidebar to begin", "or": "or", "createGroup": "Bring everyone together" };
91926
- const settings = /* @__PURE__ */ JSON.parse(`{"title":"Settings","nav":{"app":"App","capabilities":"Capabilities","automation":"Automation","agents":"Agent","connection":"Connectivity"},"tabs":{"llm":"Model Channels","agent":"Agent","skill":"Skills","appearance":"Appearance","remote":"Remote Access","mcp":"MCP Servers","search":"Search Engine","about":"About","integration":"Integration","usage":"Usage"},"panels":{"integration":{"title":"External Integrations","description":"Connect external platforms so Agents can chat with you through them","addNew":"Add Integration","empty":"No external platforms connected yet. Once bound, Agents can receive and reply to messages on the connected platform.","connected":"Connected","disconnected":"Disconnected","connecting":"Connecting","reconnecting":"Reconnecting","authFailed":"Auth Failed","testConnection":"Test Connection","disconnect":"Disconnect","reconnect":"Reconnect","bind":{"step1Title":"Get Credentials","step2Title":"Choose Target","step3Title":"Verify Connection","botId":"Bot ID","botIdPlaceholder":"Enter WeCom Bot ID","secret":"Secret","secretPlaceholder":"Enter Bot Secret","targetAgent":"Agent","targetAgentDesc":"Bot acts as the Agent's avatar","targetThread":"Group Session","targetThreadDesc":"Bot connects to a group session","selectAgent":"Select Agent","selectGroup":"Select Group","selectThread":"Select Session","next":"Next","prev":"Back","cancel":"Cancel","done":"Done","testSuccess":"Connection successful! WebSocket channel established.","testFailed":"Connection failed","summaryPlatform":"Platform","summaryBotId":"Bot ID","summaryTarget":"Target"},"confirmUnbind":"Are you sure you want to disconnect this integration?","unbindTitle":"Disconnect Integration","hint":"External integrations only work while the app is running. The Bot will go offline when the app is closed.","wecomBot":"WeCom","methodQrcode":"Scan QR Code","methodQrcodeDesc":"Scan with WeCom to get credentials automatically","methodManual":"Manual Input","methodManualDesc":"Enter Bot ID and Secret","qrLoading":"Loading QR code...","qrHint":"Open WeCom and scan the QR code above","qrTimeout":"QR code scan timed out (5 min), please retry"},"appearance":{"title":"Appearance","description":"Customize theme, language and display preferences"},"channel":{"title":"Model Channels","description":"Manage AI service channels and default models"},"mcp":{"title":"Extension Services","description":"Configure MCP services to extend Agent capabilities"},"skill":{"title":"Skills","description":"Manage skill modules available to Agents"},"search":{"title":"Search","description":"Configure web search engines and default behavior"},"remote":{"title":"Remote Access","description":"Access KAi from your phone browser with an encrypted token"},"agent":{"title":"Agents","description":"Create and manage custom Agents"},"memoryGrowth":{"title":"Memory Growth","description":"Configure how memory updates grow automatically over time"},"scheduler":{"title":"Scheduled Tasks","description":"Create and manage automated tasks on a schedule"},"about":{"title":"About KAi","description":"Multi AI Agent Collaborative Desktop App"},"multimodal":{"title":"Multimodal Capabilities","description":"Configure image, video, and voice capabilities for analysis and generation"},"usage":{"title":"Usage","description":"Review local AI work, tokens, groups, models, and tools."}},"channel":{"title":"Model Channels","add":"Add Channel","addTitle":"Add Channel","editTitle":"Edit Channel","name":"Channel Name","namePlaceholder":"e.g. OpenAI, Azure","apiType":"API Type","apiTypeOpenai":"OpenAI Compatible","apiTypeOfficialOpenai":"OpenAI","apiTypeAnthropic":"Anthropic","apiTypeGoogle":"Google Gemini","apiTypeAuto":"Auto Detect","baseUrl":"Base URL","apiKey":"API Key","defaultModel":"Default Model","selectModel":"Select model...","enterUrlAndKey":"Enter Base URL and API Key first","loadingModels":"Loading models...","searchOrType":"Search or type model name…","useCustom":"Custom","isDefault":"Default Channel","setAsDefault":"Set as default channel","default":"Default","setDefault":"Set Default","edit":"Edit","delete":"Delete","confirmDelete":"Delete this channel?","deleteTitle":"Delete Channel","showApiKey":"Show API Key","hideApiKey":"Hide API Key","empty":"No channels yet. Click the button below to create one.","deleted":"Channel deleted","setDefaultDone":"\\"{{name}}\\" is now the default channel","actions":"Actions for {{name}}","confirmDeleteMm":"This channel is used for multimodal image analysis (analyzeImage tool). Deleting it will disable that feature. Delete \\"{{name}}\\"?","tabChannels":"Channels","tabMultimodal":"Multimodal"},"llm":{"title":"LLM Configuration","model":"Model Name","modelPreset":"Model Preset","customModel":"Custom Model","apiKey":"API Key","baseUrl":"Base URL","temperature":"Temperature","maxTokens":"Max Tokens","topP":"Top P","loadingModels":"Loading models...","errors":{"network_error":"Cannot connect to API server. Please check Base URL and network connection","auth_failed":"API Key authentication failed. Please check your key","api_error":"API request failed. Please check server status"}},"remote":{"title":"Remote Access","description":"Enable it to access KAi from your phone browser.\\nAll connections use encrypted token authentication.","on":"On","off":"Off","copyLink":"Copy Link","rotateLink":"Regenerate Link","stopLink":"Stop Remote Access","rotateSuccess":"A new link is ready. The old link is no longer valid.","linkTitle":"Stable access link","linkDescription":"This link is restored automatically on next launch unless you stop it or regenerate it.","restoreMode":"Startup recovery","restoreEnabled":"Auto restore","restoreDisabled":"Do not auto restore","lastGenerated":"Last generated","notGeneratedYet":"Not generated yet","restoreFailedTitle":"Restore failed","status":{"disabled":"Off","enabling":"Starting","enabled":"On","restoring":"Restoring","rotating":"Generating new link","stopping":"Stopping","error":"Restore failed"},"qrCodeAlt":"Remote access QR code","tokenPending":"Waiting for access token...","portValue":"Port: {{port}}","connectionsValue":"Connections: {{current}}/{{max}}","addresses":"Available Addresses","connectedClients":"Connected Devices","errors":{"toggleFailed":"Failed to update remote access status.","copyFailed":"Failed to copy remote access link.","rotateFailed":"Failed to regenerate remote access link."}},"search":{"engines":"Search Engines","builtIn":"Built-in","default":"Default","setDefault":"Set as Default","addCustom":"Add Custom Engine","addEngine":"Add Search Engine","editEngine":"Edit Search Engine","name":"Engine Name","namePlaceholder":"e.g., Google Scholar","urlTemplate":"URL Template","urlTemplateHint":"Use {query} as search keyword placeholder","urlTemplateError":"URL template must contain {query} placeholder","showWindow":"Show Search Window (Debug)","confirmDelete":"Delete this search engine?","deleteTitle":"Delete Search Engine","delete":"Delete"},"language":"Language","appearance":{"theme":"Theme","themeLight":"Light","themeDark":"Dark","themeSystem":"System"},"save":"Save","cancel":"Cancel","saveFailed":"Failed to save settings. Please try again.","saveSuccess":"Saved successfully","mcp":{"title":"MCP Servers","add":"Add Server","addServer":"Add Server","addTitle":"Add Server","editTitle":"Edit Server","empty":"No MCP servers yet","confirmDelete":"Are you sure you want to delete this server?","deleteTitle":"Delete Server","serverName":"Server Name","serverType":"Type","command":"Command","args":"Arguments","url":"WebSocket URL","enabled":"Enabled","testConnection":"Test Connection","connected":"Connected","disconnected":"Disconnected","error":"Connection Error","edit":"Edit","delete":"Delete","typeStdio":"Stdio","typeCommand":"Command","typeStreamableHttp":"Streamable HTTP","typeWebsocket":"WebSocket","toolCount":"Tools","testing":"Testing...","testSuccess":"Connection successful","testFailed":"Connection failed","applyToAgent":"Apply to Agent","appliedToAgents":"Applied to {{count}} Agents","notAppliedToAnyAgent":"Not applied to any Agent","globallyDisabled":"Globally disabled","selectedCount":"{{count}} selected","searchAgent":"Search Agent","noMatchingAgents":"No matching Agents found","drawerDisabledWarning":"This MCP server is globally disabled, Agents cannot use it","filteredCount":"{{count}} Agents found","selectAll":"Select All","clearAll":"Clear All","selectFiltered":"Select shown","clearFiltered":"Clear shown"},"about":{"releaseNotes":"Release Notes","versionCopied":"Copied","autoCheckForUpdates":"Check for updates daily","checkForUpdates":"Check for Updates","checking":"Checking for updates","goDownload":"Download","newVersion":"New version available","updateHighlights":"What’s new","viewFullReleaseNotes":"View full release notes","retry":"Check Again","upToDate":"You’re up to date","updateError":"Failed to check for updates","feedback":{"title":"Feedback","placeholder":"Tell us what’s on your mind...","bug":"Bug","feature":"Feature request","other":"Other","submit":"Submit feedback","showContact":"Leave contact info","contactPlaceholder":"Email or other contact info","success":"Thanks for the feedback!","error":"Submission failed. Please try again later."}},"multimodal":{"saved":"Multimodal configuration saved","saveFailed":"Save failed","saving":"Saving…","noChannels":"No channels available. Add one in Model Channels first.","goToChannels":"Go to Model Channels","tabImageAnalysis":"Image Analysis","tabImageGeneration":"Image Generation","tabVideo":"Video","tabVoice":"Voice","comingSoon":"Coming Soon","badgeOn":"ON","badgeOff":"OFF","analysis":{"title":"Image Analysis","summary":"{channel} · {model} · {size}px","summaryDefault":"Not configured","hint":"When enabled, the Agent can use the analyzeImage tool to recognize and understand images","channel":"Channel","selectChannel":"Select a channel","modelLabel":"Model Override (optional)","modelHint":"Leave empty to use the channel default model","maxImageEdge":"Max Image Long Edge","maxImageEdgeHint":"Auto-scaled when exceeded. Lower = cheaper, higher = more detail","inactive":"Disabled","channelDeleted":"Channel Missing","incomplete":"Incomplete · Please select a channel"},"generation":{"title":"Image Generation","summary":"{channel} · {model} · {size}","summaryDefault":"Not configured","hint":"When enabled, the Agent can use the generateImage tool to create images from text","channel":"Channel","selectChannel":"Select a channel","modelLabel":"Model Override (optional)","modelHint":"Leave empty to use the channel default model","defaultSize":"Default Size (optional)","modelDefaultSize":"Use model default size","inactive":"Disabled","channelDeleted":"Channel Missing","incomplete":"Incomplete · Please select a channel"},"fallback":{"title":"Fallback Models","add":"Add Fallback","remove":"Remove","selectChannel":"Select channel","hint":"When the primary model fails, fallback models are tried in order"}},"integration":{"title":"External Integrations","description":"Connect external platforms so Agents can chat with you through them","addNew":"Add Integration","empty":"No external platforms connected yet. Once bound, Agents can receive and reply to messages on the connected platform.","connected":"Connected","disconnected":"Disconnected","connecting":"Connecting","reconnecting":"Reconnecting","authFailed":"Auth Failed","testConnection":"Test Connection","editTarget":"Edit","editTargetTitle":"Change Target","editTargetSuccess":"Target updated","disconnect":"Disconnect","reconnect":"Reconnect","createdAt":"Created {{time}}","bind":{"step0Title":"Choose Platform","stepMethodTitle":"Method","step1Title":"Get Credentials","step2Title":"Choose Target","step3Title":"Verify Connection","botId":"Bot ID","botIdPlaceholder":"Enter WeCom Bot ID","secret":"Secret","secretPlaceholder":"Enter Bot Secret","targetAgent":"Agent","targetAgentDesc":"Bot acts as the Agent's avatar","targetThread":"Group Session","targetThreadDesc":"Bot connects to a group session","selectAgent":"Select Agent","selectGroup":"Select Group","selectThread":"Select Session","next":"Next","prev":"Back","cancel":"Cancel","done":"Done","testSuccess":"Connection successful! WebSocket channel established.","testFailed":"Connection failed","summaryPlatform":"Platform","summaryBotId":"Bot ID","summaryTarget":"Target"},"confirmUnbind":"Are you sure you want to disconnect this integration?","unbindTitle":"Disconnect Integration","hint":"External integrations only work while the app is running. The Bot will go offline when the app is closed.","wecomBot":"WeCom","wecomBotDesc":"Connect via WeCom Bot, requires Bot ID and Secret","wechatPersonal":"WeChat","wechatPersonalDesc":"Connect via WeChat Personal Bot (ClawBot), scan QR to login","methodQrcode":"Scan QR Code","methodQrcodeDesc":"Scan with WeCom to get credentials automatically","methodManual":"Manual Input","methodManualDesc":"Enter Bot ID and Secret","qrLoading":"Loading QR code...","qrHint":"Open WeCom and scan the QR code above","wpQrHint":"Open WeChat and scan the QR code above to login","qrTimeout":"QR code scan timed out (5 min), please retry"},"usage":{"trustLine":"Usage statistics are stored locally, do not record conversation content, and can be cleared anytime.","clearConfirm":"Clear all usage statistics? This cannot be undone.","empty":"No usage statistics yet. Start a conversation and your AI usage will appear here.","filters":{"range":"Time Range","scope":"Usage Scope"},"range":{"today":"Today","week":"This week","month":"This month"},"scope":{"all":"All","direct":"Direct","group":"Groups"},"metrics":{"work":"AI work","tokens":"Tokens","tools":"Tool calls","messages":"Messages"},"insights":"Insights","noInsights":"Not enough data yet. Insights will appear as you use KAi.","trend":"Daily token usage","sections":{"models":"Models","agents":"Agents","groups":"Groups","tools":"Tools","sessions":"High-usage Sessions","phrases":"Common Phrases"},"phrases":{"empty":"No frequent phrases yet (needs at least 3 occurrences)","count":"Used {{count}} times","alreadyExists":"A quick reply with the same content already exists","added":"Added to quick replies","addFailed":"Failed to add","addToQuickReply":"Add to quick replies"},"retention":"Defaults to keeping the last 90 days.","clear":"Clear statistics","loadError":"Unable to load usage statistics","sessionLabel":"Session {{index}}","sessionFallback":"Unknown Session {{index}}","callsValue":"{{count}} calls","insight":{"groupTokenShare":"{{rate}}% of tokens in this period came from group collaboration.","unfinishedCallRate":"{{rate}}% of model or tool calls did not finish.","topTool":"{{name}} was the most used tool with {{count}} calls.","topGroup":"{{name}} was the most active group with {{count}} AI runs."}}}`);
92514
+ const settings = /* @__PURE__ */ JSON.parse(`{"title":"Settings","nav":{"app":"App","capabilities":"Capabilities","automation":"Automation","agents":"Agent","connection":"Connectivity"},"tabs":{"llm":"Model Channels","agent":"Agent","skill":"Skills","appearance":"Appearance","remote":"Remote Access","mcp":"MCP Servers","search":"Search Engine","about":"About","integration":"Integration","usage":"Usage"},"panels":{"integration":{"title":"External Integrations","description":"Connect external platforms so Agents can chat with you through them","addNew":"Add Integration","empty":"No external platforms connected yet. Once bound, Agents can receive and reply to messages on the connected platform.","connected":"Connected","disconnected":"Disconnected","connecting":"Connecting","reconnecting":"Reconnecting","authFailed":"Auth Failed","testConnection":"Test Connection","disconnect":"Disconnect","reconnect":"Reconnect","bind":{"step1Title":"Get Credentials","step2Title":"Choose Target","step3Title":"Verify Connection","botId":"Bot ID","botIdPlaceholder":"Enter WeCom Bot ID","secret":"Secret","secretPlaceholder":"Enter Bot Secret","targetAgent":"Agent","targetAgentDesc":"Bot acts as the Agent's avatar","targetThread":"Group Session","targetThreadDesc":"Bot connects to a group session","selectAgent":"Select Agent","selectGroup":"Select Group","selectThread":"Select Session","next":"Next","prev":"Back","cancel":"Cancel","done":"Done","testSuccess":"Connection successful! WebSocket channel established.","testFailed":"Connection failed","summaryPlatform":"Platform","summaryBotId":"Bot ID","summaryTarget":"Target"},"confirmUnbind":"Are you sure you want to disconnect this integration?","unbindTitle":"Disconnect Integration","hint":"External integrations only work while the app is running. The Bot will go offline when the app is closed.","wecomBot":"WeCom","methodQrcode":"Scan QR Code","methodQrcodeDesc":"Scan with WeCom to get credentials automatically","methodManual":"Manual Input","methodManualDesc":"Enter Bot ID and Secret","qrLoading":"Loading QR code...","qrHint":"Open WeCom and scan the QR code above","qrTimeout":"QR code scan timed out (5 min), please retry"},"appearance":{"title":"Appearance","description":"Customize theme, language and display preferences"},"channel":{"title":"Model Channels","description":"Manage AI service channels and default models"},"mcp":{"title":"Extension Services","description":"Configure MCP services to extend Agent capabilities"},"skill":{"title":"Skills","description":"Manage skill modules available to Agents"},"search":{"title":"Search","description":"Configure web search engines and default behavior"},"remote":{"title":"Remote Access","description":"Access KAi from your phone browser with an encrypted token"},"agent":{"title":"Agents","description":"Create and manage custom Agents"},"memoryGrowth":{"title":"Memory Growth","description":"Configure how memory updates grow automatically over time"},"scheduler":{"title":"Scheduled Tasks","description":"Create and manage automated tasks on a schedule"},"about":{"title":"About KAi","description":"Multi AI Agent Collaborative Desktop App"},"multimodal":{"title":"Multimodal Capabilities","description":"Configure image, video, and voice capabilities for analysis and generation"},"usage":{"title":"Usage","description":"Review local AI work, tokens, groups, models, and tools."}},"channel":{"title":"Model Channels","add":"Add Channel","addTitle":"Add Channel","editTitle":"Edit Channel","name":"Channel Name","namePlaceholder":"e.g. OpenAI, Azure","apiType":"API Type","apiTypeOpenai":"OpenAI Compatible","apiTypeOfficialOpenai":"OpenAI","apiTypeAnthropic":"Anthropic","apiTypeGoogle":"Google Gemini","apiTypeAuto":"Auto Detect","baseUrl":"Base URL","apiKey":"API Key","defaultModel":"Default Model","selectModel":"Select model...","enterUrlAndKey":"Enter Base URL and API Key first","loadingModels":"Loading models...","searchOrType":"Search or type model name…","useCustom":"Custom","isDefault":"Default Channel","setAsDefault":"Set as default channel","default":"Default","setDefault":"Set Default","edit":"Edit","delete":"Delete","confirmDelete":"Delete this channel?","deleteTitle":"Delete Channel","showApiKey":"Show API Key","hideApiKey":"Hide API Key","empty":"No channels yet. Click the button below to create one.","deleted":"Channel deleted","setDefaultDone":"\\"{{name}}\\" is now the default channel","actions":"Actions for {{name}}","confirmDeleteMm":"This channel is used for multimodal image analysis (analyzeImage tool). Deleting it will disable that feature. Delete \\"{{name}}\\"?","tabChannels":"Channels","tabMultimodal":"Multimodal"},"llm":{"title":"LLM Configuration","model":"Model Name","modelPreset":"Model Preset","customModel":"Custom Model","apiKey":"API Key","baseUrl":"Base URL","temperature":"Temperature","maxTokens":"Max Tokens","topP":"Top P","loadingModels":"Loading models...","errors":{"network_error":"Cannot connect to API server. Please check Base URL and network connection","auth_failed":"API Key authentication failed. Please check your key","api_error":"API request failed. Please check server status"}},"remote":{"title":"Remote Access","description":"Enable it to access KAi from your phone browser.\\nAll connections use encrypted token authentication.","on":"On","off":"Off","copyLink":"Copy Link","rotateLink":"Regenerate Link","stopLink":"Stop Remote Access","rotateSuccess":"A new link is ready. The old link is no longer valid.","linkTitle":"Stable access link","linkDescription":"This link is restored automatically on next launch unless you stop it or regenerate it.","restoreMode":"Startup recovery","restoreEnabled":"Auto restore","restoreDisabled":"Do not auto restore","lastGenerated":"Last generated","notGeneratedYet":"Not generated yet","restoreFailedTitle":"Restore failed","status":{"disabled":"Off","enabling":"Starting","enabled":"On","restoring":"Restoring","rotating":"Generating new link","stopping":"Stopping","error":"Restore failed"},"qrCodeAlt":"Remote access QR code","tokenPending":"Waiting for access token...","portValue":"Port: {{port}}","connectionsValue":"Connections: {{current}}/{{max}}","addresses":"Available Addresses","connectedClients":"Connected Devices","errors":{"toggleFailed":"Failed to update remote access status.","copyFailed":"Failed to copy remote access link.","rotateFailed":"Failed to regenerate remote access link."}},"search":{"engines":"Search Engines","builtIn":"Built-in","default":"Default","setDefault":"Set as Default","addCustom":"Add Custom Engine","addEngine":"Add Search Engine","editEngine":"Edit Search Engine","name":"Engine Name","namePlaceholder":"e.g., Google Scholar","urlTemplate":"URL Template","urlTemplateHint":"Use {query} as search keyword placeholder","urlTemplateError":"URL template must contain {query} placeholder","showWindow":"Show Search Window (Debug)","confirmDelete":"Delete this search engine?","deleteTitle":"Delete Search Engine","delete":"Delete"},"language":"Language","appearance":{"theme":"Theme","themeLight":"Light","themeDark":"Dark","themeSystem":"System"},"save":"Save","cancel":"Cancel","saveFailed":"Failed to save settings. Please try again.","saveSuccess":"Saved successfully","mcp":{"title":"MCP Servers","add":"Add Server","addServer":"Add Server","addTitle":"Add Server","editTitle":"Edit Server","empty":"No MCP servers yet","confirmDelete":"Are you sure you want to delete this server?","deleteTitle":"Delete Server","serverName":"Server Name","serverType":"Type","command":"Command","args":"Arguments","url":"WebSocket URL","enabled":"Enabled","testConnection":"Test Connection","connected":"Connected","disconnected":"Disconnected","error":"Connection Error","edit":"Edit","delete":"Delete","typeStdio":"Stdio","typeCommand":"Command","typeStreamableHttp":"Streamable HTTP","typeWebsocket":"WebSocket","toolCount":"Tools","testing":"Testing...","testSuccess":"Connection successful","testFailed":"Connection failed","applyToAgent":"Apply to Agent","appliedToAgents":"Applied to {{count}} Agents","notAppliedToAnyAgent":"Not applied to any Agent","globallyDisabled":"Globally disabled","selectedCount":"{{count}} selected","searchAgent":"Search Agent","noMatchingAgents":"No matching Agents found","drawerDisabledWarning":"This MCP server is globally disabled, Agents cannot use it","filteredCount":"{{count}} Agents found","selectAll":"Select All","clearAll":"Clear All","selectFiltered":"Select shown","clearFiltered":"Clear shown"},"about":{"releaseNotes":"Release Notes","versionCopied":"Copied","autoCheckForUpdates":"Check for updates daily","checkForUpdates":"Check for Updates","checking":"Checking for updates","goDownload":"Download","newVersion":"New version available","updateHighlights":"What’s new","viewFullReleaseNotes":"View full release notes","retry":"Check Again","upToDate":"You’re up to date","updateError":"Failed to check for updates","feedback":{"title":"Feedback","placeholder":"Tell us what’s on your mind...","bug":"Bug","feature":"Feature request","other":"Other","submit":"Submit feedback","showContact":"Leave contact info","contactPlaceholder":"Email or other contact info","success":"Thanks for the feedback!","error":"Submission failed. Please try again later."}},"multimodal":{"saved":"Multimodal configuration saved","saveFailed":"Save failed","saving":"Saving…","noChannels":"No channels available. Add one in Model Channels first.","goToChannels":"Go to Model Channels","tabImageAnalysis":"Image Analysis","tabImageGeneration":"Image Generation","tabVideo":"Video","tabVoice":"Voice","comingSoon":"Coming Soon","badgeOn":"ON","badgeOff":"OFF","analysis":{"title":"Image Analysis","summary":"{channel} · {model} · {size}px","summaryDefault":"Not configured","hint":"When enabled, the Agent can use the analyzeImage tool to recognize and understand images","channel":"Channel","selectChannel":"Select a channel","modelLabel":"Model Override (optional)","modelHint":"Leave empty to use the channel default model","maxImageEdge":"Max Image Long Edge","maxImageEdgeHint":"Auto-scaled when exceeded. Lower = cheaper, higher = more detail","inactive":"Disabled","channelDeleted":"Channel Missing","incomplete":"Incomplete · Please select a channel"},"generation":{"title":"Image Generation","summary":"{channel} · {model} · {size}","summaryDefault":"Not configured","hint":"When enabled, the Agent can use the generateImage tool to create images from text","channel":"Channel","selectChannel":"Select a channel","modelLabel":"Model Override (optional)","modelHint":"Leave empty to use the channel default model","defaultSize":"Default Size (optional)","modelDefaultSize":"Use model default size","inactive":"Disabled","channelDeleted":"Channel Missing","incomplete":"Incomplete · Please select a channel"},"fallback":{"title":"Fallback Models","add":"Add Fallback","remove":"Remove","selectChannel":"Select channel","hint":"When the primary model fails, fallback models are tried in order"}},"integration":{"title":"External Integrations","description":"Connect external platforms so Agents can chat with you through them","addNew":"Add Integration","empty":"No external platforms connected yet. Once bound, Agents can receive and reply to messages on the connected platform.","connected":"Connected","disconnected":"Disconnected","connecting":"Connecting","reconnecting":"Reconnecting","authFailed":"Auth Failed","testConnection":"Test Connection","editTarget":"Edit","editTargetTitle":"Change Target","editTargetSuccess":"Target updated","disconnect":"Disconnect","reconnect":"Reconnect","createdAt":"Created {{time}}","bind":{"step0Title":"Choose Platform","stepMethodTitle":"Method","step1Title":"Get Credentials","step2Title":"Choose Target","step3Title":"Verify Connection","botId":"Bot ID","botIdPlaceholder":"Enter WeCom Bot ID","secret":"Secret","secretPlaceholder":"Enter Bot Secret","targetAgent":"Agent","targetAgentDesc":"Bot acts as the Agent's avatar","targetThread":"Group","targetThreadDesc":"Connect the Bot to a group, then choose how Sessions are routed","targetAutoSession":"Route by external conversation","targetAutoSessionDesc":"Each WeCom conversation gets its own Session","selectAgent":"Select Agent","selectAgentSession":"Select Agent Session","defaultSession":"Use Agent default Session","agentSessionHint":"If left empty, messages go to this Agent's default conversation.","selectGroup":"Select Group","selectThread":"Select Session","selectAutoGroup":"Auto Sessions belong to","autoSessionHint":"Each WeCom external conversation creates one Session under this group. Later messages continue in the same Session.","autoSessionAgentHint":"Each WeCom external conversation creates one Direct Session under the selected Agent. Later messages from the same external conversation continue in that Session.","autoSessionCardHint":"One Session per external conversation","routingMode":"Session routing","routingFixed":"Fixed to a specific Session","routingAuto":"Route by external conversation","routingAutoLabel":"Route by external conversation","bindAndTest":"Bind and test","next":"Next","prev":"Back","cancel":"Cancel","done":"Done","testSuccess":"Connection successful! WebSocket channel established.","testFailed":"Connection failed","summaryPlatform":"Platform","summaryBotId":"Bot ID","summaryTarget":"Target"},"confirmUnbind":"Are you sure you want to disconnect this integration?","unbindTitle":"Disconnect Integration","hint":"External integrations only work while the app is running. The Bot will go offline when the app is closed.","wecomBot":"WeCom","wecomBotDesc":"Connect via WeCom Bot, requires Bot ID and Secret","wechatPersonal":"WeChat","wechatPersonalDesc":"Connect via WeChat Personal Bot (ClawBot), scan QR to login","methodQrcode":"Scan QR Code","methodQrcodeDesc":"Scan with WeCom to get credentials automatically","methodManual":"Manual Input","methodManualDesc":"Enter Bot ID and Secret","qrLoading":"Loading QR code...","qrHint":"Open WeCom and scan the QR code above","wpQrHint":"Open WeChat and scan the QR code above to login","qrTimeout":"QR code scan timed out (5 min), please retry"},"usage":{"trustLine":"Usage statistics are stored locally, do not record conversation content, and can be cleared anytime.","clearConfirm":"Clear all usage statistics? This cannot be undone.","empty":"No usage statistics yet. Start a conversation and your AI usage will appear here.","filters":{"range":"Time Range","scope":"Usage Scope"},"range":{"today":"Today","week":"This week","month":"This month"},"scope":{"all":"All","direct":"Direct","group":"Groups"},"metrics":{"work":"AI work","tokens":"Tokens","tools":"Tool calls","messages":"Messages"},"insights":"Insights","noInsights":"Not enough data yet. Insights will appear as you use KAi.","trend":"Daily token usage","sections":{"models":"Models","agents":"Agents","groups":"Groups","tools":"Tools","sessions":"High-usage Sessions","phrases":"Common Phrases"},"phrases":{"empty":"No frequent phrases yet (needs at least 3 occurrences)","count":"Used {{count}} times","alreadyExists":"A quick reply with the same content already exists","added":"Added to quick replies","addFailed":"Failed to add","addToQuickReply":"Add to quick replies"},"retention":"Defaults to keeping the last 90 days.","clear":"Clear statistics","loadError":"Unable to load usage statistics","sessionLabel":"Session {{index}}","sessionFallback":"Unknown Session {{index}}","callsValue":"{{count}} calls","insight":{"groupTokenShare":"{{rate}}% of tokens in this period came from group collaboration.","unfinishedCallRate":"{{rate}}% of model or tool calls did not finish.","unfinishedCallRateLessThan":"Less than {{rate}}% of model or tool calls did not finish.","topTool":"{{name}} was the most used tool with {{count}} calls.","topGroup":"{{name}} was the most active group with {{count}} AI runs."}}}`);
91927
92515
  const agent = { "name": "Name", "namePlaceholder": "e.g. Code Assistant", "channel": "Channel", "model": "Model", "description": "Capabilities Description", "descriptionPlaceholder": "Describe the agent's capabilities and purpose...", "temperature": "Temperature", "temperature.description": "Controls randomness (0-2, default 0.7)", "topP": "Top P", "topP.description": "Nucleus sampling threshold (0-1, default 1)", "maxTokens": "Max Tokens", "maxTokens.description": "Maximum output length per response. Leave empty for unlimited.", "maxTokens.unlimited": "Unlimited", "enableThinking": "Enable Thinking", "enableThinking.description": "Enable deep reasoning for more accurate responses (supported by some models)", "notifyOnDegraded": "Notify on channel issues", "notifyOnDegraded.description": "Show alert when channel is slow or unavailable", "autoFallback": "Auto-switch to fallback channel", "autoFallback.description": "Automatically try fallback channels on failure (use with caution)", "optimizeDescription": "AI Optimize Description", "optimizeFailed": "Optimization failed, please try again", "create": "Create Agent", "editTitle": "Edit Agent", "confirmDelete": "Delete this agent?", "deleteTitle": "Delete Agent", "emptyTitle": "No Agents Yet", "emptyDesc": "Create your first Agent to combine models and capabilities into a role", "createFirst": "Create your first Agent", "searchPlaceholder": "Search Agents", "noDescription": "No description", "noResults": 'No agents matching "{{query}}". Press Esc to clear', "discardTitle": "Discard Changes?", "discardMessage": "You have unsaved changes that will be lost if you leave.", "configured": "Configured", "incomplete": "Incomplete", "unconfigured": "Not configured", "noModel": "No model selected", "justNow": "Just now", "minutesAgo": "{{count}} min ago", "hoursAgo": "{{count}}h ago", "daysAgo": "{{count}}d ago", "updatedAt": "Updated {{time}}", "templateCopied": 'Created from "{{name}}" template', "templateSystemPrefix": "You are {{name}}. ", "configure": "Configure Agent", "summarizeConversation": "Summarize This Conversation", "updateMemory": "Update Memory", "writeToMemory": "Write to Memory", "writingMemory": "Writing...", "memoryWritten": "Written", "summarizePrompt": 'Please produce a structured summary of this conversation. Output exactly these four sections: Key Conclusions, Decisions Made, Action Items, Open Questions. If a section is empty, write "None". Do not update any workspace files.', "primary": "Primary", "healthy": "Healthy", "degraded": "Slow", "unhealthy": "Offline", "unknown": "Unknown", "edit": "Edit", "delete": "Delete", "add": "Add", "update": "Update", "advanced": "Advanced", "avatar": { "label": "Agent avatar", "hint": "Click the avatar to upload or remove a custom image" }, "advancedConfig": "Advanced Config", "reasoningEffort": "Reasoning Effort", "reasoningEffortLevels": { "off": "Off", "low": "Low", "medium": "Medium", "high": "High" }, "reasoningEffort.description": "Controls how much reasoning effort the model spends before answering. Higher levels are usually more reliable, but may respond more slowly.", "selected": "selected", "tab": { "basic": "Basic", "identity": "Identity", "model": "Model", "brain": "Model", "capabilities": "Capabilities", "workspace": "Workspace", "memory": "Memory" }, "summary": { "model": "Model", "skills": "Skills", "mcp": "MCP", "thinking": "Thinking" }, "notSelected": "Not selected", "mention": { "placeholder": "Select agent...", "noAgents": "No agents configured", "allDesc": "Notify all members" }, "skill": { "title": "Skills", "empty": "No skills found. Create them manually in ~/.kai/skills/", "back": "Back" }, "mcpServers": { "title": "MCP Servers", "empty": 'No enabled MCP servers. Please configure them in "MCP Servers" settings.', "connected": "Connected", "disconnected": "Disconnected", "tools": " tools" }, "toolLimit": { "title": "Built-in Tool Permissions", "summaryNone": "No restrictions", "summaryCount": "{{count}} disabled", "summaryCountWithCritical": "{{count}} disabled, including critical tool {{tool}}", "groupFile": "Files", "groupSystem": "System", "groupNetwork": "Network", "groupData": "Data", "groupAux": "Auxiliary", "disabled": "Disabled", "hint": "When a tool is disabled, this Agent cannot call that capability at runtime. Be careful with critical tools like readFile, writeFile, editFile, and shell.", "warningCritical": "Critical tool {{tool}} is disabled. The Agent may be unable to {{consequence}}.", "warningNearAll": "Only {{count}} tools remain enabled. The Agent may become barely usable for real tasks.", "warningCriticalTools": { "readFile": "read workspace content", "writeFile": "write files", "editFile": "modify existing files", "shell": "run commands or verify results" }, "toolDesc": { "readFile": "Read local files or directory contents", "writeFile": "Create or overwrite local files", "editFile": "Apply exact text replacements in files", "shell": "Run terminal commands", "webFetch": "Fetch a specific webpage or API response", "webSearch": "Search the web for live information", "sqlQuery": "Run read-only SQL queries", "analyzeImage": "Analyze images or extract text", "generateImage": "Generate images from text prompts", "skill": "Load and use predefined Skills", "createCronJob": "Create a scheduled task", "listCronJobs": "View scheduled tasks", "updateCronJob": "Update a scheduled task", "deleteCronJob": "Delete a scheduled task" } }, "workspace": { "hide": "Hide", "edit": "Edit", "openDir": "Open Directory" }, "errors": { "duplicateName": "An agent with the same name already exists. Please use a different name.", "nameRequired": "Agent name cannot be empty." }, "initMessage": { "greeting": "Hello! I am your creator.", "instruction": "Please complete your identity files based on the following information:", "name": "Name", "description": "Capabilities", "tasks": "Please complete the following tasks:", "task1": "Read the template content in IDENTITY.md and SOUL.md", "task2": "Design a suitable identity for yourself based on your name and capabilities:", "task2a": "Fill in your name, type, temperament, and Emoji in IDENTITY.md", "task2b": "Adjust your core truths, boundaries, and style in SOUL.md according to your functional positioning", "task3": "After completion, briefly tell me who you are and what you can do", "reminder": "Remember: This is your first conversation and your opportunity to define yourself." } };
91928
92516
  const skill = { "title": "Skills", "empty": "No Skills available", "add": "Add Skill", "edit": "Edit", "delete": "Delete", "back": "Back", "name": "Skill Name", "namePlaceholder": "e.g. pdf-processing", "description": "Description", "descriptionPlaceholder": "Briefly describe what this skill does", "content": "Content (Markdown)", "contentPlaceholder": "Write detailed instructions for this skill in Markdown...", "deleteConfirm": "Delete this skill?", "nameInvalid": "Name must contain only lowercase letters, numbers, and hyphens, must not start or end with a hyphen, no consecutive hyphens, max 64 characters", "selectTitle": "Select Skills", "permissionHint": "Choose which Skills this agent can use. No Skills selected = no Skill access.", "noSkills": "No available Skills", "noSkillsSelected": "No Skills selected", "manageSkills": "Manage", "searchPlaceholder": "Search Skill", "noMatchingSkills": "No matching Skills found", "selectedCount": "{{count}} selected", "done": "Done", "remove": "Remove", "notAppliedToAnyAgent": "Not applied to any Agent", "appliedToAgents": "Applied to {{count}} Agents", "globallyDisabled": "Globally disabled", "applyToAgent": "Apply to Agent", "searchAgent": "Search Agent", "noMatchingInstalledSkills": "No matching Skills found", "noMatchingAgents": "No matching Agents found", "drawerDisabledWarning": "This Skill is globally disabled, Agents cannot use it", "filteredCount": "{{count}} Agents found", "selectAll": "Select All", "clearAll": "Clear All", "tabInstalled": "Installed", "tabDiscover": "Discover", "tabSources": "Sources", "refreshInstalled": "Refresh", "checkInstalledUpdates": "Check updates", "sourceLocal": "Local install", "globalEnabled": "Globally enabled", "globalDisabled": "Globally disabled", "assignToAgent": "Assign to Agent", "viewDetails": "View details", "viewUpdates": "View updates", "status": "Status", "globalStatus": "Global status", "agentAssignment": "Agent assignment", "source": "Source", "allowedTools": "Allowed tools", "installLocation": "Install location", "discoverComingSoon": "Discover will be connected in the next phase", "discoverComingSoonDesc": "Finish the installed page refactor first, then add source management and remote search.", "sourcesComingSoon": "Source management will be connected in the next phase", "sourcesComingSoonDesc": "This area will configure and test Skill Hub Sources.", "sourcesTitle": "Skill Sources", "sourcesDesc": "Configure sources used to discover and install remote Skills. Deleting a source does not remove installed local Skills.", "addSource": "Add Source", "editSource": "Edit Source", "deleteSource": "Delete Source", "deleteSourceConfirm": 'Delete source "{{name}}"?', "deleteSourceHint": "This only removes the source configuration. Installed local Skills are not deleted.", "sourceName": "Source name", "sourceType": "Source type", "sourceTypes": { "skillhub": "Skill Hub", "static-index": "Static index", "github-repo": "GitHub repo" }, "sourceTypeHints": { "skillhub": "For Skill Registries that expose search, detail, and package download APIs.", "static-index": "For a static JSON index that declares Skills and their download URLs.", "github-repo": "For SKILL.md collections organized in a GitHub repository." }, "sourceBaseUrl": "Base URL", "sourceAuthHint": "This phase only supports unauthenticated sources. Bearer tokens will be enabled after secure storage is connected.", "sourceEnabled": "Enabled", "sourceDisabled": "Disabled", "authNone": "No auth", "authBearer": "Bearer auth", "testSource": "Test connection", "testingSource": "Testing", "testSourceSuccess": "Connection succeeded", "testSourceFailed": "Connection failed", "noSources": "No Skill Sources yet. Add a source to search remote Skills from the Discover tab.", "sourceStatus": { "connected": "Connected", "unreachable": "Unreachable", "auth_failed": "Auth failed", "incompatible": "Incompatible", "disabled": "Disabled", "unknown": "Not tested" }, "discoverSearchPlaceholder": "Search remote Skills. Type partial / empty / fail to preview states", "searchCatalog": "Search", "discoverNoSources": "No enabled sources yet. Add and enable a Skill Source from the Sources tab first.", "discoverInitial": "Enter a keyword to discover installable Skills from enabled sources.", "discoverNoResults": "No matching Skills found.", "searchSuccess": "Found {{count}} results.", "searchPartialFailed": "{{succeeded}} sources succeeded, {{failed}} sources failed.", "searchAllFailed": "All sources failed to search.", "installSkill": "Install", "installingSkill": "Installing", "installConfirm": 'Install Skill "{{name}}" from "{{source}}"?', "installSuccess": 'Installed Skill "{{name}}"', "installFailed": "Install failed", "installedState": "Installed", "openWebDetail": "Web details", "loadCatalogDetailFailed": "Failed to load Skill detail", "incompatibleSkill": "Incompatible name", "checkingInstalledUpdates": "Checking", "updateAvailableCount": "{{count}} updates available", "noInstalledUpdates": "Installed Skills are up to date", "checkInstalledUpdatesFailed": "Failed to check updates", "updateInstalledSkill": "Update", "updatingInstalledSkill": "Updating", "updateInstalledSkillSuccess": 'Updated Skill "{{name}}"', "updateInstalledSkillFailed": "Update failed", "updateVersionBadge": "{{current}} → {{latest}}", "latestVersion": "Latest version", "changelog": "Changelog", "riskHigh": "High risk", "riskFlags": "Risk capabilities", "catalogInfo": "Catalog info", "version": "Version", "license": "License", "risk": { "shell": "Shell", "write_file": "Write files", "network": "Network access", "dynamic_command": "Dynamic command" } };
91929
92517
  const session = { "openDir": "Open Directory" };
91930
92518
  const error$5 = { "network": "Network error. Please check your connection.", "rate_limit": "Rate limit exceeded. Please try again later.", "api_error": "API error. Please check your settings.", "unknown": "An error occurred. Please try again.", "retry": "Retry", "boundary": { "title": "Something went wrong", "message": "The application encountered an error", "reload": "Reload", "report": "Report Issue", "copyError": "Copy Error", "errorCopied": "Copied" }, "descriptionRequired": "Description cannot be empty", "noDefaultChannel": "Default LLM channel not configured", "channelNeedsBaseUrl": "Channel must configure baseUrl", "agentNotInConversation": "Agent {{agentId}} not in current conversation", "contentTooLong": "Content exceeds 3000 character limit", "tooManyConcurrentSearches": "Too many concurrent searches. Please wait and try again.", "invalidUrl": "Invalid or unsafe URL", "noCustomEngines": "No custom engines found", "commandRequired": "Command is required for command-based MCP server", "clientNotConnected": "Client not connected", "agentExecutionNotImplemented": "Agent execution not implemented yet", "agentIdRequired": "Missing agentId for agent_review task", "invalidCiphertext": "Invalid ciphertext format: expected 3 parts", "emptySummary": "Empty summary response" };
91931
92519
  const network = { "offline": "No internet connection" };
91932
- const message$2 = { "copy": "Copy", "copied": "Copied", "errorDetails": "Error Details", "edit": "Edit", "regenerate": "Regenerate", "delete": "Delete", "confirmDelete": "Delete this message and all messages after it?", "contextCleared": "Context Cleared", "contextCompacted": "Context compacted", "imageLoadFailed": "Image load failed", "openImageViewerHint": "Click to open image viewer", "imageViewerHint": "Double-click to toggle size, Ctrl/⌘ + wheel to zoom, Esc to close", "imageLoadError": "Failed to load image", "copyImage": "Copy image", "imageCopied": "Image copied", "imageCopyFailed": "Failed to copy image", "closeImageViewer": "Close image viewer", "zoomInImage": "Zoom in (+)", "zoomOutImage": "Zoom out (-)", "resetImageZoom": "Fit to window", "switchToCode": "Switch to code", "switchToPreview": "Switch to preview", "preview": "Preview", "previewHtml": "Preview HTML", "htmlPreviewTitle": "HTML Preview", "error": { "network": "Network Error", "rate_limit": "Rate Limit", "api_error": "API Error", "unknown": "Unknown Error" }, "errorMessage": { "network": "There was a network problem. Please check your connection and try again.", "rateLimit": "The system is busy right now. Please try again in a moment.", "rateLimitConcurrency": "The system is busy handling too many requests at once. Please try again in a moment.", "apiError": "The model service is temporarily unavailable. Please try again later.", "unknown": "Something went wrong. Please try again later." }, "fallback": { "transition": "Current model is busy. Switching to a fallback model", "tooltip": "{{from}} → {{to}} · {{reason}}", "reason": { "rateLimit": "busy", "timeout": "timed out", "apiError": "temporarily unavailable", "contextOverflow": "context too long", "unknown": "unknown reason" } }, "handoff": "Collaboration Handoff", "broadcast": "Shared Consultation", "expand": "Expand", "collapse": "Collapse", "lines": "lines", "userMessage": "User message", "agentMessage": "{{name}} reply", "generating": "Generating", "sending": "Sending", "waiting": "Waiting", "sendFailed": "Send failed", "retrySend": "Retry", "recall": "Recall", "resend": "Resend", "resendConfirmTitle": "Resend this message?", "resendConfirmMessage": "This will immediately send again: {{content}}", "tokenUsage": "Input: {{input}} | Output: {{output}}", "tokenUsageWithCache": "Input: {{input}} | Output: {{output}} | Cache hit: {{cached}}", "tokens": "tokens", "kTokens": "{{count}}K tokens", "mTokens": "{{count}}M tokens", "broadcastProgress": "{{completed}}/{{total}} completed", "broadcastStatusPending": "Pending", "broadcastStatusThinking": "Thinking", "broadcastStatusStreaming": "Streaming", "broadcastStatusDone": "Done", "broadcastStatusFailed": "Failed", "broadcastWaiting": "Waiting for response…", "broadcastNoContent": "No content", "broadcastFailed": "Response failed", "broadcastComplete": "Shared consultation finished", "broadcastAllReplied": "Everyone replied", "taskAssign": "Collaboration task started", "taskAssignedTo": "Assigned to {{name}}", "taskDetail": "View execution", "taskDetailCollapse": "Hide execution", "taskEmpty": "No execution content", "taskQueued": "Queued", "taskRunning": "In progress", "taskCompleted": "Completed", "taskFailed": "Execution failed", "taskKilled": "Ended", "taskBackgroundQueued": "Queued in background", "taskBackgroundRunning": "Running in background", "taskBackgroundCompleted": "Background complete", "taskBackgroundFailed": "Background failed", "taskBackgroundKilled": "Background ended", "broadcastWaitingMembers": "Waiting on {{count}} more member(s)" };
92520
+ const message$2 = { "copy": "Copy", "copied": "Copied", "errorDetails": "Error Details", "edit": "Edit", "regenerate": "Regenerate", "delete": "Delete", "confirmDelete": "Delete this message and all messages after it?", "contextCleared": "Context Cleared", "contextCompacted": "Context compacted", "imageLoadFailed": "Image load failed", "openImageViewerHint": "Click to open image viewer", "imageViewerHint": "Double-click to toggle size, Ctrl/⌘ + wheel to zoom, Esc to close", "imageLoadError": "Failed to load image", "copyImage": "Copy image", "imageCopied": "Image copied", "imageCopyFailed": "Failed to copy image", "closeImageViewer": "Close image viewer", "zoomInImage": "Zoom in (+)", "zoomOutImage": "Zoom out (-)", "resetImageZoom": "Fit to window", "switchToCode": "Switch to code", "switchToPreview": "Switch to preview", "preview": "Preview", "previewHtml": "Preview HTML", "htmlPreviewTitle": "HTML Preview", "error": { "network": "Network Error", "rate_limit": "Rate Limit", "api_error": "API Error", "unknown": "Unknown Error" }, "errorMessage": { "network": "There was a network problem. Please check your connection and try again.", "rateLimit": "The system is busy right now. Please try again in a moment.", "rateLimitConcurrency": "The system is busy handling too many requests at once. Please try again in a moment.", "apiError": "The model service is temporarily unavailable. Please try again later.", "unknown": "Something went wrong. Please try again later." }, "fallback": { "transition": "Primary model is temporarily unavailable. Continuing with a fallback model.", "tooltip": "{{from}} → {{to}} · {{reason}}", "usedLabel": "Used fallback {{model}}", "usedTooltip": "{{from}} → {{to}} · {{reason}}", "reason": { "rateLimit": "busy", "timeout": "timed out", "apiError": "temporarily unavailable", "contextOverflow": "context too long", "unknown": "unknown reason" } }, "retry": { "rateLimitScheduled": "Current model is busy. Retrying in {{seconds}}s · {{attempt}}/{{maxAttempts}}" }, "handoff": "Collaboration Handoff", "broadcast": "Shared Consultation", "expand": "Expand", "collapse": "Collapse", "lines": "lines", "userMessage": "User message", "agentMessage": "{{name}} reply", "generating": "Generating", "sending": "Sending", "waiting": "Waiting", "sendFailed": "Send failed", "retrySend": "Retry", "recall": "Recall", "resend": "Resend", "resendConfirmTitle": "Resend this message?", "resendConfirmMessage": "This will immediately send again: {{content}}", "tokenUsage": "Input: {{input}} | Output: {{output}}", "tokenUsageWithCache": "Input: {{input}} | Output: {{output}} | Cache hit: {{cached}}", "tokens": "tokens", "kTokens": "{{count}}K tokens", "mTokens": "{{count}}M tokens", "broadcastProgress": "{{completed}}/{{total}} completed", "broadcastStatusPending": "Pending", "broadcastStatusThinking": "Thinking", "broadcastStatusStreaming": "Streaming", "broadcastStatusDone": "Done", "broadcastStatusFailed": "Failed", "broadcastStatusCancelled": "Stopped", "broadcastWaiting": "Waiting for response…", "broadcastCancelled": "Stopped", "broadcastNoContent": "No content", "broadcastFailed": "Response failed", "broadcastComplete": "Shared consultation finished", "broadcastAllReplied": "Everyone replied", "broadcastSummary": "Shared consultation: asking {{total}} member(s)", "broadcastHeader": "Shared consultation", "broadcastAction": "Asked {{total}} member(s)", "broadcastBadgeAnswered": "Answered {{completed}}/{{total}}", "broadcastBadgeAllAnswered": "Answered {{total}}/{{total}}", "broadcastBadgeStopped": "Stopped · answered {{completed}}/{{total}}", "broadcastBadgeStoppedWithFailures": "Stopped · answered {{completed}}/{{total}} · failed {{failed}}", "broadcastBadgeAnsweredWithFailures": "Answered {{completed}}/{{total}} · failed {{failed}}", "broadcastBadgeFailed": "Failed {{count}}/{{count}}", "taskAssign": "Collaboration task started", "taskAssignedTo": "Assigned to {{name}}", "taskDetail": "View execution", "taskDetailCollapse": "Hide execution", "taskEmpty": "No execution content", "taskQueued": "Queued", "taskRunning": "In progress", "taskCompleted": "Completed", "taskFailed": "Execution failed", "taskKilled": "Ended", "taskBackgroundQueued": "Queued in background", "taskBackgroundRunning": "Running in background", "taskBackgroundCompleted": "Background complete", "taskBackgroundFailed": "Background failed", "taskBackgroundKilled": "Background ended", "broadcastWaitingMembers": "Waiting on {{count}} more member(s)" };
91933
92521
  const channel = { "primary": "Primary", "healthy": "Healthy", "degraded": "Slow", "unhealthy": "Offline", "unknown": "Unknown", "switch": "Switch to {{name}}", "slow": "Response is slow", "error": "Connection error", "viewStatus": "View channel status", "alertDegraded": "{{channel}} is slow", "alertUnhealthy": "{{channel}} is unavailable", "unknownChannel": "Unknown channel", "fallback": "Fallback Models", "fallbackSummary": "{{count}} configured", "fallbackEmpty": "No fallback models configured", "addFallback": "Add fallback channel" };
91934
92522
  const thread = { "tabs": { "label": "Threads", "newThread": "New thread", "streaming": "Replying…", "completed": "Reply completed", "paused": "Paused", "archive": "Archive thread", "renameHint": "Double-click to rename" }, "context": { "discussion": "Discussion" }, "createTitle": "New Discussion", "createSubtitle": 'Create a new discussion in "{{groupName}}"', "members": "Participants:", "memberCount": "{{count}} members will join", "memberCountShort": "{{count}} members will join", "titlePlaceholder": "Discussion topic (required)", "titleTooLong": "Title must not exceed 100 characters", "createHint": "Group members will automatically join this discussion. Send the first message to begin.", "create": "Create", "inGroup": 'A discussion in "{{groupName}}"', "sendFirst": "Send your first message to start the discussion", "placeholder": { "default": 'Discuss with {{speaker}} in "{{group}}"…', "thread": "Discuss {{title}} with {{speaker}}…" }, "badge": { "tooltip": "{{count}} active discussions" }, "archiveToast": "Discussion archived", "archiveUndo": "Undo", "archiveConfirm": "Archive this discussion?", "archiveTitle": "Archive Discussion" };
91935
92523
  const mention = { "allDesc": "Notify all members" };
@@ -91961,6 +92549,7 @@ const scheduler = { "title": "Scheduled Tasks", "createTask": "Create Task", "ed
91961
92549
  const memoryGrowth = { "title": "Memory Growth", "nightly": { "title": "Nightly organization", "description": "Consolidate long-term memory at a fixed time every day. This may update Agent or Group memory files; it will not clear or compress the current chat.", "timeLabel": "Run time", "scopeLabel": "Scope", "scopeAll": "All Agents", "scopeAgent": "Specific Agent", "scopeAllGroups": "All Groups", "scopeGroup": "Specific Group", "scopeNone": "No scope selected", "scopeAgentValue": "Specific Agent · {{agentName}}", "agentMemoryTitle": "Agent memory", "agentMemoryDescription": "Organize what each Agent remembers about the user, projects, and long-term lessons.", "groupMemoryTitle": "Group memory", "groupMemoryDescription": "Organize group decisions, project facts, and collaboration rules.", "executionOrderHint": "Group memory will run first, then Agent memory, so Agents can absorb the latest group conclusions.", "agentLabel": "Agent", "selectAgent": "Select an agent", "selectAgentFirst": "Select an agent first", "selectScopeFirst": "Select at least one memory scope", "groupLabel": "Group", "selectGroup": "Select a group", "selectGroupFirst": "Select a group first", "saved": "Nightly organization updated", "runNow": "Run update now", "runNowDone": "Memory update finished: {{succeeded}}/{{total}} targets succeeded", "runNowFailed": "Memory update failed", "runningProgress": "Updating memory", "nextMode": "Automatic mode", "enabledAt": "Enabled · runs daily at {{time}}", "disabled": "Disabled", "lastRun": "Last run", "neverRun": "Never run", "memoryFiles": "Memory files", "topicFiles": "Topic file entries", "topicFilesDescription": "These details were moved into topic files; long-term memory keeps only the summary and entry points.", "noRecentFiles": "No recent file changes", "openMemoryDir": "Open memory directory", "openMemoryDirHint": "Select an agent first to open that agent's memory directory.", "openAllGroupsDirHint": "All groups do not have a single directory. Select a specific group first.", "openMemoryDirUnavailable": "No agent selected. Cannot open memory directory.", "recentExecutions": "Recent organization records", "noExecutions": "No execution history yet", "unknownTime": "Unknown time", "executionRunning": "Memory update is running", "executionFailed": "Execution failed", "executionFinished": "Execution finished", "executionSummary": "Recorded result: {{succeeded}}/{{total}} agents succeeded", "executionSummaryCompact": "{{succeeded}}/{{total}} agents", "groupExecutionSummary": "Group {{groupName}}: {{changedFiles}} files changed", "groupExecutionSummaryCompact": "{{changedFiles}} files", "groupBatchExecutionSummary": "Group memory result: {{succeeded}}/{{total}} groups succeeded", "groupBatchExecutionSummaryCompact": "{{succeeded}}/{{total}} groups", "noChanges": "No new content", "candidates": "Candidate results", "candidateDisposition": { "promoted": "Promoted", "duplicate": "Duplicate", "deferred": "Deferred", "skipped": "Skipped" }, "candidateSource": { "direct": "Conversation", "group": "Group digest" }, "candidateTarget": { "memory": "Long-term memory", "user": "User profile", "group": "Group memory", "tools": "Tool config", "topic": "Topic file", "dailyOnly": "Daily record" }, "budgetStatus": "Long-term memory budget", "budget": { "healthy": "Healthy", "warning": "Near limit", "over": "Over limit" }, "budgetPolicy": { "conservative": "Conservative promotion", "overBudget": "Over-budget protection" }, "enableConfirmTitle": "Enable nightly organization?", "enableConfirmMessage": "After enabling it, the system will automatically organize the Agent's memory files every day at the specified time.\n\nYou can turn it off at any time and review the detailed record of each run.", "enableConfirmAction": "Enable", "executionStatus": { "running": "Running", "success": "Success", "failed": "Failed", "no-changes": "No changes" }, "autoTitle": "Auto Update", "autoEnableConfirmTitle": "Enable Auto Update?", "autoEnableConfirmMessage": "Once enabled, the system will automatically update agent memory files at the specified time each day.\n\nYou can disable it anytime and view detailed execution history.", "configChanged": "Settings changed. Save to apply.", "advancedDetails": "Advanced details", "sources": "Sources", "sourcesEmpty": "No sources available", "sourceDirect": "{{count}} sessions · {{messages}} messages", "sourceGroupDigest": "{{count}} group digests", "groupSources": "Group input / output", "groupSourcesRead": "Read", "groupSourcesWritten": "Written", "truncated": "truncated", "sourceBudgetExhausted": "Read budget was exhausted. The result only uses content that was actually read.", "fileOperation": { "create": "created", "update": "updated" }, "consolidation": "Stage2 consolidation", "consolidationMode": { "fallback": "fallback: existing daily flow", "extraction-driven": "extraction-driven: uses Stage1 extractions", "skipped-locked": "skipped: another run is active", "skipped-cooldown": "skipped: cooldown" }, "extractionCount": "extractions {{count}}", "decisionCount": "decisions {{count}}", "consolidationDecision": { "promoted": "written", "merged": "merged", "discarded": "discarded", "deferred": "candidate kept", "needs_review": "needs review" }, "moreItems": "{{count}} more items not expanded.", "reflectionSignals": "Reflection signals", "staleSignals": "stale {{count}}", "contradictionSignals": "contradiction {{count}}", "needsReview": "needs_review {{count}}", "procedureCandidates": "procedure {{count}}", "skillCandidates": "skill {{count}}", "reviewOnlyNotice": "These are review signals. The system does not automatically delete or rewrite long-term memory here.", "promotionCandidates": "Procedure / skill candidates", "promotionCandidateCount": "candidates {{count}}", "promotionReviewOnlyNotice": "Only candidate artifacts are shown here. No formal skill, workflow, or agent instruction is created automatically." } };
91962
92550
  const clear = { "confirmTitle": "Clear context?", "confirmDesc": "Messages in this conversation will stay. Only the context used for future replies will be cleared.", "confirmBtn": "Clear" };
91963
92551
  const filePreview = { "source": "Source", "preview": "Preview", "nonTextTitle": "Non-text file", "nonTextDesc": "This file cannot be previewed as text.", "openWithSystem": "Open with system app", "loadError": "Failed to load", "tooLargeTitle": "File too large", "tooLargeDesc": "File size {{size}} exceeds preview limit. Please open with system app.", "showInFolder": "Show in Folder", "download": "Download", "close": "Close", "searchPlaceholder": "Find…", "matchCase": "Match case", "previousMatch": "Previous match", "nextMatch": "Next match", "closeSearch": "Close search" };
92552
+ const messageSearch = { "placeholder": "Search current Session messages", "emptyHint": "Type to search", "previousResult": "Previous result", "nextResult": "Next result", "close": "Close search" };
91964
92553
  const cancel = "Cancel";
91965
92554
  const contextSuggestion = { "title": "Consider compacting context", "description": "This session is getting long. Compacting keeps the key points so future replies stay coherent. Your chat history won't be deleted.", "accept": "Compact context", "dismiss": "Don't suggest again for this session", "remindLater": "Remind me later", "close": "Close", "running": "Tidying up this session…", "completed": "Session tidied up. Future replies will use the key points from the summary.", "failed": "Could not tidy up this session. Try again later." };
91966
92555
  const en = {
@@ -92010,6 +92599,7 @@ const en = {
92010
92599
  memoryGrowth,
92011
92600
  clear,
92012
92601
  filePreview,
92602
+ messageSearch,
92013
92603
  cancel,
92014
92604
  contextSuggestion
92015
92605
  };
@@ -93460,7 +94050,7 @@ const metaTag = "_metaTag_yxv60_131";
93460
94050
  const metaSep = "_metaSep_yxv60_141";
93461
94051
  const metaModel = "_metaModel_yxv60_146";
93462
94052
  const itemUrl = "_itemUrl_yxv60_152";
93463
- const itemFooter = "_itemFooter_yxv60_164";
94053
+ const itemFooter$1 = "_itemFooter_yxv60_164";
93464
94054
  const footerActions$1 = "_footerActions_yxv60_174";
93465
94055
  const formWrapper$1 = "_formWrapper_yxv60_183";
93466
94056
  const formTitle$2 = "_formTitle_yxv60_189";
@@ -93523,7 +94113,7 @@ const styles$v = {
93523
94113
  metaSep,
93524
94114
  metaModel,
93525
94115
  itemUrl,
93526
- itemFooter,
94116
+ itemFooter: itemFooter$1,
93527
94117
  footerActions: footerActions$1,
93528
94118
  formWrapper: formWrapper$1,
93529
94119
  formTitle: formTitle$2,
@@ -94469,34 +95059,41 @@ function AgentAssignmentDrawer({
94469
95059
  }
94470
95060
  ) });
94471
95061
  }
94472
- const panel$5 = "_panel_esaw1_3";
94473
- const list$3 = "_list_esaw1_10";
94474
- const empty$5 = "_empty_esaw1_19";
94475
- const item$3 = "_item_esaw1_26";
94476
- const itemInfo = "_itemInfo_esaw1_42";
94477
- const itemName$1 = "_itemName_esaw1_50";
94478
- const itemMeta = "_itemMeta_esaw1_56";
94479
- const itemActions = "_itemActions_esaw1_64";
94480
- const toggleLabel = "_toggleLabel_esaw1_73";
94481
- const toggleInput = "_toggleInput_esaw1_80";
94482
- const toggleTrack = "_toggleTrack_esaw1_87";
94483
- const formWrapper = "_formWrapper_esaw1_118";
94484
- const formTitle$1 = "_formTitle_esaw1_124";
94485
- const field$5 = "_field_esaw1_131";
94486
- const label$3 = "_label_esaw1_138";
94487
- const input$3 = "_input_esaw1_144";
94488
- const formFooter$1 = "_formFooter_esaw1_161";
94489
- const statusRow = "_statusRow_esaw1_171";
94490
- const statusIcon$1 = "_statusIcon_esaw1_192";
94491
- const statusText = "_statusText_esaw1_198";
94492
- const disabledBadge = "_disabledBadge_esaw1_207";
94493
- const statusArrow = "_statusArrow_esaw1_216";
95062
+ const panel$5 = "_panel_n5zg8_3";
95063
+ const list$3 = "_list_n5zg8_10";
95064
+ const empty$5 = "_empty_n5zg8_19";
95065
+ const item$3 = "_item_n5zg8_26";
95066
+ const itemInfo = "_itemInfo_n5zg8_45";
95067
+ const itemHeader$1 = "_itemHeader_n5zg8_53";
95068
+ const itemTitleBlock = "_itemTitleBlock_n5zg8_61";
95069
+ const itemFooter = "_itemFooter_n5zg8_65";
95070
+ const itemName$1 = "_itemName_n5zg8_73";
95071
+ const itemMeta = "_itemMeta_n5zg8_80";
95072
+ const itemActions = "_itemActions_n5zg8_90";
95073
+ const toggleLabel = "_toggleLabel_n5zg8_100";
95074
+ const toggleInput = "_toggleInput_n5zg8_108";
95075
+ const toggleTrack = "_toggleTrack_n5zg8_115";
95076
+ const formWrapper = "_formWrapper_n5zg8_146";
95077
+ const formTitle$1 = "_formTitle_n5zg8_152";
95078
+ const field$5 = "_field_n5zg8_159";
95079
+ const label$3 = "_label_n5zg8_166";
95080
+ const input$3 = "_input_n5zg8_172";
95081
+ const formFooter$1 = "_formFooter_n5zg8_193";
95082
+ const statusRow = "_statusRow_n5zg8_203";
95083
+ const statusRowWarning = "_statusRowWarning_n5zg8_225";
95084
+ const statusIcon$1 = "_statusIcon_n5zg8_230";
95085
+ const statusText = "_statusText_n5zg8_237";
95086
+ const disabledBadge = "_disabledBadge_n5zg8_246";
95087
+ const statusArrow = "_statusArrow_n5zg8_257";
94494
95088
  const styles$s = {
94495
95089
  panel: panel$5,
94496
95090
  list: list$3,
94497
95091
  empty: empty$5,
94498
95092
  item: item$3,
94499
95093
  itemInfo,
95094
+ itemHeader: itemHeader$1,
95095
+ itemTitleBlock,
95096
+ itemFooter,
94500
95097
  itemName: itemName$1,
94501
95098
  itemMeta,
94502
95099
  itemActions,
@@ -94510,6 +95107,7 @@ const styles$s = {
94510
95107
  input: input$3,
94511
95108
  formFooter: formFooter$1,
94512
95109
  statusRow,
95110
+ statusRowWarning,
94513
95111
  statusIcon: statusIcon$1,
94514
95112
  statusText,
94515
95113
  disabledBadge,
@@ -94522,6 +95120,11 @@ const emptyForm = {
94522
95120
  command: "",
94523
95121
  args: []
94524
95122
  };
95123
+ const MCP_SERVER_TYPE_LABEL_KEYS = {
95124
+ command: "settings.mcp.typeCommand",
95125
+ websocket: "settings.mcp.typeWebsocket",
95126
+ "streamable-http": "settings.mcp.typeStreamableHttp"
95127
+ };
94525
95128
  function McpPanel({ onClose: _onClose }) {
94526
95129
  const { t: t2 } = useTranslation();
94527
95130
  const { showToast } = useToast();
@@ -94535,6 +95138,13 @@ function McpPanel({ onClose: _onClose }) {
94535
95138
  const [selectedAgents, setSelectedAgents] = reactExports.useState(/* @__PURE__ */ new Set());
94536
95139
  const [searchQuery, setSearchQuery] = reactExports.useState("");
94537
95140
  const [savingAgents, setSavingAgents] = reactExports.useState(false);
95141
+ const getServerEndpoint = (server) => {
95142
+ if (server.type === "command") return server.command || "";
95143
+ return server.url || "";
95144
+ };
95145
+ const getServerTypeLabel = (server) => {
95146
+ return t2(MCP_SERVER_TYPE_LABEL_KEYS[server.type]);
95147
+ };
94538
95148
  const loadServers = () => {
94539
95149
  getTransport().getMcpServers().then(setServers);
94540
95150
  };
@@ -94799,32 +95409,16 @@ function McpPanel({ onClose: _onClose }) {
94799
95409
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$s.list, children: servers.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$s.empty, children: t2("settings.mcp.empty") }) : servers.map((server) => {
94800
95410
  const serverAgents = getServerAgents(server.id);
94801
95411
  const agentCount = serverAgents.length;
94802
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.item, children: [
94803
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemInfo, children: [
94804
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$s.itemName, children: server.name }),
94805
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemMeta, children: [
94806
- server.type ? t2(
94807
- `settings.mcp.type${server.type.split("-").map((w2) => w2.charAt(0).toUpperCase() + w2.slice(1)).join("")}`
94808
- ) : t2("settings.mcp.typeCommand"),
94809
- server.type === "command" && server.command ? ` · ${server.command}` : "",
94810
- (server.type === "websocket" || server.type === "streamable-http") && server.url ? ` · ${server.url}` : ""
95412
+ const endpoint = getServerEndpoint(server);
95413
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$s.item, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemInfo, children: [
95414
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemHeader, children: [
95415
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemTitleBlock, children: [
95416
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: styles$s.itemName, children: server.name }),
95417
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemMeta, title: endpoint, children: [
95418
+ getServerTypeLabel(server),
95419
+ endpoint ? ` · ${endpoint}` : ""
95420
+ ] })
94811
95421
  ] }),
94812
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
94813
- "button",
94814
- {
94815
- type: "button",
94816
- className: styles$s.statusRow,
94817
- onClick: () => openDrawer(server.id),
94818
- children: [
94819
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.statusIcon, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { size: 14 }) }),
94820
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.statusText, children: agentCount === 0 ? t2("settings.mcp.notAppliedToAnyAgent") : t2("settings.mcp.appliedToAgents", { count: agentCount }) }),
94821
- !server.enabled && agentCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.disabledBadge, children: t2("settings.mcp.globallyDisabled") }),
94822
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.statusArrow, children: "→" })
94823
- ]
94824
- }
94825
- )
94826
- ] }),
94827
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemActions, children: [
94828
95422
  /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: styles$s.toggleLabel, children: [
94829
95423
  /* @__PURE__ */ jsxRuntimeExports.jsx(
94830
95424
  "input",
@@ -94836,26 +95430,44 @@ function McpPanel({ onClose: _onClose }) {
94836
95430
  }
94837
95431
  ),
94838
95432
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.toggleTrack })
94839
- ] }),
94840
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "ghost", size: "sm", onClick: () => openEdit(server), children: [
94841
- /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { size: 14 }),
94842
- " ",
94843
- t2("settings.mcp.edit")
94844
- ] }),
95433
+ ] })
95434
+ ] }),
95435
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemFooter, children: [
94845
95436
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
94846
- Button,
95437
+ "button",
94847
95438
  {
94848
- variant: "danger",
94849
- size: "sm",
94850
- onClick: () => handleDelete2(server.id),
95439
+ type: "button",
95440
+ className: `${styles$s.statusRow} ${!server.enabled && agentCount > 0 ? styles$s.statusRowWarning : ""}`,
95441
+ onClick: () => openDrawer(server.id),
94851
95442
  children: [
94852
- /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { size: 14 }),
94853
- t2("settings.mcp.delete")
95443
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.statusIcon, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { size: 14 }) }),
95444
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.statusText, children: agentCount === 0 ? t2("settings.mcp.notAppliedToAnyAgent") : t2("settings.mcp.appliedToAgents", { count: agentCount }) }),
95445
+ !server.enabled && agentCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$s.disabledBadge, children: t2("settings.mcp.globallyDisabled") }),
95446
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: styles$s.statusArrow, size: 16 })
94854
95447
  ]
94855
95448
  }
94856
- )
95449
+ ),
95450
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$s.itemActions, children: [
95451
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { variant: "ghost", size: "sm", onClick: () => openEdit(server), children: [
95452
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { size: 14 }),
95453
+ " ",
95454
+ t2("settings.mcp.edit")
95455
+ ] }),
95456
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
95457
+ Button,
95458
+ {
95459
+ variant: "danger",
95460
+ size: "sm",
95461
+ onClick: () => handleDelete2(server.id),
95462
+ children: [
95463
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { size: 14 }),
95464
+ t2("settings.mcp.delete")
95465
+ ]
95466
+ }
95467
+ )
95468
+ ] })
94857
95469
  ] })
94858
- ] }, server.id);
95470
+ ] }) }, server.id);
94859
95471
  }) }),
94860
95472
  activeDrawer && activeServer && /* @__PURE__ */ jsxRuntimeExports.jsx(
94861
95473
  AgentAssignmentDrawer,
@@ -95294,7 +95906,7 @@ const selectedCount = "_selectedCount_141gr_184";
95294
95906
  const input$2 = "_input_141gr_189";
95295
95907
  const textarea$1 = "_textarea_141gr_190";
95296
95908
  const optimizeBtn = "_optimizeBtn_141gr_220";
95297
- const fieldHint = "_fieldHint_141gr_242";
95909
+ const fieldHint$1 = "_fieldHint_141gr_242";
95298
95910
  const advancedSection = "_advancedSection_141gr_248";
95299
95911
  const advancedHeader = "_advancedHeader_141gr_255";
95300
95912
  const advancedIcon = "_advancedIcon_141gr_275";
@@ -95362,7 +95974,7 @@ const styles$l = {
95362
95974
  input: input$2,
95363
95975
  textarea: textarea$1,
95364
95976
  optimizeBtn,
95365
- fieldHint,
95977
+ fieldHint: fieldHint$1,
95366
95978
  advancedSection,
95367
95979
  advancedHeader,
95368
95980
  advancedIcon,
@@ -104562,57 +105174,59 @@ const useChannelStore = create$3((set2, get2) => ({
104562
105174
  },
104563
105175
  stopQrPolling: () => set2((state2) => ({ qrPolling: false, qrRequestId: state2.qrRequestId + 1 }))
104564
105176
  }));
104565
- const container$5 = "_container_1j25l_1";
104566
- const content$2 = "_content_1j25l_7";
104567
- const loading$2 = "_loading_1j25l_16";
104568
- const hint = "_hint_1j25l_26";
104569
- const empty$2 = "_empty_1j25l_43";
104570
- const emptyIcon$1 = "_emptyIcon_1j25l_52";
104571
- const emptyText$1 = "_emptyText_1j25l_57";
104572
- const channelList = "_channelList_1j25l_68";
104573
- const channelCard = "_channelCard_1j25l_74";
104574
- const cardHeader = "_cardHeader_1j25l_88";
104575
- const platformIcon$1 = "_platformIcon_1j25l_94";
104576
- const platformIconWechat = "_platformIconWechat_1j25l_104";
104577
- const platformIconWecom = "_platformIconWecom_1j25l_109";
104578
- const cardInfo = "_cardInfo_1j25l_114";
104579
- const platformName = "_platformName_1j25l_122";
104580
- const targetLabel = "_targetLabel_1j25l_128";
104581
- const createdAt = "_createdAt_1j25l_136";
104582
- const statusBadge = "_statusBadge_1j25l_148";
104583
- const cardActions = "_cardActions_1j25l_185";
104584
- const editTargetCard = "_editTargetCard_1j25l_196";
104585
- const bindFlow = "_bindFlow_1j25l_208";
104586
- const stepsIndicator = "_stepsIndicator_1j25l_215";
104587
- const stepDot = "_stepDot_1j25l_221";
104588
- const stepDotActive = "_stepDotActive_1j25l_232";
104589
- const stepNum = "_stepNum_1j25l_238";
104590
- const stepTitle$1 = "_stepTitle_1j25l_255";
104591
- const stepContent$1 = "_stepContent_1j25l_260";
104592
- const field = "_field_1j25l_266";
104593
- const stepActions = "_stepActions_1j25l_278";
104594
- const targetKind = "_targetKind_1j25l_289";
104595
- const kindBtn = "_kindBtn_1j25l_294";
104596
- const kindBtnActive = "_kindBtnActive_1j25l_313";
104597
- const summary = "_summary_1j25l_348";
104598
- const summaryRow = "_summaryRow_1j25l_358";
104599
- const summaryLabel = "_summaryLabel_1j25l_365";
104600
- const mono = "_mono_1j25l_371";
104601
- const testResult = "_testResult_1j25l_380";
104602
- const testing = "_testing_1j25l_384";
104603
- const testSuccess = "_testSuccess_1j25l_393";
104604
- const testFailed = "_testFailed_1j25l_404";
104605
- const methodChoice = "_methodChoice_1j25l_425";
104606
- const methodCard = "_methodCard_1j25l_430";
104607
- const methodCardDisabled = "_methodCardDisabled_1j25l_451";
104608
- const methodIcon = "_methodIcon_1j25l_462";
104609
- const methodTitle = "_methodTitle_1j25l_471";
104610
- const methodDesc = "_methodDesc_1j25l_477";
104611
- const qrcodeSection = "_qrcodeSection_1j25l_487";
104612
- const qrImage = "_qrImage_1j25l_494";
104613
- const qrHint = "_qrHint_1j25l_503";
104614
- const qrLoading = "_qrLoading_1j25l_509";
104615
- const error$2 = "_error_1j25l_518";
105177
+ const container$5 = "_container_1rnd8_1";
105178
+ const content$2 = "_content_1rnd8_7";
105179
+ const loading$2 = "_loading_1rnd8_16";
105180
+ const hint = "_hint_1rnd8_26";
105181
+ const empty$2 = "_empty_1rnd8_43";
105182
+ const emptyIcon$1 = "_emptyIcon_1rnd8_52";
105183
+ const emptyText$1 = "_emptyText_1rnd8_57";
105184
+ const channelList = "_channelList_1rnd8_68";
105185
+ const channelCard = "_channelCard_1rnd8_74";
105186
+ const cardHeader = "_cardHeader_1rnd8_88";
105187
+ const platformIcon$1 = "_platformIcon_1rnd8_94";
105188
+ const platformIconWechat = "_platformIconWechat_1rnd8_104";
105189
+ const platformIconWecom = "_platformIconWecom_1rnd8_109";
105190
+ const cardInfo = "_cardInfo_1rnd8_114";
105191
+ const platformName = "_platformName_1rnd8_122";
105192
+ const targetLabel = "_targetLabel_1rnd8_128";
105193
+ const targetHint = "_targetHint_1rnd8_136";
105194
+ const createdAt = "_createdAt_1rnd8_144";
105195
+ const statusBadge = "_statusBadge_1rnd8_156";
105196
+ const cardActions = "_cardActions_1rnd8_193";
105197
+ const editTargetCard = "_editTargetCard_1rnd8_204";
105198
+ const bindFlow = "_bindFlow_1rnd8_216";
105199
+ const stepsIndicator = "_stepsIndicator_1rnd8_223";
105200
+ const stepDot = "_stepDot_1rnd8_229";
105201
+ const stepDotActive = "_stepDotActive_1rnd8_240";
105202
+ const stepNum = "_stepNum_1rnd8_246";
105203
+ const stepTitle$1 = "_stepTitle_1rnd8_263";
105204
+ const stepContent$1 = "_stepContent_1rnd8_268";
105205
+ const field = "_field_1rnd8_274";
105206
+ const fieldHint = "_fieldHint_1rnd8_286";
105207
+ const stepActions = "_stepActions_1rnd8_293";
105208
+ const targetKind = "_targetKind_1rnd8_304";
105209
+ const kindBtn = "_kindBtn_1rnd8_309";
105210
+ const kindBtnActive = "_kindBtnActive_1rnd8_328";
105211
+ const summary = "_summary_1rnd8_363";
105212
+ const summaryRow = "_summaryRow_1rnd8_373";
105213
+ const summaryLabel = "_summaryLabel_1rnd8_380";
105214
+ const mono = "_mono_1rnd8_386";
105215
+ const testResult = "_testResult_1rnd8_395";
105216
+ const testing = "_testing_1rnd8_399";
105217
+ const testSuccess = "_testSuccess_1rnd8_408";
105218
+ const testFailed = "_testFailed_1rnd8_419";
105219
+ const methodChoice = "_methodChoice_1rnd8_440";
105220
+ const methodCard = "_methodCard_1rnd8_445";
105221
+ const methodCardDisabled = "_methodCardDisabled_1rnd8_466";
105222
+ const methodIcon = "_methodIcon_1rnd8_477";
105223
+ const methodTitle = "_methodTitle_1rnd8_486";
105224
+ const methodDesc = "_methodDesc_1rnd8_492";
105225
+ const qrcodeSection = "_qrcodeSection_1rnd8_502";
105226
+ const qrImage = "_qrImage_1rnd8_509";
105227
+ const qrHint = "_qrHint_1rnd8_518";
105228
+ const qrLoading = "_qrLoading_1rnd8_524";
105229
+ const error$2 = "_error_1rnd8_533";
104616
105230
  const styles$b = {
104617
105231
  container: container$5,
104618
105232
  content: content$2,
@@ -104630,14 +105244,15 @@ const styles$b = {
104630
105244
  cardInfo,
104631
105245
  platformName,
104632
105246
  targetLabel,
105247
+ targetHint,
104633
105248
  createdAt,
104634
105249
  statusBadge,
104635
- "status-connected": "_status-connected_1j25l_159",
104636
- "status-disconnected": "_status-disconnected_1j25l_164",
104637
- "status-idle": "_status-idle_1j25l_165",
104638
- "status-connecting": "_status-connecting_1j25l_170",
104639
- "status-reconnecting": "_status-reconnecting_1j25l_171",
104640
- "status-auth_failed": "_status-auth_failed_1j25l_176",
105250
+ "status-connected": "_status-connected_1rnd8_167",
105251
+ "status-disconnected": "_status-disconnected_1rnd8_172",
105252
+ "status-idle": "_status-idle_1rnd8_173",
105253
+ "status-connecting": "_status-connecting_1rnd8_178",
105254
+ "status-reconnecting": "_status-reconnecting_1rnd8_179",
105255
+ "status-auth_failed": "_status-auth_failed_1rnd8_184",
104641
105256
  cardActions,
104642
105257
  editTargetCard,
104643
105258
  bindFlow,
@@ -104648,6 +105263,7 @@ const styles$b = {
104648
105263
  stepTitle: stepTitle$1,
104649
105264
  stepContent: stepContent$1,
104650
105265
  field,
105266
+ fieldHint,
104651
105267
  stepActions,
104652
105268
  targetKind,
104653
105269
  kindBtn,
@@ -104841,6 +105457,7 @@ function ChannelList({ channels: channels2, onUnbind }) {
104841
105457
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.cardInfo, children: [
104842
105458
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$b.platformName, children: platformLabel(ch.type, t2) }),
104843
105459
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$b.targetLabel, children: isEditing ? t2("settings.integration.editTargetTitle") : ch.targetLabel }),
105460
+ !isEditing && (ch.target.kind === "auto-session" || ch.target.kind === "agent" && ch.target.routing === "per-external-conversation" || ch.target.kind === "session" && ch.target.routing === "per-external-conversation") && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$b.targetHint, children: t2("settings.integration.bind.autoSessionCardHint") }),
104844
105461
  ch.createdAt && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: styles$b.createdAt, children: t2("settings.integration.createdAt", {
104845
105462
  time: formatCreatedAt(ch.createdAt, i18n.language)
104846
105463
  }) })
@@ -104901,11 +105518,19 @@ function EditTargetCard({ channel: channel2, onCancel, onDone }) {
104901
105518
  const [agents, setAgents] = reactExports.useState([]);
104902
105519
  const [groups, setGroups] = reactExports.useState([]);
104903
105520
  const [sessions, setSessions] = reactExports.useState([]);
105521
+ const [directSessions, setDirectSessions] = reactExports.useState([]);
104904
105522
  const [saving, setSaving] = reactExports.useState(false);
104905
- const [targetKind2, setTargetKind] = reactExports.useState(channel2.target.kind);
105523
+ const initialKind = channel2.target.kind === "auto-session" ? "session" : channel2.target.kind === "agent" ? "agent" : "session";
105524
+ const canAutoRouteChannel = channel2.type === "wecom-bot";
105525
+ const initialRouting = canAutoRouteChannel && (channel2.target.kind === "auto-session" || "routing" in channel2.target && channel2.target.routing === "per-external-conversation") ? "per-external-conversation" : "fixed";
105526
+ const [targetKind2, setTargetKind] = reactExports.useState(initialKind);
104906
105527
  const [selectedAgentId, setSelectedAgentId] = reactExports.useState(channel2.target.kind === "agent" ? channel2.target.agentId : "");
104907
- const [selectedGroupId, setSelectedGroupId] = reactExports.useState(channel2.target.kind === "session" ? channel2.target.groupId : "");
104908
- const [selectedSessionId, setSelectedSessionId] = reactExports.useState(channel2.target.kind === "session" ? channel2.target.sessionId : "");
105528
+ const [selectedAgentSessionId, setSelectedAgentSessionId] = reactExports.useState(channel2.target.kind === "agent" && "sessionId" in channel2.target ? channel2.target.sessionId ?? "" : "");
105529
+ const [selectedGroupId, setSelectedGroupId] = reactExports.useState(
105530
+ channel2.target.kind === "session" ? channel2.target.groupId : channel2.target.kind === "auto-session" ? channel2.target.groupId : ""
105531
+ );
105532
+ const [selectedSessionId, setSelectedSessionId] = reactExports.useState(channel2.target.kind === "session" && "sessionId" in channel2.target ? channel2.target.sessionId : "");
105533
+ const [routingMode, setRoutingMode] = reactExports.useState(initialRouting);
104909
105534
  reactExports.useEffect(() => {
104910
105535
  let cancelled = false;
104911
105536
  async function load2() {
@@ -104913,11 +105538,11 @@ function EditTargetCard({ channel: channel2, onCancel, onDone }) {
104913
105538
  const transport = getTransport();
104914
105539
  const [agentList2, convList] = await Promise.all([
104915
105540
  transport.listAgents(),
104916
- transport.listConversations()
105541
+ transport.listGroups()
104917
105542
  ]);
104918
105543
  if (!cancelled) {
104919
105544
  setAgents(agentList2);
104920
- setGroups(convList.filter((c2) => c2.type === "group"));
105545
+ setGroups(convList);
104921
105546
  }
104922
105547
  } catch (e3) {
104923
105548
  log$6.error("Failed to load target data:", e3);
@@ -104947,14 +105572,44 @@ function EditTargetCard({ channel: channel2, onCancel, onDone }) {
104947
105572
  cancelled = true;
104948
105573
  };
104949
105574
  }, [selectedGroupId]);
105575
+ reactExports.useEffect(() => {
105576
+ if (!selectedAgentId) {
105577
+ setDirectSessions([]);
105578
+ setSelectedAgentSessionId("");
105579
+ return;
105580
+ }
105581
+ let cancelled = false;
105582
+ async function load2() {
105583
+ try {
105584
+ const list2 = await getTransport().listDirectSessions(selectedAgentId);
105585
+ if (!cancelled) setDirectSessions(list2);
105586
+ } catch {
105587
+ if (!cancelled) setDirectSessions([]);
105588
+ }
105589
+ }
105590
+ load2();
105591
+ return () => {
105592
+ cancelled = true;
105593
+ };
105594
+ }, [selectedAgentId]);
104950
105595
  const handleSave = async () => {
104951
105596
  let target2;
105597
+ const effectiveRoutingMode = canAutoRouteChannel ? routingMode : "fixed";
104952
105598
  if (targetKind2 === "agent") {
104953
105599
  if (!selectedAgentId) return;
104954
- target2 = { kind: "agent", agentId: selectedAgentId };
105600
+ target2 = {
105601
+ kind: "agent",
105602
+ agentId: selectedAgentId,
105603
+ ...selectedAgentSessionId ? { sessionId: selectedAgentSessionId } : {},
105604
+ ...effectiveRoutingMode === "per-external-conversation" ? { routing: "per-external-conversation" } : {}
105605
+ };
104955
105606
  } else {
104956
- if (!selectedGroupId || !selectedSessionId) return;
104957
- target2 = { kind: "session", groupId: selectedGroupId, sessionId: selectedSessionId };
105607
+ if (!selectedGroupId) return;
105608
+ target2 = {
105609
+ kind: "session",
105610
+ groupId: selectedGroupId,
105611
+ ...effectiveRoutingMode === "per-external-conversation" ? { routing: "per-external-conversation" } : { sessionId: selectedSessionId }
105612
+ };
104958
105613
  }
104959
105614
  setSaving(true);
104960
105615
  try {
@@ -104974,14 +105629,20 @@ function EditTargetCard({ channel: channel2, onCancel, onDone }) {
104974
105629
  agents,
104975
105630
  groups,
104976
105631
  sessions,
105632
+ directSessions,
104977
105633
  targetKind: targetKind2,
104978
105634
  setTargetKind,
104979
105635
  selectedAgentId,
104980
105636
  setSelectedAgentId,
105637
+ selectedAgentSessionId,
105638
+ setSelectedAgentSessionId,
104981
105639
  selectedGroupId,
104982
105640
  setSelectedGroupId,
104983
105641
  selectedSessionId,
104984
- setSelectedSessionId
105642
+ setSelectedSessionId,
105643
+ routingMode,
105644
+ setRoutingMode,
105645
+ channelType: channel2.type
104985
105646
  }
104986
105647
  ),
104987
105648
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.stepActions, children: [
@@ -104990,7 +105651,7 @@ function EditTargetCard({ channel: channel2, onCancel, onDone }) {
104990
105651
  Button,
104991
105652
  {
104992
105653
  onClick: handleSave,
104993
- disabled: saving || (targetKind2 === "agent" ? !selectedAgentId : !selectedGroupId || !selectedSessionId),
105654
+ disabled: saving || (targetKind2 === "agent" ? !selectedAgentId : !selectedGroupId || (canAutoRouteChannel ? routingMode : "fixed") === "fixed" && !selectedSessionId),
104994
105655
  children: [
104995
105656
  saving && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 14, className: "kai-spin" }),
104996
105657
  t2("common.confirm")
@@ -105004,16 +105665,24 @@ function TargetPicker({
105004
105665
  agents,
105005
105666
  groups,
105006
105667
  sessions,
105668
+ directSessions,
105007
105669
  targetKind: targetKind2,
105008
105670
  setTargetKind,
105009
105671
  selectedAgentId,
105010
105672
  setSelectedAgentId,
105673
+ selectedAgentSessionId,
105674
+ setSelectedAgentSessionId,
105011
105675
  selectedGroupId,
105012
105676
  setSelectedGroupId,
105013
105677
  selectedSessionId,
105014
- setSelectedSessionId
105678
+ setSelectedSessionId,
105679
+ routingMode,
105680
+ setRoutingMode,
105681
+ channelType
105015
105682
  }) {
105016
105683
  const { t: t2 } = useTranslation();
105684
+ const canAutoRoute = channelType === "wecom-bot";
105685
+ const effectiveRoutingMode = canAutoRoute ? routingMode : "fixed";
105017
105686
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
105018
105687
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.targetKind, children: [
105019
105688
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -105047,12 +105716,33 @@ function TargetPicker({
105047
105716
  }
105048
105717
  )
105049
105718
  ] }),
105050
- targetKind2 === "agent" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105051
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.selectAgent") }),
105052
- /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedAgentId, onChange: setSelectedAgentId, children: [
105053
- /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("settings.integration.bind.selectAgent") }),
105054
- agents.map((a2) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a2.id, children: a2.name }, a2.id))
105055
- ] })
105719
+ targetKind2 === "agent" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
105720
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105721
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.selectAgent") }),
105722
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedAgentId, onChange: (v2) => {
105723
+ setSelectedAgentId(v2);
105724
+ setSelectedAgentSessionId("");
105725
+ }, children: [
105726
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("settings.integration.bind.selectAgent") }),
105727
+ agents.map((a2) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: a2.id, children: a2.name }, a2.id))
105728
+ ] })
105729
+ ] }),
105730
+ selectedAgentId && canAutoRoute && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105731
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.routingMode") }),
105732
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: routingMode, onChange: (v2) => setRoutingMode(v2), children: [
105733
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "fixed", children: t2("settings.integration.bind.routingFixed") }),
105734
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "per-external-conversation", children: t2("settings.integration.bind.routingAuto") })
105735
+ ] })
105736
+ ] }),
105737
+ selectedAgentId && effectiveRoutingMode === "fixed" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105738
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.selectAgentSession") }),
105739
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedAgentSessionId, onChange: setSelectedAgentSessionId, children: [
105740
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("settings.integration.bind.defaultSession") }),
105741
+ directSessions.map((session2) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: session2.id, children: session2.title }, session2.id))
105742
+ ] }),
105743
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: styles$b.fieldHint, children: t2("settings.integration.bind.agentSessionHint") })
105744
+ ] }),
105745
+ selectedAgentId && canAutoRoute && effectiveRoutingMode === "per-external-conversation" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: styles$b.fieldHint, children: t2("settings.integration.bind.autoSessionAgentHint") })
105056
105746
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
105057
105747
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105058
105748
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.selectGroup") }),
@@ -105066,18 +105756,26 @@ function TargetPicker({
105066
105756
  },
105067
105757
  children: [
105068
105758
  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("settings.integration.bind.selectGroup") }),
105069
- groups.map((g2) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: g2.type === "group" ? g2.groupId : "", children: g2.title }, g2.id))
105759
+ groups.map((g2) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: g2.id, children: g2.name }, g2.id))
105070
105760
  ]
105071
105761
  }
105072
105762
  )
105073
105763
  ] }),
105074
- selectedGroupId && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105764
+ selectedGroupId && canAutoRoute && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105765
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.routingMode") }),
105766
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: routingMode, onChange: (v2) => setRoutingMode(v2), children: [
105767
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "fixed", children: t2("settings.integration.bind.routingFixed") }),
105768
+ /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "per-external-conversation", children: t2("settings.integration.bind.routingAuto") })
105769
+ ] })
105770
+ ] }),
105771
+ selectedGroupId && effectiveRoutingMode === "fixed" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.field, children: [
105075
105772
  /* @__PURE__ */ jsxRuntimeExports.jsx("label", { children: t2("settings.integration.bind.selectThread") }),
105076
105773
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Select, { value: selectedSessionId, onChange: setSelectedSessionId, children: [
105077
105774
  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("settings.integration.bind.selectThread") }),
105078
105775
  sessions.map((th) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: th.id, children: th.title }, th.id))
105079
105776
  ] })
105080
- ] })
105777
+ ] }),
105778
+ selectedGroupId && canAutoRoute && effectiveRoutingMode === "per-external-conversation" && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: styles$b.fieldHint, children: t2("settings.integration.bind.autoSessionHint") })
105081
105779
  ] })
105082
105780
  ] });
105083
105781
  }
@@ -105109,8 +105807,30 @@ function TargetLabel({ target: target2 }) {
105109
105807
  const transport = getTransport();
105110
105808
  if (target2.kind === "agent") {
105111
105809
  const agent2 = await transport.getAgent(target2.agentId, false);
105112
- if (!cancelled) setLabel(`${t2("settings.integration.bind.targetAgent")} · ${agent2?.name ?? target2.agentId}`);
105810
+ const agentName2 = agent2?.name ?? target2.agentId;
105811
+ if (target2.routing === "per-external-conversation") {
105812
+ if (!cancelled) setLabel(`${t2("settings.integration.bind.routingAutoLabel")} · ${agentName2}`);
105813
+ return;
105814
+ }
105815
+ if (!target2.sessionId) {
105816
+ if (!cancelled) setLabel(`${t2("settings.integration.bind.targetAgent")} · ${agentName2}`);
105817
+ return;
105818
+ }
105819
+ const session2 = await transport.getDirectSession(target2.sessionId);
105820
+ if (!cancelled) {
105821
+ setLabel(`${t2("settings.integration.bind.targetAgent")} · ${agentName2} / ${session2?.title ?? target2.sessionId}`);
105822
+ }
105823
+ } else if (target2.kind === "auto-session") {
105824
+ const group2 = await transport.getGroup(target2.groupId);
105825
+ const groupName2 = group2?.name ?? target2.groupId;
105826
+ if (!cancelled) setLabel(`${t2("settings.integration.bind.routingAutoLabel")} · ${groupName2}`);
105113
105827
  } else {
105828
+ if (target2.routing === "per-external-conversation") {
105829
+ const group22 = await transport.getGroup(target2.groupId);
105830
+ const groupName2 = group22?.name ?? target2.groupId;
105831
+ if (!cancelled) setLabel(`${t2("settings.integration.bind.routingAutoLabel")} · ${groupName2}`);
105832
+ return;
105833
+ }
105114
105834
  const group2 = await transport.getGroup(target2.groupId);
105115
105835
  const session2 = await transport.getSession(target2.sessionId);
105116
105836
  if (!cancelled) {
@@ -105120,7 +105840,15 @@ function TargetLabel({ target: target2 }) {
105120
105840
  }
105121
105841
  }
105122
105842
  } catch {
105123
- if (!cancelled) setLabel(target2.kind === "agent" ? target2.agentId : `${target2.groupId}/${target2.sessionId}`);
105843
+ if (!cancelled) {
105844
+ if (target2.kind === "agent") {
105845
+ setLabel(target2.routing === "per-external-conversation" ? `${t2("settings.integration.bind.routingAutoLabel")} · ${target2.agentId}` : target2.sessionId ? `${target2.agentId}/${target2.sessionId}` : target2.agentId);
105846
+ } else if (target2.kind === "auto-session") {
105847
+ setLabel(`${t2("settings.integration.bind.routingAutoLabel")} · ${target2.groupId}`);
105848
+ } else {
105849
+ setLabel(target2.routing === "per-external-conversation" ? `${t2("settings.integration.bind.routingAutoLabel")} · ${target2.groupId}` : `${target2.groupId}/${target2.sessionId}`);
105850
+ }
105851
+ }
105124
105852
  }
105125
105853
  }
105126
105854
  load2();
@@ -105159,10 +105887,14 @@ function BindFlow() {
105159
105887
  const [agents, setAgents] = reactExports.useState([]);
105160
105888
  const [groups, setGroups] = reactExports.useState([]);
105161
105889
  const [sessions, setSessions] = reactExports.useState([]);
105890
+ const [directSessions, setDirectSessions] = reactExports.useState([]);
105162
105891
  const [selectedGroupId, setSelectedGroupId] = reactExports.useState("");
105163
105892
  const [targetKind2, setTargetKind] = reactExports.useState("agent");
105164
105893
  const [selectedAgentId, setSelectedAgentId] = reactExports.useState("");
105894
+ const [selectedAgentSessionId, setSelectedAgentSessionId] = reactExports.useState("");
105165
105895
  const [selectedSessionId, setSelectedSessionId] = reactExports.useState("");
105896
+ const [routingMode, setRoutingMode] = reactExports.useState("fixed");
105897
+ const canAutoRouteChannel = bindChannelType === "wecom-bot";
105166
105898
  reactExports.useEffect(() => {
105167
105899
  if (bindStep !== "target") return;
105168
105900
  let cancelled = false;
@@ -105171,11 +105903,11 @@ function BindFlow() {
105171
105903
  const transport = getTransport();
105172
105904
  const [agentList2, convList] = await Promise.all([
105173
105905
  transport.listAgents(),
105174
- transport.listConversations()
105906
+ transport.listGroups()
105175
105907
  ]);
105176
105908
  if (!cancelled) {
105177
105909
  setAgents(agentList2);
105178
- setGroups(convList.filter((c2) => c2.type === "group"));
105910
+ setGroups(convList);
105179
105911
  }
105180
105912
  } catch (e3) {
105181
105913
  log$6.error("Failed to load target data:", e3);
@@ -105205,6 +105937,26 @@ function BindFlow() {
105205
105937
  cancelled = true;
105206
105938
  };
105207
105939
  }, [bindStep, selectedGroupId]);
105940
+ reactExports.useEffect(() => {
105941
+ if (bindStep !== "target" || !selectedAgentId) {
105942
+ setDirectSessions([]);
105943
+ setSelectedAgentSessionId("");
105944
+ return;
105945
+ }
105946
+ let cancelled = false;
105947
+ async function load2() {
105948
+ try {
105949
+ const list2 = await getTransport().listDirectSessions(selectedAgentId);
105950
+ if (!cancelled) setDirectSessions(list2);
105951
+ } catch {
105952
+ if (!cancelled) setDirectSessions([]);
105953
+ }
105954
+ }
105955
+ load2();
105956
+ return () => {
105957
+ cancelled = true;
105958
+ };
105959
+ }, [bindStep, selectedAgentId]);
105208
105960
  reactExports.useEffect(() => {
105209
105961
  if (!qrPolling || bindStep !== "qrcode") return;
105210
105962
  let cancelled = false;
@@ -105243,12 +105995,22 @@ function BindFlow() {
105243
105995
  };
105244
105996
  const [handleStepTargetNext, submitting] = useAsyncAction(async () => {
105245
105997
  let target2;
105998
+ const effectiveRoutingMode = canAutoRouteChannel ? routingMode : "fixed";
105246
105999
  if (targetKind2 === "agent") {
105247
106000
  if (!selectedAgentId) return;
105248
- target2 = { kind: "agent", agentId: selectedAgentId };
106001
+ target2 = {
106002
+ kind: "agent",
106003
+ agentId: selectedAgentId,
106004
+ ...selectedAgentSessionId ? { sessionId: selectedAgentSessionId } : {},
106005
+ ...effectiveRoutingMode === "per-external-conversation" ? { routing: "per-external-conversation" } : {}
106006
+ };
105249
106007
  } else {
105250
- if (!selectedGroupId || !selectedSessionId) return;
105251
- target2 = { kind: "session", groupId: selectedGroupId, sessionId: selectedSessionId };
106008
+ if (!selectedGroupId) return;
106009
+ target2 = {
106010
+ kind: "session",
106011
+ groupId: selectedGroupId,
106012
+ ...effectiveRoutingMode === "per-external-conversation" ? { routing: "per-external-conversation" } : { sessionId: selectedSessionId }
106013
+ };
105252
106014
  }
105253
106015
  setBindTarget(target2);
105254
106016
  try {
@@ -105436,14 +106198,20 @@ function BindFlow() {
105436
106198
  agents,
105437
106199
  groups,
105438
106200
  sessions,
106201
+ directSessions,
105439
106202
  targetKind: targetKind2,
105440
106203
  setTargetKind,
105441
106204
  selectedAgentId,
105442
106205
  setSelectedAgentId,
106206
+ selectedAgentSessionId,
106207
+ setSelectedAgentSessionId,
105443
106208
  selectedGroupId,
105444
106209
  setSelectedGroupId,
105445
106210
  selectedSessionId,
105446
- setSelectedSessionId
106211
+ setSelectedSessionId,
106212
+ routingMode,
106213
+ setRoutingMode,
106214
+ channelType: bindChannelType
105447
106215
  }
105448
106216
  ),
105449
106217
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$b.stepActions, children: [
@@ -105456,10 +106224,10 @@ function BindFlow() {
105456
106224
  Button,
105457
106225
  {
105458
106226
  onClick: handleStepTargetNext,
105459
- disabled: submitting || (targetKind2 === "agent" ? !selectedAgentId : !selectedGroupId || !selectedSessionId),
106227
+ disabled: submitting || (targetKind2 === "agent" ? !selectedAgentId : !selectedGroupId || (canAutoRouteChannel ? routingMode : "fixed") === "fixed" && !selectedSessionId),
105460
106228
  children: [
105461
106229
  submitting && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { size: 14, className: "kai-spin" }),
105462
- t2("settings.integration.bind.next"),
106230
+ t2("settings.integration.bind.bindAndTest"),
105463
106231
  " ",
105464
106232
  !submitting && /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowRight, { size: 14 })
105465
106233
  ]
@@ -124625,7 +125393,10 @@ function renderInsight(t2, insight) {
124625
125393
  case "group_token_share":
124626
125394
  return t2("settings.usage.insight.groupTokenShare", { rate: insight.params.rate });
124627
125395
  case "unfinished_call_rate":
124628
- return t2("settings.usage.insight.unfinishedCallRate", { rate: insight.params.rate });
125396
+ return t2(
125397
+ insight.params.approximate === "less_than" ? "settings.usage.insight.unfinishedCallRateLessThan" : "settings.usage.insight.unfinishedCallRate",
125398
+ { rate: insight.params.rate }
125399
+ );
124629
125400
  case "top_tool":
124630
125401
  return t2("settings.usage.insight.topTool", { name: insight.params.name, count: insight.params.count });
124631
125402
  case "top_group":
@@ -124973,7 +125744,7 @@ function useActiveView() {
124973
125744
  )
124974
125745
  );
124975
125746
  }
124976
- function useConversationView(sessionId) {
125747
+ function useSessionView(sessionId) {
124977
125748
  return useConversationStore(
124978
125749
  useShallow(
124979
125750
  (state2) => deriveActiveView(
@@ -125011,12 +125782,12 @@ const EMPTY_IDS = [];
125011
125782
  function getDirectWorkerId(agentId, sessionId) {
125012
125783
  return `direct:${agentId}:${sessionId}`;
125013
125784
  }
125014
- function getDisplayConversation(input2) {
125015
- const { sessionId, conversation: conversation2, conversationView, groupChats, agentConversations } = input2;
125785
+ function getConversationProjectionForSession(input2) {
125786
+ const { sessionId, conversation: conversation2, sessionView, groupChats, agentConversations } = input2;
125016
125787
  if (conversation2) return conversation2;
125017
- if (conversationView?.type === "group") {
125788
+ if (sessionView?.type === "group") {
125018
125789
  const group2 = groupChats.find(
125019
- (item2) => item2.type === "group" && item2.groupId === conversationView.groupId
125790
+ (item2) => item2.type === "group" && item2.groupId === sessionView.groupId
125020
125791
  );
125021
125792
  if (!group2 || group2.type !== "group") return null;
125022
125793
  return {
@@ -125025,8 +125796,8 @@ function getDisplayConversation(input2) {
125025
125796
  messageCount: 0
125026
125797
  };
125027
125798
  }
125028
- if (conversationView?.type === "single") {
125029
- const direct = agentConversations.get(conversationView.agentId);
125799
+ if (sessionView?.type === "single") {
125800
+ const direct = agentConversations.get(sessionView.agentId);
125030
125801
  if (!direct || direct.type !== "single") return null;
125031
125802
  return {
125032
125803
  ...direct,
@@ -125066,7 +125837,7 @@ function ChatBox({
125066
125837
  const groupChats = useConversationStore((s2) => s2.groupChats);
125067
125838
  const agentConversations = useConversationStore((s2) => s2.agentConversations);
125068
125839
  const activeView = useActiveView();
125069
- const conversationView = useConversationView(sessionId);
125840
+ const sessionView = useSessionView(sessionId);
125070
125841
  const conversation2 = useMessageStore(
125071
125842
  reactExports.useMemo(() => (s2) => s2.conversationMap.get(sessionId) ?? null, [sessionId])
125072
125843
  );
@@ -125089,14 +125860,14 @@ function ChatBox({
125089
125860
  reactExports.useMemo(() => (s2) => s2.retryingMap.get(sessionId) ?? null, [sessionId])
125090
125861
  );
125091
125862
  const displayConversation = reactExports.useMemo(
125092
- () => getDisplayConversation({
125863
+ () => getConversationProjectionForSession({
125093
125864
  sessionId,
125094
125865
  conversation: conversation2,
125095
- conversationView,
125866
+ sessionView,
125096
125867
  groupChats,
125097
125868
  agentConversations
125098
125869
  }),
125099
- [agentConversations, conversation2, conversationView, groupChats, sessionId]
125870
+ [agentConversations, conversation2, groupChats, sessionId, sessionView]
125100
125871
  );
125101
125872
  const primaryAgent = displayConversation?.type === "single" ? agents.find((a2) => a2.id === displayConversation.agentId || a2.id === memberAgentIds[0]) ?? null : null;
125102
125873
  const displayMemberAgentIds = reactExports.useMemo(
@@ -125262,8 +126033,8 @@ function ChatBox({
125262
126033
  return false;
125263
126034
  }
125264
126035
  const nextSpeakerId = msg.broadcast ? void 0 : msg.mentions[0];
125265
- if (conversationView?.type === "group" && nextSpeakerId) {
125266
- updateGroupSessionSpeaker(conversationView.sessionId, nextSpeakerId).catch((error2) => {
126036
+ if (sessionView?.type === "group" && nextSpeakerId) {
126037
+ updateGroupSessionSpeaker(sessionView.sessionId, nextSpeakerId).catch((error2) => {
125267
126038
  log$5.warn("Failed to sync session speaker after send:", error2);
125268
126039
  });
125269
126040
  }
@@ -125276,8 +126047,8 @@ function ChatBox({
125276
126047
  }
125277
126048
  },
125278
126049
  [
125279
- conversationView,
125280
126050
  handleSendMessage,
126051
+ sessionView,
125281
126052
  sessionId,
125282
126053
  setNotification,
125283
126054
  t2,
@@ -125351,7 +126122,7 @@ function ChatBox({
125351
126122
  const handleDeleteGroup = reactExports.useCallback(() => {
125352
126123
  setDeleteConfirm(true);
125353
126124
  }, []);
125354
- const notificationText = retryInfo ? t2("retrying", { attempt: retryInfo.attempt, maxAttempts: retryInfo.maxAttempts }) : notification2;
126125
+ const notificationText = notification2;
125355
126126
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: styles$F.container, children: [
125356
126127
  /* @__PURE__ */ jsxRuntimeExports.jsx(ChatNotification, { message: notificationText }),
125357
126128
  displayConversation && /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -125981,7 +126752,7 @@ function useSidebarSearch() {
125981
126752
  searchInputRef
125982
126753
  };
125983
126754
  }
125984
- const version = "1.10.11";
126755
+ const version = "1.10.12";
125985
126756
  const pkg = {
125986
126757
  version
125987
126758
  };