@zythum02/fello-server 0.1.55 → 0.1.57
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.
- package/out/renderer/assets/PopoverPopup-BcHY-oda.js +591 -0
- package/out/renderer/assets/PopoverPopup-BcHY-oda.js.br +0 -0
- package/out/renderer/assets/PopoverPopup-BcHY-oda.js.gz +0 -0
- package/out/renderer/assets/{_baseUniq-BdLqGxOi.js → _baseUniq-KD2XGr9F.js} +1 -1
- package/out/renderer/assets/_baseUniq-KD2XGr9F.js.br +0 -0
- package/out/renderer/assets/_baseUniq-KD2XGr9F.js.gz +0 -0
- package/out/renderer/assets/{arc-UpL8po5R.js → arc-CR7wDdln.js} +1 -1
- package/out/renderer/assets/arc-CR7wDdln.js.br +0 -0
- package/out/renderer/assets/arc-CR7wDdln.js.gz +0 -0
- package/out/renderer/assets/{architectureDiagram-Q4EWVU46-ManEkEbl.js → architectureDiagram-Q4EWVU46-ob7rXg_N.js} +6 -6
- package/out/renderer/assets/architectureDiagram-Q4EWVU46-ob7rXg_N.js.br +0 -0
- package/out/renderer/assets/architectureDiagram-Q4EWVU46-ob7rXg_N.js.gz +0 -0
- package/out/renderer/assets/{arrow-left-BnuWerui.js → arrow-left-Ck_ZVJr5.js} +1 -1
- package/out/renderer/assets/{arrow-up-quD46bYg.js → arrow-up-D7cOrlYE.js} +4 -15
- package/out/renderer/assets/{automation-cVl19jbl.js → automation-W30eYgU8.js} +36 -13
- package/out/renderer/assets/automation-W30eYgU8.js.br +0 -0
- package/out/renderer/assets/automation-W30eYgU8.js.gz +0 -0
- package/out/renderer/assets/{blockDiagram-DXYQGD6D-B7n8X8F6.js → blockDiagram-DXYQGD6D-DH0dgWHF.js} +7 -7
- package/out/renderer/assets/blockDiagram-DXYQGD6D-DH0dgWHF.js.br +0 -0
- package/out/renderer/assets/blockDiagram-DXYQGD6D-DH0dgWHF.js.gz +0 -0
- package/out/renderer/assets/{c4Diagram-AHTNJAMY-BoP_JNY0.js → c4Diagram-AHTNJAMY--55RlH_-.js} +3 -3
- package/out/renderer/assets/c4Diagram-AHTNJAMY--55RlH_-.js.br +0 -0
- package/out/renderer/assets/c4Diagram-AHTNJAMY--55RlH_-.js.gz +0 -0
- package/out/renderer/assets/{channel-BTAU8ahK.js → channel-Bz679Wzq.js} +1 -1
- package/out/renderer/assets/{chunk-4BX2VUAB-BCKz1EgZ.js → chunk-4BX2VUAB-0jn0O1rt.js} +1 -1
- package/out/renderer/assets/{chunk-4TB4RGXK-B2HhnMqB.js → chunk-4TB4RGXK-BI1TetiG.js} +5 -5
- package/out/renderer/assets/chunk-4TB4RGXK-BI1TetiG.js.br +0 -0
- package/out/renderer/assets/chunk-4TB4RGXK-BI1TetiG.js.gz +0 -0
- package/out/renderer/assets/{chunk-55IACEB6-Drurz_4k.js → chunk-55IACEB6-9LfmpuHC.js} +1 -1
- package/out/renderer/assets/{chunk-EDXVE4YY-Xfghcg7b.js → chunk-EDXVE4YY-CtHVLcvG.js} +1 -1
- package/out/renderer/assets/chunk-EDXVE4YY-CtHVLcvG.js.br +0 -0
- package/out/renderer/assets/chunk-EDXVE4YY-CtHVLcvG.js.gz +0 -0
- package/out/renderer/assets/{chunk-FMBD7UC4-Birgz8kz.js → chunk-FMBD7UC4-eUJaG2CL.js} +1 -1
- package/out/renderer/assets/{chunk-OYMX7WX6-Cv4jgShd.js → chunk-OYMX7WX6-D-sPmxYW.js} +3 -3
- package/out/renderer/assets/chunk-OYMX7WX6-D-sPmxYW.js.br +0 -0
- package/out/renderer/assets/chunk-OYMX7WX6-D-sPmxYW.js.gz +0 -0
- package/out/renderer/assets/{chunk-QZHKN3VN-DkqKjktH.js → chunk-QZHKN3VN-Pdv-mSqK.js} +1 -1
- package/out/renderer/assets/{chunk-YZCP3GAM-CJK_tBTq.js → chunk-YZCP3GAM-DLpllNY2.js} +1 -1
- package/out/renderer/assets/chunk-YZCP3GAM-DLpllNY2.js.br +0 -0
- package/out/renderer/assets/chunk-YZCP3GAM-DLpllNY2.js.gz +0 -0
- package/out/renderer/assets/{circle-x-C9_Yp0Tg.js → circle-x-Cs_T6g0B.js} +1 -1
- package/out/renderer/assets/{classDiagram-v2-HSJHXN6E-Bf4To0VI.js → classDiagram-6PBFFD2Q-BQx6mUfF.js} +7 -7
- package/out/renderer/assets/{classDiagram-6PBFFD2Q-Bf4To0VI.js → classDiagram-v2-HSJHXN6E-BQx6mUfF.js} +7 -7
- package/out/renderer/assets/{clone-Ci5J50Pn.js → clone-DsYDv_WX.js} +1 -1
- package/out/renderer/assets/{code-editor-BwPwET3m.js → code-editor-Ce-8PAj3.js} +2 -2
- package/out/renderer/assets/code-editor-Ce-8PAj3.js.br +0 -0
- package/out/renderer/assets/code-editor-Ce-8PAj3.js.gz +0 -0
- package/out/renderer/assets/{collapsible-CMQ8h8ID.js → collapsible-CKgHeKAs.js} +1 -1
- package/out/renderer/assets/collapsible-CKgHeKAs.js.br +0 -0
- package/out/renderer/assets/collapsible-CKgHeKAs.js.gz +0 -0
- package/out/renderer/assets/{command-nKlwdb6i.js → command-Cgkdasyl.js} +1 -1
- package/out/renderer/assets/{cose-bilkent-S5V4N54A-BZpcn2q9.js → cose-bilkent-S5V4N54A-hNCr9Ibx.js} +2 -2
- package/out/renderer/assets/cose-bilkent-S5V4N54A-hNCr9Ibx.js.br +0 -0
- package/out/renderer/assets/cose-bilkent-S5V4N54A-hNCr9Ibx.js.gz +0 -0
- package/out/renderer/assets/{dagre-KV5264BT-onHZodsn.js → dagre-KV5264BT-CGyBht8M.js} +7 -7
- package/out/renderer/assets/dagre-KV5264BT-CGyBht8M.js.br +0 -0
- package/out/renderer/assets/dagre-KV5264BT-CGyBht8M.js.gz +0 -0
- package/out/renderer/assets/{diagram-5BDNPKRD-y3QVYwp7.js → diagram-5BDNPKRD-BiZfiCzA.js} +7 -7
- package/out/renderer/assets/diagram-5BDNPKRD-BiZfiCzA.js.br +0 -0
- package/out/renderer/assets/diagram-5BDNPKRD-BiZfiCzA.js.gz +0 -0
- package/out/renderer/assets/{diagram-G4DWMVQ6-LB3RUjrJ.js → diagram-G4DWMVQ6-CWj4c_xE.js} +7 -7
- package/out/renderer/assets/diagram-G4DWMVQ6-CWj4c_xE.js.br +0 -0
- package/out/renderer/assets/diagram-G4DWMVQ6-CWj4c_xE.js.gz +0 -0
- package/out/renderer/assets/{diagram-MMDJMWI5-7NpY26IL.js → diagram-MMDJMWI5-iBnXAZDJ.js} +6 -6
- package/out/renderer/assets/diagram-MMDJMWI5-iBnXAZDJ.js.br +0 -0
- package/out/renderer/assets/diagram-MMDJMWI5-iBnXAZDJ.js.gz +0 -0
- package/out/renderer/assets/{diagram-TYMM5635-DRM1RRr4.js → diagram-TYMM5635-C7IGtL42.js} +6 -6
- package/out/renderer/assets/diagram-TYMM5635-C7IGtL42.js.br +0 -0
- package/out/renderer/assets/diagram-TYMM5635-C7IGtL42.js.gz +0 -0
- package/out/renderer/assets/{ellipsis-D_eCkauJ.js → ellipsis-DSui0Rae.js} +1 -1
- package/out/renderer/assets/{erDiagram-SMLLAGMA-DNIZ639C.js → erDiagram-SMLLAGMA-ChPUl_x9.js} +5 -5
- package/out/renderer/assets/erDiagram-SMLLAGMA-ChPUl_x9.js.br +0 -0
- package/out/renderer/assets/erDiagram-SMLLAGMA-ChPUl_x9.js.gz +0 -0
- package/out/renderer/assets/external-link-CoW4VuI3.js +15 -0
- package/out/renderer/assets/{field-YZTi9Jxc.js → field-CXofwfDF.js} +1 -1
- package/out/renderer/assets/field-CXofwfDF.js.br +0 -0
- package/out/renderer/assets/field-CXofwfDF.js.gz +0 -0
- package/out/renderer/assets/{file-text-DDtS1g4Q.js → file-text-CwFSQGtt.js} +1 -1
- package/out/renderer/assets/{flowDiagram-DWJPFMVM-C0ghMibN.js → flowDiagram-DWJPFMVM-C5Zt4Sfn.js} +7 -7
- package/out/renderer/assets/flowDiagram-DWJPFMVM-C5Zt4Sfn.js.br +0 -0
- package/out/renderer/assets/flowDiagram-DWJPFMVM-C5Zt4Sfn.js.gz +0 -0
- package/out/renderer/assets/{ganttDiagram-T4ZO3ILL-tqeHqMu4.js → ganttDiagram-T4ZO3ILL-Cp30RG1g.js} +3 -3
- package/out/renderer/assets/ganttDiagram-T4ZO3ILL-Cp30RG1g.js.br +0 -0
- package/out/renderer/assets/ganttDiagram-T4ZO3ILL-Cp30RG1g.js.gz +0 -0
- package/out/renderer/assets/{gitGraphDiagram-UUTBAWPF-D6acFhfE.js → gitGraphDiagram-UUTBAWPF-CkfzOUvM.js} +7 -7
- package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-CkfzOUvM.js.br +0 -0
- package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-CkfzOUvM.js.gz +0 -0
- package/out/renderer/assets/{graph-DqFGMaSz.js → graph-HfEt9-p2.js} +2 -2
- package/out/renderer/assets/graph-HfEt9-p2.js.br +0 -0
- package/out/renderer/assets/graph-HfEt9-p2.js.gz +0 -0
- package/out/renderer/assets/{highlighted-body-KPVGNVTW-D2IZ7Enb.js → highlighted-body-KPVGNVTW-CUokS6r6.js} +2 -2
- package/out/renderer/assets/index-Byirxhp5.css +382 -0
- package/out/renderer/assets/index-Byirxhp5.css.br +0 -0
- package/out/renderer/assets/index-Byirxhp5.css.gz +0 -0
- package/out/renderer/assets/{index-BeEZXfJZ.js → index-CKDwIiIb.js} +2277 -923
- package/out/renderer/assets/index-CKDwIiIb.js.br +0 -0
- package/out/renderer/assets/index-CKDwIiIb.js.gz +0 -0
- package/out/renderer/assets/{infoDiagram-42DDH7IO-BJeydI3V.js → infoDiagram-42DDH7IO-DbQvToBf.js} +5 -5
- package/out/renderer/assets/infoDiagram-42DDH7IO-DbQvToBf.js.br +0 -0
- package/out/renderer/assets/infoDiagram-42DDH7IO-DbQvToBf.js.gz +0 -0
- package/out/renderer/assets/{ishikawaDiagram-UXIWVN3A-DPgToD8D.js → ishikawaDiagram-UXIWVN3A-Crmx2UcL.js} +2 -2
- package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-Crmx2UcL.js.br +0 -0
- package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-Crmx2UcL.js.gz +0 -0
- package/out/renderer/assets/{item-SQsw2AyN.js → item-2gdt65LZ.js} +1 -1
- package/out/renderer/assets/item-2gdt65LZ.js.br +0 -0
- package/out/renderer/assets/item-2gdt65LZ.js.gz +0 -0
- package/out/renderer/assets/{journeyDiagram-VCZTEJTY-CAnZXd__.js → journeyDiagram-VCZTEJTY-BD3MzoDm.js} +5 -5
- package/out/renderer/assets/journeyDiagram-VCZTEJTY-BD3MzoDm.js.br +0 -0
- package/out/renderer/assets/journeyDiagram-VCZTEJTY-BD3MzoDm.js.gz +0 -0
- package/out/renderer/assets/{kanban-definition-6JOO6SKY-VCfgwCTi.js → kanban-definition-6JOO6SKY-DlPWdcq8.js} +3 -3
- package/out/renderer/assets/kanban-definition-6JOO6SKY-DlPWdcq8.js.br +0 -0
- package/out/renderer/assets/kanban-definition-6JOO6SKY-DlPWdcq8.js.gz +0 -0
- package/out/renderer/assets/keyboard-BmncEbVT.js +21 -0
- package/out/renderer/assets/{layout-lw2KhCMB.js → layout-OHsAY-70.js} +4 -4
- package/out/renderer/assets/layout-OHsAY-70.js.br +0 -0
- package/out/renderer/assets/layout-OHsAY-70.js.gz +0 -0
- package/out/renderer/assets/{linear-DmbMR7a-.js → linear-CnBTAk2r.js} +1 -1
- package/out/renderer/assets/linear-CnBTAk2r.js.br +0 -0
- package/out/renderer/assets/linear-CnBTAk2r.js.gz +0 -0
- package/out/renderer/assets/{link-2-CWpGKoWR.js → link-2-CABYiITN.js} +3 -15
- package/out/renderer/assets/{mermaid-HWGCJPDP-BufLuIVq.js → mermaid-HWGCJPDP-OB5tfzeR.js} +58 -54
- package/out/renderer/assets/mermaid-HWGCJPDP-OB5tfzeR.js.br +0 -0
- package/out/renderer/assets/mermaid-HWGCJPDP-OB5tfzeR.js.gz +0 -0
- package/out/renderer/assets/{mic-UZHvCQhw.js → mic-Bu7eaTKt.js} +1 -1
- package/out/renderer/assets/{min-BCqStlR1.js → min-lM3sC06g.js} +2 -2
- package/out/renderer/assets/min-lM3sC06g.js.br +0 -0
- package/out/renderer/assets/min-lM3sC06g.js.gz +0 -0
- package/out/renderer/assets/{mindmap-definition-QFDTVHPH-C0dBO3f9.js → mindmap-definition-QFDTVHPH-2KHTVjBe.js} +4 -4
- package/out/renderer/assets/mindmap-definition-QFDTVHPH-2KHTVjBe.js.br +0 -0
- package/out/renderer/assets/mindmap-definition-QFDTVHPH-2KHTVjBe.js.gz +0 -0
- package/out/renderer/assets/{open-guide-CWoE2W97.js → open-guide-CKryRC5n.js} +1 -1
- package/out/renderer/assets/{package-search-SZPcR_1L.js → package-search-DPG91yZB.js} +1 -1
- package/out/renderer/assets/{pieDiagram-DEJITSTG-Dv_tH6Z_.js → pieDiagram-DEJITSTG-CWRoGvfQ.js} +7 -7
- package/out/renderer/assets/pieDiagram-DEJITSTG-CWRoGvfQ.js.br +0 -0
- package/out/renderer/assets/pieDiagram-DEJITSTG-CWRoGvfQ.js.gz +0 -0
- package/out/renderer/assets/{plus-BZ0wwKkh.js → plus-CFoa8VhI.js} +1 -1
- package/out/renderer/assets/{quadrantDiagram-34T5L4WZ-Cvsj5cyu.js → quadrantDiagram-34T5L4WZ-BJVP6FPm.js} +3 -3
- package/out/renderer/assets/quadrantDiagram-34T5L4WZ-BJVP6FPm.js.br +0 -0
- package/out/renderer/assets/quadrantDiagram-34T5L4WZ-BJVP6FPm.js.gz +0 -0
- package/out/renderer/assets/{requirementDiagram-MS252O5E-CxM7H308.js → requirementDiagram-MS252O5E-_MTj_l0V.js} +4 -4
- package/out/renderer/assets/requirementDiagram-MS252O5E-_MTj_l0V.js.br +0 -0
- package/out/renderer/assets/requirementDiagram-MS252O5E-_MTj_l0V.js.gz +0 -0
- package/out/renderer/assets/{resizable-DD8ADhVy.js → resizable-CcCcCDAN.js} +1 -1
- package/out/renderer/assets/resizable-CcCcCDAN.js.br +0 -0
- package/out/renderer/assets/resizable-CcCcCDAN.js.gz +0 -0
- package/out/renderer/assets/{sankeyDiagram-XADWPNL6-BGTOA6ee.js → sankeyDiagram-XADWPNL6-BWkr3adU.js} +2 -2
- package/out/renderer/assets/sankeyDiagram-XADWPNL6-BWkr3adU.js.br +0 -0
- package/out/renderer/assets/sankeyDiagram-XADWPNL6-BWkr3adU.js.gz +0 -0
- package/out/renderer/assets/{schedule-DMyyz9A1.js → schedule-H1BEvD9Q.js} +24 -11
- package/out/renderer/assets/schedule-H1BEvD9Q.js.br +0 -0
- package/out/renderer/assets/schedule-H1BEvD9Q.js.gz +0 -0
- package/out/renderer/assets/{search-XexOgLud.js → search-B3aFhEKs.js} +1 -1
- package/out/renderer/assets/{sequenceDiagram-FGHM5R23-DezlXo1X.js → sequenceDiagram-FGHM5R23-CfRs3_Dx.js} +4 -4
- package/out/renderer/assets/sequenceDiagram-FGHM5R23-CfRs3_Dx.js.br +0 -0
- package/out/renderer/assets/sequenceDiagram-FGHM5R23-CfRs3_Dx.js.gz +0 -0
- package/out/renderer/assets/{session-DQEqHTKb.js → session-D6NE3yNE.js} +2327 -2791
- package/out/renderer/assets/session-D6NE3yNE.js.br +0 -0
- package/out/renderer/assets/session-D6NE3yNE.js.gz +0 -0
- package/out/renderer/assets/setting-dialog-CANlzubW.js +5086 -0
- package/out/renderer/assets/setting-dialog-CANlzubW.js.br +0 -0
- package/out/renderer/assets/setting-dialog-CANlzubW.js.gz +0 -0
- package/out/renderer/assets/{settings-agents-f3HkdiTw.js → settings-agents-DxIwcY7M.js} +12 -12
- package/out/renderer/assets/settings-agents-DxIwcY7M.js.br +0 -0
- package/out/renderer/assets/settings-agents-DxIwcY7M.js.gz +0 -0
- package/out/renderer/assets/settings-general-B85uTAij.js +624 -0
- package/out/renderer/assets/settings-general-B85uTAij.js.br +0 -0
- package/out/renderer/assets/settings-general-B85uTAij.js.gz +0 -0
- package/out/renderer/assets/{settings-ilink-Da336Koc.js → settings-ilink-BgeA04Nv.js} +51 -20
- package/out/renderer/assets/settings-ilink-BgeA04Nv.js.br +0 -0
- package/out/renderer/assets/settings-ilink-BgeA04Nv.js.gz +0 -0
- package/out/renderer/assets/{settings-image-generation-RmWs73ZG.js → settings-image-generation-CsWv4wXY.js} +6 -6
- package/out/renderer/assets/settings-image-generation-CsWv4wXY.js.br +0 -0
- package/out/renderer/assets/settings-image-generation-CsWv4wXY.js.gz +0 -0
- package/out/renderer/assets/{settings-layout-DL6ZEzgP.js → settings-layout-DJbT4rIH.js} +32 -7
- package/out/renderer/assets/settings-layout-DJbT4rIH.js.br +0 -0
- package/out/renderer/assets/settings-layout-DJbT4rIH.js.gz +0 -0
- package/out/renderer/assets/{settings-mcp-BKW8JKtO.js → settings-mcp-Cz6GMogp.js} +97 -29
- package/out/renderer/assets/settings-mcp-Cz6GMogp.js.br +0 -0
- package/out/renderer/assets/settings-mcp-Cz6GMogp.js.gz +0 -0
- package/out/renderer/assets/{settings-memory-o4r-_vob.js → settings-memory-Cidr_Ghw.js} +2 -2
- package/out/renderer/assets/settings-memory-Cidr_Ghw.js.br +0 -0
- package/out/renderer/assets/settings-memory-Cidr_Ghw.js.gz +0 -0
- package/out/renderer/assets/settings-peripherals-DilwOpyO.js +269 -0
- package/out/renderer/assets/settings-peripherals-DilwOpyO.js.br +0 -0
- package/out/renderer/assets/settings-peripherals-DilwOpyO.js.gz +0 -0
- package/out/renderer/assets/{settings-shortcuts-BmUGS1q_.js → settings-shortcuts-dWdRCFxB.js} +16 -6
- package/out/renderer/assets/settings-shortcuts-dWdRCFxB.js.br +0 -0
- package/out/renderer/assets/settings-shortcuts-dWdRCFxB.js.gz +0 -0
- package/out/renderer/assets/{settings-snippets-CpAOJmDF.js → settings-snippets-CrtJYwLV.js} +9 -9
- package/out/renderer/assets/settings-snippets-CrtJYwLV.js.br +0 -0
- package/out/renderer/assets/settings-snippets-CrtJYwLV.js.gz +0 -0
- package/out/renderer/assets/settings-speech-CteE8F4J.js +1369 -0
- package/out/renderer/assets/settings-speech-CteE8F4J.js.br +0 -0
- package/out/renderer/assets/settings-speech-CteE8F4J.js.gz +0 -0
- package/out/renderer/assets/{settings-webui-DIEKvTrI.js → settings-webui-DKiOzDSD.js} +3 -3
- package/out/renderer/assets/settings-webui-DKiOzDSD.js.br +0 -0
- package/out/renderer/assets/settings-webui-DKiOzDSD.js.gz +0 -0
- package/out/renderer/assets/{skills-installed-BuWBDk6r.js → skills-installed-Beqe9G7p.js} +4 -4
- package/out/renderer/assets/skills-installed-Beqe9G7p.js.br +0 -0
- package/out/renderer/assets/skills-installed-Beqe9G7p.js.gz +0 -0
- package/out/renderer/assets/{skills-layout-ByPhfHG6.js → skills-layout-BAzfcnkT.js} +2 -2
- package/out/renderer/assets/skills-layout-BAzfcnkT.js.br +0 -0
- package/out/renderer/assets/skills-layout-BAzfcnkT.js.gz +0 -0
- package/out/renderer/assets/{skills-skills-sh-wR7YNmAJ.js → skills-skills-sh-Dzocqfu4.js} +4 -4
- package/out/renderer/assets/skills-skills-sh-Dzocqfu4.js.br +0 -0
- package/out/renderer/assets/skills-skills-sh-Dzocqfu4.js.gz +0 -0
- package/out/renderer/assets/{settings-general-BcCOVmx3.js → slider-DEK94SlL.js} +4 -623
- package/out/renderer/assets/slider-DEK94SlL.js.br +0 -0
- package/out/renderer/assets/slider-DEK94SlL.js.gz +0 -0
- package/out/renderer/assets/{sortable.esm-BWvT9HIK.js → sortable.esm-Cm4rqFU7.js} +1 -1
- package/out/renderer/assets/sortable.esm-Cm4rqFU7.js.br +0 -0
- package/out/renderer/assets/sortable.esm-Cm4rqFU7.js.gz +0 -0
- package/out/renderer/assets/{standard-schema-BkTVIf7N.js → standard-schema-B43ZsT5c.js} +52 -1
- package/out/renderer/assets/standard-schema-B43ZsT5c.js.br +0 -0
- package/out/renderer/assets/standard-schema-B43ZsT5c.js.gz +0 -0
- package/out/renderer/assets/{stateDiagram-FHFEXIEX-xdKKCs-p.js → stateDiagram-FHFEXIEX-CaiRC_NA.js} +9 -9
- package/out/renderer/assets/stateDiagram-FHFEXIEX-CaiRC_NA.js.br +0 -0
- package/out/renderer/assets/stateDiagram-FHFEXIEX-CaiRC_NA.js.gz +0 -0
- package/out/renderer/assets/{stateDiagram-v2-QKLJ7IA2-BaaiQ6Kr.js → stateDiagram-v2-QKLJ7IA2-EA3ViVW-.js} +5 -5
- package/out/renderer/assets/{task-PHAOSE-W.js → task-DM-bWOFz.js} +13 -11
- package/out/renderer/assets/task-DM-bWOFz.js.br +0 -0
- package/out/renderer/assets/task-DM-bWOFz.js.gz +0 -0
- package/out/renderer/assets/{textarea-1ZWl3C-x.js → textarea-B0OAhnF7.js} +1 -1
- package/out/renderer/assets/{timeline-definition-GMOUNBTQ-DFLeLybV.js → timeline-definition-GMOUNBTQ-D-M9BAZz.js} +3 -3
- package/out/renderer/assets/timeline-definition-GMOUNBTQ-D-M9BAZz.js.br +0 -0
- package/out/renderer/assets/timeline-definition-GMOUNBTQ-D-M9BAZz.js.gz +0 -0
- package/out/renderer/assets/{vennDiagram-DHZGUBPP-PKmZLY7H.js → vennDiagram-DHZGUBPP-B_yjg_0U.js} +2 -2
- package/out/renderer/assets/vennDiagram-DHZGUBPP-B_yjg_0U.js.br +0 -0
- package/out/renderer/assets/vennDiagram-DHZGUBPP-B_yjg_0U.js.gz +0 -0
- package/out/renderer/assets/{wardley-RL74JXVD-BCH2vKnv.js → wardley-RL74JXVD-2Xd7XlwA.js} +4 -4
- package/out/renderer/assets/wardley-RL74JXVD-2Xd7XlwA.js.br +0 -0
- package/out/renderer/assets/wardley-RL74JXVD-2Xd7XlwA.js.gz +0 -0
- package/out/renderer/assets/{wardleyDiagram-NUSXRM2D-Bkd3xMno.js → wardleyDiagram-NUSXRM2D-BA9tzMk-.js} +6 -6
- package/out/renderer/assets/wardleyDiagram-NUSXRM2D-BA9tzMk-.js.br +0 -0
- package/out/renderer/assets/wardleyDiagram-NUSXRM2D-BA9tzMk-.js.gz +0 -0
- package/out/renderer/assets/{wrench-8H0LZ83G.js → wrench-QfEqqx9F.js} +1 -1
- package/out/renderer/assets/wrench-QfEqqx9F.js.br +0 -0
- package/out/renderer/assets/wrench-QfEqqx9F.js.gz +0 -0
- package/out/renderer/assets/{xlsx-view-BYx5Ha2P.js → xlsx-view-Bov2NXsI.js} +141 -79
- package/out/renderer/assets/xlsx-view-Bov2NXsI.js.br +0 -0
- package/out/renderer/assets/xlsx-view-Bov2NXsI.js.gz +0 -0
- package/out/renderer/assets/{xychartDiagram-5P7HB3ND-DCOm4uPr.js → xychartDiagram-5P7HB3ND-svs-11is.js} +3 -3
- package/out/renderer/assets/xychartDiagram-5P7HB3ND-svs-11is.js.br +0 -0
- package/out/renderer/assets/xychartDiagram-5P7HB3ND-svs-11is.js.gz +0 -0
- package/out/renderer/index.html +2 -2
- package/out/renderer/index.html.br +0 -0
- package/out/renderer/index.html.gz +0 -0
- package/out/scripts/mcp-toolbox/server.mjs +80 -1
- package/out/server/main.js +1576 -353
- package/package.json +3 -2
- package/out/renderer/assets/_baseUniq-BdLqGxOi.js.br +0 -0
- package/out/renderer/assets/_baseUniq-BdLqGxOi.js.gz +0 -0
- package/out/renderer/assets/arc-UpL8po5R.js.br +0 -0
- package/out/renderer/assets/arc-UpL8po5R.js.gz +0 -0
- package/out/renderer/assets/architectureDiagram-Q4EWVU46-ManEkEbl.js.br +0 -0
- package/out/renderer/assets/architectureDiagram-Q4EWVU46-ManEkEbl.js.gz +0 -0
- package/out/renderer/assets/automation-cVl19jbl.js.br +0 -0
- package/out/renderer/assets/automation-cVl19jbl.js.gz +0 -0
- package/out/renderer/assets/blockDiagram-DXYQGD6D-B7n8X8F6.js.br +0 -0
- package/out/renderer/assets/blockDiagram-DXYQGD6D-B7n8X8F6.js.gz +0 -0
- package/out/renderer/assets/c4Diagram-AHTNJAMY-BoP_JNY0.js.br +0 -0
- package/out/renderer/assets/c4Diagram-AHTNJAMY-BoP_JNY0.js.gz +0 -0
- package/out/renderer/assets/chunk-4TB4RGXK-B2HhnMqB.js.br +0 -0
- package/out/renderer/assets/chunk-4TB4RGXK-B2HhnMqB.js.gz +0 -0
- package/out/renderer/assets/chunk-EDXVE4YY-Xfghcg7b.js.br +0 -0
- package/out/renderer/assets/chunk-EDXVE4YY-Xfghcg7b.js.gz +0 -0
- package/out/renderer/assets/chunk-OYMX7WX6-Cv4jgShd.js.br +0 -0
- package/out/renderer/assets/chunk-OYMX7WX6-Cv4jgShd.js.gz +0 -0
- package/out/renderer/assets/chunk-YZCP3GAM-CJK_tBTq.js.br +0 -0
- package/out/renderer/assets/chunk-YZCP3GAM-CJK_tBTq.js.gz +0 -0
- package/out/renderer/assets/code-editor-BwPwET3m.js.br +0 -0
- package/out/renderer/assets/code-editor-BwPwET3m.js.gz +0 -0
- package/out/renderer/assets/collapsible-CMQ8h8ID.js.br +0 -0
- package/out/renderer/assets/collapsible-CMQ8h8ID.js.gz +0 -0
- package/out/renderer/assets/cose-bilkent-S5V4N54A-BZpcn2q9.js.br +0 -0
- package/out/renderer/assets/cose-bilkent-S5V4N54A-BZpcn2q9.js.gz +0 -0
- package/out/renderer/assets/dagre-KV5264BT-onHZodsn.js.br +0 -0
- package/out/renderer/assets/dagre-KV5264BT-onHZodsn.js.gz +0 -0
- package/out/renderer/assets/diagram-5BDNPKRD-y3QVYwp7.js.br +0 -0
- package/out/renderer/assets/diagram-5BDNPKRD-y3QVYwp7.js.gz +0 -0
- package/out/renderer/assets/diagram-G4DWMVQ6-LB3RUjrJ.js.br +0 -0
- package/out/renderer/assets/diagram-G4DWMVQ6-LB3RUjrJ.js.gz +0 -0
- package/out/renderer/assets/diagram-MMDJMWI5-7NpY26IL.js.br +0 -0
- package/out/renderer/assets/diagram-MMDJMWI5-7NpY26IL.js.gz +0 -0
- package/out/renderer/assets/diagram-TYMM5635-DRM1RRr4.js.br +0 -0
- package/out/renderer/assets/diagram-TYMM5635-DRM1RRr4.js.gz +0 -0
- package/out/renderer/assets/erDiagram-SMLLAGMA-DNIZ639C.js.br +0 -0
- package/out/renderer/assets/erDiagram-SMLLAGMA-DNIZ639C.js.gz +0 -0
- package/out/renderer/assets/field-YZTi9Jxc.js.br +0 -0
- package/out/renderer/assets/field-YZTi9Jxc.js.gz +0 -0
- package/out/renderer/assets/flowDiagram-DWJPFMVM-C0ghMibN.js.br +0 -0
- package/out/renderer/assets/flowDiagram-DWJPFMVM-C0ghMibN.js.gz +0 -0
- package/out/renderer/assets/ganttDiagram-T4ZO3ILL-tqeHqMu4.js.br +0 -0
- package/out/renderer/assets/ganttDiagram-T4ZO3ILL-tqeHqMu4.js.gz +0 -0
- package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-D6acFhfE.js.br +0 -0
- package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-D6acFhfE.js.gz +0 -0
- package/out/renderer/assets/graph-DqFGMaSz.js.br +0 -0
- package/out/renderer/assets/graph-DqFGMaSz.js.gz +0 -0
- package/out/renderer/assets/index-BZTYKZe8.css +0 -382
- package/out/renderer/assets/index-BZTYKZe8.css.br +0 -0
- package/out/renderer/assets/index-BZTYKZe8.css.gz +0 -0
- package/out/renderer/assets/index-BeEZXfJZ.js.br +0 -0
- package/out/renderer/assets/index-BeEZXfJZ.js.gz +0 -0
- package/out/renderer/assets/infoDiagram-42DDH7IO-BJeydI3V.js.br +0 -0
- package/out/renderer/assets/infoDiagram-42DDH7IO-BJeydI3V.js.gz +0 -0
- package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-DPgToD8D.js.br +0 -0
- package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-DPgToD8D.js.gz +0 -0
- package/out/renderer/assets/item-SQsw2AyN.js.br +0 -0
- package/out/renderer/assets/item-SQsw2AyN.js.gz +0 -0
- package/out/renderer/assets/journeyDiagram-VCZTEJTY-CAnZXd__.js.br +0 -0
- package/out/renderer/assets/journeyDiagram-VCZTEJTY-CAnZXd__.js.gz +0 -0
- package/out/renderer/assets/kanban-definition-6JOO6SKY-VCfgwCTi.js.br +0 -0
- package/out/renderer/assets/kanban-definition-6JOO6SKY-VCfgwCTi.js.gz +0 -0
- package/out/renderer/assets/layout-lw2KhCMB.js.br +0 -0
- package/out/renderer/assets/layout-lw2KhCMB.js.gz +0 -0
- package/out/renderer/assets/linear-DmbMR7a-.js.br +0 -0
- package/out/renderer/assets/linear-DmbMR7a-.js.gz +0 -0
- package/out/renderer/assets/link-2-CWpGKoWR.js.br +0 -0
- package/out/renderer/assets/link-2-CWpGKoWR.js.gz +0 -0
- package/out/renderer/assets/mermaid-HWGCJPDP-BufLuIVq.js.br +0 -0
- package/out/renderer/assets/mermaid-HWGCJPDP-BufLuIVq.js.gz +0 -0
- package/out/renderer/assets/min-BCqStlR1.js.br +0 -0
- package/out/renderer/assets/min-BCqStlR1.js.gz +0 -0
- package/out/renderer/assets/mindmap-definition-QFDTVHPH-C0dBO3f9.js.br +0 -0
- package/out/renderer/assets/mindmap-definition-QFDTVHPH-C0dBO3f9.js.gz +0 -0
- package/out/renderer/assets/pieDiagram-DEJITSTG-Dv_tH6Z_.js.br +0 -0
- package/out/renderer/assets/pieDiagram-DEJITSTG-Dv_tH6Z_.js.gz +0 -0
- package/out/renderer/assets/quadrantDiagram-34T5L4WZ-Cvsj5cyu.js.br +0 -0
- package/out/renderer/assets/quadrantDiagram-34T5L4WZ-Cvsj5cyu.js.gz +0 -0
- package/out/renderer/assets/requirementDiagram-MS252O5E-CxM7H308.js.br +0 -0
- package/out/renderer/assets/requirementDiagram-MS252O5E-CxM7H308.js.gz +0 -0
- package/out/renderer/assets/resizable-DD8ADhVy.js.br +0 -0
- package/out/renderer/assets/resizable-DD8ADhVy.js.gz +0 -0
- package/out/renderer/assets/sankeyDiagram-XADWPNL6-BGTOA6ee.js.br +0 -0
- package/out/renderer/assets/sankeyDiagram-XADWPNL6-BGTOA6ee.js.gz +0 -0
- package/out/renderer/assets/schedule-DMyyz9A1.js.br +0 -0
- package/out/renderer/assets/schedule-DMyyz9A1.js.gz +0 -0
- package/out/renderer/assets/sequenceDiagram-FGHM5R23-DezlXo1X.js.br +0 -0
- package/out/renderer/assets/sequenceDiagram-FGHM5R23-DezlXo1X.js.gz +0 -0
- package/out/renderer/assets/session-DQEqHTKb.js.br +0 -0
- package/out/renderer/assets/session-DQEqHTKb.js.gz +0 -0
- package/out/renderer/assets/setting-dialog-BdiZbd8J.js +0 -642
- package/out/renderer/assets/setting-dialog-BdiZbd8J.js.br +0 -0
- package/out/renderer/assets/setting-dialog-BdiZbd8J.js.gz +0 -0
- package/out/renderer/assets/settings-2-q22Cv4G7.js +0 -16
- package/out/renderer/assets/settings-agents-f3HkdiTw.js.br +0 -0
- package/out/renderer/assets/settings-agents-f3HkdiTw.js.gz +0 -0
- package/out/renderer/assets/settings-general-BcCOVmx3.js.br +0 -0
- package/out/renderer/assets/settings-general-BcCOVmx3.js.gz +0 -0
- package/out/renderer/assets/settings-ilink-Da336Koc.js.br +0 -0
- package/out/renderer/assets/settings-ilink-Da336Koc.js.gz +0 -0
- package/out/renderer/assets/settings-image-generation-RmWs73ZG.js.br +0 -0
- package/out/renderer/assets/settings-image-generation-RmWs73ZG.js.gz +0 -0
- package/out/renderer/assets/settings-layout-DL6ZEzgP.js.br +0 -0
- package/out/renderer/assets/settings-layout-DL6ZEzgP.js.gz +0 -0
- package/out/renderer/assets/settings-mcp-BKW8JKtO.js.br +0 -0
- package/out/renderer/assets/settings-mcp-BKW8JKtO.js.gz +0 -0
- package/out/renderer/assets/settings-memory-o4r-_vob.js.br +0 -0
- package/out/renderer/assets/settings-memory-o4r-_vob.js.gz +0 -0
- package/out/renderer/assets/settings-shortcuts-BmUGS1q_.js.br +0 -0
- package/out/renderer/assets/settings-shortcuts-BmUGS1q_.js.gz +0 -0
- package/out/renderer/assets/settings-snippets-CpAOJmDF.js.br +0 -0
- package/out/renderer/assets/settings-snippets-CpAOJmDF.js.gz +0 -0
- package/out/renderer/assets/settings-speech-to-text-C8KHNGE4.js +0 -1054
- package/out/renderer/assets/settings-speech-to-text-C8KHNGE4.js.br +0 -0
- package/out/renderer/assets/settings-speech-to-text-C8KHNGE4.js.gz +0 -0
- package/out/renderer/assets/settings-webui-DIEKvTrI.js.br +0 -0
- package/out/renderer/assets/settings-webui-DIEKvTrI.js.gz +0 -0
- package/out/renderer/assets/skills-installed-BuWBDk6r.js.br +0 -0
- package/out/renderer/assets/skills-installed-BuWBDk6r.js.gz +0 -0
- package/out/renderer/assets/skills-layout-ByPhfHG6.js.br +0 -0
- package/out/renderer/assets/skills-layout-ByPhfHG6.js.gz +0 -0
- package/out/renderer/assets/skills-skills-sh-wR7YNmAJ.js.br +0 -0
- package/out/renderer/assets/skills-skills-sh-wR7YNmAJ.js.gz +0 -0
- package/out/renderer/assets/sortable.esm-BWvT9HIK.js.br +0 -0
- package/out/renderer/assets/sortable.esm-BWvT9HIK.js.gz +0 -0
- package/out/renderer/assets/standard-schema-BkTVIf7N.js.br +0 -0
- package/out/renderer/assets/standard-schema-BkTVIf7N.js.gz +0 -0
- package/out/renderer/assets/stateDiagram-FHFEXIEX-xdKKCs-p.js.br +0 -0
- package/out/renderer/assets/stateDiagram-FHFEXIEX-xdKKCs-p.js.gz +0 -0
- package/out/renderer/assets/task-PHAOSE-W.js.br +0 -0
- package/out/renderer/assets/task-PHAOSE-W.js.gz +0 -0
- package/out/renderer/assets/timeline-definition-GMOUNBTQ-DFLeLybV.js.br +0 -0
- package/out/renderer/assets/timeline-definition-GMOUNBTQ-DFLeLybV.js.gz +0 -0
- package/out/renderer/assets/vennDiagram-DHZGUBPP-PKmZLY7H.js.br +0 -0
- package/out/renderer/assets/vennDiagram-DHZGUBPP-PKmZLY7H.js.gz +0 -0
- package/out/renderer/assets/wardley-RL74JXVD-BCH2vKnv.js.br +0 -0
- package/out/renderer/assets/wardley-RL74JXVD-BCH2vKnv.js.gz +0 -0
- package/out/renderer/assets/wardleyDiagram-NUSXRM2D-Bkd3xMno.js.br +0 -0
- package/out/renderer/assets/wardleyDiagram-NUSXRM2D-Bkd3xMno.js.gz +0 -0
- package/out/renderer/assets/wrench-8H0LZ83G.js.br +0 -0
- package/out/renderer/assets/wrench-8H0LZ83G.js.gz +0 -0
- package/out/renderer/assets/xlsx-view-BYx5Ha2P.js.br +0 -0
- package/out/renderer/assets/xlsx-view-BYx5Ha2P.js.gz +0 -0
- package/out/renderer/assets/xychartDiagram-5P7HB3ND-DCOm4uPr.js.br +0 -0
- package/out/renderer/assets/xychartDiagram-5P7HB3ND-DCOm4uPr.js.gz +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./session-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./session-D6NE3yNE.js","./slider-DEK94SlL.js","./PopoverPopup-BcHY-oda.js","./xlsx-view-Bov2NXsI.js","./mermaid-HWGCJPDP-OB5tfzeR.js","./collapsible-CKgHeKAs.js","./item-2gdt65LZ.js","./file-text-CwFSQGtt.js","./link-2-CABYiITN.js","./external-link-CoW4VuI3.js","./search-B3aFhEKs.js","./schemas-BL-_QQNp.js","./wrench-QfEqqx9F.js","./ellipsis-DSui0Rae.js","./xlsx-view-CylPXjk8.css","./arrow-up-D7cOrlYE.js","./mic-Bu7eaTKt.js","./keyboard-BmncEbVT.js","./arrow-left-Ck_ZVJr5.js","./plus-CFoa8VhI.js","./resizable-CcCcCDAN.js","./settings-layout-DJbT4rIH.js","./command-Cgkdasyl.js","./settings-general-B85uTAij.js","./field-CXofwfDF.js","./settings-shortcuts-dWdRCFxB.js","./settings-agents-DxIwcY7M.js","./open-guide-CKryRC5n.js","./sortable.esm-Cm4rqFU7.js","./standard-schema-B43ZsT5c.js","./textarea-B0OAhnF7.js","./circle-x-Cs_T6g0B.js","./settings-mcp-Cz6GMogp.js","./settings-webui-DKiOzDSD.js","./settings-ilink-BgeA04Nv.js","./settings-snippets-CrtJYwLV.js","./settings-memory-Cidr_Ghw.js","./settings-image-generation-CsWv4wXY.js","./settings-speech-CteE8F4J.js","./settings-peripherals-DilwOpyO.js","./skills-layout-BAzfcnkT.js","./package-search-DPG91yZB.js","./skills-installed-Beqe9G7p.js","./skills-skills-sh-Dzocqfu4.js","./automation-W30eYgU8.js","./setting-dialog-CANlzubW.js","./schedule-H1BEvD9Q.js","./task-DM-bWOFz.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
function _mergeNamespaces(n, m) {
|
|
3
3
|
for (var i = 0; i < m.length; i++) {
|
|
4
4
|
const e = m[i];
|
|
@@ -14969,7 +14969,7 @@ var Immer2 = class {
|
|
|
14969
14969
|
if (!isDraftable(base))
|
|
14970
14970
|
die(8);
|
|
14971
14971
|
if (isDraft(base))
|
|
14972
|
-
base = current(base);
|
|
14972
|
+
base = current$1(base);
|
|
14973
14973
|
const scope = enterScope(this);
|
|
14974
14974
|
const proxy = createProxy$1(scope, base, void 0);
|
|
14975
14975
|
proxy[DRAFT_STATE].isManual_ = true;
|
|
@@ -15053,7 +15053,7 @@ function createProxy$1(rootScope, value, parent, key) {
|
|
|
15053
15053
|
}
|
|
15054
15054
|
return draft;
|
|
15055
15055
|
}
|
|
15056
|
-
function current(value) {
|
|
15056
|
+
function current$1(value) {
|
|
15057
15057
|
if (!isDraft(value))
|
|
15058
15058
|
die(10, value);
|
|
15059
15059
|
return currentImpl(value);
|
|
@@ -15940,8 +15940,9 @@ const useAppStore = create((set2, get2) => ({
|
|
|
15940
15940
|
voiceInput: { altDoublePress: true },
|
|
15941
15941
|
snippets: [],
|
|
15942
15942
|
imageGeneration: [],
|
|
15943
|
-
|
|
15943
|
+
speechProviders: [],
|
|
15944
15944
|
shortcuts: {},
|
|
15945
|
+
peripherals: [],
|
|
15945
15946
|
webUIStatus: { enabled: false, url: null },
|
|
15946
15947
|
ilinkStatus: { connected: false },
|
|
15947
15948
|
activeIlinkSessionId: null,
|
|
@@ -16076,8 +16077,9 @@ const useAppStore = create((set2, get2) => ({
|
|
|
16076
16077
|
setVoiceInput: (voiceInput) => set2({ voiceInput }),
|
|
16077
16078
|
setSnippets: (snippets) => set2({ snippets }),
|
|
16078
16079
|
setImageGeneration: (imageGeneration2) => set2({ imageGeneration: imageGeneration2 }),
|
|
16079
|
-
|
|
16080
|
+
setSpeechProviders: (speechProviders) => set2({ speechProviders }),
|
|
16080
16081
|
setShortcuts: (shortcuts) => set2({ shortcuts }),
|
|
16082
|
+
setPeripherals: (peripherals) => set2({ peripherals }),
|
|
16081
16083
|
setWebUIStatus: (status) => set2({ webUIStatus: status }),
|
|
16082
16084
|
setIlinkStatus: (status) => set2({ ilinkStatus: status }),
|
|
16083
16085
|
setActiveIlinkSessionId: (sessionId) => set2({ activeIlinkSessionId: sessionId }),
|
|
@@ -18421,7 +18423,7 @@ const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
|
|
18421
18423
|
});
|
|
18422
18424
|
};
|
|
18423
18425
|
const isString = (obj) => typeof obj === "string";
|
|
18424
|
-
const isObject = (obj) => typeof obj === "object" && obj !== null;
|
|
18426
|
+
const isObject$1 = (obj) => typeof obj === "object" && obj !== null;
|
|
18425
18427
|
const matchHtmlEntity = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g;
|
|
18426
18428
|
const htmlEntities = {
|
|
18427
18429
|
"&": "&",
|
|
@@ -18553,7 +18555,7 @@ function requireShim() {
|
|
|
18553
18555
|
var shimExports = requireShim();
|
|
18554
18556
|
const notReadyT = (k2, optsOrDefaultValue) => {
|
|
18555
18557
|
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
18556
|
-
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
18558
|
+
if (isObject$1(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
18557
18559
|
if (typeof k2 === "function") return "";
|
|
18558
18560
|
if (Array.isArray(k2)) {
|
|
18559
18561
|
const last = k2[k2.length - 1];
|
|
@@ -18721,17 +18723,17 @@ const useTranslation = (ns, props = {}) => {
|
|
|
18721
18723
|
}
|
|
18722
18724
|
return ret;
|
|
18723
18725
|
};
|
|
18724
|
-
const sidebar$1 = { "welcome": "Welcome", "skills": "Skills", "automation": "Automation", "projects": "Projects", "noProjects": "No projects yet", "noProjectsHint": "Add a project folder to get started", "addProject": "Add Project", "noAgentsHint": "Configure an agent first", "configureAgent": "Configure Agent", "revealInFinder": "Reveal in Finder", "rename": "Rename", "delete": "Delete", "renameProject": "Rename Project", "renameSession": "Rename Session", "deleteSession": "Delete Session", "enterNewProjectName": "Enter a new project name.", "enterNewSessionName": "Enter a new session name.", "addProjectTitle": "Add Project", "enterProjectPath": "Enter absolute path to project on the server:", "pathCannotBeEmpty": "Path cannot be empty", "webuiEnabled": "WebUI Enabled", "deleteProject": "Delete Project", "deleteProjectConfirm": 'Delete project "{{title}}" and all sessions in it?\nThis action cannot be undone.', "deleteSessionConfirm": 'Delete session "{{title}}"?\nThis action cannot be undone.', "cancel": "Cancel", "save": "Save", "settings": "Settings", "agents": "Agents", "addProjectFailed": "Failed to add project.", "newSessionFailed": "Failed to create a new session.", "loadSessionFailed": "Failed to load session.", "revealInFinderFailed": "Failed to reveal in Finder.", "openInEditorFailed": "Failed to open in editor.", "projectExists": "Project already exists.", "projectNameEmpty": "Project name cannot be empty.", "sessionNameEmpty": "Session name cannot be empty.", "newSession": "New Session", "viewSession": "View Session", "projectActions": "Project actions for {{title}}", "createSessionInProject": "Create session in {{title}}", "sessionActions": "Session actions for {{title}}", "ilinkSetActive": "Set WeChat Active", "ilinkUnsetActive": "Unset WeChat Active", "failedToUpdateIlinkSession": "Failed to update WeChat active session.", "sessionOperationInProgress": "Another session operation is already in progress.", "ilinkActiveStatus": "WeChat Active", "ilinkInactiveStatus": "Not WeChat Active", "restartSession": "Restart Session", "closeSession": "Close Session", "closingSession": "Closing…", "failedToCloseSession": "Failed to close session.", "failedToDeleteSession": "Failed to delete session.", "failedToDeleteProject": "Failed to delete project.", "failedToLoadSession": "Failed to load session.", "failedToUpdateMcpServers": "Failed to update MCP servers", "collapse": "Collapse sidebar", "expand": "Expand sidebar", "updated": "Updated", "created": "Created", "sessionCount": "{{count}} sessions", "sessionCount_one": "{{count}} session", "newSessionDialog": { "title": "Create session", "agent": "Agent", "selectAgent": "Select an agent", "
|
|
18726
|
+
const sidebar$1 = { "welcome": "Welcome", "skills": "Skills", "automation": "Automation", "projects": "Projects", "noProjects": "No projects yet", "noProjectsHint": "Add a project folder to get started", "addProject": "Add Project", "noAgentsHint": "Configure an agent first", "configureAgent": "Configure Agent", "revealInFinder": "Reveal in Finder", "copyProjectPath": "Copy Project Path", "rename": "Rename", "delete": "Delete", "renameProject": "Rename Project", "renameSession": "Rename Session", "deleteSession": "Delete Session", "enterNewProjectName": "Enter a new project name.", "enterNewSessionName": "Enter a new session name.", "addProjectTitle": "Add Project", "enterProjectPath": "Enter absolute path to project on the server:", "pathCannotBeEmpty": "Path cannot be empty", "webuiEnabled": "WebUI Enabled", "deleteProject": "Delete Project", "deleteProjectConfirm": 'Delete project "{{title}}" and all sessions in it?\nThis action cannot be undone.', "deleteSessionConfirm": 'Delete session "{{title}}"?\nThis action cannot be undone.', "cancel": "Cancel", "save": "Save", "settings": "Settings", "agents": "Agents", "addProjectFailed": "Failed to add project.", "dropFolderOnly": "Only folders can be dropped to add a project.", "newSessionFailed": "Failed to create a new session.", "loadSessionFailed": "Failed to load session.", "revealInFinderFailed": "Failed to reveal in Finder.", "openInEditorFailed": "Failed to open in editor.", "projectExists": "Project already exists.", "projectNameEmpty": "Project name cannot be empty.", "sessionNameEmpty": "Session name cannot be empty.", "newSession": "New Session", "viewSession": "View Session", "projectActions": "Project actions for {{title}}", "createSessionInProject": "Create session in {{title}}", "sessionActions": "Session actions for {{title}}", "ilinkSetActive": "Set WeChat Active", "ilinkUnsetActive": "Unset WeChat Active", "failedToUpdateIlinkSession": "Failed to update WeChat active session.", "sessionOperationInProgress": "Another session operation is already in progress.", "ilinkActiveStatus": "WeChat Active", "ilinkInactiveStatus": "Not WeChat Active", "restartSession": "Restart Session", "closeSession": "Close Session", "closingSession": "Closing…", "failedToCloseSession": "Failed to close session.", "failedToDeleteSession": "Failed to delete session.", "failedToDeleteProject": "Failed to delete project.", "failedToLoadSession": "Failed to load session.", "failedToUpdateMcpServers": "Failed to update MCP servers", "collapse": "Collapse sidebar", "expand": "Expand sidebar", "updated": "Updated", "created": "Created", "sessionCount": "{{count}} sessions", "sessionCount_one": "{{count}} session", "newSessionDialog": { "title": "Create session", "agent": "Agent", "selectAgent": "Select an agent", "permission": "Permission", "permissionAsk": "Ask", "permissionAllowAll": "Allow all", "create": "Create" } };
|
|
18725
18727
|
const skills$1 = { "title": "Skills", "installed": { "label": "Installed", "noDescription": "No description provided.", "revealInFinder": "Reveal in Finder", "viewSkill": "View SKILL.md", "uninstall": "Uninstall", "uninstallTitle": "Uninstall Skill", "uninstallConfirm": "Are you sure you want to uninstall {{name}}? ", "cancel": "Cancel", "uninstalledSuccess": "Skill {{name}} uninstalled", "uninstallFailed": "Failed to uninstall: {{message}}", "revealFailed": "Failed to reveal in Finder: {{message}}", "loadFailed": "Failed to load skills", "loadContentFailed": "Error loading skill content: {{message}}", "noSkills": "No skills installed." }, "skillsSh": { "label": "skills.sh", "title": "Discover Skills", "desc": "Explore and install community skills to enhance your agents.", "searchPlaceholder": "Search skills (e.g. pr-review, react-best-practices)...", "install": "Install", "installSuccess": "Skill {{name}} installed", "installFailed": "Install failed", "noResults": "No skills found", "installs": "{{count}} installs", "installedStatus": "Installed", "authorPrefix": "by " } };
|
|
18726
18728
|
const contextMenu$1 = { "cut": "Cut", "copy": "Copy", "paste": "Paste", "selectAll": "Select All" };
|
|
18727
18729
|
const commands$1 = { "focusChatInput": { "title": "Focus chat input", "description": "Move focus to the chat input." }, "focusChatArea": { "title": "Focus chat area", "description": "Move focus to the chat conversation." }, "focusFileTree": { "title": "Focus file tree", "description": "Move focus to the project file tree." }, "focusTerminalList": { "title": "Focus terminal list", "description": "Move focus to the terminal list." }, "focusSidebarSessions": { "title": "Focus session list", "description": "Move focus to the session list." } };
|
|
18728
|
-
const settings$1 = /* @__PURE__ */ JSON.parse(`{"themeDesc":"Customize the appearance of the application","languageDesc":"Select the display language","title":"Settings","general":{"title":"General","desc":"Manage your application settings.","theme":"Theme","light":"Light","dark":"Dark","system":"System","language":"Language","english":"English","chinese":"简体中文","saveThemeFailed":"Failed to save theme setting.","saveLanguageFailed":"Failed to save language setting.","groupAppearance":"Appearance","groupProject":"Project","autoWatchFiles":"Auto Watch Files","autoWatchFilesDesc":"Automatically watch project file changes","saveFileWatcherFailed":"Failed to save file watcher setting.","groupVoiceInput":"Voice Input","altDoublePress":"Double-press Alt","altDoublePressDesc":"Double-press Alt quickly while an input is focused to start or stop voice input.","saveVoiceInputFailed":"Failed to save voice input setting.","groupNetwork":"Network","proxy":"Network Proxy","proxyDesc":"Configure the network proxy used by Fello for Node requests, subprocesses and the UI.","proxyEdit":"Edit proxy settings","proxyOff":"Direct","proxySystem":"System","groupSound":"Sound","soundEnabled":"Sound Effects","soundEnabledDesc":"Play sound effects for notifications","soundVolume":"Volume","soundVolumeDesc":"Adjust notification volume","soundTheme":"Sound Style","soundThemeDesc":"Select the sound effect style","soundSoft":"Soft","soundCrisp":"Crisp","soundTest":"Test","soundTestDesc":"Preview the current sound effect","soundTestPlay":"Play","saveSoundFailed":"Failed to save sound setting.","groupEditor":"Editor","editor":"Open in Editor","editorDesc":"Choose the editor to open files","selectEditor":"Select editor","saveEditorFailed":"Failed to save editor setting."},"shortcuts":{"title":"Shortcuts","desc":"Customize keyboard shortcuts for common actions.","navigation":"Navigation","recording":"Press a shortcut","changeShortcut":"Change shortcut","unassigned":"Unassigned","delete":"Delete","set":"Set","restore":"Restore","setTitle":"Set shortcut","setDesc":"Press the shortcut you want to use.","cancel":"Cancel","confirm":"Confirm","reset":"Reset to default","conflict":"Already used by {{command}}.","saveFailed":"Failed to save shortcuts."},"agents":{"desc":"Manage agent configurations and startup commands.","description":"Configure agents","title":"Agents","guide":"User Guide","addStdioAgent":"Add via ACP Agent","addApiAgent":"Add via API Key","editStdioAgent":"Edit ACP Agent","editApiAgent":"Edit API Agent","dialogDesc":"Configure the agent ID, command, arguments and environment variables.","apiDialogDesc":"Configure provider, endpoint and authentication for API agent.","agentId":"Agent ID (Name)","apiProvider":"Provider","apiBaseUrl":"Base URL","apiKey":"API Key","apiHeaders":"Headers (JSON)","contextWindowTokens":"Context Window (tokens)","modelIdTemplate":"Model Id Template","models":"Models (one per line)","modelsHint":"Usually not needed — models are fetched automatically. Only specify if the API doesn't return the models you need","command":"Command","args":"Arguments","envVars":"Environment Variables (JSON)","envJson":"Environment Variables (JSON)","quickPreset":"Quick preset","cancel":"Cancel","save":"Save","edit":"Edit","delete":"Delete","dragToReorder":"Drag to reorder","noAgents":"No agents configured","errorIdCommand":"ID and Command are required.","errorDuplicateId":"An agent with this ID already exists.","errorEnvJson":"Env must be a valid JSON object.","errorContextWindowTokens":"Context Window must be a positive integer.","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Agent","confirmDeleteDesc":"Are you sure you want to delete this agent? This action cannot be undone.","confirmDeleteDescWithSessions":"Are you sure you want to delete this agent? {{count}} session(s) will also be deleted. This action cannot be undone.","reset":"Reset Agent","resetSuccess":"Agent reset.","resetFailed":"Failed to reset agent.","deleteAllSessions":"Delete All Sessions","confirmDeleteAllSessionsTitle":"Delete All Sessions","confirmDeleteAllSessionsDesc":"All sessions for this agent will be permanently deleted. This action cannot be undone.","deleteAllSessionsSuccess":"{{count}} session(s) deleted.","deleteAllSessionsFailed":"Failed to delete sessions.","validation":{"enterId":"Please enter an agent ID.","idFormat":"Only letters, numbers, _ and - allowed.","selectProvider":"Please select a provider.","enterBaseUrl":"Please enter a base URL.","enterApiKey":"Please enter an API key.","enterCommand":"Please enter a command.","jsonObject":"Must be a valid JSON object with string values.","positiveInteger":"Must be a positive integer."}},"mcp":{"desc":"Manage MCP server configurations and startup commands.","description":"Configure MCP Servers","title":"MCP Servers","guide":"User Guide","addMcp":"Add MCP Server","addStdioMcp":"Add Stdio MCP","addHttpMcp":"Add HTTP MCP","addSseMcp":"Add SSE MCP","recommended":{"exa":{"name":"Exa","desc":"Exa MCP Server — AI Web Search"}},"editMcp":"Edit MCP Server","dialogDesc":"Configure the MCP server ID, command, arguments and environment variables.","mcpId":"MCP Server ID (Name)","command":"Command","args":"Arguments","envVars":"Environment Variables (JSON)","envJson":"Environment Variables (JSON)","url":"URL","headers":"Headers (JSON)","headersJson":"Headers (JSON)","httpDialogDesc":"Configure the MCP server ID, HTTP URL and request headers.","sseDialogDesc":"Configure the MCP server ID, SSE endpoint URL and request headers.","cancel":"Cancel","save":"Save","edit":"Edit","delete":"Delete","dragToReorder":"Drag to reorder","noMcpServers":"No MCP servers configured","errorIdRequired":"ID is required.","errorUrlRequired":"URL is required.","errorIdCommand":"ID and Command are required.","errorDuplicateId":"An MCP server with this ID already exists.","errorHeadersJson":"Headers must be a valid JSON object.","errorEnvJson":"Env must be a valid JSON object.","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete MCP Server","confirmDeleteDesc":"Are you sure you want to delete this MCP server? This action cannot be undone.","validation":{"enterId":"Please enter a server ID.","idFormat":"Only letters, numbers, _ and - allowed.","enterCommand":"Please enter a command.","enterUrl":"Please enter a URL.","jsonObject":"Must be a valid JSON object with string values."}},"webui":{"desc":"Configure remote access to the Fello interface.","title":"WebUI","guide":"User Guide","enable":"Enable WebUI","enableDesc":"Allow remote access to Fello interface via browser","accessUrl":"Access URL","accessDesc":"Note: This URL contains a temporary token. The WebUI will be disabled when you restart the application.","enableAccess":"Enable WebUI Access","port":"Port:","token":"Token:","autoGenerated":"Auto-generated","copy":"Copy","note":"Note: This URL contains a temporary token. The WebUI will be disabled when you restart the application.","updateFailed":"Failed to update configuration.","disabledInWebUI":"WebUI configuration is disabled when running inside the browser."},"ilink":{"title":"WeChat iLink","guide":"User Guide","description":"Connect Fello to WeChat via iLink Bot API. Once connected, a ClawBot contact will appear in your WeChat, allowing you to chat with your AI agent from anywhere.","connected":"Connected","notConnected":"Not Connected","notConnectedHint":"Scan QR code with WeChat to connect","login":"Login","loggingIn":"Waiting...","disconnect":"Disconnect","scanPrompt":"Scan with WeChat to login","qrcodeExpired":"QR code expired, please try again","scanned":"Scanned! Please confirm on your phone.","browserOpened":"QR code opened in browser. Scan with WeChat to login.","activeSession":"Active Session for WeChat","activeSessionHint":"Messages from WeChat will be routed to this session. Right-click a session in the sidebar to set it as active.","selectSession":"-- Select a session --","none":"-- None --","howItWorks":"How it works","step1":"Click \\"Login\\" to open the QR code in your browser","step2":"Scan the QR code with WeChat","step3":"A \\"ClawBot\\" contact appears in your WeChat","step4":"Chat with ClawBot — messages are routed to the active session above","step5":"Right-click any session in the sidebar to set it as active for WeChat","useOriginalImage":"Use Original Image","useOriginalImageDesc":"Send full-size images to the model (uses more tokens). When off, thumbnails are used.","keepaliveMaxCount":"Keepalive Messages","keepaliveMaxCountDesc":"Max consecutive keepalive messages while thinking.","commandsTitle":"WeChat \\"!\\" Commands","commandsDesc":"Messages starting with ! or ! are commands. They interrupt the current agent execution (cancelling an ongoing reply) and then run the corresponding action.","cmdSwitchSession":"Switch Session","cmdSwitchSessionDesc":"List all sessions (grouped by project); reply with a number to switch.","cmdNewSession":"New Session","cmdNewSessionDesc":"List all projects; reply with a number to create a session in that project and switch to it.","cmdSwitchModel":"Switch Model","cmdSwitchModelDesc":"List models available in the current session; reply with a number to switch (API agents only).","cmdSnippet":"Quick Snippet","cmdSnippetDesc":"List configured snippets; reply with a number to send that content to the agent.","cmdStatus":"View Status","cmdStatusDesc":"Show active session info (title, project, agent, features, MCP status)."},"snippets":{"title":"Snippets","desc":"Manage reusable text snippets for quick insertion.","description":"Configure Snippets","add":"Add Snippet","edit":"Edit Snippet","delete":"Delete","save":"Save","cancel":"Cancel","empty":"No snippets configured","saveFailed":"Failed to save snippets.","titleLabel":"Title","titlePlaceholder":"Title","contentLabel":"Content","contentPlaceholder":"Content","dialogDesc":"Configure the snippet title and content.","confirmDeleteTitle":"Delete Snippet","confirmDeleteDesc":"Are you sure you want to delete this snippet? This action cannot be undone.","validation":{"enterTitle":"Please enter a title.","enterContent":"Please enter content."}},"memory":{"title":"Memory","desc":"View and manage persistent project-level memory.","projectMemories":"Project Memories","refresh":"Refresh","clear":"Clear","cleared":"Memory cleared.","clearFailed":"Failed to clear memory.","delete":"Delete","deleted":"Memory entry deleted.","deleteFailed":"Failed to delete memory entry.","confirmDeleteTitle":"Delete Memory Entry","confirmDeleteDesc":"Are you sure you want to delete this memory entry? This cannot be undone.","confirmClearTitle":"Clear Memory","confirmClearDesc":"Are you sure you want to clear all memory for project \\"{{title}}\\"? This cannot be undone.","revealInFinder":"Reveal in Finder","revealFailed":"Failed to reveal file.","noFile":"No memory file found.","noProjects":"No projects found.","empty":"No memories stored.","entries":"Entries"},"imageGeneration":{"title":"Image Generation","desc":"Configure image generation providers. The active provider will be available as a tool for agents.","providers":"Providers","add":"Add Provider","addProvider":"Add Provider","editProvider":"Edit Provider","dialogDesc":"Configure provider, endpoint and authentication for image generation.","edit":"Edit","delete":"Delete","empty":"No image generation providers configured","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Provider","confirmDeleteDesc":"Are you sure you want to delete this image generation provider?","cancel":"Cancel","save":"Save","form":{"name":"Name","provider":"Provider","baseUrl":"Base URL","baseUrlHint":"Request → {baseUrl}/images/generations","apiKey":"API Key","headers":"Headers (JSON)","extraBody":"Extra Body (JSON)","extraBodyHint":"Additional parameters merged into request body (e.g. quality, style).","model":"Model"},"validation":{"enterName":"Please enter a name.","selectProvider":"Please select a provider.","enterBaseUrl":"Please enter a base URL.","enterApiKey":"Please enter an API key.","enterModel":"Please enter the model name.","jsonObject":"Must be a valid JSON object with string values."}},"speechToText":{"title":"Speech to Text","desc":"Configure realtime speech recognition providers for chat voice input.","guide":"User Guide","providers":"Providers","add":"Add Provider","addProvider":"Add Provider","editProvider":"Edit Provider","dialogDesc":"Configure a realtime speech-to-text provider for voice input.","edit":"Edit","delete":"Delete","empty":"No speech-to-text providers configured","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Provider","confirmDeleteDesc":"Delete this speech provider?","cancel":"Cancel","save":"Save","validation":{"enterName":"Please enter a name.","selectProvider":"Please select a provider.","enterApiKey":"Please enter an API key.","enterAppId":"Please enter an App ID.","enterApiSecret":"Please enter an API secret."},"form":{"name":"Name","provider":"Provider","appId":"App ID","apiKey":"API Key","apiSecret":"API Secret","optional":" (optional)","language":"Language (optional)"}},"proxy":{"title":"Network Proxy","mode":"Proxy Mode","off":"Direct","offDesc":"Connect directly without a proxy","manual":"Manual","manualDesc":"Specify a proxy server manually for all network requests","system":"System","systemDesc":"Use the system proxy settings (macOS/Windows or environment variables)","httpProxy":"HTTP Proxy","httpProxyPlaceholder":"e.g. http://127.0.0.1:7890","httpsProxy":"HTTPS Proxy (optional)","httpsProxyHint":"Falls back to the HTTP proxy when empty.","noProxy":"No Proxy (optional)","noProxyPlaceholder":"e.g. localhost,127.0.0.1,*.internal","username":"Username (optional)","password":"Password (optional)","cancel":"Cancel","save":"Save","later":"Later","restartNow":"Restart Now","restartTitle":"Restart Required","restartDesc":"Proxy settings saved. Restart Fello to apply the new proxy configuration.","restartManualDesc":"Proxy settings saved. Please manually restart the Fello server process to apply the new configuration.","saveFailed":"Failed to save proxy settings.","validation":{"httpProxyRequired":"HTTP proxy URL is required in manual mode.","invalidProxyUrl":"{{field}} should start with http:// or https://, or use a host:port address (e.g. 127.0.0.1:7890)."}}}`);
|
|
18729
|
-
const chat$1 = { "failedToLoadSession": "Failed to load session.", "failedToUpdateMcpServers": "Failed to update MCP servers." };
|
|
18730
|
+
const settings$1 = /* @__PURE__ */ JSON.parse(`{"themeDesc":"Customize the appearance of the application","languageDesc":"Select the display language","title":"Settings","general":{"title":"General","desc":"Manage your application settings.","theme":"Theme","light":"Light","dark":"Dark","system":"System","language":"Language","english":"English","chinese":"简体中文","saveThemeFailed":"Failed to save theme setting.","saveLanguageFailed":"Failed to save language setting.","groupAppearance":"Appearance","groupProject":"Project","autoWatchFiles":"Auto Watch Files","autoWatchFilesDesc":"Automatically watch project file changes","saveFileWatcherFailed":"Failed to save file watcher setting.","groupVoiceInput":"Voice Input","altDoublePress":"Double-press Alt","altDoublePressDesc":"Double-press Alt quickly while an input is focused to start or stop voice input.","saveVoiceInputFailed":"Failed to save voice input setting.","groupNetwork":"Network","proxy":"Network Proxy","proxyDesc":"Configure the network proxy used by Fello for Node requests, subprocesses and the UI.","proxyEdit":"Edit proxy settings","proxyOff":"Direct","proxySystem":"System","groupSound":"Sound","soundEnabled":"Sound Effects","soundEnabledDesc":"Play sound effects for notifications","soundVolume":"Volume","soundVolumeDesc":"Adjust notification volume","soundTheme":"Sound Style","soundThemeDesc":"Select the sound effect style","soundSoft":"Soft","soundCrisp":"Crisp","soundTest":"Test","soundTestDesc":"Preview the current sound effect","soundTestPlay":"Play","saveSoundFailed":"Failed to save sound setting.","groupEditor":"Editor","editor":"Open in Editor","editorDesc":"Choose the editor to open files","selectEditor":"Select editor","saveEditorFailed":"Failed to save editor setting."},"shortcuts":{"title":"Shortcuts","desc":"Customize keyboard shortcuts for common actions.","navigation":"Navigation","recording":"Press a shortcut","changeShortcut":"Change shortcut","unassigned":"Unassigned","delete":"Delete","set":"Set","restore":"Restore","setTitle":"Set shortcut","setDesc":"Press the shortcut you want to use.","cancel":"Cancel","confirm":"Confirm","reset":"Reset to default","conflict":"Already used by {{command}}.","saveFailed":"Failed to save shortcuts."},"agents":{"desc":"Manage agent configurations and startup commands.","description":"Configure agents","title":"Agents","guide":"User Guide","addStdioAgent":"Add via ACP Agent","addApiAgent":"Add via API Key","editStdioAgent":"Edit ACP Agent","editApiAgent":"Edit API Agent","dialogDesc":"Configure the agent ID, command, arguments and environment variables.","apiDialogDesc":"Configure provider, endpoint and authentication for API agent.","agentId":"Agent ID (Name)","apiProvider":"Provider","apiBaseUrl":"Base URL","apiKey":"API Key","apiHeaders":"Headers (JSON)","contextWindowTokens":"Context Window (tokens)","modelIdTemplate":"Model Id Template","models":"Models (one per line)","modelsHint":"Usually not needed — models are fetched automatically. Only specify if the API doesn't return the models you need","command":"Command","args":"Arguments","envVars":"Environment Variables (JSON)","envJson":"Environment Variables (JSON)","quickPreset":"Quick preset","cancel":"Cancel","save":"Save","edit":"Edit","delete":"Delete","dragToReorder":"Drag to reorder","noAgents":"No agents configured","errorIdCommand":"ID and Command are required.","errorDuplicateId":"An agent with this ID already exists.","errorEnvJson":"Env must be a valid JSON object.","errorContextWindowTokens":"Context Window must be a positive integer.","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Agent","confirmDeleteDesc":"Are you sure you want to delete this agent? This action cannot be undone.","confirmDeleteDescWithSessions":"Are you sure you want to delete this agent? {{count}} session(s) will also be deleted. This action cannot be undone.","reset":"Reset Agent","resetSuccess":"Agent reset.","resetFailed":"Failed to reset agent.","deleteAllSessions":"Delete All Sessions","confirmDeleteAllSessionsTitle":"Delete All Sessions","confirmDeleteAllSessionsDesc":"All sessions for this agent will be permanently deleted. This action cannot be undone.","deleteAllSessionsSuccess":"{{count}} session(s) deleted.","deleteAllSessionsFailed":"Failed to delete sessions.","validation":{"enterId":"Please enter an agent ID.","idFormat":"Only letters, numbers, _ and - allowed.","selectProvider":"Please select a provider.","enterBaseUrl":"Please enter a base URL.","enterApiKey":"Please enter an API key.","enterCommand":"Please enter a command.","jsonObject":"Must be a valid JSON object with string values.","positiveInteger":"Must be a positive integer."}},"mcp":{"desc":"Manage MCP server configurations and startup commands.","description":"Configure MCP Servers","title":"MCP Servers","guide":"User Guide","addMcp":"Add MCP Server","addStdioMcp":"Add Stdio MCP","addHttpMcp":"Add HTTP MCP","addSseMcp":"Add SSE MCP","recommended":{"exa":{"name":"Exa","desc":"Exa MCP Server — AI Web Search"},"chrome-devtools":{"name":"Chrome DevTools","desc":"Chrome DevTools MCP Server — Browser Automation & Debugging"},"mijia-api":{"name":"Mijia","desc":"Mijia MCP Server — Xiaomi Smart Home Control"},"blender":{"name":"Blender","desc":"Blender MCP Server — Natural Language Blender Control"}},"editMcp":"Edit MCP Server","dialogDesc":"Configure the MCP server ID, command, arguments and environment variables.","mcpId":"MCP Server ID (Name)","command":"Command","args":"Arguments","envVars":"Environment Variables (JSON)","envJson":"Environment Variables (JSON)","url":"URL","headers":"Headers (JSON)","headersJson":"Headers (JSON)","httpDialogDesc":"Configure the MCP server ID, HTTP URL and request headers.","sseDialogDesc":"Configure the MCP server ID, SSE endpoint URL and request headers.","cancel":"Cancel","save":"Save","edit":"Edit","delete":"Delete","dragToReorder":"Drag to reorder","noMcpServers":"No MCP servers configured","errorIdRequired":"ID is required.","errorUrlRequired":"URL is required.","errorIdCommand":"ID and Command are required.","errorDuplicateId":"An MCP server with this ID already exists.","errorHeadersJson":"Headers must be a valid JSON object.","errorEnvJson":"Env must be a valid JSON object.","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete MCP Server","confirmDeleteDesc":"Are you sure you want to delete this MCP server? This action cannot be undone.","validation":{"enterId":"Please enter a server ID.","idFormat":"Only letters, numbers, _ and - allowed.","enterCommand":"Please enter a command.","enterUrl":"Please enter a URL.","jsonObject":"Must be a valid JSON object with string values."}},"webui":{"desc":"Configure remote access to the Fello interface.","title":"WebUI","guide":"User Guide","enable":"Enable WebUI","enableDesc":"Allow remote access to Fello interface via browser","accessUrl":"Access URL","accessDesc":"Note: This URL contains a temporary token. The WebUI will be disabled when you restart the application.","enableAccess":"Enable WebUI Access","port":"Port:","token":"Token:","autoGenerated":"Auto-generated","copy":"Copy","note":"Note: This URL contains a temporary token. The WebUI will be disabled when you restart the application.","updateFailed":"Failed to update configuration.","disabledInWebUI":"WebUI configuration is disabled when running inside the browser."},"ilink":{"title":"WeChat iLink","guide":"User Guide","description":"Connect Fello to WeChat via iLink Bot API. Once connected, a ClawBot contact will appear in your WeChat, allowing you to chat with your AI agent from anywhere.","connected":"Connected","notConnected":"Not Connected","notConnectedHint":"Scan QR code with WeChat to connect","login":"Login","loggingIn":"Waiting...","disconnect":"Disconnect","qrcodeExpired":"QR code expired, please try again","scanned":"Scanned! Please confirm on your phone.","browserOpened":"QR code opened in browser. Scan with WeChat to login.","activeSession":"Active Session for WeChat","activeSessionHint":"Messages from WeChat will be routed to this session. Right-click a session in the sidebar to set it as active.","selectSession":"-- Select a session --","none":"-- None --","howItWorks":"How it works","step1":"Click \\"Login\\" to open the QR code in your browser","step2":"Scan the QR code with WeChat","step3":"A \\"ClawBot\\" contact appears in your WeChat","step4":"Chat with ClawBot — messages are routed to the active session above","step5":"Right-click any session in the sidebar to set it as active for WeChat","useOriginalImage":"Use Original Image","useOriginalImageDesc":"Send full-size images to the model (uses more tokens). When off, thumbnails are used.","commandsTitle":"WeChat \\"!\\" Commands","commandsDesc":"Messages starting with ! are commands. They interrupt the current agent execution (cancelling an ongoing reply) and then run the corresponding action.","cmdSwitchSession":"Switch Session","cmdSwitchSessionDesc":"List all sessions (grouped by project); reply with a number to switch.","cmdNewSession":"New Session","cmdNewSessionDesc":"List all projects; reply with a number to create a session in that project and switch to it.","cmdSwitchModel":"Switch Model","cmdSwitchModelDesc":"List models available in the current session; reply with a number to switch (API agents only).","cmdSnippet":"Quick Snippet","cmdSnippetDesc":"List configured snippets; reply with a number to send that content to the agent.","cmdFeature":"Toggle Features","cmdFeatureDesc":"List the current session's features; reply with a number to toggle one. The session restarts so the change takes effect.","cmdToggleMcp":"Toggle MCP Servers","cmdToggleMcpDesc":"List the session's MCP servers; reply with a number to toggle one. The session restarts so the change takes effect.","cmdPermission":"Switch Permission","cmdPermissionDesc":"List the permission modes (Ask / Allow all); reply with a number to switch. Applied immediately, without restarting the session.","cmdStatus":"View Status","cmdStatusDesc":"Show active session info (title, project, agent, permission, features, MCP status)."},"snippets":{"title":"Snippets","desc":"Manage reusable text snippets for quick insertion.","description":"Configure Snippets","add":"Add Snippet","edit":"Edit Snippet","delete":"Delete","dragToReorder":"Drag to reorder","save":"Save","cancel":"Cancel","empty":"No snippets configured","saveFailed":"Failed to save snippets.","titleLabel":"Title","titlePlaceholder":"Title","contentLabel":"Content","contentPlaceholder":"Content","dialogDesc":"Configure the snippet title and content.","confirmDeleteTitle":"Delete Snippet","confirmDeleteDesc":"Are you sure you want to delete this snippet? This action cannot be undone.","validation":{"enterTitle":"Please enter a title.","enterContent":"Please enter content."}},"memory":{"title":"Memory","desc":"View and manage persistent project-level memory.","projectMemories":"Project Memories","refresh":"Refresh","clear":"Clear","cleared":"Memory cleared.","clearFailed":"Failed to clear memory.","delete":"Delete","deleted":"Memory entry deleted.","deleteFailed":"Failed to delete memory entry.","confirmDeleteTitle":"Delete Memory Entry","confirmDeleteDesc":"Are you sure you want to delete this memory entry? This cannot be undone.","confirmClearTitle":"Clear Memory","confirmClearDesc":"Are you sure you want to clear all memory for project \\"{{title}}\\"? This cannot be undone.","revealInFinder":"Reveal in Finder","revealFailed":"Failed to reveal file.","noFile":"No memory file found.","noProjects":"No projects found.","empty":"No memories stored.","entries":"Entries"},"imageGeneration":{"title":"Image Generation","desc":"Configure image generation providers. The active provider will be available as a tool for agents.","providers":"Providers","add":"Add Provider","addProvider":"Add Provider","editProvider":"Edit Provider","dialogDesc":"Configure provider, endpoint and authentication for image generation.","edit":"Edit","delete":"Delete","empty":"No image generation providers configured","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Provider","confirmDeleteDesc":"Are you sure you want to delete this image generation provider?","cancel":"Cancel","save":"Save","form":{"name":"Name","provider":"Provider","baseUrl":"Base URL","baseUrlHint":"Request → {baseUrl}/images/generations","apiKey":"API Key","headers":"Headers (JSON)","extraBody":"Extra Body (JSON)","extraBodyHint":"Additional parameters merged into request body (e.g. quality, style).","model":"Model"},"validation":{"enterName":"Please enter a name.","selectProvider":"Please select a provider.","enterBaseUrl":"Please enter a base URL.","enterApiKey":"Please enter an API key.","enterModel":"Please enter the model name.","jsonObject":"Must be a valid JSON object with string values."}},"speech":{"title":"Speech","desc":"Configure voice input (speech-to-text) and voice output (speech synthesis).","guide":"User Guide","providers":"Providers","add":"Add Provider","addProvider":"Add Provider","editProvider":"Edit Provider","dialogDesc":"Configure one provider for speech recognition and/or speech synthesis.","edit":"Edit","delete":"Delete","empty":"No speech providers configured","updateFailed":"Failed to update configuration.","confirmDeleteTitle":"Delete Provider","confirmDeleteDesc":"Are you sure you want to delete this speech provider?","cancel":"Cancel","save":"Save","shortRecognition":"ASR","shortSynthesis":"TTS","form":{"name":"Name","provider":"Provider","apiKey":"API Key","appId":"App ID","apiSecret":"API Secret","language":"Language","voice":"Voice","optional":" (optional)","recognition":"Recognition","recognitionDesc":"Realtime speech-to-text for chat voice input.","synthesis":"Synthesis","synthesisDesc":"Read agent replies out loud with this voice."},"validation":{"enterName":"Please enter a name.","selectProvider":"Please select a provider.","enterApiKey":"Please enter an API key.","enterAppId":"Please enter an App ID.","enterApiSecret":"Please enter an API secret."}},"proxy":{"title":"Network Proxy","mode":"Proxy Mode","off":"Direct","offDesc":"Connect directly without a proxy","manual":"Manual","manualDesc":"Specify a proxy server manually for all network requests","system":"System","systemDesc":"Use the system proxy settings (macOS/Windows or environment variables)","httpProxy":"HTTP Proxy","httpProxyPlaceholder":"e.g. http://127.0.0.1:7890","httpsProxy":"HTTPS Proxy (optional)","httpsProxyHint":"Falls back to the HTTP proxy when empty.","noProxy":"No Proxy (optional)","noProxyPlaceholder":"e.g. localhost,127.0.0.1,*.internal","username":"Username (optional)","password":"Password (optional)","cancel":"Cancel","save":"Save","later":"Later","restartNow":"Restart Now","restartTitle":"Restart Required","restartDesc":"Proxy settings saved. Restart Fello to apply the new proxy configuration.","restartManualDesc":"Proxy settings saved. Please manually restart the Fello server process to apply the new configuration.","saveFailed":"Failed to save proxy settings.","validation":{"httpProxyRequired":"HTTP proxy URL is required in manual mode.","invalidProxyUrl":"{{field}} should start with http:// or https://, or use a host:port address (e.g. 127.0.0.1:7890)."}},"peripherals":{"title":"Peripherals","desc":"Connect Bluetooth / HID peripherals and enable the ones whose special behavior should apply.","desktopOnly":"Peripherals are available in the desktop app only.","unsupportedPlatform":"Not supported on this platform","voiceCapable":"Voice input","productPage":"Product page","connectFailed":"Failed to connect the peripheral.","updateFailed":"Failed to update peripheral settings.","status":{"bluetooth":"Bluetooth connected"},"keys":{"voice":"Voice","back":"Back"},"phase":{"inactive":"Inactive","unsupported":"Unsupported","unavailable":"Unavailable","preparing":"Preparing","scanning":"Searching","connecting":"Connecting","connected":"Connected","error":"Error","disconnected":"Disconnected"},"openPermissionSettings":"Input Monitoring settings","permissionHint":"macOS needs the Input Monitoring permission to read HID keys, enable Fello here (press + if it is not listed). ","reconnect":"Reconnect"}}`);
|
|
18731
|
+
const chat$1 = { "failedToLoadSession": "Failed to load session.", "failedToUpdateMcpServers": "Failed to update MCP servers.", "readAloud": "Read aloud" };
|
|
18730
18732
|
const tokenUsage$1 = { "title": "Token Usage Breakdown", "loading": "Loading…", "noData": "No token breakdown data available", "promptCount": "{{count}} prompts", "promptLabel": "Prompt #{{count}}", "noBreakdown": "No detailed breakdown available for this prompt", "input": "Input", "output": "Output", "inputShort": "in", "outputShort": "out", "totalTokens": "Total", "thought": "Thought", "cacheRead": "Cache Read", "cacheWrite": "Cache Write", "cached": "Cached", "tokens": "tokens", "token": "token", "sessionTotal": "Session Total", "systemPrompt": "System Prompt", "tools": "Tools", "history": "History", "userMessage": "User Message", "inputComposition": "Input Composition", "delta": "Estimation delta", "toolsDefinition": "Tools Definition", "toolsCount": "{{count}} tools · {{tokens}} tokens", "more": "+{{count}} more", "steps": "Steps", "stepsCount": "{{count}} steps", "toolCalls": "tool calls", "noCache": "No Cache", "text": "Text", "stepTime": "Step Time", "responseTime": "Response Time", "arguments": "Arguments", "result": "Result", "execution": "Execution", "performance": "Performance", "totalTime": "Total Time", "outputSpeed": "Output Speed", "tokensPerSecond": "token/s", "firstToken": "First Token" };
|
|
18731
18733
|
const planBubble$1 = { "title": "Plan", "summary": "{{completed}} / {{total}} completed", "status": { "pending": "Pending", "inProgress": "In progress", "completed": "Completed" }, "priority": { "high": "High", "medium": "Medium", "low": "Low" } };
|
|
18732
|
-
const constant$1 = { "feature": { "
|
|
18733
|
-
const chatHeader$1 = { "sessionId": "Session", "openSessionFolder": "Open Session Folder", "projectId": "Project", "openProjectFolder": "Open Project Folder", "refresh": "Restart Session", "closeSession": "Close Session", "closingSession": "Closing…", "failedToCloseSession": "Failed to close session.", "sessionOperationInProgress": "Another session operation is already in progress.", "contextWindow": "Context Window", "used": "Used", "size": "Size", "percentUsed": "{{pct}}% used", "remaining": "{{count}} remaining", "lastTurn": "Last Turn", "input": "Input", "output": "Output", "total": "Total", "thought": "Thought", "cacheRead": "Cache read", "cacheWrite": "Cache write", "cost": "Cost", "viewBreakdown": "View Breakdown" };
|
|
18734
|
-
const chatInput$1 = { "placeholderDisabled": "Start a new chat to begin...", "placeholderActive": "Ask anything... (Enter to send)", "mode": "Mode", "suggestions": "Suggestions", "messageInput": "Message input", "stop": "Stop", "send": "Send", "tokensUsage": "In: {{input}} Out: {{output}} Total: {{total}}{{thoughtStr}}", "tokensTotal": "{{total}}k tokens", "generationFailed": "Generation failed.", "attach": "Attach file", "reference": "Reference", "mention": "Mention", "snippets": "Snippets", "snippetsEmpty": "No snippets. Click to add in Settings.", "selectModel": "Select model", "stopReasonMaxTokens": "Reached maximum token limit", "stopReasonMaxTurnRequests": "Reached maximum turn limit", "stopReasonRefusal": "Model refused to respond", "stopReasonCancelled": "Generation was cancelled", "voiceInput": "Voice input", "selectVoiceInputDevice": "Select microphone", "stopVoiceInput": "Stop voice input", "startingVoiceInput": "Starting voice input", "voiceInputNotConfigured": "Configure voice input in Settings", "noAudioInputDevices": "No audio input devices found" };
|
|
18734
|
+
const constant$1 = { "feature": { "askUser": "Ask Me", "skills": "Skills", "shareToUser": "Share to User", "search": "Search", "memory": "Memory", "imageGeneration": "Image Generation" } };
|
|
18735
|
+
const chatHeader$1 = { "sessionId": "Session", "openSessionFolder": "Open Session Folder", "projectId": "Project", "openProjectFolder": "Open Project Folder", "refresh": "Restart Session", "closeSession": "Close Session", "closingSession": "Closing…", "failedToCloseSession": "Failed to close session.", "sessionOperationInProgress": "Another session operation is already in progress.", "contextWindow": "Context Window", "used": "Used", "size": "Size", "percentUsed": "{{pct}}% used", "remaining": "{{count}} remaining", "lastTurn": "Last Turn", "input": "Input", "output": "Output", "total": "Total", "thought": "Thought", "cacheRead": "Cache read", "cacheWrite": "Cache write", "cost": "Cost", "viewBreakdown": "View Breakdown", "autoRead": "Auto-read replies", "volume": "Volume", "reading": "Reading…", "stopReading": "Stop reading" };
|
|
18736
|
+
const chatInput$1 = { "placeholderDisabled": "Start a new chat to begin...", "placeholderActive": "Ask anything... (Enter to send)", "mode": "Mode", "suggestions": "Suggestions", "messageInput": "Message input", "stop": "Stop", "send": "Send", "tokensUsage": "In: {{input}} Out: {{output}} Total: {{total}}{{thoughtStr}}", "tokensTotal": "{{total}}k tokens", "generationFailed": "Generation failed.", "attach": "Attach file", "reference": "Reference", "mention": "Mention", "snippets": "Snippets", "snippetsEmpty": "No snippets. Click to add in Settings.", "selectModel": "Select model", "stopReasonMaxTokens": "Reached maximum token limit", "stopReasonMaxTurnRequests": "Reached maximum turn limit", "stopReasonRefusal": "Model refused to respond", "stopReasonCancelled": "Generation was cancelled", "voiceInput": "Voice input", "selectVoiceInputDevice": "Select microphone", "stopVoiceInput": "Stop voice input", "startingVoiceInput": "Starting voice input", "voiceInputNotConfigured": "Configure voice input in Settings", "noAudioInputDevices": "No audio input devices found", "voicePanelTitle": "Voice input", "voicePanelEmpty": "No speech detected", "voicePanelCancel": "Cancel", "voicePanelSend": "Send", "voicePanelAutoSendLabel": "s until auto-send", "voicePanelHint": "Speak now — keep going for as long as you need", "voicePanelHoldHint": "Release to finish — everything you said is kept", "voicePanelToInput": "Fill into input box" };
|
|
18735
18737
|
const filePanel$1 = { "title": "Files", "view": "View", "emptyDirectory": "Empty directory", "newFile": "New File", "newFolder": "New Folder", "rename": "Rename", "copyPath": "Copy Path", "copyRelativePath": "Copy Relative Path", "revealInFinder": "Reveal in Finder", "openInEditor": "Open in {{editor}}", "delete": "Delete", "deleteConfirmSingle": 'How would you like to delete "{{name}}"?', "deleteConfirmMultiple": "How would you like to delete {{count}} items?", "dragItems": "{{count}} items", "cancel": "Cancel", "moveToTrash": "Move to Trash", "moveToRecycleBin": "Move to Recycle Bin", "moveConfirmTitle": "Move", "moveConfirmSingle": 'Move "{{name}}" to "{{dest}}"?', "moveConfirmMultiple": 'Move {{count}} items to "{{dest}}"?', "moveConfirmSingleToRoot": 'Move "{{name}}" to the root directory?', "moveConfirmMultipleToRoot": "Move {{count}} items to the root directory?", "loading": "Loading...", "collapseFolders": "Collapse Folders", "refresh": "Refresh", "addToChat": "Add to Chat", "noProject": "No project selected" };
|
|
18736
18738
|
const toolBubble$1 = { "tool": "Tool", "stop": "Stop", "stopping": "Stopping…", "result": "Result", "terminal": "Terminal" };
|
|
18737
18739
|
const imageView$1 = { "fallbackAlt": "Image" };
|
|
@@ -18744,20 +18746,21 @@ const subagentBubble$1 = { "thinking": "Thinking...", "waitingForTask": "Waiting
|
|
|
18744
18746
|
const chatTimeline$1 = { "userMessageIndex": "User message {{index}}", "jumpToUserMessage": "Jump to {{label}}" };
|
|
18745
18747
|
const thinkingBubble$1 = { "thinking": "Thinking...", "thought": "Thought" };
|
|
18746
18748
|
const userBubble$1 = { "copy": "Copy", "locate": "Locate" };
|
|
18747
|
-
const session$1 = { "usageSummary": "{{total}} tk ( ↓ {{input}} ↑ {{output}}{{cachedPart}} )", "usageSummaryCached": " ↻ {{cached}}", "connecting": "Connecting to agent...", "connectionFailed": "Failed to connect to agent", "
|
|
18749
|
+
const session$1 = { "usageSummary": "{{total}} tk ( ↓ {{input}} ↑ {{output}}{{cachedPart}} )", "usageSummaryCached": " ↻ {{cached}}", "connecting": "Connecting to agent...", "connectionFailed": "Failed to connect to agent", "connectionFailedHint": "If a session setting (such as MCP or features) is causing this, adjust it below and reload.", "reload": "Reload", "operationInProgress": "Another session operation is already in progress.", "failedToLoadSession": "Failed to load session.", "failedToUpdateMcpServers": "Failed to update MCP servers" };
|
|
18750
|
+
const sessionConfig$1 = { "permission": "Permission", "permissionAsk": "Ask", "permissionAllowAll": "Allow all", "features": "Features", "mcpServers": "MCP Servers", "noMcpServers": "No MCP servers configured" };
|
|
18748
18751
|
const terminalPanel$1 = { "title": "Terminal", "noTerminalSelected": "No terminal selected", "addTerminal": "Add terminal", "view": "View", "delete": "Delete terminal" };
|
|
18749
18752
|
const permission$1 = { "title": "Permission Required", "error": "Failed to respond to permission request" };
|
|
18750
18753
|
const errorBoundary$1 = { "title": "Something went wrong", "defaultMessage": "An unexpected error occurred in the application.", "reload": "Reload Application" };
|
|
18751
18754
|
const panel$1 = { "files": "Files", "terminal": "Terminal", "noProjectSelected": "No project selected" };
|
|
18752
18755
|
const contentBlock$1 = { "unsupported": "Unsupported block type: {{type}}", "download": "Download", "revealInFinder": "Reveal in Finder", "copyToWorkspace": "Copy to Workspace", "copySuccess": "Copied to workspace", "openLink": "Open Link", "invalidImage": "[Invalid Image block]", "invalidAudio": "[Invalid Audio block]", "image": "Image:", "audio": "Audio:", "imageAlt": "Agent provided image", "fileTooLarge": "File is too large (exceeds 20MB)" };
|
|
18753
18756
|
const detail$1 = { "noContent": "No content" };
|
|
18754
|
-
const fileDetail$1 = { "fileNotFound": "File not found", "fileTooLarge": "File is too large to preview", "fileFormatNotSupported": "File format not supported for preview", "errorLoading": "Error loading file", "loading": "Loading...", "noChanges": "No changes detected", "resetZoom": "Reset", "preview": "Preview", "code": "Code", "compare": "Compare", "fileModifiedNotice": "File modified. Please refresh.", "edit": "Edit", "save": "Save", "saving": "Saving…", "saved": "Saved", "saveSuccess": "Saved", "saveFailed": "Save failed", "unsaved": "Unsaved", "copyFileContent": "Copy File Content", "addFileToChat": "Add File to Chat", "addSelectionToChat": "Add Selection to Chat", "loadError": "Failed to load", "zoomOut": "Zoom out", "zoomIn": "Zoom in", "previousPage": "Previous page", "nextPage": "Next page", "previousSlide": "Previous slide", "nextSlide": "Next slide", "speakerNotes": "Notes", "closeNotes": "Close" };
|
|
18757
|
+
const fileDetail$1 = { "fileNotFound": "File not found", "fileTooLarge": "File is too large to preview", "fileFormatNotSupported": "File format not supported for preview", "mediaPlaybackFailed": "Failed to play this file", "errorLoading": "Error loading file", "loading": "Loading...", "noChanges": "No changes detected", "resetZoom": "Reset", "preview": "Preview", "code": "Code", "compare": "Compare", "fileModifiedNotice": "File modified. Please refresh.", "edit": "Edit", "save": "Save", "saving": "Saving…", "saved": "Saved", "saveSuccess": "Saved", "saveFailed": "Save failed", "unsaved": "Unsaved", "copyFileContent": "Copy File Content", "addFileToChat": "Add File to Chat", "addSelectionToChat": "Add Selection to Chat", "loadError": "Failed to load", "zoomOut": "Zoom out", "zoomIn": "Zoom in", "previousPage": "Previous page", "nextPage": "Next page", "previousSlide": "Previous slide", "nextSlide": "Next slide", "speakerNotes": "Notes", "closeNotes": "Close" };
|
|
18755
18758
|
const htmlDetail$1 = { "fileNotFound": "File not found or inaccessible", "errorLoading": "Failed to load", "loadFailed": "Page load failed", "retry": "Retry", "openInBrowser": "Open in browser", "webuiNotEnabled": "Enable WebUI first to open in browser", "open": "Open", "refresh": "Refresh" };
|
|
18756
18759
|
const welcome$1 = { "title": "Fello", "desc": "Yet another Agent client based on the ACP protocol. Connect with the agent and begin collaborating.", "hint": "Start a new chat from the sidebar", "getStarted": "Get Started", "stepAgent": "Configure Agent", "stepAgentDesc": "Add an AI agent (Stdio or API) to power your conversations", "stepAgentDone": "{{count}} agent(s) configured", "stepProject": "Add Project", "stepProjectDesc": "Select a local project folder as your workspace", "stepProjectDone": "{{count}} project(s) added", "stepChat": "Start Chat", "stepChatDesc": "Create a new AI conversation in your project", "allDone": "All set! Start a new chat from the sidebar" };
|
|
18757
18760
|
const askUser$1 = { "title": "Request", "other": "Custom reply", "back": "Use options", "inputPlaceholder": "Type your response... (Enter to send)", "submit": "Submit", "autoClose": "Auto closes on timeout", "collapse": "Collapse", "expand": "Expand" };
|
|
18758
|
-
const shareToUser$1 = { "copyToProject": "Copy to project", "reveal": "Reveal in Finder", "loadFailed": "Failed to load image", "download": "Download" };
|
|
18761
|
+
const shareToUser$1 = { "copyToProject": "Copy to project", "reveal": "Reveal in Finder", "loadFailed": "Failed to load image", "playbackFailed": "Failed to play this file", "download": "Download" };
|
|
18759
18762
|
const imageGeneration$1 = { "copyToProject": "Copy to project", "reveal": "Reveal in Finder", "loadFailed": "Failed to load image", "download": "Download" };
|
|
18760
|
-
const automation$1 = { "title": "Automation", "agent": "Agent", "alwaysDisabled": "always disabled", "anyMoment": "Any moment now", "back": "Back", "cancel": "Cancel", "create": "Create", "createFirst": "Create your first schedule", "delete": "Delete", "deleteConfirm": 'Delete "{{name}}" permanently?', "deleteTaskConfirm": "Delete this task permanently?", "deleteTaskTitle": "Delete Task", "deleteTitle": "Delete Schedule", "dialogDesc": "Configure the automated task schedule and prompt.", "editSchedule": "Edit Schedule", "editSettings": "Edit settings", "features": "Features", "files": "Files", "lastRun": "Last", "lessThanMinute": "Less than 1 min", "manual": "Manual", "manualDesc": "Manual trigger only. No automatic scheduling.", "mcpServers": "MCP Servers", "model": "Model", "modelPlaceholder": "Default model", "newSchedule": "New Schedule", "nextRun": "Next", "noFiles": "No files generated", "noSchedules": "No schedules yet", "emptyHint": "Schedule AI tasks to run automatically with cron expressions", "noTasksDesc": 'No runs yet. Click "Trigger now" to start the first run.', "prompt": "Prompt", "promptPlaceholder": "What should the agent do?", "remainingRuns": "Run Limit", "remainingRunsCount": "{{count}} runs left", "remainingRunsCount_one": "{{count}} run left", "remainingRunsDesc": "Empty = unlimited", "remainingRunsPlaceholder": "∞", "save": "Save", "schedule": "Schedule", "scheduleName": "Schedule Name", "scheduleNamePlaceholder": "e.g. Morning Standup Summary", "scheduleNotFound": "Schedule not found", "schedules": "schedules", "selectFileToPreview": "Select a file to preview", "selectTaskToPreview": "Select a task to preview files", "selectTask": "Select a task", "
|
|
18763
|
+
const automation$1 = { "title": "Automation", "agent": "Agent", "alwaysDisabled": "always disabled", "anyMoment": "Any moment now", "back": "Back", "cancel": "Cancel", "create": "Create", "createFirst": "Create your first schedule", "delete": "Delete", "deleteConfirm": 'Delete "{{name}}" permanently?', "deleteTaskConfirm": "Delete this task permanently?", "deleteTaskTitle": "Delete Task", "deleteTitle": "Delete Schedule", "dialogDesc": "Configure the automated task schedule and prompt.", "editSchedule": "Edit Schedule", "editSettings": "Edit settings", "features": "Features", "files": "Files", "lastRun": "Last", "lessThanMinute": "Less than 1 min", "manual": "Manual", "manualDesc": "Manual trigger only. No automatic scheduling.", "mcpServers": "MCP Servers", "model": "Model", "modelPlaceholder": "Default model", "newSchedule": "New Schedule", "nextRun": "Next", "noFiles": "No files generated", "noSchedules": "No schedules yet", "emptyHint": "Schedule AI tasks to run automatically with cron expressions", "noTasksDesc": 'No runs yet. Click "Trigger now" to start the first run.', "prompt": "Prompt", "promptPlaceholder": "What should the agent do?", "remainingRuns": "Run Limit", "remainingRunsCount": "{{count}} runs left", "remainingRunsCount_one": "{{count}} run left", "remainingRunsDesc": "Empty = unlimited", "remainingRunsPlaceholder": "∞", "save": "Save", "schedule": "Schedule", "scheduleName": "Schedule Name", "scheduleNamePlaceholder": "e.g. Morning Standup Summary", "scheduleNotFound": "Schedule not found", "schedules": "schedules", "selectFileToPreview": "Select a file to preview", "selectTaskToPreview": "Select a task to preview files", "selectTask": "Select a task", "recurring": "Recurring", "once": "Once", "oncePickDate": "Pick a date", "onceDesc": "Runs once at the specified time.", "missed": "Missed", "lastTriggered": "Last triggered", "duration": { "minutes": "{{minutes}} min", "hoursMinutes": "{{hours}}h {{minutes}}m", "daysHours": "{{days}}d {{hours}}h" }, "triggerNow": "Trigger now", "validation": { "nameRequired": "Name is required", "agentRequired": "Agent is required", "promptRequired": "Prompt is required", "runLimitInvalid": "Run limit must be a non-negative integer.", "onceTimeInvalid": "Please pick a future time." }, "cron": { "at": "at", "atMinute": "at min", "custom": "Custom", "daily": "Every day", "hourly": "Every N hours", "weekdays": "Weekdays", "weekly": "Every week", "nextRun": "Next run", "nextRunIn": "Next run in", "days": { "0": "Sun", "1": "Mon", "2": "Tue", "3": "Wed", "4": "Thu", "5": "Fri", "6": "Sat" } } };
|
|
18761
18764
|
const en = {
|
|
18762
18765
|
sidebar: sidebar$1,
|
|
18763
18766
|
skills: skills$1,
|
|
@@ -18783,6 +18786,7 @@ const en = {
|
|
|
18783
18786
|
thinkingBubble: thinkingBubble$1,
|
|
18784
18787
|
userBubble: userBubble$1,
|
|
18785
18788
|
session: session$1,
|
|
18789
|
+
sessionConfig: sessionConfig$1,
|
|
18786
18790
|
terminalPanel: terminalPanel$1,
|
|
18787
18791
|
permission: permission$1,
|
|
18788
18792
|
errorBoundary: errorBoundary$1,
|
|
@@ -18797,17 +18801,17 @@ const en = {
|
|
|
18797
18801
|
imageGeneration: imageGeneration$1,
|
|
18798
18802
|
automation: automation$1
|
|
18799
18803
|
};
|
|
18800
|
-
const sidebar = { "welcome": "欢迎使用", "skills": "技能", "automation": "自动化", "projects": "项目", "noProjects": "暂无项目", "noProjectsHint": "添加一个项目文件夹开始", "addProject": "添加项目", "noAgentsHint": "请先配置 Agent", "configureAgent": "配置 Agent", "revealInFinder": "在访达中显示", "rename": "重命名", "delete": "删除", "renameProject": "重命名项目", "renameSession": "重命名会话", "deleteSession": "删除会话", "enterNewProjectName": "请输入新的项目名称。", "enterNewSessionName": "请输入新的会话名称。", "addProjectTitle": "添加项目", "enterProjectPath": "请输入服务器上的项目绝对路径:", "pathCannotBeEmpty": "路径不能为空", "webuiEnabled": "已启用 WebUI", "deleteProject": "删除项目", "deleteProjectConfirm": "是否删除项目“{{title}}”及其所有会话?\n此操作无法撤销。", "deleteSessionConfirm": "是否删除会话“{{title}}”?\n此操作无法撤销。", "cancel": "取消", "save": "保存", "settings": "设置", "agents": "智能体", "addProjectFailed": "添加项目失败。", "newSessionFailed": "创建新会话失败。", "loadSessionFailed": "加载会话失败。", "revealInFinderFailed": "在访达中显示失败。", "openInEditorFailed": "在编辑器中打开失败。", "projectExists": "项目已存在。", "projectNameEmpty": "项目名称不能为空。", "sessionNameEmpty": "会话名称不能为空。", "newSession": "新会话", "viewSession": "查看会话", "projectActions": "项目操作:{{title}}", "createSessionInProject": "在 {{title}} 中创建会话", "sessionActions": "会话操作:{{title}}", "ilinkSetActive": "设为微信活跃会话", "ilinkUnsetActive": "取消微信活跃", "failedToUpdateIlinkSession": "更新微信活跃会话失败。", "sessionOperationInProgress": "已有其他会话操作正在进行中。", "ilinkActiveStatus": "微信活跃", "ilinkInactiveStatus": "非微信活跃", "restartSession": "重启会话", "closeSession": "关闭会话", "closingSession": "关闭中…", "failedToCloseSession": "关闭会话失败。", "failedToDeleteSession": "删除会话失败。", "failedToDeleteProject": "删除项目失败。", "failedToLoadSession": "加载会话失败。", "failedToUpdateMcpServers": "更新 MCP 服务器失败。", "collapse": "收起侧边栏", "expand": "展开侧边栏", "updated": "更新于", "created": "创建于", "sessionCount": "{{count}} 个会话", "newSessionDialog": { "title": "新建会话", "agent": "智能体", "selectAgent": "选择智能体", "
|
|
18804
|
+
const sidebar = { "welcome": "欢迎使用", "skills": "技能", "automation": "自动化", "projects": "项目", "noProjects": "暂无项目", "noProjectsHint": "添加一个项目文件夹开始", "addProject": "添加项目", "noAgentsHint": "请先配置 Agent", "configureAgent": "配置 Agent", "revealInFinder": "在访达中显示", "copyProjectPath": "复制项目路径", "rename": "重命名", "delete": "删除", "renameProject": "重命名项目", "renameSession": "重命名会话", "deleteSession": "删除会话", "enterNewProjectName": "请输入新的项目名称。", "enterNewSessionName": "请输入新的会话名称。", "addProjectTitle": "添加项目", "enterProjectPath": "请输入服务器上的项目绝对路径:", "pathCannotBeEmpty": "路径不能为空", "webuiEnabled": "已启用 WebUI", "deleteProject": "删除项目", "deleteProjectConfirm": "是否删除项目“{{title}}”及其所有会话?\n此操作无法撤销。", "deleteSessionConfirm": "是否删除会话“{{title}}”?\n此操作无法撤销。", "cancel": "取消", "save": "保存", "settings": "设置", "agents": "智能体", "addProjectFailed": "添加项目失败。", "dropFolderOnly": "只能将文件夹拖入以添加项目。", "newSessionFailed": "创建新会话失败。", "loadSessionFailed": "加载会话失败。", "revealInFinderFailed": "在访达中显示失败。", "openInEditorFailed": "在编辑器中打开失败。", "projectExists": "项目已存在。", "projectNameEmpty": "项目名称不能为空。", "sessionNameEmpty": "会话名称不能为空。", "newSession": "新会话", "viewSession": "查看会话", "projectActions": "项目操作:{{title}}", "createSessionInProject": "在 {{title}} 中创建会话", "sessionActions": "会话操作:{{title}}", "ilinkSetActive": "设为微信活跃会话", "ilinkUnsetActive": "取消微信活跃", "failedToUpdateIlinkSession": "更新微信活跃会话失败。", "sessionOperationInProgress": "已有其他会话操作正在进行中。", "ilinkActiveStatus": "微信活跃", "ilinkInactiveStatus": "非微信活跃", "restartSession": "重启会话", "closeSession": "关闭会话", "closingSession": "关闭中…", "failedToCloseSession": "关闭会话失败。", "failedToDeleteSession": "删除会话失败。", "failedToDeleteProject": "删除项目失败。", "failedToLoadSession": "加载会话失败。", "failedToUpdateMcpServers": "更新 MCP 服务器失败。", "collapse": "收起侧边栏", "expand": "展开侧边栏", "updated": "更新于", "created": "创建于", "sessionCount": "{{count}} 个会话", "newSessionDialog": { "title": "新建会话", "agent": "智能体", "selectAgent": "选择智能体", "permission": "权限", "permissionAsk": "每次询问", "permissionAllowAll": "全部允许", "create": "创建" } };
|
|
18801
18805
|
const skills = { "title": "技能", "installed": { "label": "已安装", "noDescription": "暂无描述。", "revealInFinder": "在访达中显示", "viewSkill": "查看 SKILL.md", "uninstall": "卸载", "uninstallTitle": "卸载技能", "uninstallConfirm": "确定要卸载 {{name}} 吗?", "cancel": "取消", "uninstalledSuccess": "技能 {{name}} 已卸载", "uninstallFailed": "卸载失败:{{message}}", "revealFailed": "在访达中显示失败:{{message}}", "loadFailed": "加载技能失败", "loadContentFailed": "加载技能内容出错:{{message}}", "noSkills": "暂无安装的技能" }, "skillsSh": { "label": "skills.sh", "title": "探索技能", "desc": "浏览并安装社区提供的技能,以增强你的 Agent 能力。", "searchPlaceholder": "搜索技能(例如:pr-review, react-best-practices)...", "install": "安装", "installSuccess": "技能 {{name}} 已安装", "installFailed": "安装失败", "noResults": "未找到相关技能", "installs": "{{count}} 次安装", "installedStatus": "已安装", "authorPrefix": "作者: " } };
|
|
18802
18806
|
const contextMenu = { "cut": "剪切", "copy": "复制", "paste": "粘贴", "selectAll": "全选" };
|
|
18803
18807
|
const commands = { "focusChatInput": { "title": "聚焦聊天输入框", "description": "将焦点移动到聊天输入框。" }, "focusChatArea": { "title": "聚焦聊天区域", "description": "将焦点移动到聊天内容区域。" }, "focusFileTree": { "title": "聚焦文件树", "description": "将焦点移动到项目文件树。" }, "focusTerminalList": { "title": "聚焦终端列表", "description": "将焦点移动到终端列表。" }, "focusSidebarSessions": { "title": "聚焦会话列表", "description": "将焦点移动到会话列表。" } };
|
|
18804
|
-
const settings = { "themeDesc": "自定义应用的外观", "languageDesc": "选择应用显示的语言", "title": "设置", "general": { "title": "通用", "desc": "管理应用设置。", "theme": "主题", "light": "浅色", "dark": "深色", "system": "跟随系统", "language": "语言", "english": "English", "chinese": "简体中文", "saveThemeFailed": "保存主题设置失败。", "saveLanguageFailed": "保存语言设置失败。", "groupAppearance": "外观", "groupProject": "项目", "autoWatchFiles": "自动监听文件", "autoWatchFilesDesc": "自动监听项目文件变更", "saveFileWatcherFailed": "保存文件监听设置失败。", "groupVoiceInput": "语音输入", "altDoublePress": "双击 Alt 快捷键", "altDoublePressDesc": "输入框聚焦时快速双击 Alt,开始或停止语音输入。", "saveVoiceInputFailed": "保存语音输入设置失败。", "groupNetwork": "网络", "proxy": "网络代理", "proxyDesc": "配置 Fello 的网络代理,应用于 Node 请求、子进程与界面。", "proxyEdit": "修改代理设置", "proxyOff": "直连", "proxySystem": "跟随系统", "groupSound": "音效", "soundEnabled": "音效", "soundEnabledDesc": "播放通知音效", "soundVolume": "音量", "soundVolumeDesc": "调整通知音量", "soundTheme": "音效风格", "soundThemeDesc": "选择音效风格", "soundSoft": "柔和", "soundCrisp": "清脆", "soundTest": "试听", "soundTestDesc": "预览当前音效效果", "soundTestPlay": "播放", "saveSoundFailed": "保存音效设置失败。", "groupEditor": "编辑器", "editor": "使用编辑器打开", "editorDesc": "选择用于打开文件的编辑器", "selectEditor": "选择编辑器", "saveEditorFailed": "保存编辑器设置失败。" }, "shortcuts": { "title": "快捷键", "desc": "自定义常用操作的键盘快捷键。", "navigation": "导航", "recording": "请按下快捷键", "changeShortcut": "修改快捷键", "unassigned": "未设置", "delete": "删除", "set": "设置", "restore": "还原", "setTitle": "设置快捷键", "setDesc": "请按下要使用的快捷键。", "cancel": "取消", "confirm": "确认", "reset": "恢复默认", "conflict": "已被 {{command}} 使用。", "saveFailed": "保存快捷键失败。" }, "agents": { "desc": "管理智能体的配置和启动命令。", "description": "配置智能体", "title": "智能体", "guide": "使用手册", "addStdioAgent": "通过 ACP Agent 添加", "addApiAgent": "通过 API Key 添加", "editStdioAgent": "编辑 ACP Agent", "editApiAgent": "编辑 API Agent", "dialogDesc": "配置智能体 ID、命令、参数和环境变量。", "apiDialogDesc": "配置 API 智能体的提供商、端点和认证信息。", "agentId": "智能体 ID (名称)", "apiProvider": "提供商", "apiBaseUrl": "Base URL", "apiKey": "API Key", "apiHeaders": "请求头 (JSON)", "contextWindowTokens": "上下文窗口 (token)", "modelIdTemplate": "Model Id 模版", "models": "模型列表 (每行一个)", "modelsHint": "通常无需填写,会自动获取。仅在接口未返回所需模型时手动指定", "command": "命令", "args": "参数", "envVars": "环境变量 (JSON)", "envJson": "环境变量 (JSON)", "quickPreset": "快速预设", "cancel": "取消", "save": "保存", "edit": "编辑", "delete": "删除", "dragToReorder": "拖拽排序", "noAgents": "未配置任何智能体", "errorIdCommand": "ID 和命令不能为空。", "errorDuplicateId": "已存在具有该 ID 的智能体。", "errorEnvJson": "环境变量必须是有效的 JSON 对象。", "errorContextWindowTokens": "上下文窗口必须为正整数。", "updateFailed": "更新配置失败。", "confirmDeleteTitle": "删除智能体", "confirmDeleteDesc": "确定要删除此智能体吗?此操作无法撤销。", "confirmDeleteDescWithSessions": "确定要删除此智能体吗?{{count}} 个会话也将被同时删除。此操作无法撤销。", "reset": "重置智能体", "resetSuccess": "智能体已重置。", "resetFailed": "重置智能体失败。", "deleteAllSessions": "删除所有会话", "confirmDeleteAllSessionsTitle": "删除所有会话", "confirmDeleteAllSessionsDesc": "此智能体的所有会话将被永久删除。此操作无法撤销。", "deleteAllSessionsSuccess": "已删除 {{count}} 个会话。", "deleteAllSessionsFailed": "删除会话失败。", "validation": { "enterId": "请输入智能体 ID。", "idFormat": "只允许字母、数字、_ 和 -。", "selectProvider": "请选择提供商。", "enterBaseUrl": "请输入 Base URL。", "enterApiKey": "请输入 API Key。", "enterCommand": "请输入命令。", "jsonObject": "必须是有效的 JSON 对象(值为字符串)。", "positiveInteger": "必须为正整数。" } }, "mcp": { "desc": "管理 MCP 服务器的配置和启动命令。", "description": "配置 MCP 服务器", "title": "MCP 服务器", "guide": "使用手册", "addMcp": "添加 MCP 服务器", "addStdioMcp": "添加 Stdio MCP", "addHttpMcp": "添加 HTTP MCP", "addSseMcp": "添加 SSE MCP", "recommended": { "exa": { "name": "Exa", "desc": "Exa MCP 服务器 — AI 网络搜索" } }, "editMcp": "编辑 MCP 服务器", "dialogDesc": "配置 MCP 服务器 ID、命令、参数和环境变量。", "mcpId": "MCP 服务器 ID (名称)", "command": "命令", "args": "参数", "envVars": "环境变量 (JSON)", "envJson": "环境变量 (JSON)", "url": "URL", "headers": "请求头 (JSON)", "headersJson": "请求头 (JSON)", "httpDialogDesc": "配置 MCP 服务器 ID、HTTP URL 和请求头。", "sseDialogDesc": "配置 MCP 服务器 ID、SSE 端点 URL 和请求头。", "cancel": "取消", "save": "保存", "edit": "编辑", "delete": "删除", "dragToReorder": "拖拽排序", "noMcpServers": "未配置任何 MCP 服务器", "errorIdRequired": "ID 不能为空。", "errorUrlRequired": "URL 不能为空。", "errorIdCommand": "ID 和命令不能为空。", "errorDuplicateId": "已存在具有该 ID 的 MCP 服务器。", "errorHeadersJson": "请求头必须是有效的 JSON 对象。", "errorEnvJson": "环境变量必须是有效的 JSON 对象。", "updateFailed": "更新配置失败。", "confirmDeleteTitle": "删除 MCP 服务器", "confirmDeleteDesc": "确定要删除此 MCP 服务器吗?此操作无法撤销。", "validation": { "enterId": "请输入服务器 ID。", "idFormat": "只允许字母、数字、_ 和 -。", "enterCommand": "请输入命令。", "enterUrl": "请输入 URL。", "jsonObject": "必须是有效的 JSON 对象(值为字符串)。" } }, "webui": { "desc": "配置对 Fello 界面的远程访问。", "title": "WebUI", "guide": "使用手册", "enable": "启用 WebUI", "enableDesc": "允许通过浏览器远程访问 Fello 界面", "enableAccess": "启用 WebUI 访问", "port": "端口:", "token": "Token:", "autoGenerated": "自动生成", "accessUrl": "访问地址", "accessDesc": "注意:此地址包含临时访问令牌,应用重启后将失效。", "copy": "复制", "note": "注意:此地址包含临时访问令牌,应用重启后将失效。", "updateFailed": "更新配置失败。", "disabledInWebUI": "WebUI 配置在浏览器中不可用。" }, "ilink": { "title": "微信 iLink", "guide": "使用手册", "description": "通过 iLink Bot API 将 Fello 接入微信。连接后,微信中会出现一个 ClawBot 联系人,你可以随时随地与 AI 智能体对话。", "connected": "已连接", "notConnected": "未连接", "notConnectedHint": "使用微信扫描二维码连接", "login": "登录", "loggingIn": "等待扫码...", "disconnect": "断开连接", "scanPrompt": "使用微信扫描二维码登录", "qrcodeExpired": "二维码已过期,请重新获取", "scanned": "已扫码!请在手机上确认登录。", "browserOpened": "二维码已在浏览器中打开,请使用微信扫码登录。", "activeSession": "微信活跃会话", "activeSessionHint": "微信消息将路由到此会话。可在侧边栏右键会话设为活跃。", "selectSession": "-- 选择一个会话 --", "none": "-- 无 --", "howItWorks": "使用说明", "step1": "点击「登录」在浏览器中打开二维码。", "step2": "使用微信扫描二维码。", "step3": "微信中出现「ClawBot」联系人。", "step4": "与 ClawBot 聊天 — 消息将路由到上方选择的活跃会话。", "step5": "在侧边栏右键任意会话即可设为微信活跃会话。", "useOriginalImage": "使用原图", "useOriginalImageDesc": "向模型发送原始大小的图片(消耗更多 token)。关闭时使用缩略图。", "keepaliveMaxCount": "保活消息", "keepaliveMaxCountDesc": "AI 思考时最大连续保活消息数。", "commandsTitle": "微信 ! 命令", "commandsDesc": "在微信中发送以 ! 或 ! 开头的消息即为命令。命令会中断当前 Agent 执行(如正在生成回复则立即取消),然后执行对应操作。", "cmdSwitchSession": "切换会话", "cmdSwitchSessionDesc": "列出所有会话(按项目分组),回复序号切换到对应会话。", "cmdNewSession": "新建会话", "cmdNewSessionDesc": "列出所有项目,回复序号在该项目下创建新会话并自动切换。", "cmdSwitchModel": "切换模型", "cmdSwitchModelDesc": "列出当前会话可用的模型,回复序号切换(仅 API Agent 支持)。", "cmdSnippet": "快捷短语", "cmdSnippetDesc": "列出已配置的 Snippets,回复序号将对应内容发送给 Agent。", "cmdStatus": "查看状态", "cmdStatusDesc": "显示当前活跃会话信息(标题、项目、Agent、Features、MCP 状态)。" }, "snippets": { "title": "快捷短语", "desc": "管理可复用的文本片段,快速插入到对话中。", "description": "配置快捷短语", "add": "添加短语", "edit": "编辑短语", "delete": "删除", "save": "保存", "cancel": "取消", "empty": "暂无快捷短语", "saveFailed": "保存快捷短语失败。", "titleLabel": "标题", "titlePlaceholder": "标题", "contentLabel": "内容", "contentPlaceholder": "内容", "dialogDesc": "配置短语的标题和内容。", "confirmDeleteTitle": "删除短语", "confirmDeleteDesc": "确定要删除此短语吗?此操作无法撤销。", "validation": { "enterTitle": "请输入标题。", "enterContent": "请输入内容。" } }, "memory": { "title": "记忆", "desc": "查看和管理项目级持久化记忆。", "projectMemories": "项目记忆", "refresh": "刷新", "clear": "清除", "cleared": "记忆已清除。", "clearFailed": "清除记忆失败。", "delete": "删除", "deleted": "记忆条目已删除。", "deleteFailed": "删除记忆条目失败。", "confirmDeleteTitle": "删除记忆条目", "confirmDeleteDesc": "确定要删除此记忆条目吗?此操作不可撤销。", "confirmClearTitle": "清除记忆", "confirmClearDesc": '确定要清除项目 "{{title}}" 的所有记忆吗?此操作不可撤销。', "revealInFinder": "在访达中显示", "revealFailed": "显示文件失败。", "noFile": "未找到记忆文件。", "noProjects": "未找到项目。", "empty": "暂无记忆。", "entries": "条目" }, "imageGeneration": { "title": "图片生成", "desc": "配置图片生成服务提供商。激活的提供商将作为工具供 Agent 使用。", "providers": "提供商", "add": "添加提供商", "addProvider": "添加提供商", "editProvider": "编辑提供商", "dialogDesc": "配置图片生成的提供商、端点和认证信息。", "edit": "编辑", "delete": "删除", "empty": "尚未配置图片生成提供商", "updateFailed": "更新配置失败。", "confirmDeleteTitle": "删除提供商", "confirmDeleteDesc": "确定要删除此图片生成提供商吗?", "cancel": "取消", "save": "保存", "form": { "name": "名称", "provider": "提供商", "baseUrl": "Base URL", "baseUrlHint": "请求将发送至 {baseUrl}/images/generations", "apiKey": "API Key", "headers": "请求头 (JSON)", "extraBody": "额外参数 (JSON)", "extraBodyHint": "合并到请求体中的额外参数(如 quality、style 等厂商特有参数)。", "model": "模型" }, "validation": { "enterName": "请输入名称。", "selectProvider": "请选择提供商。", "enterBaseUrl": "请输入 Base URL。", "enterApiKey": "请输入 API Key。", "enterModel": "请输入模型名称。", "jsonObject": "必须是有效的 JSON 对象(值为字符串)。" } }, "speechToText": { "title": "语音识别", "desc": "配置聊天输入框使用的实时语音识别服务商。", "guide": "使用手册", "providers": "服务商", "add": "添加服务商", "addProvider": "添加服务商", "editProvider": "编辑服务商", "dialogDesc": "配置实时语音输入的服务商和认证信息。", "edit": "编辑", "delete": "删除", "empty": "尚未配置语音识别服务商", "updateFailed": "更新配置失败。", "confirmDeleteTitle": "删除服务商", "confirmDeleteDesc": "确定删除这个语音识别服务商吗?", "cancel": "取消", "save": "保存", "validation": { "enterName": "请输入名称。", "selectProvider": "请选择服务商。", "enterApiKey": "请输入 API Key。", "enterAppId": "请输入 App ID。", "enterApiSecret": "请输入 API Secret。" }, "form": { "name": "名称", "provider": "服务商", "appId": "App ID", "apiKey": "API Key", "apiSecret": "API Secret", "optional": "(可选)", "language": "语言(可选)" } }, "proxy": { "title": "网络代理", "mode": "代理模式", "off": "直连", "offDesc": "不使用代理,直接连接", "manual": "手动", "manualDesc": "手动指定代理服务器,所有网络请求走代理", "system": "跟随系统", "systemDesc": "使用系统代理设置(macOS/Windows 或环境变量)", "httpProxy": "HTTP 代理", "httpProxyPlaceholder": "例如 http://127.0.0.1:7890", "httpsProxy": "HTTPS 代理(可选)", "httpsProxyHint": "留空时回退到 HTTP 代理。", "noProxy": "不使用代理(可选)", "noProxyPlaceholder": "例如 localhost,127.0.0.1,*.internal", "username": "用户名(可选)", "password": "密码(可选)", "cancel": "取消", "save": "保存", "later": "稍后", "restartNow": "立即重启", "restartTitle": "需要重启", "restartDesc": "代理设置已保存,重启 Fello 后新的代理配置才会生效。", "restartManualDesc": "代理设置已保存,请手动重启 Fello 服务端进程后生效。", "saveFailed": "保存代理设置失败。", "validation": { "httpProxyRequired": "手动模式下必须填写 HTTP 代理地址。", "invalidProxyUrl": "{{field}} 应以 http:// 或 https:// 开头,或使用 host:port 形式(例如 127.0.0.1:7890)。" } } };
|
|
18805
|
-
const chat = { "failedToLoadSession": "加载会话失败。", "failedToUpdateMcpServers": "更新 MCP 服务器失败。" };
|
|
18808
|
+
const settings = /* @__PURE__ */ JSON.parse('{"themeDesc":"自定义应用的外观","languageDesc":"选择应用显示的语言","title":"设置","general":{"title":"通用","desc":"管理应用设置。","theme":"主题","light":"浅色","dark":"深色","system":"跟随系统","language":"语言","english":"English","chinese":"简体中文","saveThemeFailed":"保存主题设置失败。","saveLanguageFailed":"保存语言设置失败。","groupAppearance":"外观","groupProject":"项目","autoWatchFiles":"自动监听文件","autoWatchFilesDesc":"自动监听项目文件变更","saveFileWatcherFailed":"保存文件监听设置失败。","groupVoiceInput":"语音输入","altDoublePress":"双击 Alt 快捷键","altDoublePressDesc":"输入框聚焦时快速双击 Alt,开始或停止语音输入。","saveVoiceInputFailed":"保存语音输入设置失败。","groupNetwork":"网络","proxy":"网络代理","proxyDesc":"配置 Fello 的网络代理,应用于 Node 请求、子进程与界面。","proxyEdit":"修改代理设置","proxyOff":"直连","proxySystem":"跟随系统","groupSound":"音效","soundEnabled":"音效","soundEnabledDesc":"播放通知音效","soundVolume":"音量","soundVolumeDesc":"调整通知音量","soundTheme":"音效风格","soundThemeDesc":"选择音效风格","soundSoft":"柔和","soundCrisp":"清脆","soundTest":"试听","soundTestDesc":"预览当前音效效果","soundTestPlay":"播放","saveSoundFailed":"保存音效设置失败。","groupEditor":"编辑器","editor":"使用编辑器打开","editorDesc":"选择用于打开文件的编辑器","selectEditor":"选择编辑器","saveEditorFailed":"保存编辑器设置失败。"},"shortcuts":{"title":"快捷键","desc":"自定义常用操作的键盘快捷键。","navigation":"导航","recording":"请按下快捷键","changeShortcut":"修改快捷键","unassigned":"未设置","delete":"删除","set":"设置","restore":"还原","setTitle":"设置快捷键","setDesc":"请按下要使用的快捷键。","cancel":"取消","confirm":"确认","reset":"恢复默认","conflict":"已被 {{command}} 使用。","saveFailed":"保存快捷键失败。"},"agents":{"desc":"管理智能体的配置和启动命令。","description":"配置智能体","title":"智能体","guide":"使用手册","addStdioAgent":"通过 ACP Agent 添加","addApiAgent":"通过 API Key 添加","editStdioAgent":"编辑 ACP Agent","editApiAgent":"编辑 API Agent","dialogDesc":"配置智能体 ID、命令、参数和环境变量。","apiDialogDesc":"配置 API 智能体的提供商、端点和认证信息。","agentId":"智能体 ID (名称)","apiProvider":"提供商","apiBaseUrl":"Base URL","apiKey":"API Key","apiHeaders":"请求头 (JSON)","contextWindowTokens":"上下文窗口 (token)","modelIdTemplate":"Model Id 模版","models":"模型列表 (每行一个)","modelsHint":"通常无需填写,会自动获取。仅在接口未返回所需模型时手动指定","command":"命令","args":"参数","envVars":"环境变量 (JSON)","envJson":"环境变量 (JSON)","quickPreset":"快速预设","cancel":"取消","save":"保存","edit":"编辑","delete":"删除","dragToReorder":"拖拽排序","noAgents":"未配置任何智能体","errorIdCommand":"ID 和命令不能为空。","errorDuplicateId":"已存在具有该 ID 的智能体。","errorEnvJson":"环境变量必须是有效的 JSON 对象。","errorContextWindowTokens":"上下文窗口必须为正整数。","updateFailed":"更新配置失败。","confirmDeleteTitle":"删除智能体","confirmDeleteDesc":"确定要删除此智能体吗?此操作无法撤销。","confirmDeleteDescWithSessions":"确定要删除此智能体吗?{{count}} 个会话也将被同时删除。此操作无法撤销。","reset":"重置智能体","resetSuccess":"智能体已重置。","resetFailed":"重置智能体失败。","deleteAllSessions":"删除所有会话","confirmDeleteAllSessionsTitle":"删除所有会话","confirmDeleteAllSessionsDesc":"此智能体的所有会话将被永久删除。此操作无法撤销。","deleteAllSessionsSuccess":"已删除 {{count}} 个会话。","deleteAllSessionsFailed":"删除会话失败。","validation":{"enterId":"请输入智能体 ID。","idFormat":"只允许字母、数字、_ 和 -。","selectProvider":"请选择提供商。","enterBaseUrl":"请输入 Base URL。","enterApiKey":"请输入 API Key。","enterCommand":"请输入命令。","jsonObject":"必须是有效的 JSON 对象(值为字符串)。","positiveInteger":"必须为正整数。"}},"mcp":{"desc":"管理 MCP 服务器的配置和启动命令。","description":"配置 MCP 服务器","title":"MCP 服务器","guide":"使用手册","addMcp":"添加 MCP 服务器","addStdioMcp":"添加 Stdio MCP","addHttpMcp":"添加 HTTP MCP","addSseMcp":"添加 SSE MCP","recommended":{"exa":{"name":"Exa","desc":"Exa MCP 服务器 — AI 网络搜索"},"chrome-devtools":{"name":"Chrome DevTools","desc":"Chrome DevTools MCP 服务器 — 浏览器自动化与调试"},"mijia-api":{"name":"Mijia","desc":"米家 MCP 服务器 — 小米智能家居控制"},"blender":{"name":"Blender","desc":"Blender MCP 服务器 — 自然语言控制 Blender"}},"editMcp":"编辑 MCP 服务器","dialogDesc":"配置 MCP 服务器 ID、命令、参数和环境变量。","mcpId":"MCP 服务器 ID (名称)","command":"命令","args":"参数","envVars":"环境变量 (JSON)","envJson":"环境变量 (JSON)","url":"URL","headers":"请求头 (JSON)","headersJson":"请求头 (JSON)","httpDialogDesc":"配置 MCP 服务器 ID、HTTP URL 和请求头。","sseDialogDesc":"配置 MCP 服务器 ID、SSE 端点 URL 和请求头。","cancel":"取消","save":"保存","edit":"编辑","delete":"删除","dragToReorder":"拖拽排序","noMcpServers":"未配置任何 MCP 服务器","errorIdRequired":"ID 不能为空。","errorUrlRequired":"URL 不能为空。","errorIdCommand":"ID 和命令不能为空。","errorDuplicateId":"已存在具有该 ID 的 MCP 服务器。","errorHeadersJson":"请求头必须是有效的 JSON 对象。","errorEnvJson":"环境变量必须是有效的 JSON 对象。","updateFailed":"更新配置失败。","confirmDeleteTitle":"删除 MCP 服务器","confirmDeleteDesc":"确定要删除此 MCP 服务器吗?此操作无法撤销。","validation":{"enterId":"请输入服务器 ID。","idFormat":"只允许字母、数字、_ 和 -。","enterCommand":"请输入命令。","enterUrl":"请输入 URL。","jsonObject":"必须是有效的 JSON 对象(值为字符串)。"}},"webui":{"desc":"配置对 Fello 界面的远程访问。","title":"WebUI","guide":"使用手册","enable":"启用 WebUI","enableDesc":"允许通过浏览器远程访问 Fello 界面","enableAccess":"启用 WebUI 访问","port":"端口:","token":"Token:","autoGenerated":"自动生成","accessUrl":"访问地址","accessDesc":"注意:此地址包含临时访问令牌,应用重启后将失效。","copy":"复制","note":"注意:此地址包含临时访问令牌,应用重启后将失效。","updateFailed":"更新配置失败。","disabledInWebUI":"WebUI 配置在浏览器中不可用。"},"ilink":{"title":"微信 iLink","guide":"使用手册","description":"通过 iLink Bot API 将 Fello 接入微信。连接后,微信中会出现一个 ClawBot 联系人,你可以随时随地与 AI 智能体对话。","connected":"已连接","notConnected":"未连接","notConnectedHint":"使用微信扫描二维码连接","login":"登录","loggingIn":"等待扫码...","disconnect":"断开连接","qrcodeExpired":"二维码已过期,请重新获取","scanned":"已扫码!请在手机上确认登录。","browserOpened":"二维码已在浏览器中打开,请使用微信扫码登录。","activeSession":"微信活跃会话","activeSessionHint":"微信消息将路由到此会话。可在侧边栏右键会话设为活跃。","selectSession":"-- 选择一个会话 --","none":"-- 无 --","howItWorks":"使用说明","step1":"点击「登录」在浏览器中打开二维码。","step2":"使用微信扫描二维码。","step3":"微信中出现「ClawBot」联系人。","step4":"与 ClawBot 聊天 — 消息将路由到上方选择的活跃会话。","step5":"在侧边栏右键任意会话即可设为微信活跃会话。","useOriginalImage":"使用原图","useOriginalImageDesc":"向模型发送原始大小的图片(消耗更多 token)。关闭时使用缩略图。","commandsTitle":"微信 ! 命令","commandsDesc":"在微信中发送以 ! 开头的消息即为命令。命令会中断当前 Agent 执行(如正在生成回复则立即取消),然后执行对应操作。","cmdSwitchSession":"切换会话","cmdSwitchSessionDesc":"列出所有会话(按项目分组),回复序号切换到对应会话。","cmdNewSession":"新建会话","cmdNewSessionDesc":"列出所有项目,回复序号在该项目下创建新会话并自动切换。","cmdSwitchModel":"切换模型","cmdSwitchModelDesc":"列出当前会话可用的模型,回复序号切换(仅 API Agent 支持)。","cmdSnippet":"快捷短语","cmdSnippetDesc":"列出已配置的 Snippets,回复序号将对应内容发送给 Agent。","cmdFeature":"切换功能","cmdFeatureDesc":"列出当前会话的功能,回复序号切换该项。会话会重启以使改动生效。","cmdToggleMcp":"切换 MCP 服务器","cmdToggleMcpDesc":"列出当前会话的 MCP 服务器,回复序号切换该项。会话会重启以使改动生效。","cmdPermission":"切换权限","cmdPermissionDesc":"列出权限模式(每次询问 / 全部允许),回复序号切换。即时生效,不会重启会话。","cmdStatus":"查看状态","cmdStatusDesc":"显示当前活跃会话信息(标题、项目、Agent、权限、Features、MCP 状态)。"},"snippets":{"title":"快捷短语","desc":"管理可复用的文本片段,快速插入到对话中。","description":"配置快捷短语","add":"添加短语","edit":"编辑短语","delete":"删除","dragToReorder":"拖拽排序","save":"保存","cancel":"取消","empty":"暂无快捷短语","saveFailed":"保存快捷短语失败。","titleLabel":"标题","titlePlaceholder":"标题","contentLabel":"内容","contentPlaceholder":"内容","dialogDesc":"配置短语的标题和内容。","confirmDeleteTitle":"删除短语","confirmDeleteDesc":"确定要删除此短语吗?此操作无法撤销。","validation":{"enterTitle":"请输入标题。","enterContent":"请输入内容。"}},"memory":{"title":"记忆","desc":"查看和管理项目级持久化记忆。","projectMemories":"项目记忆","refresh":"刷新","clear":"清除","cleared":"记忆已清除。","clearFailed":"清除记忆失败。","delete":"删除","deleted":"记忆条目已删除。","deleteFailed":"删除记忆条目失败。","confirmDeleteTitle":"删除记忆条目","confirmDeleteDesc":"确定要删除此记忆条目吗?此操作不可撤销。","confirmClearTitle":"清除记忆","confirmClearDesc":"确定要清除项目 \\"{{title}}\\" 的所有记忆吗?此操作不可撤销。","revealInFinder":"在访达中显示","revealFailed":"显示文件失败。","noFile":"未找到记忆文件。","noProjects":"未找到项目。","empty":"暂无记忆。","entries":"条目"},"imageGeneration":{"title":"图片生成","desc":"配置图片生成服务提供商。激活的提供商将作为工具供 Agent 使用。","providers":"提供商","add":"添加提供商","addProvider":"添加提供商","editProvider":"编辑提供商","dialogDesc":"配置图片生成的提供商、端点和认证信息。","edit":"编辑","delete":"删除","empty":"尚未配置图片生成提供商","updateFailed":"更新配置失败。","confirmDeleteTitle":"删除提供商","confirmDeleteDesc":"确定要删除此图片生成提供商吗?","cancel":"取消","save":"保存","form":{"name":"名称","provider":"提供商","baseUrl":"Base URL","baseUrlHint":"请求将发送至 {baseUrl}/images/generations","apiKey":"API Key","headers":"请求头 (JSON)","extraBody":"额外参数 (JSON)","extraBodyHint":"合并到请求体中的额外参数(如 quality、style 等厂商特有参数)。","model":"模型"},"validation":{"enterName":"请输入名称。","selectProvider":"请选择提供商。","enterBaseUrl":"请输入 Base URL。","enterApiKey":"请输入 API Key。","enterModel":"请输入模型名称。","jsonObject":"必须是有效的 JSON 对象(值为字符串)。"}},"speech":{"title":"语音","desc":"配置语音输入(识别)与语音输出(合成朗读)。","guide":"使用手册","providers":"服务商","add":"添加服务商","addProvider":"添加服务商","editProvider":"编辑服务商","dialogDesc":"为一个服务商配置语音识别和(或)语音合成。","edit":"编辑","delete":"删除","empty":"尚未配置语音服务商","updateFailed":"更新配置失败。","confirmDeleteTitle":"删除服务商","confirmDeleteDesc":"确定要删除此语音服务商吗?","cancel":"取消","save":"保存","shortRecognition":"识别","shortSynthesis":"合成","form":{"name":"名称","provider":"服务商","apiKey":"API Key","appId":"App ID","apiSecret":"API Secret","language":"语言","voice":"音色","optional":"(可选)","recognition":"识别","recognitionDesc":"聊天输入框使用的实时语音识别。","synthesis":"合成","synthesisDesc":"用该音色朗读 Agent 回复。"},"validation":{"enterName":"请输入名称。","selectProvider":"请选择服务商。","enterApiKey":"请输入 API Key。","enterAppId":"请输入 App ID。","enterApiSecret":"请输入 API Secret。"}},"proxy":{"title":"网络代理","mode":"代理模式","off":"直连","offDesc":"不使用代理,直接连接","manual":"手动","manualDesc":"手动指定代理服务器,所有网络请求走代理","system":"跟随系统","systemDesc":"使用系统代理设置(macOS/Windows 或环境变量)","httpProxy":"HTTP 代理","httpProxyPlaceholder":"例如 http://127.0.0.1:7890","httpsProxy":"HTTPS 代理(可选)","httpsProxyHint":"留空时回退到 HTTP 代理。","noProxy":"不使用代理(可选)","noProxyPlaceholder":"例如 localhost,127.0.0.1,*.internal","username":"用户名(可选)","password":"密码(可选)","cancel":"取消","save":"保存","later":"稍后","restartNow":"立即重启","restartTitle":"需要重启","restartDesc":"代理设置已保存,重启 Fello 后新的代理配置才会生效。","restartManualDesc":"代理设置已保存,请手动重启 Fello 服务端进程后生效。","saveFailed":"保存代理设置失败。","validation":{"httpProxyRequired":"手动模式下必须填写 HTTP 代理地址。","invalidProxyUrl":"{{field}} 应以 http:// 或 https:// 开头,或使用 host:port 形式(例如 127.0.0.1:7890)。"}},"peripherals":{"title":"外设","desc":"连接蓝牙 / HID 外设,并开启需要生效的外设(只有生效的外设才会启用它的专用逻辑)。","desktopOnly":"外设仅在桌面应用中可用。","unsupportedPlatform":"当前平台不支持","voiceCapable":"支持语音输入","productPage":"产品页面","connectFailed":"连接外设失败。","updateFailed":"更新外设设置失败。","status":{"bluetooth":"蓝牙已连接"},"keys":{"voice":"语音","back":"返回"},"phase":{"inactive":"未生效","unsupported":"不支持","unavailable":"不可用","preparing":"准备中","scanning":"查找中","connecting":"连接中","connected":"已连接","error":"错误","disconnected":"已断开"},"openPermissionSettings":"输入监控设置","permissionHint":"macOS 需要「输入监控」权限才能读取 HID 按键;请手动勾选(列表中没有 Fello 时点「+」添加)。","reconnect":"重新连接"}}');
|
|
18809
|
+
const chat = { "failedToLoadSession": "加载会话失败。", "failedToUpdateMcpServers": "更新 MCP 服务器失败。", "readAloud": "朗读" };
|
|
18806
18810
|
const tokenUsage = { "title": "Token 使用明细", "loading": "加载中…", "noData": "暂无 Token 使用明细", "promptCount": "{{count}} 轮对话", "promptLabel": "第 {{count}} 轮对话", "noBreakdown": "此提示词没有详细的 Token 明细", "input": "输入", "output": "输出", "inputShort": "输入", "outputShort": "输出", "totalTokens": "总计", "thought": "思考", "cacheRead": "缓存读取", "cacheWrite": "缓存写入", "cached": "缓存", "tokens": "Token", "token": "Token", "sessionTotal": "会话总计", "systemPrompt": "系统提示词", "tools": "工具", "history": "历史消息", "userMessage": "用户消息", "inputComposition": "输入组成", "delta": "估算差值", "toolsDefinition": "工具定义", "toolsCount": "{{count}} 个工具 · {{tokens}} tokens", "more": "+{{count}} 项", "steps": "步骤", "stepsCount": "{{count}} 步", "toolCalls": "工具调用", "noCache": "未缓存", "text": "文本", "stepTime": "步骤耗时", "responseTime": "响应耗时", "arguments": "参数", "result": "结果", "execution": "执行耗时", "performance": "性能", "totalTime": "总耗时", "outputSpeed": "输出速度", "tokensPerSecond": "Token/s", "firstToken": "首个 Token" };
|
|
18807
18811
|
const planBubble = { "title": "计划", "summary": "已完成 {{completed}} / {{total}}", "status": { "pending": "等待中", "inProgress": "进行中", "completed": "已完成" }, "priority": { "high": "高优先级", "medium": "中优先级", "low": "低优先级" } };
|
|
18808
|
-
const constant = { "feature": { "
|
|
18809
|
-
const chatHeader = { "sessionId": "会话编号", "openSessionFolder": "打开会话文件夹", "projectId": "项目目录", "openProjectFolder": "打开项目文件夹", "refresh": "重启会话", "closeSession": "关闭会话", "closingSession": "关闭中…", "failedToCloseSession": "关闭会话失败。", "sessionOperationInProgress": "已有其他会话操作正在进行中。", "contextWindow": "上下文窗口", "used": "已用", "size": "上限", "percentUsed": "已用 {{pct}}%", "remaining": "剩余 {{count}}", "lastTurn": "上一轮", "input": "输入", "output": "输出", "total": "总计", "thought": "思考", "cacheRead": "缓存读取", "cacheWrite": "缓存写入", "cost": "费用", "viewBreakdown": "查看明细" };
|
|
18810
|
-
const chatInput = { "placeholderDisabled": "请先开启新的会话...", "placeholderActive": "有任何问题请问我... (回车发送)", "mode": "模式", "suggestions": "建议", "messageInput": "消息输入", "stop": "停止", "send": "发送", "tokensUsage": "输入: {{input}} 输出: {{output}} 总计: {{total}}{{thoughtStr}}", "tokensTotal": "{{total}}k tokens", "generationFailed": "生成失败。", "attach": "附加文件", "reference": "引用", "mention": "应用", "snippets": "快捷短语", "snippetsEmpty": "暂无短语,点击前往设置添加。", "selectModel": "选择模型", "stopReasonMaxTokens": "已达到最大 token 限制", "stopReasonMaxTurnRequests": "已达到最大轮次限制", "stopReasonRefusal": "模型拒绝回答", "stopReasonCancelled": "生成已取消", "voiceInput": "语音输入", "selectVoiceInputDevice": "选择麦克风", "stopVoiceInput": "停止语音输入", "startingVoiceInput": "正在启动语音输入", "voiceInputNotConfigured": "请先在设置中配置语音识别", "noAudioInputDevices": "未找到音频输入设备" };
|
|
18812
|
+
const constant = { "feature": { "askUser": "向我提问", "skills": "技能", "shareToUser": "分享给用户", "search": "项目检索", "memory": "记忆", "imageGeneration": "图片生成" } };
|
|
18813
|
+
const chatHeader = { "sessionId": "会话编号", "openSessionFolder": "打开会话文件夹", "projectId": "项目目录", "openProjectFolder": "打开项目文件夹", "refresh": "重启会话", "closeSession": "关闭会话", "closingSession": "关闭中…", "failedToCloseSession": "关闭会话失败。", "sessionOperationInProgress": "已有其他会话操作正在进行中。", "contextWindow": "上下文窗口", "used": "已用", "size": "上限", "percentUsed": "已用 {{pct}}%", "remaining": "剩余 {{count}}", "lastTurn": "上一轮", "input": "输入", "output": "输出", "total": "总计", "thought": "思考", "cacheRead": "缓存读取", "cacheWrite": "缓存写入", "cost": "费用", "viewBreakdown": "查看明细", "autoRead": "自动朗读回复", "volume": "音量", "reading": "正在朗读…", "stopReading": "停止朗读" };
|
|
18814
|
+
const chatInput = { "placeholderDisabled": "请先开启新的会话...", "placeholderActive": "有任何问题请问我... (回车发送)", "mode": "模式", "suggestions": "建议", "messageInput": "消息输入", "stop": "停止", "send": "发送", "tokensUsage": "输入: {{input}} 输出: {{output}} 总计: {{total}}{{thoughtStr}}", "tokensTotal": "{{total}}k tokens", "generationFailed": "生成失败。", "attach": "附加文件", "reference": "引用", "mention": "应用", "snippets": "快捷短语", "snippetsEmpty": "暂无短语,点击前往设置添加。", "selectModel": "选择模型", "stopReasonMaxTokens": "已达到最大 token 限制", "stopReasonMaxTurnRequests": "已达到最大轮次限制", "stopReasonRefusal": "模型拒绝回答", "stopReasonCancelled": "生成已取消", "voiceInput": "语音输入", "selectVoiceInputDevice": "选择麦克风", "stopVoiceInput": "停止语音输入", "startingVoiceInput": "正在启动语音输入", "voiceInputNotConfigured": "请先在设置中配置语音识别", "noAudioInputDevices": "未找到音频输入设备", "voicePanelTitle": "语音输入", "voicePanelEmpty": "没有识别到语音", "voicePanelCancel": "取消", "voicePanelSend": "发送", "voicePanelAutoSendLabel": "秒后自动发送", "voicePanelHint": "可以开始说话,想讲多久都行", "voicePanelHoldHint": "松手结束,说过的内容都会保留", "voicePanelToInput": "填入输入框" };
|
|
18811
18815
|
const filePanel = { "title": "文件", "view": "查看", "emptyDirectory": "空目录", "newFile": "新建文件", "newFolder": "新建文件夹", "rename": "重命名", "copyPath": "复制路径", "copyRelativePath": "复制相对路径", "revealInFinder": "在访达中显示", "openInEditor": "使用 {{editor}} 打开", "delete": "删除", "deleteConfirmSingle": "是否删除“{{name}}”?", "deleteConfirmMultiple": "是否删除选中的 {{count}} 个项目?", "dragItems": "{{count}} 个项目", "cancel": "取消", "moveToTrash": "移至废纸篓", "moveToRecycleBin": "移至回收站", "moveConfirmTitle": "移动", "moveConfirmSingle": "是否将“{{name}}”移动到“{{dest}}”?", "moveConfirmMultiple": "是否将 {{count}} 个项目移动到“{{dest}}”?", "moveConfirmSingleToRoot": "是否将“{{name}}”移动到根目录?", "moveConfirmMultipleToRoot": "是否将 {{count}} 个项目移动到根目录?", "loading": "加载中...", "collapseFolders": "折叠文件夹", "refresh": "刷新", "addToChat": "添加到对话", "noProject": "未选择项目" };
|
|
18812
18816
|
const toolBubble = { "tool": "工具", "stop": "停止", "stopping": "停止中…", "result": "结果", "terminal": "终端" };
|
|
18813
18817
|
const imageView = { "fallbackAlt": "图片" };
|
|
@@ -18820,20 +18824,21 @@ const subagentBubble = { "thinking": "思考中...", "waitingForTask": "等待
|
|
|
18820
18824
|
const chatTimeline = { "userMessageIndex": "第 {{index}} 条用户消息", "jumpToUserMessage": "跳转到{{label}}" };
|
|
18821
18825
|
const thinkingBubble = { "thinking": "思考中...", "thought": "思考过程" };
|
|
18822
18826
|
const userBubble = { "copy": "复制", "locate": "定位" };
|
|
18823
|
-
const session = { "usageSummary": "{{total}} tk ( ↓ {{input}} ↑ {{output}}{{cachedPart}} )", "usageSummaryCached": " ↻ {{cached}}", "connecting": "正在连接智能体...", "connectionFailed": "连接智能体失败", "
|
|
18827
|
+
const session = { "usageSummary": "{{total}} tk ( ↓ {{input}} ↑ {{output}}{{cachedPart}} )", "usageSummaryCached": " ↻ {{cached}}", "connecting": "正在连接智能体...", "connectionFailed": "连接智能体失败", "connectionFailedHint": "会话设置(如 MCP、功能)异常时可调整下方选项,再重新加载。", "reload": "重新加载", "operationInProgress": "已有其他会话操作正在进行中。", "failedToLoadSession": "加载会话失败。", "failedToUpdateMcpServers": "更新 MCP 服务器失败" };
|
|
18828
|
+
const sessionConfig = { "permission": "权限", "permissionAsk": "每次询问", "permissionAllowAll": "全部允许", "features": "功能", "mcpServers": "MCP 服务器", "noMcpServers": "未配置 MCP 服务器" };
|
|
18824
18829
|
const terminalPanel = { "title": "终端", "noTerminalSelected": "未选择终端", "addTerminal": "添加终端", "view": "查看", "delete": "删除终端" };
|
|
18825
18830
|
const permission = { "title": "需要权限", "error": "响应权限请求失败" };
|
|
18826
18831
|
const errorBoundary = { "title": "出了点问题", "defaultMessage": "应用程序发生意外错误。", "reload": "重新加载应用" };
|
|
18827
18832
|
const panel = { "files": "文件", "terminal": "终端", "noProjectSelected": "未选择项目" };
|
|
18828
18833
|
const contentBlock = { "unsupported": "不支持的内容块:{{type}}", "download": "下载", "revealInFinder": "在访达中显示", "copyToWorkspace": "复制到工作区", "copySuccess": "已复制到工作区", "openLink": "打开链接", "invalidImage": "[无效的图片块]", "invalidAudio": "[无效的音频块]", "image": "图片:", "audio": "音频:", "imageAlt": "智能体提供的图片", "fileTooLarge": "文件过大 (超过 20MB)" };
|
|
18829
18834
|
const detail = { "noContent": "无内容" };
|
|
18830
|
-
const fileDetail = { "fileNotFound": "文件不存在", "fileTooLarge": "该文件过大不支持预览", "fileFormatNotSupported": "该文件格式不支持预览", "errorLoading": "加载文件失败", "loading": "加载中...", "noChanges": "无变更", "resetZoom": "重置", "preview": "预览", "code": "源码", "compare": "对比", "fileModifiedNotice": "文件已被修改,请刷新", "edit": "编辑", "save": "保存", "saving": "保存中…", "saved": "已保存", "saveSuccess": "已保存", "saveFailed": "保存失败", "unsaved": "未保存", "copyFileContent": "复制文件内容", "addFileToChat": "添加文件到会话", "addSelectionToChat": "添加选中内容到会话", "loadError": "加载失败", "zoomOut": "缩小", "zoomIn": "放大", "previousPage": "上一页", "nextPage": "下一页", "previousSlide": "上一张", "nextSlide": "下一张", "speakerNotes": "备注", "closeNotes": "关闭" };
|
|
18835
|
+
const fileDetail = { "fileNotFound": "文件不存在", "fileTooLarge": "该文件过大不支持预览", "fileFormatNotSupported": "该文件格式不支持预览", "mediaPlaybackFailed": "该文件无法播放", "errorLoading": "加载文件失败", "loading": "加载中...", "noChanges": "无变更", "resetZoom": "重置", "preview": "预览", "code": "源码", "compare": "对比", "fileModifiedNotice": "文件已被修改,请刷新", "edit": "编辑", "save": "保存", "saving": "保存中…", "saved": "已保存", "saveSuccess": "已保存", "saveFailed": "保存失败", "unsaved": "未保存", "copyFileContent": "复制文件内容", "addFileToChat": "添加文件到会话", "addSelectionToChat": "添加选中内容到会话", "loadError": "加载失败", "zoomOut": "缩小", "zoomIn": "放大", "previousPage": "上一页", "nextPage": "下一页", "previousSlide": "上一张", "nextSlide": "下一张", "speakerNotes": "备注", "closeNotes": "关闭" };
|
|
18831
18836
|
const htmlDetail = { "fileNotFound": "文件不存在或无法访问", "errorLoading": "加载失败", "loadFailed": "页面加载失败", "retry": "重试", "openInBrowser": "在浏览器中打开", "webuiNotEnabled": "请先启用 WebUI 才能在浏览器中打开", "open": "打开", "refresh": "刷新" };
|
|
18832
18837
|
const welcome = { "title": "Fello", "desc": "又一个基于 ACP 协议的 Agent 客户端,连接智能体并开始协作。", "hint": "从左侧边栏新建会话开始", "getStarted": "开始使用", "stepAgent": "配置 Agent", "stepAgentDesc": "添加一个 AI 智能体(本地 Stdio 或 API)来驱动对话", "stepAgentDone": "已配置 {{count}} 个 Agent", "stepProject": "添加项目", "stepProjectDesc": "选择一个本地项目文件夹作为工作区", "stepProjectDone": "已添加 {{count}} 个项目", "stepChat": "开始会话", "stepChatDesc": "在项目中创建一个新的 AI 对话", "allDone": "一切就绪!从左侧边栏开始新会话吧" };
|
|
18833
18838
|
const askUser = { "title": "请求", "other": "自定义回复", "back": "使用选项", "inputPlaceholder": "输入你的回复...(回车发送)", "submit": "提交", "autoClose": "超时后自动关闭", "collapse": "收起", "expand": "展开" };
|
|
18834
|
-
const shareToUser = { "copyToProject": "复制到项目", "reveal": "在访达中显示", "loadFailed": "图片加载失败" };
|
|
18839
|
+
const shareToUser = { "copyToProject": "复制到项目", "reveal": "在访达中显示", "loadFailed": "图片加载失败", "playbackFailed": "该文件无法播放", "download": "下载" };
|
|
18835
18840
|
const imageGeneration = { "copyToProject": "复制到项目", "reveal": "在访达中显示", "loadFailed": "图片加载失败", "download": "下载" };
|
|
18836
|
-
const automation = { "title": "自动化", "agent": "智能体", "alwaysDisabled": "始终禁用", "anyMoment": "即将执行", "back": "返回", "cancel": "取消", "create": "创建", "createFirst": "创建你的第一个计划", "delete": "删除", "deleteConfirm": "确定永久删除「{{name}}」?", "deleteTaskConfirm": "确定永久删除此任务?", "deleteTaskTitle": "删除任务", "deleteTitle": "删除计划", "dialogDesc": "配置自动化计划的执行规则和 Prompt。", "editSchedule": "编辑计划", "editSettings": "编辑设置", "features": "功能", "files": "文件", "lastRun": "上次", "lessThanMinute": "不到 1 分钟", "manual": "手动", "manualDesc": "
|
|
18841
|
+
const automation = { "title": "自动化", "agent": "智能体", "alwaysDisabled": "始终禁用", "anyMoment": "即将执行", "back": "返回", "cancel": "取消", "create": "创建", "createFirst": "创建你的第一个计划", "delete": "删除", "deleteConfirm": "确定永久删除「{{name}}」?", "deleteTaskConfirm": "确定永久删除此任务?", "deleteTaskTitle": "删除任务", "deleteTitle": "删除计划", "dialogDesc": "配置自动化计划的执行规则和 Prompt。", "editSchedule": "编辑计划", "editSettings": "编辑设置", "features": "功能", "files": "文件", "lastRun": "上次", "lessThanMinute": "不到 1 分钟", "manual": "手动", "manualDesc": "仅手动触发,无周期计划。", "mcpServers": "MCP 服务器", "model": "模型", "modelPlaceholder": "默认模型", "newSchedule": "新建计划", "nextRun": "下次", "noFiles": "暂无生成文件", "noSchedules": "暂无计划", "emptyHint": "通过 cron 表达式配置周期 AI 任务,让 Agent 自动执行", "noTasksDesc": "暂无运行记录。点击「立即触发」开始第一次运行。", "prompt": "提示词", "promptPlaceholder": "智能体需要执行什么任务?", "remainingRuns": "执行次数", "remainingRunsCount": "剩余 {{count}} 次", "remainingRunsDesc": "留空为不限次数", "remainingRunsPlaceholder": "∞", "save": "保存", "schedule": "计划", "scheduleName": "计划名称", "scheduleNamePlaceholder": "例如:每日站会摘要", "scheduleNotFound": "计划未找到", "schedules": "计划", "selectFileToPreview": "选择文件预览", "selectTaskToPreview": "选择任务查看文件", "selectTask": "选择一个任务", "recurring": "周期", "once": "单次", "oncePickDate": "选择日期", "onceDesc": "在指定时间触发一次。", "missed": "已错过", "lastTriggered": "上次触发", "duration": { "minutes": "{{minutes}} 分钟", "hoursMinutes": "{{hours}} 小时 {{minutes}} 分钟", "daysHours": "{{days}} 天 {{hours}} 小时" }, "triggerNow": "立即触发", "validation": { "nameRequired": "名称不能为空", "agentRequired": "请选择智能体", "promptRequired": "提示词不能为空", "runLimitInvalid": "执行次数必须是非负整数。", "onceTimeInvalid": "请选择一个未来的时间。" }, "cron": { "at": "在", "atMinute": "第", "custom": "自定义", "daily": "每天", "hourly": "每隔 N 小时", "weekdays": "工作日", "weekly": "每周", "nextRun": "下次执行", "nextRunIn": "距离下次执行还有", "days": { "0": "周日", "1": "周一", "2": "周二", "3": "周三", "4": "周四", "5": "周五", "6": "周六" } } };
|
|
18837
18842
|
const zhCN = {
|
|
18838
18843
|
sidebar,
|
|
18839
18844
|
skills,
|
|
@@ -18859,6 +18864,7 @@ const zhCN = {
|
|
|
18859
18864
|
thinkingBubble,
|
|
18860
18865
|
userBubble,
|
|
18861
18866
|
session,
|
|
18867
|
+
sessionConfig,
|
|
18862
18868
|
terminalPanel,
|
|
18863
18869
|
permission,
|
|
18864
18870
|
errorBoundary,
|
|
@@ -22238,26 +22244,6 @@ const twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
|
|
|
22238
22244
|
function cn$1(...inputs) {
|
|
22239
22245
|
return twMerge(clsx(inputs));
|
|
22240
22246
|
}
|
|
22241
|
-
function formatUpdatedTime(updatedAt) {
|
|
22242
|
-
const date = new Date(updatedAt);
|
|
22243
|
-
const now = /* @__PURE__ */ new Date();
|
|
22244
|
-
const isSameYear = date.getFullYear() === now.getFullYear();
|
|
22245
|
-
const isSameMonth = isSameYear && date.getMonth() === now.getMonth();
|
|
22246
|
-
const isSameDay = isSameMonth && date.getDate() === now.getDate();
|
|
22247
|
-
const hours = date.getHours().toString().padStart(2, "0");
|
|
22248
|
-
const minutes = date.getMinutes().toString().padStart(2, "0");
|
|
22249
|
-
const timeStr = `${hours}:${minutes}`;
|
|
22250
|
-
if (isSameDay) {
|
|
22251
|
-
return timeStr;
|
|
22252
|
-
}
|
|
22253
|
-
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
22254
|
-
const day = date.getDate().toString().padStart(2, "0");
|
|
22255
|
-
if (isSameYear) {
|
|
22256
|
-
return `${month}-${day} ${timeStr}`;
|
|
22257
|
-
}
|
|
22258
|
-
const year = date.getFullYear();
|
|
22259
|
-
return `${year}-${month}-${day} ${timeStr}`;
|
|
22260
|
-
}
|
|
22261
22247
|
function formatDuration(ms) {
|
|
22262
22248
|
if (ms < 0) return "0s";
|
|
22263
22249
|
if (ms < 1e3) return `${ms}ms`;
|
|
@@ -22451,6 +22437,13 @@ bridge.on("task-update", (payload) => emit("task-update", payload));
|
|
|
22451
22437
|
bridge.on("asr-transcript", (payload) => emit("asr-transcript", payload));
|
|
22452
22438
|
bridge.on("asr-error", (payload) => emit("asr-error", payload));
|
|
22453
22439
|
bridge.on("asr-closed", (payload) => emit("asr-closed", payload));
|
|
22440
|
+
bridge.on("tts-audio", (payload) => emit("tts-audio", payload));
|
|
22441
|
+
bridge.on("tts-error", (payload) => emit("tts-error", payload));
|
|
22442
|
+
bridge.on("tts-closed", (payload) => emit("tts-closed", payload));
|
|
22443
|
+
bridge.on("peripheral-status", (payload) => emit("peripheral-status", payload));
|
|
22444
|
+
bridge.on("peripheral-key", (payload) => emit("peripheral-key", payload));
|
|
22445
|
+
bridge.on("peripheral-audio", (payload) => emit("peripheral-audio", payload));
|
|
22446
|
+
bridge.on("peripheral-audio-state", (payload) => emit("peripheral-audio-state", payload));
|
|
22454
22447
|
void invokeIPC("registerClient", { clientId }).catch(() => {
|
|
22455
22448
|
});
|
|
22456
22449
|
function calculateUserMessageChunk(state, subSessionId, update2, displayId, receivedAt) {
|
|
@@ -22928,7 +22921,12 @@ async function loadSession(sessionId, { force = false, loadHistory = false } = {
|
|
|
22928
22921
|
}
|
|
22929
22922
|
async function restartSession(options) {
|
|
22930
22923
|
return withSessionLifecycleLock(options.session.id, "restart", async () => {
|
|
22931
|
-
const {
|
|
22924
|
+
const {
|
|
22925
|
+
session: session2,
|
|
22926
|
+
mcpServers = session2.mcpServers,
|
|
22927
|
+
features = session2.features,
|
|
22928
|
+
permissionMode
|
|
22929
|
+
} = options;
|
|
22932
22930
|
let loadingStarted = false;
|
|
22933
22931
|
try {
|
|
22934
22932
|
const store = useAppStore.getState();
|
|
@@ -22941,7 +22939,8 @@ async function restartSession(options) {
|
|
|
22941
22939
|
await request.updateSession({
|
|
22942
22940
|
sessionId: session2.id,
|
|
22943
22941
|
mcpServers,
|
|
22944
|
-
features
|
|
22942
|
+
features,
|
|
22943
|
+
...permissionMode !== void 0 ? { permissionMode } : {}
|
|
22945
22944
|
});
|
|
22946
22945
|
} catch (error) {
|
|
22947
22946
|
throw new RestartSessionError("update", error);
|
|
@@ -22951,6 +22950,7 @@ async function restartSession(options) {
|
|
|
22951
22950
|
...currentSession,
|
|
22952
22951
|
mcpServers,
|
|
22953
22952
|
features,
|
|
22953
|
+
...permissionMode !== void 0 ? { permissionMode } : {},
|
|
22954
22954
|
isStreaming: false
|
|
22955
22955
|
});
|
|
22956
22956
|
let historyDisplayIds;
|
|
@@ -40632,6 +40632,44 @@ const IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
|
40632
40632
|
function isImageMimeType(mimeType) {
|
|
40633
40633
|
return !!mimeType && IMAGE_MIME_TYPES.has(mimeType);
|
|
40634
40634
|
}
|
|
40635
|
+
const AUDIO_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
40636
|
+
"mp3",
|
|
40637
|
+
"wav",
|
|
40638
|
+
"m4a",
|
|
40639
|
+
"aac",
|
|
40640
|
+
"flac",
|
|
40641
|
+
"ogg",
|
|
40642
|
+
"oga",
|
|
40643
|
+
"opus",
|
|
40644
|
+
"amr",
|
|
40645
|
+
"wma",
|
|
40646
|
+
"aiff",
|
|
40647
|
+
"aif",
|
|
40648
|
+
"caf"
|
|
40649
|
+
]);
|
|
40650
|
+
const VIDEO_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
40651
|
+
"mp4",
|
|
40652
|
+
"m4v",
|
|
40653
|
+
"mov",
|
|
40654
|
+
"webm",
|
|
40655
|
+
"mkv",
|
|
40656
|
+
"avi",
|
|
40657
|
+
"wmv",
|
|
40658
|
+
"flv",
|
|
40659
|
+
"mpg",
|
|
40660
|
+
"mpeg",
|
|
40661
|
+
"3gp"
|
|
40662
|
+
]);
|
|
40663
|
+
function getMediaKind(mimeType, filename) {
|
|
40664
|
+
const mime = mimeType?.trim().toLowerCase();
|
|
40665
|
+
if (mime?.startsWith("audio/")) return "audio";
|
|
40666
|
+
if (mime?.startsWith("video/")) return "video";
|
|
40667
|
+
const ext = filename?.split(".").pop()?.trim().toLowerCase();
|
|
40668
|
+
if (!ext) return null;
|
|
40669
|
+
if (AUDIO_EXTENSIONS.has(ext)) return "audio";
|
|
40670
|
+
if (VIDEO_EXTENSIONS.has(ext)) return "video";
|
|
40671
|
+
return null;
|
|
40672
|
+
}
|
|
40635
40673
|
const ALL_FEATURES = [
|
|
40636
40674
|
"skills",
|
|
40637
40675
|
"search",
|
|
@@ -40750,6 +40788,39 @@ const electron = {
|
|
|
40750
40788
|
};
|
|
40751
40789
|
const handler = (updaterEvent) => callback(updaterEvent);
|
|
40752
40790
|
return window.fello.onUpdater(handler);
|
|
40791
|
+
},
|
|
40792
|
+
/**
|
|
40793
|
+
* 外设(Electron 专属)。
|
|
40794
|
+
*
|
|
40795
|
+
* WebUI 下所有方法都是 no-op / 空数组:外设运行时只在桌面应用里装载,
|
|
40796
|
+
* 设置页据此显示「仅桌面应用可用」。
|
|
40797
|
+
*/
|
|
40798
|
+
peripherals: {
|
|
40799
|
+
/**
|
|
40800
|
+
* 打开系统的「输入监控」隐私面板:权限状态无法查询,且用户拒绝过之后系统不会再弹窗
|
|
40801
|
+
* (首次打开 HID 设备时系统本来就会弹),所以给一个由用户主动点的直达入口。
|
|
40802
|
+
*/
|
|
40803
|
+
openPermissionSettings: async () => {
|
|
40804
|
+
if (isWebUI || !window.fello) return;
|
|
40805
|
+
return window.fello.invoke("openPeripheralPermissionSettings");
|
|
40806
|
+
},
|
|
40807
|
+
getStatuses: async () => {
|
|
40808
|
+
if (isWebUI || !window.fello) return [];
|
|
40809
|
+
return window.fello.invoke("getPeripheralStatuses");
|
|
40810
|
+
},
|
|
40811
|
+
connect: async (peripheralId) => {
|
|
40812
|
+
if (isWebUI || !window.fello) return;
|
|
40813
|
+
return window.fello.invoke("peripheralConnect", peripheralId);
|
|
40814
|
+
},
|
|
40815
|
+
/** @returns captureId:用于过滤属于上一次采集的迟到音频帧。 */
|
|
40816
|
+
voiceStart: async (peripheralId) => {
|
|
40817
|
+
if (isWebUI || !window.fello) return 0;
|
|
40818
|
+
return window.fello.invoke("peripheralVoiceStart", peripheralId);
|
|
40819
|
+
},
|
|
40820
|
+
voiceStop: async (peripheralId) => {
|
|
40821
|
+
if (isWebUI || !window.fello) return;
|
|
40822
|
+
return window.fello.invoke("peripheralVoiceStop", peripheralId);
|
|
40823
|
+
}
|
|
40753
40824
|
}
|
|
40754
40825
|
};
|
|
40755
40826
|
function useRender(params) {
|
|
@@ -44076,6 +44147,120 @@ function Switch({
|
|
|
44076
44147
|
}
|
|
44077
44148
|
);
|
|
44078
44149
|
}
|
|
44150
|
+
function SessionConfigFields({
|
|
44151
|
+
mcpServers,
|
|
44152
|
+
onMcpServersChange,
|
|
44153
|
+
features,
|
|
44154
|
+
onFeaturesChange,
|
|
44155
|
+
permissionMode,
|
|
44156
|
+
onPermissionModeChange,
|
|
44157
|
+
variant = "popover",
|
|
44158
|
+
className
|
|
44159
|
+
}) {
|
|
44160
|
+
const { t } = useTranslation();
|
|
44161
|
+
const configuredMcpServers = useAppStore((state) => state.configuredMcpServers);
|
|
44162
|
+
const isCard = variant === "card";
|
|
44163
|
+
const toggleFeature = (feature, checked2) => {
|
|
44164
|
+
onFeaturesChange(
|
|
44165
|
+
checked2 ? [...features, feature] : features.filter((item) => item !== feature)
|
|
44166
|
+
);
|
|
44167
|
+
};
|
|
44168
|
+
const toggleMcpServer = (mcpServerId, checked2) => {
|
|
44169
|
+
onMcpServersChange(
|
|
44170
|
+
checked2 ? [...mcpServers, mcpServerId] : mcpServers.filter((id) => id !== mcpServerId)
|
|
44171
|
+
);
|
|
44172
|
+
};
|
|
44173
|
+
const sectionTitleClassName = isCard ? "text-xs text-muted-foreground" : "px-2 py-1 text-xs font-semibold text-foreground/80";
|
|
44174
|
+
const showMcpSection = isCard || configuredMcpServers.length > 0;
|
|
44175
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1(isCard ? "flex flex-col gap-4" : void 0, className), children: [
|
|
44176
|
+
permissionMode !== void 0 && onPermissionModeChange !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1(isCard && "flex flex-col gap-2"), children: [
|
|
44177
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: sectionTitleClassName, children: t("sessionConfig.permission", "Permission") }),
|
|
44178
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44179
|
+
Tabs,
|
|
44180
|
+
{
|
|
44181
|
+
value: permissionMode,
|
|
44182
|
+
onValueChange: (value) => {
|
|
44183
|
+
if (value === "ask" || value === "allow-all") onPermissionModeChange(value);
|
|
44184
|
+
},
|
|
44185
|
+
className: cn$1("w-full", !isCard && "px-2 my-2"),
|
|
44186
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "w-full", children: [
|
|
44187
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "ask", className: "text-xs", children: t("sessionConfig.permissionAsk", "Ask") }),
|
|
44188
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "allow-all", className: "text-xs", children: t("sessionConfig.permissionAllowAll", "Allow all") })
|
|
44189
|
+
] })
|
|
44190
|
+
}
|
|
44191
|
+
),
|
|
44192
|
+
!isCard && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-border/50 my-1" })
|
|
44193
|
+
] }),
|
|
44194
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1(isCard && "flex flex-col gap-2"), children: [
|
|
44195
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: sectionTitleClassName, children: t("sessionConfig.features", "Features") }),
|
|
44196
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: toggleGridClassName(ALL_FEATURES.length, variant), children: ALL_FEATURES.map((feature) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44197
|
+
ToggleRow,
|
|
44198
|
+
{
|
|
44199
|
+
variant,
|
|
44200
|
+
label: t(FEATURE_I18N_KEYS[feature], { defaultValue: feature }),
|
|
44201
|
+
checked: features.includes(feature),
|
|
44202
|
+
onToggle: (checked2) => toggleFeature(feature, checked2)
|
|
44203
|
+
},
|
|
44204
|
+
feature
|
|
44205
|
+
)) }),
|
|
44206
|
+
!isCard && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-border/50 my-1" })
|
|
44207
|
+
] }),
|
|
44208
|
+
showMcpSection && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cn$1(isCard && "flex flex-col gap-2"), children: [
|
|
44209
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1(sectionTitleClassName, !isCard && "mt-1"), children: t("sessionConfig.mcpServers", "MCP Servers") }),
|
|
44210
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: toggleGridClassName(configuredMcpServers.length, variant), children: configuredMcpServers.map((mcpServer) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44211
|
+
ToggleRow,
|
|
44212
|
+
{
|
|
44213
|
+
variant,
|
|
44214
|
+
label: mcpServer.id,
|
|
44215
|
+
title: mcpServer.id,
|
|
44216
|
+
checked: mcpServers.includes(mcpServer.id),
|
|
44217
|
+
onToggle: (checked2) => toggleMcpServer(mcpServer.id, checked2)
|
|
44218
|
+
},
|
|
44219
|
+
mcpServer.id
|
|
44220
|
+
)) }),
|
|
44221
|
+
configuredMcpServers.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: t("sessionConfig.noMcpServers", "No MCP servers configured") })
|
|
44222
|
+
] })
|
|
44223
|
+
] });
|
|
44224
|
+
}
|
|
44225
|
+
function toggleGridClassName(count, variant) {
|
|
44226
|
+
if (variant === "card") {
|
|
44227
|
+
return count >= 2 ? "grid grid-cols-2 gap-1" : "flex flex-col gap-1";
|
|
44228
|
+
}
|
|
44229
|
+
return count >= 2 ? "grid grid-cols-2 gap-0.5" : void 0;
|
|
44230
|
+
}
|
|
44231
|
+
function ToggleRow({
|
|
44232
|
+
variant,
|
|
44233
|
+
label,
|
|
44234
|
+
title,
|
|
44235
|
+
checked: checked2,
|
|
44236
|
+
onToggle
|
|
44237
|
+
}) {
|
|
44238
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
44239
|
+
"div",
|
|
44240
|
+
{
|
|
44241
|
+
className: cn$1(
|
|
44242
|
+
"flex items-center justify-between cursor-default transition-colors",
|
|
44243
|
+
variant === "card" ? "h-7 rounded border bg-secondary/50 px-2 text-xs hover:bg-accent" : "rounded px-2 py-1.5 text-xs hover:bg-accent/50"
|
|
44244
|
+
),
|
|
44245
|
+
onClick: () => onToggle(!checked2),
|
|
44246
|
+
children: [
|
|
44247
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44248
|
+
"span",
|
|
44249
|
+
{
|
|
44250
|
+
className: cn$1(
|
|
44251
|
+
"truncate",
|
|
44252
|
+
variant === "popover" && "mr-2",
|
|
44253
|
+
checked2 ? "text-muted-foreground" : "text-muted-foreground/50"
|
|
44254
|
+
),
|
|
44255
|
+
title,
|
|
44256
|
+
children: label
|
|
44257
|
+
}
|
|
44258
|
+
),
|
|
44259
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Switch, { size: "sm", checked: checked2, onCheckedChange: onToggle }) })
|
|
44260
|
+
]
|
|
44261
|
+
}
|
|
44262
|
+
);
|
|
44263
|
+
}
|
|
44079
44264
|
const ScrollAreaRootContext = /* @__PURE__ */ reactExports.createContext(void 0);
|
|
44080
44265
|
function useScrollAreaRootContext() {
|
|
44081
44266
|
const context = reactExports.useContext(ScrollAreaRootContext);
|
|
@@ -44917,27 +45102,6 @@ function ScrollArea({
|
|
|
44917
45102
|
hideScrollBar,
|
|
44918
45103
|
...props
|
|
44919
45104
|
}) {
|
|
44920
|
-
const handleViewportKeyDown = (event) => {
|
|
44921
|
-
const viewport = event.currentTarget;
|
|
44922
|
-
if (event.defaultPrevented || event.target !== viewport || viewport.ownerDocument.activeElement !== viewport) {
|
|
44923
|
-
return;
|
|
44924
|
-
}
|
|
44925
|
-
const isMetaEdgeShortcut = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
|
|
44926
|
-
const isPlainEdgeShortcut = !event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
|
|
44927
|
-
let top = null;
|
|
44928
|
-
if (isMetaEdgeShortcut && event.key === "ArrowUp") {
|
|
44929
|
-
top = 0;
|
|
44930
|
-
} else if (isMetaEdgeShortcut && event.key === "ArrowDown") {
|
|
44931
|
-
top = viewport.scrollHeight;
|
|
44932
|
-
} else if (isPlainEdgeShortcut && event.key === "Home") {
|
|
44933
|
-
top = 0;
|
|
44934
|
-
} else if (isPlainEdgeShortcut && event.key === "End") {
|
|
44935
|
-
top = viewport.scrollHeight;
|
|
44936
|
-
}
|
|
44937
|
-
if (top === null) return;
|
|
44938
|
-
event.preventDefault();
|
|
44939
|
-
viewport.scrollTo({ top, behavior: "smooth" });
|
|
44940
|
-
};
|
|
44941
45105
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
44942
45106
|
ScrollAreaRoot,
|
|
44943
45107
|
{
|
|
@@ -44951,7 +45115,6 @@ function ScrollArea({
|
|
|
44951
45115
|
"data-slot": "scroll-area-viewport",
|
|
44952
45116
|
className: cn$1("size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:outline-1", viewportClassName),
|
|
44953
45117
|
style: { overflowAnchor: "auto" },
|
|
44954
|
-
onKeyDown: handleViewportKeyDown,
|
|
44955
45118
|
children
|
|
44956
45119
|
}
|
|
44957
45120
|
),
|
|
@@ -45702,6 +45865,23 @@ function useFocusTarget(id, handler, enabled = true) {
|
|
|
45702
45865
|
function useFocusTargetRegistry() {
|
|
45703
45866
|
return useFocusTargetContext();
|
|
45704
45867
|
}
|
|
45868
|
+
function isContextMenuKey(event) {
|
|
45869
|
+
return event.key === "ContextMenu" || event.shiftKey && event.code === "F10";
|
|
45870
|
+
}
|
|
45871
|
+
function openContextMenuFromKeyboard(element) {
|
|
45872
|
+
const rect = element.getBoundingClientRect();
|
|
45873
|
+
element.dispatchEvent(
|
|
45874
|
+
new MouseEvent("contextmenu", {
|
|
45875
|
+
bubbles: true,
|
|
45876
|
+
cancelable: true,
|
|
45877
|
+
view: window,
|
|
45878
|
+
button: 2,
|
|
45879
|
+
buttons: 2,
|
|
45880
|
+
clientX: rect.left + rect.width / 2,
|
|
45881
|
+
clientY: rect.top + rect.height / 2
|
|
45882
|
+
})
|
|
45883
|
+
);
|
|
45884
|
+
}
|
|
45705
45885
|
const keyCodeMap = {
|
|
45706
45886
|
esc: "Escape",
|
|
45707
45887
|
escape: "Escape",
|
|
@@ -45816,9 +45996,25 @@ function projectHoverId(id) {
|
|
|
45816
45996
|
function sessionHoverId(id) {
|
|
45817
45997
|
return `s:${id}`;
|
|
45818
45998
|
}
|
|
45999
|
+
const TREE_NODES_TYPE = "application/x-fello-tree-nodes";
|
|
45819
46000
|
function sidebarNavigationItemKey(item) {
|
|
45820
46001
|
return item.type === "project" ? `project:${item.id}` : `session:${item.id}`;
|
|
45821
46002
|
}
|
|
46003
|
+
function SessionRowStatus({ sessionId, isStreaming }) {
|
|
46004
|
+
const kind = useAppStore((s) => {
|
|
46005
|
+
const state = s.sessionStates.get(sessionId);
|
|
46006
|
+
if ((state?.askUserRequests?.length ?? 0) > 0) return "ask";
|
|
46007
|
+
if (state?.completedStatus === "error") return "error";
|
|
46008
|
+
if (state?.completedStatus === "success") return "success";
|
|
46009
|
+
if (state?.completedAt) return "success";
|
|
46010
|
+
return "none";
|
|
46011
|
+
});
|
|
46012
|
+
if (kind === "ask") return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className: "size-3 shrink-0 text-sky-500" });
|
|
46013
|
+
if (isStreaming) return /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin shrink-0" });
|
|
46014
|
+
if (kind === "success") return /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3 shrink-0 text-green-500" });
|
|
46015
|
+
if (kind === "error") return /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "size-3 shrink-0 text-yellow-500" });
|
|
46016
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "size-3 shrink-0" });
|
|
46017
|
+
}
|
|
45822
46018
|
function Sidebar() {
|
|
45823
46019
|
const { t, i18n } = useTranslation();
|
|
45824
46020
|
const navigate = useNavigate();
|
|
@@ -45851,46 +46047,44 @@ function Sidebar() {
|
|
|
45851
46047
|
const currentPath = optimisticPath ?? location.pathname;
|
|
45852
46048
|
const matchSession = currentPath.match(/^\/session-view\/(.+)$/);
|
|
45853
46049
|
const activeSessionId = matchSession ? matchSession[1] : null;
|
|
45854
|
-
const
|
|
45855
|
-
|
|
45856
|
-
|
|
45857
|
-
|
|
45858
|
-
|
|
45859
|
-
|
|
45860
|
-
|
|
45861
|
-
|
|
45862
|
-
|
|
45863
|
-
|
|
45864
|
-
|
|
45865
|
-
|
|
45866
|
-
|
|
45867
|
-
|
|
45868
|
-
|
|
45869
|
-
|
|
46050
|
+
const isMacApp = useAppStore((s) => s.isMacApp);
|
|
46051
|
+
const isFullScreen = useAppStore((s) => s.isFullScreen);
|
|
46052
|
+
const projects = useAppStore((s) => s.projects);
|
|
46053
|
+
const sessions = useAppStore((s) => s.sessions);
|
|
46054
|
+
const setProjects = useAppStore((s) => s.setProjects);
|
|
46055
|
+
const setSessions = useAppStore((s) => s.setSessions);
|
|
46056
|
+
const sidebarOpen = useAppStore((s) => s.sidebarOpen);
|
|
46057
|
+
const setSidebarOpen = useAppStore((s) => s.setSidebarOpen);
|
|
46058
|
+
const configuredAgents = useAppStore((s) => s.configuredAgents);
|
|
46059
|
+
const configuredMcpServers = useAppStore((s) => s.configuredMcpServers);
|
|
46060
|
+
const webUIStatus = useAppStore((s) => s.webUIStatus);
|
|
46061
|
+
const ilinkStatus = useAppStore((s) => s.ilinkStatus);
|
|
46062
|
+
const activeIlinkSessionId = useAppStore((s) => s.activeIlinkSessionId);
|
|
46063
|
+
const activeCompletedAt = useAppStore(
|
|
46064
|
+
(s) => activeSessionId ? s.sessionStates.get(activeSessionId)?.completedAt ?? null : null
|
|
46065
|
+
);
|
|
45870
46066
|
const completedAtTimerRef = reactExports.useRef(null);
|
|
45871
46067
|
reactExports.useEffect(() => {
|
|
45872
46068
|
if (!activeSessionId) return;
|
|
45873
46069
|
if (!sessions.some((s) => s.id === activeSessionId)) return;
|
|
45874
|
-
|
|
45875
|
-
if (
|
|
45876
|
-
|
|
45877
|
-
clearTimeout(completedAtTimerRef.current);
|
|
45878
|
-
}
|
|
45879
|
-
completedAtTimerRef.current = setTimeout(() => {
|
|
45880
|
-
useAppStore.getState().updateSessionState(activeSessionId, () => ({
|
|
45881
|
-
completedAt: null,
|
|
45882
|
-
completedStatus: null
|
|
45883
|
-
}));
|
|
45884
|
-
completedAtTimerRef.current = null;
|
|
45885
|
-
}, 3e3);
|
|
46070
|
+
if (!activeCompletedAt) return;
|
|
46071
|
+
if (completedAtTimerRef.current) {
|
|
46072
|
+
clearTimeout(completedAtTimerRef.current);
|
|
45886
46073
|
}
|
|
46074
|
+
completedAtTimerRef.current = setTimeout(() => {
|
|
46075
|
+
useAppStore.getState().updateSessionState(activeSessionId, () => ({
|
|
46076
|
+
completedAt: null,
|
|
46077
|
+
completedStatus: null
|
|
46078
|
+
}));
|
|
46079
|
+
completedAtTimerRef.current = null;
|
|
46080
|
+
}, 3e3);
|
|
45887
46081
|
return () => {
|
|
45888
46082
|
if (completedAtTimerRef.current) {
|
|
45889
46083
|
clearTimeout(completedAtTimerRef.current);
|
|
45890
46084
|
completedAtTimerRef.current = null;
|
|
45891
46085
|
}
|
|
45892
46086
|
};
|
|
45893
|
-
}, [activeSessionId,
|
|
46087
|
+
}, [activeSessionId, activeCompletedAt, sessions]);
|
|
45894
46088
|
const enabledAgents = reactExports.useMemo(
|
|
45895
46089
|
() => configuredAgents.filter((a) => !a.disabled),
|
|
45896
46090
|
[configuredAgents]
|
|
@@ -45953,6 +46147,81 @@ function Sidebar() {
|
|
|
45953
46147
|
reactExports.useEffect(() => {
|
|
45954
46148
|
handleAddProjectRef.current = handleAddProject;
|
|
45955
46149
|
});
|
|
46150
|
+
const [projectDropActive, setProjectDropActive] = reactExports.useState(false);
|
|
46151
|
+
const projectDragLeaveTimer = reactExports.useRef(null);
|
|
46152
|
+
reactExports.useEffect(
|
|
46153
|
+
() => () => {
|
|
46154
|
+
if (projectDragLeaveTimer.current) clearTimeout(projectDragLeaveTimer.current);
|
|
46155
|
+
},
|
|
46156
|
+
[]
|
|
46157
|
+
);
|
|
46158
|
+
const extractDropPaths = (dataTransfer) => {
|
|
46159
|
+
const paths = [];
|
|
46160
|
+
for (const file of Array.from(dataTransfer.files ?? [])) {
|
|
46161
|
+
const absPath = electron.getPathForFile(file);
|
|
46162
|
+
if (absPath) paths.push(absPath);
|
|
46163
|
+
}
|
|
46164
|
+
if (paths.length > 0) return paths;
|
|
46165
|
+
const uriList = dataTransfer.getData("text/uri-list");
|
|
46166
|
+
return (uriList ? uriList.split("\n") : []).map((uri) => uri.trim()).filter((uri) => uri.startsWith("file://")).map((uri) => decodeURIComponent(uri.replace(/^file:\/\//, ""))).filter(Boolean);
|
|
46167
|
+
};
|
|
46168
|
+
const handleProjectDropDragOver = (event) => {
|
|
46169
|
+
if (isWebUI) return;
|
|
46170
|
+
const types = event.dataTransfer.types;
|
|
46171
|
+
if (types.includes(TREE_NODES_TYPE)) return;
|
|
46172
|
+
if (!types.includes("Files") && !types.includes("text/uri-list")) return;
|
|
46173
|
+
event.preventDefault();
|
|
46174
|
+
event.stopPropagation();
|
|
46175
|
+
event.dataTransfer.dropEffect = "copy";
|
|
46176
|
+
if (projectDragLeaveTimer.current) {
|
|
46177
|
+
clearTimeout(projectDragLeaveTimer.current);
|
|
46178
|
+
projectDragLeaveTimer.current = null;
|
|
46179
|
+
}
|
|
46180
|
+
setProjectDropActive(true);
|
|
46181
|
+
};
|
|
46182
|
+
const handleProjectDropDragLeave = (event) => {
|
|
46183
|
+
event.preventDefault();
|
|
46184
|
+
if (projectDragLeaveTimer.current) clearTimeout(projectDragLeaveTimer.current);
|
|
46185
|
+
projectDragLeaveTimer.current = setTimeout(() => setProjectDropActive(false), 50);
|
|
46186
|
+
};
|
|
46187
|
+
const handleProjectDropDrop = async (event) => {
|
|
46188
|
+
event.preventDefault();
|
|
46189
|
+
event.stopPropagation();
|
|
46190
|
+
if (projectDragLeaveTimer.current) {
|
|
46191
|
+
clearTimeout(projectDragLeaveTimer.current);
|
|
46192
|
+
projectDragLeaveTimer.current = null;
|
|
46193
|
+
}
|
|
46194
|
+
setProjectDropActive(false);
|
|
46195
|
+
if (event.dataTransfer.getData(TREE_NODES_TYPE)) return;
|
|
46196
|
+
if (isWebUI) return;
|
|
46197
|
+
const paths = [...new Set(extractDropPaths(event.dataTransfer))];
|
|
46198
|
+
if (paths.length === 0) return;
|
|
46199
|
+
const added = [];
|
|
46200
|
+
let failedCount = 0;
|
|
46201
|
+
for (const path of paths) {
|
|
46202
|
+
try {
|
|
46203
|
+
added.push(await request.addProject(path));
|
|
46204
|
+
} catch (err) {
|
|
46205
|
+
failedCount += 1;
|
|
46206
|
+
console.error("Failed to add dropped path as project:", err);
|
|
46207
|
+
}
|
|
46208
|
+
}
|
|
46209
|
+
if (failedCount > 0) {
|
|
46210
|
+
toast2.error(t("sidebar.dropFolderOnly", "Only folders can be dropped to add a project."));
|
|
46211
|
+
}
|
|
46212
|
+
if (added.length === 0) return;
|
|
46213
|
+
try {
|
|
46214
|
+
await refreshData();
|
|
46215
|
+
setExpandedProjects((prev) => {
|
|
46216
|
+
const next = { ...prev };
|
|
46217
|
+
for (const project of added) next[project.id] = true;
|
|
46218
|
+
return next;
|
|
46219
|
+
});
|
|
46220
|
+
if (added.length === 1) openNewSessionDialog(added[0].id);
|
|
46221
|
+
} catch (err) {
|
|
46222
|
+
toast2.error(getErrorMessage(err, t("sidebar.addProjectFailed", "Failed to add project.")));
|
|
46223
|
+
}
|
|
46224
|
+
};
|
|
45956
46225
|
const handleNewSession = async (projectId, agentId, params) => {
|
|
45957
46226
|
try {
|
|
45958
46227
|
setExpandedProjects((prev) => ({ ...prev, [projectId]: true }));
|
|
@@ -46214,6 +46483,9 @@ function Sidebar() {
|
|
|
46214
46483
|
);
|
|
46215
46484
|
}
|
|
46216
46485
|
};
|
|
46486
|
+
const handleCopyProjectPath = async (project) => {
|
|
46487
|
+
await copyText(project.cwd);
|
|
46488
|
+
};
|
|
46217
46489
|
const sortedProjects = reactExports.useMemo(
|
|
46218
46490
|
() => [...projects].sort((a, b2) => a.title.localeCompare(b2.title)),
|
|
46219
46491
|
[projects]
|
|
@@ -46291,7 +46563,7 @@ function Sidebar() {
|
|
|
46291
46563
|
useFocusTarget("sidebar-sessions", focusSidebarSessions);
|
|
46292
46564
|
const handleNavigationKeyDown = (event, item) => {
|
|
46293
46565
|
const { key } = event;
|
|
46294
|
-
const isVerticalNavigationKey = key === "ArrowUp" || key === "ArrowDown"
|
|
46566
|
+
const isVerticalNavigationKey = key === "ArrowUp" || key === "ArrowDown";
|
|
46295
46567
|
if (isVerticalNavigationKey) {
|
|
46296
46568
|
event.preventDefault();
|
|
46297
46569
|
event.stopPropagation();
|
|
@@ -46303,7 +46575,7 @@ function Sidebar() {
|
|
|
46303
46575
|
addProjectButtonRef.current?.focus({ preventScroll: true });
|
|
46304
46576
|
return;
|
|
46305
46577
|
}
|
|
46306
|
-
const nextIndex =
|
|
46578
|
+
const nextIndex = Math.max(
|
|
46307
46579
|
0,
|
|
46308
46580
|
Math.min(navigationItems.length - 1, currentIndex + (key === "ArrowDown" ? 1 : -1))
|
|
46309
46581
|
);
|
|
@@ -46311,22 +46583,10 @@ function Sidebar() {
|
|
|
46311
46583
|
if (nextItem) focusNavigationItem(nextItem);
|
|
46312
46584
|
return;
|
|
46313
46585
|
}
|
|
46314
|
-
if (
|
|
46586
|
+
if (isContextMenuKey(event)) {
|
|
46315
46587
|
event.preventDefault();
|
|
46316
46588
|
event.stopPropagation();
|
|
46317
|
-
|
|
46318
|
-
const rect = target.getBoundingClientRect();
|
|
46319
|
-
target.dispatchEvent(
|
|
46320
|
-
new MouseEvent("contextmenu", {
|
|
46321
|
-
bubbles: true,
|
|
46322
|
-
cancelable: true,
|
|
46323
|
-
view: window,
|
|
46324
|
-
button: 2,
|
|
46325
|
-
buttons: 2,
|
|
46326
|
-
clientX: rect.left + rect.width / 2,
|
|
46327
|
-
clientY: rect.top + rect.height / 2
|
|
46328
|
-
})
|
|
46329
|
-
);
|
|
46589
|
+
openContextMenuFromKeyboard(event.currentTarget);
|
|
46330
46590
|
return;
|
|
46331
46591
|
}
|
|
46332
46592
|
if (key === "ArrowLeft" || key === "ArrowRight") {
|
|
@@ -46363,7 +46623,7 @@ function Sidebar() {
|
|
|
46363
46623
|
};
|
|
46364
46624
|
const handleAddProjectKeyDown = (event) => {
|
|
46365
46625
|
const { key } = event;
|
|
46366
|
-
if (key === "ArrowLeft" || key === "ArrowRight"
|
|
46626
|
+
if (key === "ArrowLeft" || key === "ArrowRight") {
|
|
46367
46627
|
event.preventDefault();
|
|
46368
46628
|
event.stopPropagation();
|
|
46369
46629
|
addProjectButtonRef.current?.focus({ preventScroll: true });
|
|
@@ -46437,512 +46697,533 @@ function Sidebar() {
|
|
|
46437
46697
|
}
|
|
46438
46698
|
)
|
|
46439
46699
|
] }),
|
|
46440
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46441
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-normal tracking-wide text-sidebar-foreground/40 uppercase select-none", children: t("sidebar.projects") }),
|
|
46442
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46443
|
-
Button,
|
|
46444
|
-
{
|
|
46445
|
-
ref: addProjectButtonRef,
|
|
46446
|
-
variant: "ghost",
|
|
46447
|
-
size: "icon",
|
|
46448
|
-
tabIndex: -1,
|
|
46449
|
-
className: "size-6 -mr-1 text-sidebar-foreground/45 hover:bg-sidebar-accent/30 hover:text-sidebar-foreground/70",
|
|
46450
|
-
onClick: handleAddProject,
|
|
46451
|
-
onKeyDown: handleAddProjectKeyDown,
|
|
46452
|
-
"aria-label": t("sidebar.addProject", "Add project"),
|
|
46453
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderPlus, { className: "size-3.5" })
|
|
46454
|
-
}
|
|
46455
|
-
)
|
|
46456
|
-
] }),
|
|
46457
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46700
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46458
46701
|
"div",
|
|
46459
46702
|
{
|
|
46460
|
-
|
|
46461
|
-
|
|
46462
|
-
|
|
46463
|
-
|
|
46464
|
-
children:
|
|
46465
|
-
|
|
46466
|
-
|
|
46467
|
-
|
|
46468
|
-
|
|
46469
|
-
const connectedSessions = projectSessions.filter(
|
|
46470
|
-
(session2) => session2.connectionStatus === "connected"
|
|
46471
|
-
);
|
|
46472
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5 group", children: [
|
|
46473
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46474
|
-
HoverCard,
|
|
46703
|
+
className: "relative flex min-h-0 flex-1 flex-col",
|
|
46704
|
+
onDragOver: handleProjectDropDragOver,
|
|
46705
|
+
onDragLeave: handleProjectDropDragLeave,
|
|
46706
|
+
onDrop: (event) => void handleProjectDropDrop(event),
|
|
46707
|
+
children: [
|
|
46708
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between px-3 pt-2", children: [
|
|
46709
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-normal tracking-wide text-sidebar-foreground/40 uppercase select-none", children: t("sidebar.projects") }),
|
|
46710
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46711
|
+
Button,
|
|
46475
46712
|
{
|
|
46476
|
-
|
|
46477
|
-
|
|
46478
|
-
|
|
46479
|
-
|
|
46480
|
-
|
|
46481
|
-
|
|
46482
|
-
|
|
46483
|
-
|
|
46484
|
-
children:
|
|
46485
|
-
|
|
46486
|
-
|
|
46713
|
+
ref: addProjectButtonRef,
|
|
46714
|
+
variant: "ghost",
|
|
46715
|
+
size: "icon",
|
|
46716
|
+
tabIndex: -1,
|
|
46717
|
+
className: "size-6 -mr-1 text-sidebar-foreground/45 hover:bg-sidebar-accent/30 hover:text-sidebar-foreground/70",
|
|
46718
|
+
onClick: handleAddProject,
|
|
46719
|
+
onKeyDown: handleAddProjectKeyDown,
|
|
46720
|
+
"aria-label": t("sidebar.addProject", "Add project"),
|
|
46721
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderPlus, { className: "size-3.5" })
|
|
46722
|
+
}
|
|
46723
|
+
)
|
|
46724
|
+
] }),
|
|
46725
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46726
|
+
"div",
|
|
46727
|
+
{
|
|
46728
|
+
ref: sessionListRef,
|
|
46729
|
+
role: "tree",
|
|
46730
|
+
"aria-label": t("sidebar.sessions", "Sessions"),
|
|
46731
|
+
className: "space-y-0.5 p-1.5 outline-none focus:ring-1 focus:ring-ring/50",
|
|
46732
|
+
children: sortedProjects.map((project) => {
|
|
46733
|
+
const projectSessions = sessionsByProject[project.id] ?? [];
|
|
46734
|
+
const expanded = isProjectExpanded(project.id);
|
|
46735
|
+
const currentHoverId = projectHoverId(project.id);
|
|
46736
|
+
const latestProjectUpdateAt = projectSessions.length > 0 ? projectSessions.reduce((max2, session2) => Math.max(max2, session2.updatedAt), 0) : project.createdAt;
|
|
46737
|
+
const connectedSessions = projectSessions.filter(
|
|
46738
|
+
(session2) => session2.connectionStatus === "connected"
|
|
46739
|
+
);
|
|
46740
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0.5 group", children: [
|
|
46741
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46742
|
+
HoverCard,
|
|
46487
46743
|
{
|
|
46744
|
+
open: hoverId === currentHoverId,
|
|
46488
46745
|
onOpenChange: (open2) => {
|
|
46489
|
-
setContextMenuId(open2 ? currentHoverId : null);
|
|
46490
46746
|
if (open2) {
|
|
46747
|
+
if (contextMenuId === null) setHoverId(currentHoverId);
|
|
46748
|
+
} else if (hoverId === currentHoverId && hoveredTriggerIdRef.current !== currentHoverId) {
|
|
46491
46749
|
setHoverId(null);
|
|
46492
|
-
} else if (hoveredTriggerIdRef.current === currentHoverId) {
|
|
46493
|
-
setHoverId(currentHoverId);
|
|
46494
46750
|
}
|
|
46495
46751
|
},
|
|
46496
46752
|
children: [
|
|
46497
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46498
|
-
|
|
46753
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(HoverCardTrigger, { render: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}), delay: 0, closeDelay: 100, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46754
|
+
ContextMenu,
|
|
46499
46755
|
{
|
|
46500
|
-
|
|
46501
|
-
|
|
46502
|
-
{
|
|
46503
|
-
|
|
46504
|
-
|
|
46505
|
-
|
|
46506
|
-
id: project.id
|
|
46507
|
-
});
|
|
46508
|
-
if (element) {
|
|
46509
|
-
navigationItemRefs.current.set(key, element);
|
|
46510
|
-
} else {
|
|
46511
|
-
navigationItemRefs.current.delete(key);
|
|
46512
|
-
}
|
|
46513
|
-
},
|
|
46514
|
-
tabIndex: -1,
|
|
46515
|
-
role: "treeitem",
|
|
46516
|
-
"aria-level": 1,
|
|
46517
|
-
"aria-expanded": expanded,
|
|
46518
|
-
onClick: () => toggleProject(project.id),
|
|
46519
|
-
onKeyDown: (event) => handleNavigationKeyDown(event, {
|
|
46520
|
-
type: "project",
|
|
46521
|
-
id: project.id
|
|
46522
|
-
}),
|
|
46523
|
-
onPointerEnter: () => {
|
|
46524
|
-
hoveredTriggerIdRef.current = currentHoverId;
|
|
46525
|
-
},
|
|
46526
|
-
onPointerLeave: () => {
|
|
46527
|
-
hoveredTriggerIdRef.current = null;
|
|
46528
|
-
},
|
|
46529
|
-
className: cn$1(
|
|
46530
|
-
"flex h-7 cursor-default items-center gap-1.5 rounded-md px-1.5 text-xs font-normal transition-colors text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-foreground/95 outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
46531
|
-
connectedSessions.length > 0 ? "text-sidebar-foreground/60" : "",
|
|
46532
|
-
hoverId === currentHoverId || contextMenuId === currentHoverId ? "bg-sidebar-accent" : ""
|
|
46533
|
-
)
|
|
46756
|
+
onOpenChange: (open2) => {
|
|
46757
|
+
setContextMenuId(open2 ? currentHoverId : null);
|
|
46758
|
+
if (open2) {
|
|
46759
|
+
setHoverId(null);
|
|
46760
|
+
} else if (hoveredTriggerIdRef.current === currentHoverId) {
|
|
46761
|
+
setHoverId(currentHoverId);
|
|
46534
46762
|
}
|
|
46535
|
-
|
|
46763
|
+
},
|
|
46536
46764
|
children: [
|
|
46537
|
-
|
|
46538
|
-
|
|
46539
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46540
|
-
"button",
|
|
46765
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46766
|
+
ContextMenuTrigger,
|
|
46541
46767
|
{
|
|
46542
|
-
|
|
46543
|
-
|
|
46544
|
-
|
|
46545
|
-
|
|
46546
|
-
|
|
46547
|
-
|
|
46548
|
-
|
|
46549
|
-
|
|
46550
|
-
|
|
46551
|
-
|
|
46552
|
-
|
|
46768
|
+
render: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46769
|
+
"div",
|
|
46770
|
+
{
|
|
46771
|
+
ref: (element) => {
|
|
46772
|
+
const key = sidebarNavigationItemKey({
|
|
46773
|
+
type: "project",
|
|
46774
|
+
id: project.id
|
|
46775
|
+
});
|
|
46776
|
+
if (element) {
|
|
46777
|
+
navigationItemRefs.current.set(key, element);
|
|
46778
|
+
} else {
|
|
46779
|
+
navigationItemRefs.current.delete(key);
|
|
46780
|
+
}
|
|
46781
|
+
},
|
|
46782
|
+
tabIndex: -1,
|
|
46783
|
+
role: "treeitem",
|
|
46784
|
+
"aria-level": 1,
|
|
46785
|
+
"aria-expanded": expanded,
|
|
46786
|
+
onClick: () => toggleProject(project.id),
|
|
46787
|
+
onKeyDown: (event) => handleNavigationKeyDown(event, {
|
|
46788
|
+
type: "project",
|
|
46789
|
+
id: project.id
|
|
46790
|
+
}),
|
|
46791
|
+
onPointerEnter: () => {
|
|
46792
|
+
hoveredTriggerIdRef.current = currentHoverId;
|
|
46793
|
+
},
|
|
46794
|
+
onPointerLeave: () => {
|
|
46795
|
+
hoveredTriggerIdRef.current = null;
|
|
46796
|
+
},
|
|
46797
|
+
className: cn$1(
|
|
46798
|
+
"flex h-7 cursor-default items-center gap-1.5 rounded-md px-1.5 text-xs font-normal transition-colors text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-foreground/95 outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
46799
|
+
connectedSessions.length > 0 ? "text-sidebar-foreground/60" : "",
|
|
46800
|
+
hoverId === currentHoverId || contextMenuId === currentHoverId ? "bg-sidebar-accent" : ""
|
|
46801
|
+
)
|
|
46802
|
+
}
|
|
46803
|
+
),
|
|
46804
|
+
children: [
|
|
46805
|
+
expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(FolderClosed, { className: "size-3.5" }),
|
|
46806
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate leading-normal font-normal uppercase select-none", children: project.title }),
|
|
46807
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46808
|
+
"button",
|
|
46809
|
+
{
|
|
46810
|
+
type: "button",
|
|
46811
|
+
onClick: (e) => {
|
|
46812
|
+
e.stopPropagation();
|
|
46813
|
+
openNewSessionDialog(project.id);
|
|
46814
|
+
},
|
|
46815
|
+
className: `flex size-4 items-center justify-center rounded-sm text-sidebar-foreground/40 hover:bg-sidebar-accent/25 hover:text-sidebar-foreground/70 transition-opacity duration-300 ${projectSessions.length === 0 ? "opacity-100" : "opacity-0 group-hover:opacity-100"}`,
|
|
46816
|
+
"aria-label": t("sidebar.createSessionInProject", {
|
|
46817
|
+
defaultValue: "Create session in {{title}}",
|
|
46818
|
+
title: project.title
|
|
46819
|
+
}),
|
|
46820
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageCirclePlus, { className: "size-3.5" })
|
|
46821
|
+
}
|
|
46822
|
+
)
|
|
46823
|
+
]
|
|
46553
46824
|
}
|
|
46554
|
-
)
|
|
46825
|
+
),
|
|
46826
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuContent, { className: "w-48", children: [
|
|
46827
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46828
|
+
ContextMenuItem,
|
|
46829
|
+
{
|
|
46830
|
+
onClick: () => openNewSessionDialog(project.id),
|
|
46831
|
+
className: "font-medium text-foreground",
|
|
46832
|
+
children: [
|
|
46833
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageCirclePlus, { className: "size-3" }),
|
|
46834
|
+
t("sidebar.newSession", "New Session")
|
|
46835
|
+
]
|
|
46836
|
+
}
|
|
46837
|
+
),
|
|
46838
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
46839
|
+
!isWebUI && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46840
|
+
ContextMenuItem,
|
|
46841
|
+
{
|
|
46842
|
+
onClick: () => void handleRevealProjectInFinder(project),
|
|
46843
|
+
children: [
|
|
46844
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3" }),
|
|
46845
|
+
t("sidebar.revealInFinder")
|
|
46846
|
+
]
|
|
46847
|
+
}
|
|
46848
|
+
),
|
|
46849
|
+
!isWebUI && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46850
|
+
ContextMenuItem,
|
|
46851
|
+
{
|
|
46852
|
+
onClick: () => void handleOpenProjectInEditor(project),
|
|
46853
|
+
children: [
|
|
46854
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Code, { className: "size-3" }),
|
|
46855
|
+
t("filePanel.openInEditor", {
|
|
46856
|
+
editor: EDITOR_LABELS[useAppStore.getState().editor.name] ?? "Editor"
|
|
46857
|
+
})
|
|
46858
|
+
]
|
|
46859
|
+
}
|
|
46860
|
+
),
|
|
46861
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: () => void handleCopyProjectPath(project), children: [
|
|
46862
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" }),
|
|
46863
|
+
t("sidebar.copyProjectPath")
|
|
46864
|
+
] }),
|
|
46865
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: () => void handleRenameProject(project), children: [
|
|
46866
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "size-3" }),
|
|
46867
|
+
t("sidebar.rename")
|
|
46868
|
+
] }),
|
|
46869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
46870
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46871
|
+
ContextMenuItem,
|
|
46872
|
+
{
|
|
46873
|
+
variant: "destructive",
|
|
46874
|
+
onClick: () => void handleDeleteProject(project),
|
|
46875
|
+
children: [
|
|
46876
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash, { className: "size-3" }),
|
|
46877
|
+
t("sidebar.deleteProject")
|
|
46878
|
+
]
|
|
46879
|
+
}
|
|
46880
|
+
)
|
|
46881
|
+
] })
|
|
46555
46882
|
]
|
|
46556
46883
|
}
|
|
46557
|
-
),
|
|
46558
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
46559
|
-
|
|
46560
|
-
|
|
46561
|
-
|
|
46562
|
-
|
|
46563
|
-
|
|
46564
|
-
|
|
46565
|
-
|
|
46566
|
-
|
|
46567
|
-
|
|
46568
|
-
|
|
46569
|
-
|
|
46570
|
-
|
|
46571
|
-
|
|
46572
|
-
|
|
46573
|
-
|
|
46574
|
-
|
|
46575
|
-
|
|
46576
|
-
|
|
46577
|
-
|
|
46578
|
-
|
|
46579
|
-
|
|
46580
|
-
|
|
46581
|
-
|
|
46582
|
-
|
|
46583
|
-
|
|
46584
|
-
|
|
46585
|
-
|
|
46586
|
-
|
|
46587
|
-
|
|
46588
|
-
|
|
46589
|
-
|
|
46590
|
-
|
|
46591
|
-
|
|
46592
|
-
|
|
46593
|
-
|
|
46594
|
-
|
|
46595
|
-
|
|
46596
|
-
|
|
46597
|
-
|
|
46598
|
-
|
|
46599
|
-
|
|
46600
|
-
|
|
46601
|
-
|
|
46602
|
-
|
|
46603
|
-
] })
|
|
46884
|
+
) }),
|
|
46885
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46886
|
+
HoverCardContent,
|
|
46887
|
+
{
|
|
46888
|
+
side: "right",
|
|
46889
|
+
align: "start",
|
|
46890
|
+
sideOffset: 12,
|
|
46891
|
+
alignOffset: 0,
|
|
46892
|
+
className: "w-54 max-w-[20vw] p-3",
|
|
46893
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
46894
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium leading-snug line-clamp-2 wrap-break-word", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: project.title }) }),
|
|
46895
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46896
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { className: "size-3 shrink-0" }),
|
|
46897
|
+
isWebUI ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", title: project.cwd, children: project.cwd }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46898
|
+
"button",
|
|
46899
|
+
{
|
|
46900
|
+
type: "button",
|
|
46901
|
+
onClick: () => void handleRevealProjectInFinder(project),
|
|
46902
|
+
title: project.cwd,
|
|
46903
|
+
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
46904
|
+
children: project.cwd
|
|
46905
|
+
}
|
|
46906
|
+
)
|
|
46907
|
+
] }),
|
|
46908
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46909
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircle, { className: "size-3 shrink-0" }),
|
|
46910
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: t("sidebar.sessionCount", "{{count}} sessions", {
|
|
46911
|
+
count: projectSessions.length
|
|
46912
|
+
}) })
|
|
46913
|
+
] }),
|
|
46914
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46915
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }),
|
|
46916
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
46917
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
46918
|
+
t(
|
|
46919
|
+
projectSessions.length > 0 ? "sidebar.updated" : "sidebar.created",
|
|
46920
|
+
projectSessions.length > 0 ? "Updated" : "Created"
|
|
46921
|
+
),
|
|
46922
|
+
":"
|
|
46923
|
+
] }),
|
|
46924
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(latestProjectUpdateAt, i18n.language) })
|
|
46925
|
+
] })
|
|
46926
|
+
] })
|
|
46927
|
+
] })
|
|
46928
|
+
}
|
|
46929
|
+
)
|
|
46604
46930
|
]
|
|
46605
46931
|
}
|
|
46606
|
-
)
|
|
46607
|
-
|
|
46608
|
-
|
|
46609
|
-
|
|
46610
|
-
|
|
46611
|
-
|
|
46612
|
-
sideOffset: 12,
|
|
46613
|
-
alignOffset: 0,
|
|
46614
|
-
className: "w-54 max-w-[20vw] p-3",
|
|
46615
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
46616
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium leading-snug line-clamp-2 wrap-break-word", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: project.title }) }),
|
|
46617
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46618
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { className: "size-3 shrink-0" }),
|
|
46619
|
-
isWebUI ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", title: project.cwd, children: project.cwd }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46620
|
-
"button",
|
|
46621
|
-
{
|
|
46622
|
-
type: "button",
|
|
46623
|
-
onClick: () => void handleRevealProjectInFinder(project),
|
|
46624
|
-
title: project.cwd,
|
|
46625
|
-
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
46626
|
-
children: project.cwd
|
|
46627
|
-
}
|
|
46628
|
-
)
|
|
46629
|
-
] }),
|
|
46630
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46631
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircle, { className: "size-3 shrink-0" }),
|
|
46632
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: t("sidebar.sessionCount", "{{count}} sessions", {
|
|
46633
|
-
count: projectSessions.length
|
|
46634
|
-
}) })
|
|
46635
|
-
] }),
|
|
46636
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46637
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }),
|
|
46638
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
46639
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
46640
|
-
t(
|
|
46641
|
-
projectSessions.length > 0 ? "sidebar.updated" : "sidebar.created",
|
|
46642
|
-
projectSessions.length > 0 ? "Updated" : "Created"
|
|
46643
|
-
),
|
|
46644
|
-
":"
|
|
46645
|
-
] }),
|
|
46646
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(latestProjectUpdateAt, i18n.language) })
|
|
46647
|
-
] })
|
|
46648
|
-
] })
|
|
46649
|
-
] })
|
|
46650
|
-
}
|
|
46651
|
-
)
|
|
46652
|
-
]
|
|
46653
|
-
}
|
|
46654
|
-
),
|
|
46655
|
-
expanded && projectSessions.map((session2) => {
|
|
46656
|
-
const currentHoverId2 = sessionHoverId(session2.id);
|
|
46657
|
-
const agentLabel = configuredAgents.find((a) => a.id === session2.agentId)?.id || session2.agentId;
|
|
46658
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46659
|
-
HoverCard,
|
|
46660
|
-
{
|
|
46661
|
-
open: hoverId === currentHoverId2,
|
|
46662
|
-
onOpenChange: (open2) => {
|
|
46663
|
-
if (open2) {
|
|
46664
|
-
if (contextMenuId === null) setHoverId(currentHoverId2);
|
|
46665
|
-
} else if (hoverId === currentHoverId2 && hoveredTriggerIdRef.current !== currentHoverId2) {
|
|
46666
|
-
setHoverId(null);
|
|
46667
|
-
}
|
|
46668
|
-
},
|
|
46669
|
-
children: [
|
|
46670
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(HoverCardTrigger, { render: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}), delay: 0, closeDelay: 100, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46671
|
-
ContextMenu,
|
|
46932
|
+
),
|
|
46933
|
+
expanded && projectSessions.map((session2) => {
|
|
46934
|
+
const currentHoverId2 = sessionHoverId(session2.id);
|
|
46935
|
+
const agentLabel = configuredAgents.find((a) => a.id === session2.agentId)?.id || session2.agentId;
|
|
46936
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46937
|
+
HoverCard,
|
|
46672
46938
|
{
|
|
46939
|
+
open: hoverId === currentHoverId2,
|
|
46673
46940
|
onOpenChange: (open2) => {
|
|
46674
|
-
setContextMenuId(open2 ? currentHoverId2 : null);
|
|
46675
46941
|
if (open2) {
|
|
46942
|
+
if (contextMenuId === null) setHoverId(currentHoverId2);
|
|
46943
|
+
} else if (hoverId === currentHoverId2 && hoveredTriggerIdRef.current !== currentHoverId2) {
|
|
46676
46944
|
setHoverId(null);
|
|
46677
|
-
} else if (hoveredTriggerIdRef.current === currentHoverId2) {
|
|
46678
|
-
setHoverId(currentHoverId2);
|
|
46679
46945
|
}
|
|
46680
46946
|
},
|
|
46681
46947
|
children: [
|
|
46682
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46683
|
-
|
|
46948
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(HoverCardTrigger, { render: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}), delay: 0, closeDelay: 100, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46949
|
+
ContextMenu,
|
|
46684
46950
|
{
|
|
46685
|
-
|
|
46686
|
-
|
|
46687
|
-
{
|
|
46688
|
-
|
|
46689
|
-
|
|
46690
|
-
|
|
46691
|
-
id: session2.id,
|
|
46692
|
-
projectId: project.id
|
|
46693
|
-
});
|
|
46694
|
-
if (element) {
|
|
46695
|
-
navigationItemRefs.current.set(key, element);
|
|
46696
|
-
} else {
|
|
46697
|
-
navigationItemRefs.current.delete(key);
|
|
46698
|
-
}
|
|
46699
|
-
},
|
|
46700
|
-
tabIndex: -1,
|
|
46701
|
-
role: "treeitem",
|
|
46702
|
-
"aria-level": 2,
|
|
46703
|
-
"aria-current": activeSessionId === session2.id ? "page" : void 0,
|
|
46704
|
-
onClick: () => handleSelectSession(session2),
|
|
46705
|
-
onKeyDown: (event) => handleNavigationKeyDown(event, {
|
|
46706
|
-
type: "session",
|
|
46707
|
-
id: session2.id,
|
|
46708
|
-
projectId: project.id
|
|
46709
|
-
}),
|
|
46710
|
-
onPointerEnter: () => {
|
|
46711
|
-
hoveredTriggerIdRef.current = currentHoverId2;
|
|
46712
|
-
},
|
|
46713
|
-
onPointerLeave: () => {
|
|
46714
|
-
hoveredTriggerIdRef.current = null;
|
|
46715
|
-
},
|
|
46716
|
-
className: `group flex h-7 cursor-default items-center justify-between rounded-md pl-1.5 pr-2 text-xs font-normal transition-colors outline-none focus-visible:ring-1 focus-visible:ring-ring ${activeSessionId === session2.id ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-foreground/95"} ${hoverId === currentHoverId2 || contextMenuId === currentHoverId2 ? "bg-sidebar-accent" : ""}`
|
|
46951
|
+
onOpenChange: (open2) => {
|
|
46952
|
+
setContextMenuId(open2 ? currentHoverId2 : null);
|
|
46953
|
+
if (open2) {
|
|
46954
|
+
setHoverId(null);
|
|
46955
|
+
} else if (hoveredTriggerIdRef.current === currentHoverId2) {
|
|
46956
|
+
setHoverId(currentHoverId2);
|
|
46717
46957
|
}
|
|
46718
|
-
|
|
46719
|
-
children:
|
|
46720
|
-
|
|
46721
|
-
|
|
46722
|
-
|
|
46723
|
-
|
|
46724
|
-
|
|
46725
|
-
|
|
46726
|
-
|
|
46727
|
-
|
|
46728
|
-
|
|
46729
|
-
|
|
46730
|
-
|
|
46731
|
-
|
|
46732
|
-
|
|
46733
|
-
|
|
46734
|
-
|
|
46735
|
-
|
|
46736
|
-
|
|
46737
|
-
|
|
46738
|
-
|
|
46739
|
-
|
|
46958
|
+
},
|
|
46959
|
+
children: [
|
|
46960
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46961
|
+
ContextMenuTrigger,
|
|
46962
|
+
{
|
|
46963
|
+
render: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46964
|
+
"div",
|
|
46965
|
+
{
|
|
46966
|
+
ref: (element) => {
|
|
46967
|
+
const key = sidebarNavigationItemKey({
|
|
46968
|
+
type: "session",
|
|
46969
|
+
id: session2.id,
|
|
46970
|
+
projectId: project.id
|
|
46971
|
+
});
|
|
46972
|
+
if (element) {
|
|
46973
|
+
navigationItemRefs.current.set(key, element);
|
|
46974
|
+
} else {
|
|
46975
|
+
navigationItemRefs.current.delete(key);
|
|
46976
|
+
}
|
|
46977
|
+
},
|
|
46978
|
+
tabIndex: -1,
|
|
46979
|
+
role: "treeitem",
|
|
46980
|
+
"aria-level": 2,
|
|
46981
|
+
"aria-current": activeSessionId === session2.id ? "page" : void 0,
|
|
46982
|
+
onClick: () => handleSelectSession(session2),
|
|
46983
|
+
onKeyDown: (event) => handleNavigationKeyDown(event, {
|
|
46984
|
+
type: "session",
|
|
46985
|
+
id: session2.id,
|
|
46986
|
+
projectId: project.id
|
|
46987
|
+
}),
|
|
46988
|
+
onPointerEnter: () => {
|
|
46989
|
+
hoveredTriggerIdRef.current = currentHoverId2;
|
|
46990
|
+
},
|
|
46991
|
+
onPointerLeave: () => {
|
|
46992
|
+
hoveredTriggerIdRef.current = null;
|
|
46993
|
+
},
|
|
46994
|
+
className: `group flex h-7 cursor-default items-center justify-between rounded-md pl-1.5 pr-2 text-xs font-normal transition-colors outline-none focus-visible:ring-1 focus-visible:ring-ring ${activeSessionId === session2.id ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-foreground/95"} ${hoverId === currentHoverId2 || contextMenuId === currentHoverId2 ? "bg-sidebar-accent" : ""}`
|
|
46740
46995
|
}
|
|
46741
|
-
|
|
46742
|
-
|
|
46996
|
+
),
|
|
46997
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46998
|
+
"div",
|
|
46999
|
+
{
|
|
47000
|
+
className: cn$1(
|
|
47001
|
+
"flex min-w-0 flex-1 items-center gap-1.5",
|
|
47002
|
+
session2.connectionStatus === "connected" ? "" : "opacity-60"
|
|
47003
|
+
),
|
|
47004
|
+
children: [
|
|
47005
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47006
|
+
SessionRowStatus,
|
|
47007
|
+
{
|
|
47008
|
+
sessionId: session2.id,
|
|
47009
|
+
isStreaming: session2.isStreaming
|
|
47010
|
+
}
|
|
47011
|
+
),
|
|
47012
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47013
|
+
Badge,
|
|
47014
|
+
{
|
|
47015
|
+
variant: "outline",
|
|
47016
|
+
className: "px-1 -ml-0.5 text-[10px] uppercase select-none max-w-24",
|
|
47017
|
+
children: agentLabel
|
|
47018
|
+
}
|
|
47019
|
+
),
|
|
47020
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 truncate leading-normal select-none", children: session2.title || t("sidebar.newSession", "New Session") }),
|
|
47021
|
+
activeIlinkSessionId === session2.id && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircle, { className: "size-3 shrink-0 text-green-500" })
|
|
47022
|
+
]
|
|
46743
47023
|
}
|
|
46744
|
-
|
|
46745
|
-
|
|
46746
|
-
|
|
46747
|
-
|
|
47024
|
+
)
|
|
47025
|
+
}
|
|
47026
|
+
),
|
|
47027
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuContent, { className: "w-48", children: [
|
|
47028
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47029
|
+
ContextMenuItem,
|
|
47030
|
+
{
|
|
47031
|
+
onClick: () => handleSelectSession(session2),
|
|
47032
|
+
className: "font-medium text-foreground",
|
|
47033
|
+
children: [
|
|
47034
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "size-3" }),
|
|
47035
|
+
t("sidebar.viewSession", "View Session")
|
|
47036
|
+
]
|
|
47037
|
+
}
|
|
47038
|
+
),
|
|
47039
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
47040
|
+
!isWebUI && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47041
|
+
ContextMenuItem,
|
|
47042
|
+
{
|
|
47043
|
+
onClick: () => void handleRevealProjectInFinder(project),
|
|
47044
|
+
children: [
|
|
47045
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3" }),
|
|
47046
|
+
t("sidebar.revealInFinder")
|
|
47047
|
+
]
|
|
47048
|
+
}
|
|
47049
|
+
),
|
|
47050
|
+
!isWebUI && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47051
|
+
ContextMenuItem,
|
|
47052
|
+
{
|
|
47053
|
+
onClick: () => void handleOpenProjectInEditor(project),
|
|
47054
|
+
children: [
|
|
47055
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Code, { className: "size-3" }),
|
|
47056
|
+
t("filePanel.openInEditor", {
|
|
47057
|
+
editor: EDITOR_LABELS[useAppStore.getState().editor.name] ?? "Editor"
|
|
47058
|
+
})
|
|
47059
|
+
]
|
|
47060
|
+
}
|
|
47061
|
+
),
|
|
47062
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47063
|
+
ContextMenuItem,
|
|
47064
|
+
{
|
|
47065
|
+
onClick: () => void handleCopyProjectPath(project),
|
|
47066
|
+
children: [
|
|
47067
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" }),
|
|
47068
|
+
t("sidebar.copyProjectPath")
|
|
47069
|
+
]
|
|
47070
|
+
}
|
|
47071
|
+
),
|
|
47072
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: () => handleRenameSession(session2), children: [
|
|
47073
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { className: "size-3" }),
|
|
47074
|
+
t("sidebar.rename")
|
|
47075
|
+
] }),
|
|
47076
|
+
ilinkStatus.connected && activeIlinkSessionId !== session2.id && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47077
|
+
ContextMenuItem,
|
|
47078
|
+
{
|
|
47079
|
+
onClick: () => void handleSetActiveIlinkSession(session2.id),
|
|
47080
|
+
children: [
|
|
47081
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircle, { className: "size-3" }),
|
|
47082
|
+
t("sidebar.ilinkSetActive", "Set as WeChat Active")
|
|
47083
|
+
]
|
|
47084
|
+
}
|
|
47085
|
+
),
|
|
47086
|
+
ilinkStatus.connected && activeIlinkSessionId === session2.id && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47087
|
+
ContextMenuItem,
|
|
47088
|
+
{
|
|
47089
|
+
onClick: () => void handleSetActiveIlinkSession(""),
|
|
47090
|
+
children: [
|
|
47091
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircle, { className: "size-3 text-green-500" }),
|
|
47092
|
+
t("sidebar.ilinkUnsetActive", "Unset WeChat Active")
|
|
47093
|
+
]
|
|
47094
|
+
}
|
|
47095
|
+
),
|
|
47096
|
+
session2.connectionStatus === "connected" && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
47097
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
47098
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47099
|
+
ContextMenuItem,
|
|
46748
47100
|
{
|
|
46749
|
-
|
|
46750
|
-
|
|
46751
|
-
children:
|
|
47101
|
+
onClick: () => void handleRestartSession(session2),
|
|
47102
|
+
disabled: sessionAction !== null,
|
|
47103
|
+
children: [
|
|
47104
|
+
sessionAction?.id === session2.id && sessionAction.type === "restart" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3" }),
|
|
47105
|
+
t("sidebar.restartSession", "Restart Session")
|
|
47106
|
+
]
|
|
46752
47107
|
}
|
|
46753
47108
|
),
|
|
46754
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
46755
|
-
|
|
46756
|
-
|
|
46757
|
-
|
|
46758
|
-
|
|
47109
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47110
|
+
ContextMenuItem,
|
|
47111
|
+
{
|
|
47112
|
+
onClick: () => void handleCloseSession(session2),
|
|
47113
|
+
disabled: sessionAction !== null,
|
|
47114
|
+
children: [
|
|
47115
|
+
sessionAction?.id === session2.id && sessionAction.type === "close" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Power, { className: "size-3" }),
|
|
47116
|
+
sessionAction?.id === session2.id && sessionAction.type === "close" ? t("sidebar.closingSession", "Closing…") : t("sidebar.closeSession", "Close Session")
|
|
47117
|
+
]
|
|
47118
|
+
}
|
|
47119
|
+
)
|
|
47120
|
+
] }),
|
|
47121
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
47122
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47123
|
+
ContextMenuItem,
|
|
47124
|
+
{
|
|
47125
|
+
variant: "destructive",
|
|
47126
|
+
onClick: () => void handleDeleteSession(session2),
|
|
47127
|
+
disabled: sessionAction !== null,
|
|
47128
|
+
children: [
|
|
47129
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash, { className: "size-3" }),
|
|
47130
|
+
t("sidebar.deleteSession")
|
|
47131
|
+
]
|
|
47132
|
+
}
|
|
47133
|
+
)
|
|
47134
|
+
] })
|
|
47135
|
+
]
|
|
46759
47136
|
}
|
|
46760
|
-
),
|
|
46761
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
46762
|
-
|
|
46763
|
-
|
|
46764
|
-
|
|
46765
|
-
|
|
46766
|
-
|
|
46767
|
-
|
|
46768
|
-
|
|
46769
|
-
|
|
46770
|
-
|
|
46771
|
-
|
|
46772
|
-
|
|
46773
|
-
|
|
46774
|
-
|
|
46775
|
-
|
|
46776
|
-
|
|
46777
|
-
|
|
46778
|
-
|
|
46779
|
-
|
|
46780
|
-
|
|
46781
|
-
|
|
46782
|
-
|
|
46783
|
-
|
|
46784
|
-
|
|
46785
|
-
|
|
46786
|
-
|
|
46787
|
-
|
|
46788
|
-
children: [
|
|
46789
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46790
|
-
|
|
46791
|
-
|
|
46792
|
-
|
|
46793
|
-
|
|
46794
|
-
|
|
46795
|
-
|
|
46796
|
-
|
|
46797
|
-
|
|
46798
|
-
|
|
46799
|
-
|
|
46800
|
-
|
|
46801
|
-
|
|
46802
|
-
|
|
46803
|
-
|
|
46804
|
-
|
|
46805
|
-
|
|
46806
|
-
|
|
46807
|
-
]
|
|
46808
|
-
|
|
46809
|
-
|
|
46810
|
-
|
|
46811
|
-
|
|
46812
|
-
|
|
46813
|
-
|
|
46814
|
-
|
|
46815
|
-
|
|
46816
|
-
|
|
46817
|
-
|
|
46818
|
-
|
|
46819
|
-
|
|
46820
|
-
|
|
46821
|
-
|
|
46822
|
-
|
|
46823
|
-
|
|
46824
|
-
|
|
46825
|
-
|
|
46826
|
-
|
|
46827
|
-
|
|
46828
|
-
|
|
46829
|
-
|
|
46830
|
-
|
|
46831
|
-
|
|
46832
|
-
|
|
46833
|
-
|
|
46834
|
-
|
|
46835
|
-
|
|
46836
|
-
onClick: () => void handleCloseSession(session2),
|
|
46837
|
-
disabled: sessionAction !== null,
|
|
46838
|
-
children: [
|
|
46839
|
-
sessionAction?.id === session2.id && sessionAction.type === "close" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Power, { className: "size-3" }),
|
|
46840
|
-
sessionAction?.id === session2.id && sessionAction.type === "close" ? t("sidebar.closingSession", "Closing…") : t("sidebar.closeSession", "Close Session")
|
|
46841
|
-
]
|
|
46842
|
-
}
|
|
46843
|
-
)
|
|
46844
|
-
] }),
|
|
46845
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
|
|
46846
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46847
|
-
ContextMenuItem,
|
|
46848
|
-
{
|
|
46849
|
-
variant: "destructive",
|
|
46850
|
-
onClick: () => void handleDeleteSession(session2),
|
|
46851
|
-
disabled: sessionAction !== null,
|
|
46852
|
-
children: [
|
|
46853
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Trash, { className: "size-3" }),
|
|
46854
|
-
t("sidebar.deleteSession")
|
|
46855
|
-
]
|
|
46856
|
-
}
|
|
46857
|
-
)
|
|
46858
|
-
] })
|
|
47137
|
+
) }),
|
|
47138
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47139
|
+
HoverCardContent,
|
|
47140
|
+
{
|
|
47141
|
+
side: "right",
|
|
47142
|
+
align: "start",
|
|
47143
|
+
sideOffset: 12,
|
|
47144
|
+
alignOffset: 0,
|
|
47145
|
+
className: "w-54 max-w-[20vw] p-3",
|
|
47146
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
47147
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium leading-snug line-clamp-2 wrap-break-word", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: session2.title || t("sidebar.newSession", "New Session") }) }),
|
|
47148
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
47149
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Bot, { className: "size-3 shrink-0" }),
|
|
47150
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: session2.agentId })
|
|
47151
|
+
] }),
|
|
47152
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
47153
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { className: "size-3 shrink-0" }),
|
|
47154
|
+
isWebUI ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: project.title }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47155
|
+
"button",
|
|
47156
|
+
{
|
|
47157
|
+
type: "button",
|
|
47158
|
+
onClick: () => void handleRevealProjectInFinder(project),
|
|
47159
|
+
title: project.cwd,
|
|
47160
|
+
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
47161
|
+
children: project.title
|
|
47162
|
+
}
|
|
47163
|
+
)
|
|
47164
|
+
] }),
|
|
47165
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
47166
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }),
|
|
47167
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
47168
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
47169
|
+
t("sidebar.updated", "Updated"),
|
|
47170
|
+
":"
|
|
47171
|
+
] }),
|
|
47172
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(session2.updatedAt, i18n.language) })
|
|
47173
|
+
] })
|
|
47174
|
+
] }),
|
|
47175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
47176
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CalendarDays, { className: "size-3 shrink-0" }),
|
|
47177
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
47178
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
47179
|
+
t("sidebar.created", "Created"),
|
|
47180
|
+
":"
|
|
47181
|
+
] }),
|
|
47182
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(session2.createdAt, i18n.language) })
|
|
47183
|
+
] })
|
|
47184
|
+
] }),
|
|
47185
|
+
ilinkStatus.connected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
47186
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47187
|
+
MessageCircle,
|
|
47188
|
+
{
|
|
47189
|
+
className: cn$1(
|
|
47190
|
+
"size-3 shrink-0",
|
|
47191
|
+
activeIlinkSessionId === session2.id && "text-green-500"
|
|
47192
|
+
)
|
|
47193
|
+
}
|
|
47194
|
+
),
|
|
47195
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47196
|
+
"button",
|
|
47197
|
+
{
|
|
47198
|
+
type: "button",
|
|
47199
|
+
onClick: () => void handleSetActiveIlinkSession(
|
|
47200
|
+
activeIlinkSessionId === session2.id ? "" : session2.id
|
|
47201
|
+
),
|
|
47202
|
+
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
47203
|
+
children: t(
|
|
47204
|
+
activeIlinkSessionId === session2.id ? "sidebar.ilinkActiveStatus" : "sidebar.ilinkInactiveStatus",
|
|
47205
|
+
activeIlinkSessionId === session2.id ? "WeChat Active" : "Not WeChat Active"
|
|
47206
|
+
)
|
|
47207
|
+
}
|
|
47208
|
+
)
|
|
47209
|
+
] })
|
|
47210
|
+
] })
|
|
47211
|
+
}
|
|
47212
|
+
)
|
|
46859
47213
|
]
|
|
46860
|
-
}
|
|
46861
|
-
|
|
46862
|
-
|
|
46863
|
-
|
|
46864
|
-
|
|
46865
|
-
|
|
46866
|
-
|
|
46867
|
-
|
|
46868
|
-
|
|
46869
|
-
|
|
46870
|
-
|
|
46871
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium leading-snug line-clamp-2 wrap-break-word", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: session2.title || t("sidebar.newSession", "New Session") }) }),
|
|
46872
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46873
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Bot, { className: "size-3 shrink-0" }),
|
|
46874
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: session2.agentId })
|
|
46875
|
-
] }),
|
|
46876
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46877
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Folder, { className: "size-3 shrink-0" }),
|
|
46878
|
-
isWebUI ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: project.title }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46879
|
-
"button",
|
|
46880
|
-
{
|
|
46881
|
-
type: "button",
|
|
46882
|
-
onClick: () => void handleRevealProjectInFinder(project),
|
|
46883
|
-
title: project.cwd,
|
|
46884
|
-
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
46885
|
-
children: project.title
|
|
46886
|
-
}
|
|
46887
|
-
)
|
|
46888
|
-
] }),
|
|
46889
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46890
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "size-3 shrink-0" }),
|
|
46891
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
46892
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
46893
|
-
t("sidebar.updated", "Updated"),
|
|
46894
|
-
":"
|
|
46895
|
-
] }),
|
|
46896
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(session2.updatedAt, i18n.language) })
|
|
46897
|
-
] })
|
|
46898
|
-
] }),
|
|
46899
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46900
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(CalendarDays, { className: "size-3 shrink-0" }),
|
|
46901
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "truncate", children: [
|
|
46902
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "mr-1", children: [
|
|
46903
|
-
t("sidebar.created", "Created"),
|
|
46904
|
-
":"
|
|
46905
|
-
] }),
|
|
46906
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: formatRelativeTime(session2.createdAt, i18n.language) })
|
|
46907
|
-
] })
|
|
46908
|
-
] }),
|
|
46909
|
-
ilinkStatus.connected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground py-px", children: [
|
|
46910
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46911
|
-
MessageCircle,
|
|
46912
|
-
{
|
|
46913
|
-
className: cn$1(
|
|
46914
|
-
"size-3 shrink-0",
|
|
46915
|
-
activeIlinkSessionId === session2.id && "text-green-500"
|
|
46916
|
-
)
|
|
46917
|
-
}
|
|
46918
|
-
),
|
|
46919
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
46920
|
-
"button",
|
|
46921
|
-
{
|
|
46922
|
-
type: "button",
|
|
46923
|
-
onClick: () => void handleSetActiveIlinkSession(
|
|
46924
|
-
activeIlinkSessionId === session2.id ? "" : session2.id
|
|
46925
|
-
),
|
|
46926
|
-
className: "min-w-0 flex-1 truncate text-left transition-colors hover:text-foreground",
|
|
46927
|
-
children: t(
|
|
46928
|
-
activeIlinkSessionId === session2.id ? "sidebar.ilinkActiveStatus" : "sidebar.ilinkInactiveStatus",
|
|
46929
|
-
activeIlinkSessionId === session2.id ? "WeChat Active" : "Not WeChat Active"
|
|
46930
|
-
)
|
|
46931
|
-
}
|
|
46932
|
-
)
|
|
46933
|
-
] })
|
|
46934
|
-
] })
|
|
46935
|
-
}
|
|
46936
|
-
)
|
|
46937
|
-
]
|
|
46938
|
-
},
|
|
46939
|
-
session2.id
|
|
46940
|
-
);
|
|
46941
|
-
})
|
|
46942
|
-
] }, project.id);
|
|
46943
|
-
})
|
|
47214
|
+
},
|
|
47215
|
+
session2.id
|
|
47216
|
+
);
|
|
47217
|
+
})
|
|
47218
|
+
] }, project.id);
|
|
47219
|
+
})
|
|
47220
|
+
}
|
|
47221
|
+
) }),
|
|
47222
|
+
projectDropActive && // 与 FilePanel 项目根落点同款的整块高亮(不参与布局)
|
|
47223
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pointer-events-none absolute inset-x-1 inset-y-1 rounded-md bg-primary/5 inset-ring-1 inset-ring-primary" })
|
|
47224
|
+
]
|
|
46944
47225
|
}
|
|
46945
|
-
)
|
|
47226
|
+
),
|
|
46946
47227
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-auto border-t border-border", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
46947
47228
|
Button,
|
|
46948
47229
|
{
|
|
@@ -47036,106 +47317,16 @@ function Sidebar() {
|
|
|
47036
47317
|
})()
|
|
47037
47318
|
] })
|
|
47038
47319
|
] }),
|
|
47039
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
47040
|
-
|
|
47041
|
-
|
|
47042
|
-
"
|
|
47043
|
-
|
|
47044
|
-
|
|
47045
|
-
|
|
47046
|
-
|
|
47047
|
-
|
|
47048
|
-
|
|
47049
|
-
onClick: () => setNewSessionFeatures(
|
|
47050
|
-
(prev) => prev.includes(feature) ? prev.filter((f2) => f2 !== feature) : [...prev, feature]
|
|
47051
|
-
),
|
|
47052
|
-
children: [
|
|
47053
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47054
|
-
"div",
|
|
47055
|
-
{
|
|
47056
|
-
className: cn$1(
|
|
47057
|
-
"text-xs truncate",
|
|
47058
|
-
!newSessionFeatures.includes(feature) ? "text-muted-foreground/50" : "text-muted-foreground"
|
|
47059
|
-
),
|
|
47060
|
-
children: t(FEATURE_I18N_KEYS[feature], { defaultValue: feature })
|
|
47061
|
-
}
|
|
47062
|
-
),
|
|
47063
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47064
|
-
Switch,
|
|
47065
|
-
{
|
|
47066
|
-
size: "sm",
|
|
47067
|
-
checked: newSessionFeatures.includes(feature),
|
|
47068
|
-
onCheckedChange: (checked2) => {
|
|
47069
|
-
setNewSessionFeatures(
|
|
47070
|
-
(prev) => checked2 ? [...prev, feature] : prev.filter((f2) => f2 !== feature)
|
|
47071
|
-
);
|
|
47072
|
-
}
|
|
47073
|
-
}
|
|
47074
|
-
) })
|
|
47075
|
-
]
|
|
47076
|
-
},
|
|
47077
|
-
feature
|
|
47078
|
-
))
|
|
47079
|
-
}
|
|
47080
|
-
)
|
|
47081
|
-
] }),
|
|
47082
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
47083
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: t("sidebar.newSessionDialog.mcp", { defaultValue: "MCP" }) }),
|
|
47084
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47085
|
-
"div",
|
|
47086
|
-
{
|
|
47087
|
-
className: configuredMcpServers.length >= 2 ? "grid grid-cols-2 gap-1" : "flex flex-col gap-1",
|
|
47088
|
-
children: [
|
|
47089
|
-
configuredMcpServers.map((mcp) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
47090
|
-
"div",
|
|
47091
|
-
{
|
|
47092
|
-
className: "flex items-center justify-between rounded border bg-secondary/50 px-2 h-7 cursor-default hover:bg-accent transition-colors",
|
|
47093
|
-
onClick: () => {
|
|
47094
|
-
setNewSessionMcpIds((prev) => {
|
|
47095
|
-
const next = new Set(prev);
|
|
47096
|
-
if (next.has(mcp.id)) next.delete(mcp.id);
|
|
47097
|
-
else next.add(mcp.id);
|
|
47098
|
-
return next;
|
|
47099
|
-
});
|
|
47100
|
-
},
|
|
47101
|
-
children: [
|
|
47102
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47103
|
-
"div",
|
|
47104
|
-
{
|
|
47105
|
-
className: cn$1(
|
|
47106
|
-
"text-xs truncate",
|
|
47107
|
-
!newSessionMcpIds.has(mcp.id) ? "text-muted-foreground/50" : "text-muted-foreground"
|
|
47108
|
-
),
|
|
47109
|
-
title: mcp.id,
|
|
47110
|
-
children: mcp.id
|
|
47111
|
-
}
|
|
47112
|
-
),
|
|
47113
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47114
|
-
Switch,
|
|
47115
|
-
{
|
|
47116
|
-
size: "sm",
|
|
47117
|
-
checked: newSessionMcpIds.has(mcp.id),
|
|
47118
|
-
onCheckedChange: (checked2) => {
|
|
47119
|
-
setNewSessionMcpIds((prev) => {
|
|
47120
|
-
const next = new Set(prev);
|
|
47121
|
-
if (checked2) next.add(mcp.id);
|
|
47122
|
-
else next.delete(mcp.id);
|
|
47123
|
-
return next;
|
|
47124
|
-
});
|
|
47125
|
-
}
|
|
47126
|
-
}
|
|
47127
|
-
) })
|
|
47128
|
-
]
|
|
47129
|
-
},
|
|
47130
|
-
mcp.id
|
|
47131
|
-
)),
|
|
47132
|
-
configuredMcpServers.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-muted-foreground", children: t("sidebar.newSessionDialog.noMcp", {
|
|
47133
|
-
defaultValue: "No MCP servers configured"
|
|
47134
|
-
}) })
|
|
47135
|
-
]
|
|
47136
|
-
}
|
|
47137
|
-
)
|
|
47138
|
-
] })
|
|
47320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47321
|
+
SessionConfigFields,
|
|
47322
|
+
{
|
|
47323
|
+
variant: "card",
|
|
47324
|
+
features: newSessionFeatures,
|
|
47325
|
+
onFeaturesChange: setNewSessionFeatures,
|
|
47326
|
+
mcpServers: Array.from(newSessionMcpIds),
|
|
47327
|
+
onMcpServersChange: (next) => setNewSessionMcpIds(new Set(next))
|
|
47328
|
+
}
|
|
47329
|
+
)
|
|
47139
47330
|
] }),
|
|
47140
47331
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(DialogFooter, { children: [
|
|
47141
47332
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -47383,7 +47574,7 @@ function Welcome() {
|
|
|
47383
47574
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute bottom-3 right-4 text-[11px] text-muted-foreground/40 z-10 pointer-events-none", children: [
|
|
47384
47575
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
|
|
47385
47576
|
"v",
|
|
47386
|
-
"0.1.
|
|
47577
|
+
"0.1.57"
|
|
47387
47578
|
] }),
|
|
47388
47579
|
false
|
|
47389
47580
|
] }),
|
|
@@ -47545,63 +47736,67 @@ function Welcome() {
|
|
|
47545
47736
|
function lazyNamed(loader, name) {
|
|
47546
47737
|
return reactExports.lazy(() => loader().then((mod) => ({ default: mod[name] })));
|
|
47547
47738
|
}
|
|
47548
|
-
const Session = lazyNamed(() => __vitePreload(() => import("./session-
|
|
47739
|
+
const Session = lazyNamed(() => __vitePreload(() => import("./session-D6NE3yNE.js"), true ? __vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]) : void 0, import.meta.url), "Session");
|
|
47549
47740
|
const SettingsLayout = lazyNamed(
|
|
47550
|
-
() => __vitePreload(() => import("./settings-layout-
|
|
47741
|
+
() => __vitePreload(() => import("./settings-layout-DJbT4rIH.js"), true ? __vite__mapDeps([21,22,12,16]) : void 0, import.meta.url),
|
|
47551
47742
|
"SettingsLayout"
|
|
47552
47743
|
);
|
|
47553
47744
|
const SettingsGeneral = lazyNamed(
|
|
47554
|
-
() => __vitePreload(() => import("./settings-general-
|
|
47745
|
+
() => __vitePreload(() => import("./settings-general-B85uTAij.js"), true ? __vite__mapDeps([23,24,1]) : void 0, import.meta.url),
|
|
47555
47746
|
"SettingsGeneral"
|
|
47556
47747
|
);
|
|
47557
47748
|
const SettingsShortcuts = lazyNamed(
|
|
47558
|
-
() => __vitePreload(() => import("./settings-shortcuts-
|
|
47749
|
+
() => __vitePreload(() => import("./settings-shortcuts-dWdRCFxB.js"), true ? __vite__mapDeps([25,22,15,18]) : void 0, import.meta.url),
|
|
47559
47750
|
"SettingsShortcuts"
|
|
47560
47751
|
);
|
|
47561
47752
|
const SettingsAgents = lazyNamed(
|
|
47562
|
-
() => __vitePreload(() => import("./settings-agents-
|
|
47753
|
+
() => __vitePreload(() => import("./settings-agents-DxIwcY7M.js"), true ? __vite__mapDeps([26,27,28,29,30,24,13,11,19,31]) : void 0, import.meta.url),
|
|
47563
47754
|
"SettingsAgents"
|
|
47564
47755
|
);
|
|
47565
47756
|
const SettingsMcp = lazyNamed(
|
|
47566
|
-
() => __vitePreload(() => import("./settings-mcp-
|
|
47757
|
+
() => __vitePreload(() => import("./settings-mcp-Cz6GMogp.js"), true ? __vite__mapDeps([32,27,28,29,30,24,11,19,9]) : void 0, import.meta.url),
|
|
47567
47758
|
"SettingsMcp"
|
|
47568
47759
|
);
|
|
47569
47760
|
const SettingsWebUI = lazyNamed(
|
|
47570
|
-
() => __vitePreload(() => import("./settings-webui-
|
|
47761
|
+
() => __vitePreload(() => import("./settings-webui-DKiOzDSD.js"), true ? __vite__mapDeps([33,27]) : void 0, import.meta.url),
|
|
47571
47762
|
"SettingsWebUI"
|
|
47572
47763
|
);
|
|
47573
47764
|
const SettingsILink = lazyNamed(
|
|
47574
|
-
() => __vitePreload(() => import("./settings-ilink-
|
|
47765
|
+
() => __vitePreload(() => import("./settings-ilink-BgeA04Nv.js"), true ? __vite__mapDeps([34,27,8,9]) : void 0, import.meta.url),
|
|
47575
47766
|
"SettingsILink"
|
|
47576
47767
|
);
|
|
47577
47768
|
const SettingsSnippets = lazyNamed(
|
|
47578
|
-
() => __vitePreload(() => import("./settings-snippets-
|
|
47769
|
+
() => __vitePreload(() => import("./settings-snippets-CrtJYwLV.js"), true ? __vite__mapDeps([35,29,30,24,11,28,19]) : void 0, import.meta.url),
|
|
47579
47770
|
"SettingsSnippets"
|
|
47580
47771
|
);
|
|
47581
47772
|
const SettingsMemory = lazyNamed(
|
|
47582
|
-
() => __vitePreload(() => import("./settings-memory-
|
|
47773
|
+
() => __vitePreload(() => import("./settings-memory-Cidr_Ghw.js"), true ? __vite__mapDeps([36,5]) : void 0, import.meta.url),
|
|
47583
47774
|
"SettingsMemory"
|
|
47584
47775
|
);
|
|
47585
47776
|
const SettingsImageGeneration = lazyNamed(
|
|
47586
|
-
() => __vitePreload(() => import("./settings-image-generation-
|
|
47777
|
+
() => __vitePreload(() => import("./settings-image-generation-CsWv4wXY.js"), true ? __vite__mapDeps([37,29,30,24,19,13,11]) : void 0, import.meta.url),
|
|
47587
47778
|
"SettingsImageGeneration"
|
|
47588
47779
|
);
|
|
47589
|
-
const
|
|
47590
|
-
() => __vitePreload(() => import("./settings-speech-
|
|
47591
|
-
"
|
|
47780
|
+
const SettingsSpeech = lazyNamed(
|
|
47781
|
+
() => __vitePreload(() => import("./settings-speech-CteE8F4J.js"), true ? __vite__mapDeps([38,27,29,24,11,19]) : void 0, import.meta.url),
|
|
47782
|
+
"SettingsSpeech"
|
|
47592
47783
|
);
|
|
47593
|
-
const
|
|
47784
|
+
const SettingsPeripherals = lazyNamed(
|
|
47785
|
+
() => __vitePreload(() => import("./settings-peripherals-DilwOpyO.js"), true ? __vite__mapDeps([39,17,9]) : void 0, import.meta.url),
|
|
47786
|
+
"SettingsPeripherals"
|
|
47787
|
+
);
|
|
47788
|
+
const SkillsLayout = lazyNamed(() => __vitePreload(() => import("./skills-layout-BAzfcnkT.js"), true ? __vite__mapDeps([40,41]) : void 0, import.meta.url), "SkillsLayout");
|
|
47594
47789
|
const SkillsInstalled = lazyNamed(
|
|
47595
|
-
() => __vitePreload(() => import("./skills-installed-
|
|
47790
|
+
() => __vitePreload(() => import("./skills-installed-Beqe9G7p.js"), true ? __vite__mapDeps([42,4,6,7]) : void 0, import.meta.url),
|
|
47596
47791
|
"SkillsInstalled"
|
|
47597
47792
|
);
|
|
47598
47793
|
const SkillsSh = lazyNamed(
|
|
47599
|
-
() => __vitePreload(() => import("./skills-skills-sh-
|
|
47794
|
+
() => __vitePreload(() => import("./skills-skills-sh-Dzocqfu4.js"), true ? __vite__mapDeps([43,6,10,41]) : void 0, import.meta.url),
|
|
47600
47795
|
"SkillsSh"
|
|
47601
47796
|
);
|
|
47602
|
-
const Automation = lazyNamed(() => __vitePreload(() => import("./automation-
|
|
47603
|
-
const Schedule = lazyNamed(() => __vitePreload(() => import("./schedule-
|
|
47604
|
-
const Task = lazyNamed(() => __vitePreload(() => import("./task-
|
|
47797
|
+
const Automation = lazyNamed(() => __vitePreload(() => import("./automation-W30eYgU8.js"), true ? __vite__mapDeps([44,6,45,30,24,2,19]) : void 0, import.meta.url), "Automation");
|
|
47798
|
+
const Schedule = lazyNamed(() => __vitePreload(() => import("./schedule-H1BEvD9Q.js"), true ? __vite__mapDeps([46,20,45,30,24,2,18,7,31]) : void 0, import.meta.url), "Schedule");
|
|
47799
|
+
const Task = lazyNamed(() => __vitePreload(() => import("./task-DM-bWOFz.js"), true ? __vite__mapDeps([47,20,4,3,5,6,7,8,9,10,11,12,13,14]) : void 0, import.meta.url), "Task");
|
|
47605
47800
|
function SessionWrapper() {
|
|
47606
47801
|
const { sessionId } = useParams();
|
|
47607
47802
|
const sessionInfo = useAppStore((s) => s.sessions.find((x2) => x2.id === sessionId));
|
|
@@ -47637,7 +47832,8 @@ function AppRouter() {
|
|
|
47637
47832
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "snippets", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsSnippets, {}) }),
|
|
47638
47833
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "memory", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsMemory, {}) }),
|
|
47639
47834
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "image-generation", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsImageGeneration, {}) }),
|
|
47640
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "speech
|
|
47835
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "speech", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsSpeech, {}) }),
|
|
47836
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "peripherals", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsPeripherals, {}) })
|
|
47641
47837
|
] }),
|
|
47642
47838
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Route, { path: "/skills", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SkillsLayout, {}), children: [
|
|
47643
47839
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Route, { path: "installed", element: /* @__PURE__ */ jsxRuntimeExports.jsx(SkillsInstalled, {}) }),
|
|
@@ -47651,7 +47847,7 @@ function AppRouter() {
|
|
|
47651
47847
|
{
|
|
47652
47848
|
className: cn$1(
|
|
47653
47849
|
"flex h-12 w-12 absolute z-10 top-0 items-center justify-center transition-all duration-200",
|
|
47654
|
-
sidebarOpen ? "left-49 -ml-px" : showMacTrafficLightSpace ? "left-
|
|
47850
|
+
sidebarOpen ? "left-49 -ml-px" : showMacTrafficLightSpace ? "left-17" : "left-0"
|
|
47655
47851
|
),
|
|
47656
47852
|
style: { WebkitAppRegion: "no-drag" },
|
|
47657
47853
|
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -47671,6 +47867,690 @@ function AppRouter() {
|
|
|
47671
47867
|
)
|
|
47672
47868
|
] });
|
|
47673
47869
|
}
|
|
47870
|
+
const XIAOMI_RC003 = {
|
|
47871
|
+
id: "xiaomi-rc003",
|
|
47872
|
+
name: "Xiaomi Bluetooth Remote 2 Pro (RC003)",
|
|
47873
|
+
productUrl: "https://www.mi.com/xiaomi-bluetooth-remote-2-pro",
|
|
47874
|
+
platforms: ["darwin"],
|
|
47875
|
+
statusLabelKey: "settings.peripherals.status.bluetooth",
|
|
47876
|
+
keys: [
|
|
47877
|
+
{
|
|
47878
|
+
id: "voice",
|
|
47879
|
+
labelKey: "settings.peripherals.keys.voice",
|
|
47880
|
+
transport: "keyboard",
|
|
47881
|
+
kind: "hold",
|
|
47882
|
+
code: "F5"
|
|
47883
|
+
},
|
|
47884
|
+
{
|
|
47885
|
+
id: "back",
|
|
47886
|
+
labelKey: "settings.peripherals.keys.back",
|
|
47887
|
+
// 走 HID 报文(设备私有编码,见下方 `hid.keyMappings`)→ 注入系统按键,
|
|
47888
|
+
// 不是系统直接派发的键盘事件,所以没有 `code`。
|
|
47889
|
+
transport: "hid",
|
|
47890
|
+
kind: "press",
|
|
47891
|
+
// 注意:**这个字段不能删** —— 它是「HID 报文 → 注入系统按键」的唯一开关:
|
|
47892
|
+
// index.ts 把它塞进 peripheral-key 事件,渲染层 `if (!event.systemKey) return;`
|
|
47893
|
+
// 一旦为空就静默丢弃(按键没反应、也没有任何报错)。
|
|
47894
|
+
systemKey: "Escape"
|
|
47895
|
+
}
|
|
47896
|
+
],
|
|
47897
|
+
hid: {
|
|
47898
|
+
vendorId: 10007,
|
|
47899
|
+
productId: 12984,
|
|
47900
|
+
keyMappings: [
|
|
47901
|
+
{
|
|
47902
|
+
keyId: "back",
|
|
47903
|
+
reportPrefix: [1, 0, 0],
|
|
47904
|
+
codeIndex: 3,
|
|
47905
|
+
pressCode: 241,
|
|
47906
|
+
releaseCode: 0
|
|
47907
|
+
}
|
|
47908
|
+
]
|
|
47909
|
+
},
|
|
47910
|
+
bluetooth: {
|
|
47911
|
+
kind: "atvv-voice",
|
|
47912
|
+
audio: { sampleRate: 16e3, channels: 1, bitsPerSample: 16 }
|
|
47913
|
+
}
|
|
47914
|
+
};
|
|
47915
|
+
const BUILTIN_PERIPHERALS = [XIAOMI_RC003];
|
|
47916
|
+
function isPeripheralSupportedOnPlatform(peripheral, platform2) {
|
|
47917
|
+
return peripheral.platforms.includes(platform2);
|
|
47918
|
+
}
|
|
47919
|
+
function isPeripheralRuntimeAvailable(options) {
|
|
47920
|
+
if (options.isWebUI) return false;
|
|
47921
|
+
return BUILTIN_PERIPHERALS.some(
|
|
47922
|
+
(peripheral) => isPeripheralSupportedOnPlatform(peripheral, options.platform)
|
|
47923
|
+
);
|
|
47924
|
+
}
|
|
47925
|
+
function getRendererPlatform() {
|
|
47926
|
+
const bridge2 = window.fello;
|
|
47927
|
+
if (!bridge2) return "linux";
|
|
47928
|
+
if (bridge2.isMacApp) return "darwin";
|
|
47929
|
+
if (bridge2.isWinApp) return "win32";
|
|
47930
|
+
return "linux";
|
|
47931
|
+
}
|
|
47932
|
+
const RENDERER_PLATFORM = getRendererPlatform();
|
|
47933
|
+
const TARGET_SAMPLE_RATE = 16e3;
|
|
47934
|
+
const FRAME_SAMPLES = 320;
|
|
47935
|
+
const PERIPHERAL_LEVEL_FLOOR = 0.15;
|
|
47936
|
+
const PERIPHERAL_LEVEL_WARMUP_MS = 300;
|
|
47937
|
+
const workletSource = `
|
|
47938
|
+
class FelloPcmProcessor extends AudioWorkletProcessor {
|
|
47939
|
+
constructor() {
|
|
47940
|
+
super();
|
|
47941
|
+
this.buffer = [];
|
|
47942
|
+
this.position = 0;
|
|
47943
|
+
this.output = [];
|
|
47944
|
+
this.ratio = sampleRate / ${TARGET_SAMPLE_RATE};
|
|
47945
|
+
}
|
|
47946
|
+
process(inputs, outputs) {
|
|
47947
|
+
const input = inputs[0] && inputs[0][0];
|
|
47948
|
+
if (input) {
|
|
47949
|
+
for (let i = 0; i < input.length; i++) this.buffer.push(input[i]);
|
|
47950
|
+
while (this.position + 1 < this.buffer.length) {
|
|
47951
|
+
const index = Math.floor(this.position);
|
|
47952
|
+
const fraction = this.position - index;
|
|
47953
|
+
const sample = this.buffer[index] * (1 - fraction) + this.buffer[index + 1] * fraction;
|
|
47954
|
+
const clamped = Math.max(-1, Math.min(1, sample));
|
|
47955
|
+
this.output.push(clamped < 0 ? clamped * 32768 : clamped * 32767);
|
|
47956
|
+
this.position += this.ratio;
|
|
47957
|
+
if (this.output.length >= ${FRAME_SAMPLES}) {
|
|
47958
|
+
const pcm = new Int16Array(${FRAME_SAMPLES});
|
|
47959
|
+
for (let i = 0; i < ${FRAME_SAMPLES}; i++) pcm[i] = this.output[i];
|
|
47960
|
+
this.output = this.output.slice(${FRAME_SAMPLES});
|
|
47961
|
+
this.port.postMessage(pcm.buffer, [pcm.buffer]);
|
|
47962
|
+
}
|
|
47963
|
+
}
|
|
47964
|
+
const remove = Math.max(0, Math.floor(this.position));
|
|
47965
|
+
if (remove > 0) {
|
|
47966
|
+
this.buffer = this.buffer.slice(remove);
|
|
47967
|
+
this.position -= remove;
|
|
47968
|
+
}
|
|
47969
|
+
}
|
|
47970
|
+
const output = outputs[0] && outputs[0][0];
|
|
47971
|
+
if (output) output.fill(0);
|
|
47972
|
+
return true;
|
|
47973
|
+
}
|
|
47974
|
+
}
|
|
47975
|
+
registerProcessor("fello-pcm-processor", FelloPcmProcessor);
|
|
47976
|
+
`;
|
|
47977
|
+
function arrayBufferToBase64(buffer) {
|
|
47978
|
+
const bytes = new Uint8Array(buffer);
|
|
47979
|
+
let binary = "";
|
|
47980
|
+
const chunkSize = 32768;
|
|
47981
|
+
for (let offset2 = 0; offset2 < bytes.length; offset2 += chunkSize) {
|
|
47982
|
+
binary += String.fromCharCode(...bytes.subarray(offset2, offset2 + chunkSize));
|
|
47983
|
+
}
|
|
47984
|
+
return btoa(binary);
|
|
47985
|
+
}
|
|
47986
|
+
function errorMessage(error) {
|
|
47987
|
+
return error instanceof Error ? error.message : String(error);
|
|
47988
|
+
}
|
|
47989
|
+
function base64ToArrayBuffer(base64) {
|
|
47990
|
+
const binary = atob(base64);
|
|
47991
|
+
const bytes = new Uint8Array(binary.length);
|
|
47992
|
+
for (let index2 = 0; index2 < binary.length; index2 += 1) {
|
|
47993
|
+
bytes[index2] = binary.charCodeAt(index2);
|
|
47994
|
+
}
|
|
47995
|
+
return bytes.buffer;
|
|
47996
|
+
}
|
|
47997
|
+
function useRealtimeAsr(options) {
|
|
47998
|
+
const { onTranscript, onError, onRecordingChange, source = "microphone" } = options;
|
|
47999
|
+
const configured = useAppStore(
|
|
48000
|
+
(state) => state.speechProviders.some((provider) => provider.asrEnabled)
|
|
48001
|
+
);
|
|
48002
|
+
const [recording, setRecording] = reactExports.useState(false);
|
|
48003
|
+
const [audioLevel, setAudioLevel] = reactExports.useState(0);
|
|
48004
|
+
const [inputDevices, setInputDevices] = reactExports.useState([]);
|
|
48005
|
+
const asrSessionIdRef = reactExports.useRef(null);
|
|
48006
|
+
const peripheralIdRef = reactExports.useRef(null);
|
|
48007
|
+
const captureIdRef = reactExports.useRef(0);
|
|
48008
|
+
const streamRef = reactExports.useRef(null);
|
|
48009
|
+
const audioContextRef = reactExports.useRef(null);
|
|
48010
|
+
const sourceRef = reactExports.useRef(null);
|
|
48011
|
+
const nodeRef = reactExports.useRef(null);
|
|
48012
|
+
const stoppedRef = reactExports.useRef(false);
|
|
48013
|
+
const stoppingRef = reactExports.useRef(false);
|
|
48014
|
+
const recordingRef = reactExports.useRef(false);
|
|
48015
|
+
const audioLevelValueRef = reactExports.useRef(0);
|
|
48016
|
+
const audioLevelFrameRef = reactExports.useRef(null);
|
|
48017
|
+
const stopRef = reactExports.useRef(async () => {
|
|
48018
|
+
});
|
|
48019
|
+
const stopPromiseRef = reactExports.useRef(null);
|
|
48020
|
+
const callbacksRef = reactExports.useRef({ onTranscript, onError, onRecordingChange });
|
|
48021
|
+
callbacksRef.current = { onTranscript, onError, onRecordingChange };
|
|
48022
|
+
const setRecordingState = reactExports.useCallback((value) => {
|
|
48023
|
+
recordingRef.current = value;
|
|
48024
|
+
setRecording(value);
|
|
48025
|
+
callbacksRef.current.onRecordingChange?.(value);
|
|
48026
|
+
}, []);
|
|
48027
|
+
reactExports.useEffect(() => {
|
|
48028
|
+
const handleTranscript = (event) => {
|
|
48029
|
+
if (event.clientId !== clientId || event.asrSessionId !== asrSessionIdRef.current) return;
|
|
48030
|
+
callbacksRef.current.onTranscript?.({
|
|
48031
|
+
text: event.text,
|
|
48032
|
+
isFinal: event.isFinal,
|
|
48033
|
+
id: event.id,
|
|
48034
|
+
index: event.index,
|
|
48035
|
+
// 交给消费方做「会话隔离」用,见 RealtimeAsrTranscript.asrSessionId
|
|
48036
|
+
asrSessionId: event.asrSessionId
|
|
48037
|
+
});
|
|
48038
|
+
};
|
|
48039
|
+
const handleError = (event) => {
|
|
48040
|
+
if (event.clientId !== clientId || event.asrSessionId !== asrSessionIdRef.current) return;
|
|
48041
|
+
callbacksRef.current.onError?.(event.message);
|
|
48042
|
+
};
|
|
48043
|
+
const handleClosed = (event) => {
|
|
48044
|
+
if (event.clientId !== clientId || event.asrSessionId !== asrSessionIdRef.current) return;
|
|
48045
|
+
if (recordingRef.current && !stoppingRef.current) {
|
|
48046
|
+
callbacksRef.current.onError?.("实时语音识别连接已关闭。");
|
|
48047
|
+
void stopRef.current();
|
|
48048
|
+
}
|
|
48049
|
+
};
|
|
48050
|
+
subscribe.on("asr-transcript", handleTranscript);
|
|
48051
|
+
subscribe.on("asr-error", handleError);
|
|
48052
|
+
subscribe.on("asr-closed", handleClosed);
|
|
48053
|
+
return () => {
|
|
48054
|
+
subscribe.off("asr-transcript", handleTranscript);
|
|
48055
|
+
subscribe.off("asr-error", handleError);
|
|
48056
|
+
subscribe.off("asr-closed", handleClosed);
|
|
48057
|
+
};
|
|
48058
|
+
}, [setRecordingState]);
|
|
48059
|
+
const levelGateUntilRef = reactExports.useRef(0);
|
|
48060
|
+
const updateAudioLevel = reactExports.useCallback(
|
|
48061
|
+
(buffer) => {
|
|
48062
|
+
const samples = new Int16Array(buffer);
|
|
48063
|
+
if (samples.length === 0) return;
|
|
48064
|
+
if (source === "peripheral" && Date.now() < levelGateUntilRef.current) {
|
|
48065
|
+
audioLevelValueRef.current = 0;
|
|
48066
|
+
return;
|
|
48067
|
+
}
|
|
48068
|
+
let sumSquares = 0;
|
|
48069
|
+
for (const sample of samples) {
|
|
48070
|
+
const normalized = sample / 32768;
|
|
48071
|
+
sumSquares += normalized * normalized;
|
|
48072
|
+
}
|
|
48073
|
+
const rms = Math.sqrt(sumSquares / samples.length);
|
|
48074
|
+
const amplified = Math.min(1, rms * 4);
|
|
48075
|
+
const compressed = Math.sqrt(amplified);
|
|
48076
|
+
audioLevelValueRef.current = source === "peripheral" ? Math.max(0, (compressed - PERIPHERAL_LEVEL_FLOOR) / (1 - PERIPHERAL_LEVEL_FLOOR)) : amplified;
|
|
48077
|
+
if (audioLevelFrameRef.current !== null) return;
|
|
48078
|
+
audioLevelFrameRef.current = requestAnimationFrame(() => {
|
|
48079
|
+
audioLevelFrameRef.current = null;
|
|
48080
|
+
setAudioLevel(audioLevelValueRef.current);
|
|
48081
|
+
});
|
|
48082
|
+
},
|
|
48083
|
+
[source]
|
|
48084
|
+
);
|
|
48085
|
+
reactExports.useEffect(() => {
|
|
48086
|
+
if (source !== "peripheral") return;
|
|
48087
|
+
const handleAudio = (event) => {
|
|
48088
|
+
const asrSessionId = asrSessionIdRef.current;
|
|
48089
|
+
if (!asrSessionId || stoppedRef.current) return;
|
|
48090
|
+
if (event.peripheralId !== peripheralIdRef.current) return;
|
|
48091
|
+
if (event.captureId === 0 || event.captureId !== captureIdRef.current) return;
|
|
48092
|
+
updateAudioLevel(base64ToArrayBuffer(event.audioB64));
|
|
48093
|
+
void request.sendRealtimeAsrFrame({ clientId, asrSessionId, audioB64: event.audioB64 }).catch((error) => callbacksRef.current.onError?.(errorMessage(error)));
|
|
48094
|
+
};
|
|
48095
|
+
subscribe.on("peripheral-audio", handleAudio);
|
|
48096
|
+
return () => subscribe.off("peripheral-audio", handleAudio);
|
|
48097
|
+
}, [source, updateAudioLevel]);
|
|
48098
|
+
const cleanupAudio = reactExports.useCallback(async () => {
|
|
48099
|
+
if (audioLevelFrameRef.current !== null) {
|
|
48100
|
+
cancelAnimationFrame(audioLevelFrameRef.current);
|
|
48101
|
+
audioLevelFrameRef.current = null;
|
|
48102
|
+
}
|
|
48103
|
+
audioLevelValueRef.current = 0;
|
|
48104
|
+
setAudioLevel(0);
|
|
48105
|
+
nodeRef.current?.disconnect();
|
|
48106
|
+
sourceRef.current?.disconnect();
|
|
48107
|
+
streamRef.current?.getTracks().forEach((track) => track.stop());
|
|
48108
|
+
streamRef.current = null;
|
|
48109
|
+
nodeRef.current = null;
|
|
48110
|
+
sourceRef.current = null;
|
|
48111
|
+
const context = audioContextRef.current;
|
|
48112
|
+
audioContextRef.current = null;
|
|
48113
|
+
await context?.close().catch(() => void 0);
|
|
48114
|
+
}, []);
|
|
48115
|
+
const refreshInputDevices = reactExports.useCallback(async () => {
|
|
48116
|
+
if (!navigator.mediaDevices?.enumerateDevices) return [];
|
|
48117
|
+
try {
|
|
48118
|
+
let devices = await navigator.mediaDevices.enumerateDevices();
|
|
48119
|
+
if (devices.length > 0 && devices.every((device) => !device.label)) {
|
|
48120
|
+
try {
|
|
48121
|
+
const permissionStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
48122
|
+
permissionStream.getTracks().forEach((track) => track.stop());
|
|
48123
|
+
devices = await navigator.mediaDevices.enumerateDevices();
|
|
48124
|
+
} catch {
|
|
48125
|
+
}
|
|
48126
|
+
}
|
|
48127
|
+
const audioInputs = devices.filter((device) => device.kind === "audioinput").map((device, index2) => ({
|
|
48128
|
+
deviceId: device.deviceId,
|
|
48129
|
+
label: device.label || `Microphone ${index2 + 1}`
|
|
48130
|
+
}));
|
|
48131
|
+
setInputDevices(audioInputs);
|
|
48132
|
+
return audioInputs;
|
|
48133
|
+
} catch (error) {
|
|
48134
|
+
callbacksRef.current.onError?.(errorMessage(error));
|
|
48135
|
+
return [];
|
|
48136
|
+
}
|
|
48137
|
+
}, []);
|
|
48138
|
+
const start = reactExports.useCallback(
|
|
48139
|
+
async (deviceId = "default") => {
|
|
48140
|
+
if (stopPromiseRef.current) await stopPromiseRef.current.catch(() => void 0);
|
|
48141
|
+
if (asrSessionIdRef.current) await stopRef.current().catch(() => void 0);
|
|
48142
|
+
if (recordingRef.current || !configured) return;
|
|
48143
|
+
const asrSessionId = `asr_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
48144
|
+
asrSessionIdRef.current = asrSessionId;
|
|
48145
|
+
stoppedRef.current = false;
|
|
48146
|
+
stoppingRef.current = false;
|
|
48147
|
+
if (source === "peripheral") {
|
|
48148
|
+
const peripheralId = deviceId;
|
|
48149
|
+
peripheralIdRef.current = peripheralId;
|
|
48150
|
+
captureIdRef.current = 0;
|
|
48151
|
+
try {
|
|
48152
|
+
await request.startRealtimeAsr({ clientId, asrSessionId });
|
|
48153
|
+
const captureId = await electron.peripherals.voiceStart(peripheralId);
|
|
48154
|
+
if (!Number.isFinite(captureId) || captureId <= 0) {
|
|
48155
|
+
throw new Error(
|
|
48156
|
+
`外设音频通道未返回有效的采集标识(captureId=${String(captureId)}),本次录音已取消。`
|
|
48157
|
+
);
|
|
48158
|
+
}
|
|
48159
|
+
captureIdRef.current = captureId;
|
|
48160
|
+
levelGateUntilRef.current = Date.now() + PERIPHERAL_LEVEL_WARMUP_MS;
|
|
48161
|
+
audioLevelValueRef.current = 0;
|
|
48162
|
+
setAudioLevel(0);
|
|
48163
|
+
setRecordingState(true);
|
|
48164
|
+
} catch (error) {
|
|
48165
|
+
await request.stopRealtimeAsr({ clientId, asrSessionId }).catch(() => void 0);
|
|
48166
|
+
await electron.peripherals.voiceStop(peripheralId).catch(() => void 0);
|
|
48167
|
+
asrSessionIdRef.current = null;
|
|
48168
|
+
peripheralIdRef.current = null;
|
|
48169
|
+
captureIdRef.current = 0;
|
|
48170
|
+
callbacksRef.current.onError?.(errorMessage(error));
|
|
48171
|
+
setRecordingState(false);
|
|
48172
|
+
}
|
|
48173
|
+
return;
|
|
48174
|
+
}
|
|
48175
|
+
try {
|
|
48176
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
48177
|
+
audio: {
|
|
48178
|
+
channelCount: 1,
|
|
48179
|
+
echoCancellation: true,
|
|
48180
|
+
noiseSuppression: true,
|
|
48181
|
+
...deviceId !== "default" ? { deviceId: { exact: deviceId } } : {}
|
|
48182
|
+
}
|
|
48183
|
+
});
|
|
48184
|
+
streamRef.current = stream;
|
|
48185
|
+
const audioContext = new AudioContext();
|
|
48186
|
+
audioContextRef.current = audioContext;
|
|
48187
|
+
await audioContext.resume();
|
|
48188
|
+
const workletUrl = URL.createObjectURL(
|
|
48189
|
+
new Blob([workletSource], { type: "application/javascript" })
|
|
48190
|
+
);
|
|
48191
|
+
try {
|
|
48192
|
+
await audioContext.audioWorklet.addModule(workletUrl);
|
|
48193
|
+
} finally {
|
|
48194
|
+
URL.revokeObjectURL(workletUrl);
|
|
48195
|
+
}
|
|
48196
|
+
const source2 = audioContext.createMediaStreamSource(stream);
|
|
48197
|
+
const node = new AudioWorkletNode(audioContext, "fello-pcm-processor");
|
|
48198
|
+
const silentGain = audioContext.createGain();
|
|
48199
|
+
silentGain.gain.value = 0;
|
|
48200
|
+
node.port.onmessage = (message2) => {
|
|
48201
|
+
if (stoppedRef.current || asrSessionIdRef.current !== asrSessionId) return;
|
|
48202
|
+
updateAudioLevel(message2.data);
|
|
48203
|
+
void request.sendRealtimeAsrFrame({
|
|
48204
|
+
clientId,
|
|
48205
|
+
asrSessionId,
|
|
48206
|
+
audioB64: arrayBufferToBase64(message2.data)
|
|
48207
|
+
}).catch((error) => callbacksRef.current.onError?.(errorMessage(error)));
|
|
48208
|
+
};
|
|
48209
|
+
sourceRef.current = source2;
|
|
48210
|
+
nodeRef.current = node;
|
|
48211
|
+
await request.startRealtimeAsr({ clientId, asrSessionId });
|
|
48212
|
+
source2.connect(node);
|
|
48213
|
+
node.connect(silentGain);
|
|
48214
|
+
silentGain.connect(audioContext.destination);
|
|
48215
|
+
setRecordingState(true);
|
|
48216
|
+
} catch (error) {
|
|
48217
|
+
await cleanupAudio();
|
|
48218
|
+
await request.stopRealtimeAsr({ clientId, asrSessionId }).catch(() => void 0);
|
|
48219
|
+
asrSessionIdRef.current = null;
|
|
48220
|
+
callbacksRef.current.onError?.(errorMessage(error));
|
|
48221
|
+
setRecordingState(false);
|
|
48222
|
+
}
|
|
48223
|
+
},
|
|
48224
|
+
[cleanupAudio, configured, setRecordingState, updateAudioLevel, source]
|
|
48225
|
+
);
|
|
48226
|
+
const runStopStreaming = reactExports.useCallback(async () => {
|
|
48227
|
+
if (!asrSessionIdRef.current) return;
|
|
48228
|
+
setRecordingState(false);
|
|
48229
|
+
audioLevelValueRef.current = 0;
|
|
48230
|
+
setAudioLevel(0);
|
|
48231
|
+
if (source === "peripheral") {
|
|
48232
|
+
const peripheralId = peripheralIdRef.current;
|
|
48233
|
+
if (peripheralId) {
|
|
48234
|
+
await electron.peripherals.voiceStop(peripheralId).catch(() => void 0);
|
|
48235
|
+
}
|
|
48236
|
+
stoppedRef.current = true;
|
|
48237
|
+
return;
|
|
48238
|
+
}
|
|
48239
|
+
stoppedRef.current = true;
|
|
48240
|
+
await cleanupAudio();
|
|
48241
|
+
}, [cleanupAudio, setRecordingState, source]);
|
|
48242
|
+
const runCloseSession = reactExports.useCallback(async () => {
|
|
48243
|
+
const asrSessionId = asrSessionIdRef.current;
|
|
48244
|
+
if (!asrSessionId) return;
|
|
48245
|
+
stoppingRef.current = true;
|
|
48246
|
+
await request.stopRealtimeAsr({ clientId, asrSessionId }).catch((error) => {
|
|
48247
|
+
callbacksRef.current.onError?.(errorMessage(error));
|
|
48248
|
+
});
|
|
48249
|
+
asrSessionIdRef.current = null;
|
|
48250
|
+
peripheralIdRef.current = null;
|
|
48251
|
+
captureIdRef.current = 0;
|
|
48252
|
+
stoppingRef.current = false;
|
|
48253
|
+
}, []);
|
|
48254
|
+
const runStop = reactExports.useCallback(async () => {
|
|
48255
|
+
await runStopStreaming();
|
|
48256
|
+
await runCloseSession();
|
|
48257
|
+
setRecordingState(false);
|
|
48258
|
+
}, [runCloseSession, runStopStreaming, setRecordingState]);
|
|
48259
|
+
const stop = reactExports.useCallback(async () => {
|
|
48260
|
+
if (stopPromiseRef.current) return stopPromiseRef.current;
|
|
48261
|
+
const run = runStop();
|
|
48262
|
+
stopPromiseRef.current = run;
|
|
48263
|
+
try {
|
|
48264
|
+
await run;
|
|
48265
|
+
} finally {
|
|
48266
|
+
if (stopPromiseRef.current === run) stopPromiseRef.current = null;
|
|
48267
|
+
}
|
|
48268
|
+
}, [runStop]);
|
|
48269
|
+
stopRef.current = stop;
|
|
48270
|
+
reactExports.useEffect(() => {
|
|
48271
|
+
return () => {
|
|
48272
|
+
stoppedRef.current = true;
|
|
48273
|
+
void stopRef.current();
|
|
48274
|
+
};
|
|
48275
|
+
}, []);
|
|
48276
|
+
const toggle = reactExports.useCallback(() => {
|
|
48277
|
+
void (recordingRef.current ? stop() : start());
|
|
48278
|
+
}, [start, stop]);
|
|
48279
|
+
return {
|
|
48280
|
+
recording,
|
|
48281
|
+
audioLevel,
|
|
48282
|
+
configured,
|
|
48283
|
+
inputDevices,
|
|
48284
|
+
refreshInputDevices,
|
|
48285
|
+
start,
|
|
48286
|
+
stop,
|
|
48287
|
+
toggle
|
|
48288
|
+
};
|
|
48289
|
+
}
|
|
48290
|
+
const DEFAULT_MAX_DURATION = 5 * 60 * 1e3;
|
|
48291
|
+
const VoicePanelContext = reactExports.createContext(null);
|
|
48292
|
+
const VoicePanelDataContext = reactExports.createContext(null);
|
|
48293
|
+
function useVoicePanelContext() {
|
|
48294
|
+
const context = useVoicePanelContextOptional();
|
|
48295
|
+
if (!context) {
|
|
48296
|
+
throw new Error("Voice panel hooks must be used within VoicePanelProvider");
|
|
48297
|
+
}
|
|
48298
|
+
return context;
|
|
48299
|
+
}
|
|
48300
|
+
function useVoicePanelContextOptional() {
|
|
48301
|
+
return reactExports.useContext(VoicePanelContext);
|
|
48302
|
+
}
|
|
48303
|
+
function useTranscriptSegments() {
|
|
48304
|
+
const [segments, setSegments] = reactExports.useState([]);
|
|
48305
|
+
const segmentsRef = reactExports.useRef([]);
|
|
48306
|
+
const currentKeyRef = reactExports.useRef(null);
|
|
48307
|
+
const streamSeqRef = reactExports.useRef(0);
|
|
48308
|
+
const textRef = reactExports.useRef("");
|
|
48309
|
+
const append = reactExports.useCallback(
|
|
48310
|
+
(transcript) => {
|
|
48311
|
+
const scope = transcript.asrSessionId ?? "session";
|
|
48312
|
+
const key = transcript.id !== void 0 ? `${scope}:id:${transcript.id}` : transcript.index !== void 0 ? `${scope}:index:${transcript.index}` : currentKeyRef.current ?? `${scope}:stream:${streamSeqRef.current++}`;
|
|
48313
|
+
currentKeyRef.current = transcript.isFinal ? null : key;
|
|
48314
|
+
const list = segmentsRef.current;
|
|
48315
|
+
const at = list.findIndex((segment) => segment.key === key);
|
|
48316
|
+
if (at >= 0) list[at] = { key, text: transcript.text };
|
|
48317
|
+
else list.push({ key, text: transcript.text });
|
|
48318
|
+
textRef.current = list.map((segment) => segment.text).join("");
|
|
48319
|
+
setSegments([...list]);
|
|
48320
|
+
},
|
|
48321
|
+
[]
|
|
48322
|
+
);
|
|
48323
|
+
const clear = reactExports.useCallback(() => {
|
|
48324
|
+
segmentsRef.current = [];
|
|
48325
|
+
currentKeyRef.current = null;
|
|
48326
|
+
textRef.current = "";
|
|
48327
|
+
setSegments([]);
|
|
48328
|
+
}, []);
|
|
48329
|
+
const text = segments.map((segment) => segment.text).join("");
|
|
48330
|
+
return { text, textRef, append, clear };
|
|
48331
|
+
}
|
|
48332
|
+
function VoicePanelProvider({ children }) {
|
|
48333
|
+
const { t } = useTranslation();
|
|
48334
|
+
const { toast: toast2 } = useMessage();
|
|
48335
|
+
const [phase, setPhase] = reactExports.useState("idle");
|
|
48336
|
+
const [error, setErrorState] = reactExports.useState(null);
|
|
48337
|
+
const errorRef = reactExports.useRef(null);
|
|
48338
|
+
const setError = reactExports.useCallback((next) => {
|
|
48339
|
+
errorRef.current = next;
|
|
48340
|
+
setErrorState(next);
|
|
48341
|
+
}, []);
|
|
48342
|
+
const [activeTargetId, setActiveTargetId] = reactExports.useState(null);
|
|
48343
|
+
const targetsRef = reactExports.useRef(/* @__PURE__ */ new Map());
|
|
48344
|
+
const phaseRef = reactExports.useRef("idle");
|
|
48345
|
+
const activeTargetRef = reactExports.useRef(null);
|
|
48346
|
+
const stopAsrRef = reactExports.useRef(async () => {
|
|
48347
|
+
});
|
|
48348
|
+
const transcript = useTranscriptSegments();
|
|
48349
|
+
const setPhaseBoth = reactExports.useCallback((next) => {
|
|
48350
|
+
phaseRef.current = next;
|
|
48351
|
+
setPhase(next);
|
|
48352
|
+
}, []);
|
|
48353
|
+
const resolveTarget = reactExports.useCallback(() => {
|
|
48354
|
+
let found = null;
|
|
48355
|
+
for (const [id, record] of targetsRef.current) {
|
|
48356
|
+
if (record.enabled) found = [id, record];
|
|
48357
|
+
}
|
|
48358
|
+
return found;
|
|
48359
|
+
}, []);
|
|
48360
|
+
const asr = useRealtimeAsr({
|
|
48361
|
+
source: "peripheral",
|
|
48362
|
+
onTranscript: (result) => transcript.append(result),
|
|
48363
|
+
onError: (message2) => setError(message2)
|
|
48364
|
+
});
|
|
48365
|
+
const { start: startAsr, stop: stopAsr } = asr;
|
|
48366
|
+
const { clear: clearTranscript, text: transcriptText, textRef } = transcript;
|
|
48367
|
+
const reset = reactExports.useCallback(() => {
|
|
48368
|
+
clearTranscript();
|
|
48369
|
+
setError(null);
|
|
48370
|
+
setActiveTargetId(null);
|
|
48371
|
+
activeTargetRef.current = null;
|
|
48372
|
+
setPhaseBoth("idle");
|
|
48373
|
+
}, [clearTranscript, setError, setPhaseBoth]);
|
|
48374
|
+
const close = reactExports.useCallback(() => {
|
|
48375
|
+
if (phaseRef.current === "idle") return;
|
|
48376
|
+
void stopAsr();
|
|
48377
|
+
reset();
|
|
48378
|
+
}, [reset, stopAsr]);
|
|
48379
|
+
const stop = reactExports.useCallback(() => {
|
|
48380
|
+
if (phaseRef.current === "idle") return;
|
|
48381
|
+
if (textRef.current.trim().length === 0 && !errorRef.current) {
|
|
48382
|
+
close();
|
|
48383
|
+
return;
|
|
48384
|
+
}
|
|
48385
|
+
setPhaseBoth("review");
|
|
48386
|
+
void stopAsr();
|
|
48387
|
+
}, [close, setPhaseBoth, stopAsr, textRef]);
|
|
48388
|
+
const start = reactExports.useCallback(
|
|
48389
|
+
(peripheralId) => {
|
|
48390
|
+
if (phaseRef.current === "recording") return;
|
|
48391
|
+
const appending = phaseRef.current === "review";
|
|
48392
|
+
const target = resolveTarget();
|
|
48393
|
+
if (!target) return;
|
|
48394
|
+
if (!asr.configured) {
|
|
48395
|
+
toast2.error(t("chatInput.voiceInputNotConfigured", "Configure voice input in Settings"));
|
|
48396
|
+
return;
|
|
48397
|
+
}
|
|
48398
|
+
if (!appending) clearTranscript();
|
|
48399
|
+
setError(null);
|
|
48400
|
+
activeTargetRef.current = target[0];
|
|
48401
|
+
setActiveTargetId(target[0]);
|
|
48402
|
+
setPhaseBoth("recording");
|
|
48403
|
+
void startAsr(peripheralId);
|
|
48404
|
+
},
|
|
48405
|
+
[asr.configured, clearTranscript, resolveTarget, setError, setPhaseBoth, startAsr, t, toast2]
|
|
48406
|
+
);
|
|
48407
|
+
const registerTarget = reactExports.useCallback(
|
|
48408
|
+
(id, record) => {
|
|
48409
|
+
targetsRef.current.set(id, record);
|
|
48410
|
+
return () => {
|
|
48411
|
+
if (targetsRef.current.get(id) !== record) return;
|
|
48412
|
+
targetsRef.current.delete(id);
|
|
48413
|
+
if (activeTargetRef.current === id) {
|
|
48414
|
+
void stopAsrRef.current();
|
|
48415
|
+
clearTranscript();
|
|
48416
|
+
setError(null);
|
|
48417
|
+
activeTargetRef.current = null;
|
|
48418
|
+
setActiveTargetId(null);
|
|
48419
|
+
setPhaseBoth("idle");
|
|
48420
|
+
}
|
|
48421
|
+
};
|
|
48422
|
+
},
|
|
48423
|
+
[clearTranscript, setError, setPhaseBoth]
|
|
48424
|
+
);
|
|
48425
|
+
reactExports.useEffect(() => {
|
|
48426
|
+
stopAsrRef.current = stopAsr;
|
|
48427
|
+
}, [stopAsr]);
|
|
48428
|
+
reactExports.useEffect(() => {
|
|
48429
|
+
if (phase !== "recording") return;
|
|
48430
|
+
const timer = setTimeout(() => stop(), DEFAULT_MAX_DURATION);
|
|
48431
|
+
return () => clearTimeout(timer);
|
|
48432
|
+
}, [phase, stop]);
|
|
48433
|
+
reactExports.useEffect(() => {
|
|
48434
|
+
if (phase === "idle") return;
|
|
48435
|
+
const handleKeyDown = (event) => {
|
|
48436
|
+
if (event.key !== "Escape" || event.isComposing) return;
|
|
48437
|
+
event.preventDefault();
|
|
48438
|
+
event.stopPropagation();
|
|
48439
|
+
close();
|
|
48440
|
+
};
|
|
48441
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
48442
|
+
return () => window.removeEventListener("keydown", handleKeyDown, true);
|
|
48443
|
+
}, [phase, close]);
|
|
48444
|
+
const value = reactExports.useMemo(
|
|
48445
|
+
() => ({ registerTarget, start, stop, active: phase !== "idle" }),
|
|
48446
|
+
[registerTarget, start, stop, phase]
|
|
48447
|
+
);
|
|
48448
|
+
const dataValue = reactExports.useMemo(
|
|
48449
|
+
() => ({
|
|
48450
|
+
panel: phase === "idle" ? null : {
|
|
48451
|
+
phase,
|
|
48452
|
+
transcript: transcriptText,
|
|
48453
|
+
error,
|
|
48454
|
+
audioLevel: asr.audioLevel,
|
|
48455
|
+
audioActive: asr.recording,
|
|
48456
|
+
close
|
|
48457
|
+
},
|
|
48458
|
+
activeTargetId,
|
|
48459
|
+
phase
|
|
48460
|
+
}),
|
|
48461
|
+
[phase, transcriptText, error, asr.audioLevel, asr.recording, close, activeTargetId]
|
|
48462
|
+
);
|
|
48463
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(VoicePanelContext.Provider, { value, children: /* @__PURE__ */ jsxRuntimeExports.jsx(VoicePanelDataContext.Provider, { value: dataValue, children }) });
|
|
48464
|
+
}
|
|
48465
|
+
function useVoicePanelTarget(options) {
|
|
48466
|
+
const registerTarget = useVoicePanelContextOptional()?.registerTarget;
|
|
48467
|
+
const dataValue = reactExports.useContext(VoicePanelDataContext);
|
|
48468
|
+
const [id] = reactExports.useState(() => /* @__PURE__ */ Symbol("VoicePanelTarget"));
|
|
48469
|
+
const recordRef = reactExports.useRef({ enabled: false });
|
|
48470
|
+
reactExports.useEffect(() => {
|
|
48471
|
+
recordRef.current.enabled = options.enabled;
|
|
48472
|
+
}, [options.enabled]);
|
|
48473
|
+
reactExports.useEffect(() => {
|
|
48474
|
+
if (!registerTarget) return;
|
|
48475
|
+
return registerTarget(id, recordRef.current);
|
|
48476
|
+
}, [id, registerTarget]);
|
|
48477
|
+
if (!dataValue || dataValue.phase === "idle" || dataValue.activeTargetId !== id) {
|
|
48478
|
+
return null;
|
|
48479
|
+
}
|
|
48480
|
+
return dataValue.panel;
|
|
48481
|
+
}
|
|
48482
|
+
function useVoicePanelController() {
|
|
48483
|
+
const { start, stop, active } = useVoicePanelContext();
|
|
48484
|
+
return { start, stop, active };
|
|
48485
|
+
}
|
|
48486
|
+
function PeripheralRuntime() {
|
|
48487
|
+
const peripherals = useAppStore((state) => state.peripherals);
|
|
48488
|
+
const { start: startVoicePanel, stop: stopVoicePanel } = useVoicePanelController();
|
|
48489
|
+
const platform2 = RENDERER_PLATFORM;
|
|
48490
|
+
const available = isPeripheralRuntimeAvailable({ isWebUI, platform: platform2 });
|
|
48491
|
+
const enabledIds = reactExports.useMemo(
|
|
48492
|
+
() => new Set(peripherals.filter((entry) => entry.enabled).map((entry) => entry.id)),
|
|
48493
|
+
[peripherals]
|
|
48494
|
+
);
|
|
48495
|
+
const holdKeyOwners = reactExports.useMemo(() => {
|
|
48496
|
+
const owners = /* @__PURE__ */ new Map();
|
|
48497
|
+
if (!available) return owners;
|
|
48498
|
+
for (const peripheral of BUILTIN_PERIPHERALS) {
|
|
48499
|
+
if (!enabledIds.has(peripheral.id)) continue;
|
|
48500
|
+
if (!isPeripheralSupportedOnPlatform(peripheral, platform2)) continue;
|
|
48501
|
+
for (const key of peripheral.keys) {
|
|
48502
|
+
if (key.transport !== "keyboard" || key.kind !== "hold" || !key.code) continue;
|
|
48503
|
+
owners.set(key.code, peripheral.id);
|
|
48504
|
+
}
|
|
48505
|
+
}
|
|
48506
|
+
return owners;
|
|
48507
|
+
}, [available, enabledIds, platform2]);
|
|
48508
|
+
reactExports.useEffect(() => {
|
|
48509
|
+
if (holdKeyOwners.size === 0) return;
|
|
48510
|
+
const handleKeyDown = (event) => {
|
|
48511
|
+
if (event.repeat || event.isComposing) return;
|
|
48512
|
+
const peripheralId = holdKeyOwners.get(event.code);
|
|
48513
|
+
if (!peripheralId) return;
|
|
48514
|
+
event.preventDefault();
|
|
48515
|
+
event.stopPropagation();
|
|
48516
|
+
startVoicePanel(peripheralId);
|
|
48517
|
+
};
|
|
48518
|
+
const handleKeyUp = (event) => {
|
|
48519
|
+
if (!holdKeyOwners.has(event.code)) return;
|
|
48520
|
+
event.preventDefault();
|
|
48521
|
+
stopVoicePanel();
|
|
48522
|
+
};
|
|
48523
|
+
const handleBlur = () => stopVoicePanel();
|
|
48524
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
48525
|
+
window.addEventListener("keyup", handleKeyUp, true);
|
|
48526
|
+
window.addEventListener("blur", handleBlur);
|
|
48527
|
+
return () => {
|
|
48528
|
+
window.removeEventListener("keydown", handleKeyDown, true);
|
|
48529
|
+
window.removeEventListener("keyup", handleKeyUp, true);
|
|
48530
|
+
window.removeEventListener("blur", handleBlur);
|
|
48531
|
+
};
|
|
48532
|
+
}, [holdKeyOwners, startVoicePanel, stopVoicePanel]);
|
|
48533
|
+
reactExports.useEffect(() => {
|
|
48534
|
+
if (!available) return;
|
|
48535
|
+
const handlePeripheralKey = (event) => {
|
|
48536
|
+
if (!enabledIds.has(event.peripheralId)) return;
|
|
48537
|
+
if (!event.systemKey) return;
|
|
48538
|
+
if (!document.hasFocus()) return;
|
|
48539
|
+
const target = document.activeElement ?? document.body;
|
|
48540
|
+
target.dispatchEvent(
|
|
48541
|
+
new KeyboardEvent(event.action === "down" ? "keydown" : "keyup", {
|
|
48542
|
+
key: event.systemKey,
|
|
48543
|
+
code: event.systemKey,
|
|
48544
|
+
bubbles: true,
|
|
48545
|
+
cancelable: true
|
|
48546
|
+
})
|
|
48547
|
+
);
|
|
48548
|
+
};
|
|
48549
|
+
subscribe.on("peripheral-key", handlePeripheralKey);
|
|
48550
|
+
return () => subscribe.off("peripheral-key", handlePeripheralKey);
|
|
48551
|
+
}, [available, enabledIds]);
|
|
48552
|
+
return null;
|
|
48553
|
+
}
|
|
47674
48554
|
const COMMAND_DEFINITIONS = [
|
|
47675
48555
|
{
|
|
47676
48556
|
id: "focus.chatInput",
|
|
@@ -47846,6 +48726,449 @@ function useCommandShortcuts(commands2, overrides) {
|
|
|
47846
48726
|
);
|
|
47847
48727
|
useKeyboardShortcuts(shortcuts);
|
|
47848
48728
|
}
|
|
48729
|
+
const STORAGE_KEY = "fello.tts.prefs";
|
|
48730
|
+
const DEFAULT_PREFS = { autoRead: false, volume: 100 };
|
|
48731
|
+
function isObject(value) {
|
|
48732
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
48733
|
+
}
|
|
48734
|
+
function clampVolume(value) {
|
|
48735
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_PREFS.volume;
|
|
48736
|
+
return Math.min(100, Math.max(0, Math.round(value)));
|
|
48737
|
+
}
|
|
48738
|
+
function readPrefs() {
|
|
48739
|
+
try {
|
|
48740
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
48741
|
+
if (!raw) return DEFAULT_PREFS;
|
|
48742
|
+
const parsed = JSON.parse(raw);
|
|
48743
|
+
if (!isObject(parsed)) return DEFAULT_PREFS;
|
|
48744
|
+
return {
|
|
48745
|
+
autoRead: typeof parsed.autoRead === "boolean" ? parsed.autoRead : DEFAULT_PREFS.autoRead,
|
|
48746
|
+
volume: clampVolume(parsed.volume)
|
|
48747
|
+
};
|
|
48748
|
+
} catch {
|
|
48749
|
+
return DEFAULT_PREFS;
|
|
48750
|
+
}
|
|
48751
|
+
}
|
|
48752
|
+
function writePrefs(prefs) {
|
|
48753
|
+
try {
|
|
48754
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
|
|
48755
|
+
} catch {
|
|
48756
|
+
}
|
|
48757
|
+
}
|
|
48758
|
+
const useTtsPrefsStore = create((set2, get2) => ({
|
|
48759
|
+
...readPrefs(),
|
|
48760
|
+
setAutoRead: (autoRead) => {
|
|
48761
|
+
set2({ autoRead });
|
|
48762
|
+
writePrefs({ autoRead, volume: get2().volume });
|
|
48763
|
+
},
|
|
48764
|
+
setVolume: (volume) => {
|
|
48765
|
+
const next = clampVolume(volume);
|
|
48766
|
+
set2({ volume: next });
|
|
48767
|
+
writePrefs({ autoRead: get2().autoRead, volume: next });
|
|
48768
|
+
}
|
|
48769
|
+
}));
|
|
48770
|
+
function getTtsPrefs() {
|
|
48771
|
+
const { autoRead, volume } = useTtsPrefsStore.getState();
|
|
48772
|
+
return { autoRead, volume };
|
|
48773
|
+
}
|
|
48774
|
+
const useTtsPlaybackStore = create((set2) => ({
|
|
48775
|
+
activeSessionId: null,
|
|
48776
|
+
setActiveSessionId: (activeSessionId) => set2({ activeSessionId })
|
|
48777
|
+
}));
|
|
48778
|
+
class TtsPlayer {
|
|
48779
|
+
context = null;
|
|
48780
|
+
masterGain = null;
|
|
48781
|
+
session = null;
|
|
48782
|
+
/** master GainNode 的目标增益(0-1),来自渲染层音量偏好 */
|
|
48783
|
+
gain = getTtsPrefs().volume / 100;
|
|
48784
|
+
constructor() {
|
|
48785
|
+
useTtsPrefsStore.subscribe((state) => this.applyVolume(state.volume));
|
|
48786
|
+
}
|
|
48787
|
+
applyVolume(volume) {
|
|
48788
|
+
this.gain = Math.min(1, Math.max(0, volume / 100));
|
|
48789
|
+
if (this.masterGain) this.masterGain.gain.value = this.gain;
|
|
48790
|
+
}
|
|
48791
|
+
ensureContext() {
|
|
48792
|
+
if (!this.context) {
|
|
48793
|
+
this.context = new AudioContext();
|
|
48794
|
+
this.masterGain = this.context.createGain();
|
|
48795
|
+
this.masterGain.gain.value = this.gain;
|
|
48796
|
+
this.masterGain.connect(this.context.destination);
|
|
48797
|
+
}
|
|
48798
|
+
if (this.context.state === "suspended") {
|
|
48799
|
+
void this.context.resume();
|
|
48800
|
+
}
|
|
48801
|
+
return this.context;
|
|
48802
|
+
}
|
|
48803
|
+
stopSession(playback) {
|
|
48804
|
+
for (const source of playback.sources) {
|
|
48805
|
+
try {
|
|
48806
|
+
source.stop();
|
|
48807
|
+
} catch {
|
|
48808
|
+
}
|
|
48809
|
+
source.disconnect();
|
|
48810
|
+
}
|
|
48811
|
+
playback.sources.clear();
|
|
48812
|
+
}
|
|
48813
|
+
/**
|
|
48814
|
+
* 追加一段 PCM16(base64)到播放队列。
|
|
48815
|
+
* 新会话到达时抢占:停旧会话、清队列、切换。
|
|
48816
|
+
*/
|
|
48817
|
+
enqueueChunk(params) {
|
|
48818
|
+
const { sessionId, audioB64, sampleRate } = params;
|
|
48819
|
+
const context = this.ensureContext();
|
|
48820
|
+
const masterGain = this.masterGain;
|
|
48821
|
+
if (!this.session || this.session.sessionId !== sessionId) {
|
|
48822
|
+
if (this.session) this.stopSession(this.session);
|
|
48823
|
+
this.session = { sessionId, nextStartTime: 0, sources: /* @__PURE__ */ new Set() };
|
|
48824
|
+
useTtsPlaybackStore.getState().setActiveSessionId(sessionId);
|
|
48825
|
+
}
|
|
48826
|
+
const playback = this.session;
|
|
48827
|
+
const bytes = Uint8Array.from(atob(audioB64), (c) => c.charCodeAt(0));
|
|
48828
|
+
if (bytes.length % 2 !== 0) return;
|
|
48829
|
+
const pcm = new Int16Array(bytes.buffer, bytes.byteOffset, bytes.length / 2);
|
|
48830
|
+
const buffer = context.createBuffer(1, pcm.length, sampleRate);
|
|
48831
|
+
const channel = buffer.getChannelData(0);
|
|
48832
|
+
for (let i = 0; i < pcm.length; i++) channel[i] = pcm[i] / 32768;
|
|
48833
|
+
const source = context.createBufferSource();
|
|
48834
|
+
source.buffer = buffer;
|
|
48835
|
+
source.connect(masterGain);
|
|
48836
|
+
const startAt = Math.max(context.currentTime + 0.05, playback.nextStartTime);
|
|
48837
|
+
playback.nextStartTime = startAt + buffer.duration;
|
|
48838
|
+
source.onended = () => {
|
|
48839
|
+
playback.sources.delete(source);
|
|
48840
|
+
source.disconnect();
|
|
48841
|
+
if (playback.sources.size === 0 && this.session === playback && playback.nextStartTime <= (this.context?.currentTime ?? 0) + 0.02) {
|
|
48842
|
+
this.session = null;
|
|
48843
|
+
useTtsPlaybackStore.getState().setActiveSessionId(null);
|
|
48844
|
+
}
|
|
48845
|
+
};
|
|
48846
|
+
playback.sources.add(source);
|
|
48847
|
+
source.start(startAt);
|
|
48848
|
+
}
|
|
48849
|
+
/** 停止当前播放(清队列 + 清状态)。 */
|
|
48850
|
+
stop() {
|
|
48851
|
+
if (!this.session) return;
|
|
48852
|
+
this.stopSession(this.session);
|
|
48853
|
+
this.session = null;
|
|
48854
|
+
useTtsPlaybackStore.getState().setActiveSessionId(null);
|
|
48855
|
+
}
|
|
48856
|
+
}
|
|
48857
|
+
const ttsPlayer = new TtsPlayer();
|
|
48858
|
+
function removeMarkdown(md, options) {
|
|
48859
|
+
options = options || {};
|
|
48860
|
+
options.listUnicodeChar = options.hasOwnProperty("listUnicodeChar") ? options.listUnicodeChar : false;
|
|
48861
|
+
options.stripListLeaders = options.hasOwnProperty("stripListLeaders") ? options.stripListLeaders : true;
|
|
48862
|
+
options.gfm = options.hasOwnProperty("gfm") ? options.gfm : true;
|
|
48863
|
+
options.useImgAltText = options.hasOwnProperty("useImgAltText") ? options.useImgAltText : true;
|
|
48864
|
+
options.abbr = options.hasOwnProperty("abbr") ? options.abbr : false;
|
|
48865
|
+
options.replaceLinksWithURL = options.hasOwnProperty("replaceLinksWithURL") ? options.replaceLinksWithURL : false;
|
|
48866
|
+
options.separateLinksAndTexts = options.hasOwnProperty("separateLinksAndTexts") ? options.separateLinksAndTexts : null;
|
|
48867
|
+
options.htmlTagsToSkip = options.hasOwnProperty("htmlTagsToSkip") ? options.htmlTagsToSkip : [];
|
|
48868
|
+
options.throwError = options.hasOwnProperty("throwError") ? options.throwError : false;
|
|
48869
|
+
var output = md || "";
|
|
48870
|
+
output = output.replace(/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/gm, "");
|
|
48871
|
+
try {
|
|
48872
|
+
if (options.stripListLeaders) {
|
|
48873
|
+
if (options.listUnicodeChar)
|
|
48874
|
+
output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, options.listUnicodeChar + " $1");
|
|
48875
|
+
else
|
|
48876
|
+
output = output.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, "$1");
|
|
48877
|
+
}
|
|
48878
|
+
if (options.gfm) {
|
|
48879
|
+
output = output.replace(/\n={2,}/g, "\n").replace(/~{3}.*\n/g, "").replace(/~~/g, "").replace(/```(?:.*)\n([\s\S]*?)```/g, (_2, code) => code.trim());
|
|
48880
|
+
}
|
|
48881
|
+
if (options.abbr) {
|
|
48882
|
+
output = output.replace(/\*\[.*\]:.*\n/, "");
|
|
48883
|
+
}
|
|
48884
|
+
let htmlReplaceRegex = /<[^>]*>/g;
|
|
48885
|
+
if (options.htmlTagsToSkip && options.htmlTagsToSkip.length > 0) {
|
|
48886
|
+
const joinedHtmlTagsToSkip = options.htmlTagsToSkip.join("|");
|
|
48887
|
+
htmlReplaceRegex = new RegExp(
|
|
48888
|
+
`<(?!/?(${joinedHtmlTagsToSkip})(?=>|s[^>]*>))[^>]*>`,
|
|
48889
|
+
"g"
|
|
48890
|
+
);
|
|
48891
|
+
}
|
|
48892
|
+
if (options.separateLinksAndTexts) {
|
|
48893
|
+
output = output.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1" + options.separateLinksAndTexts + "$2");
|
|
48894
|
+
}
|
|
48895
|
+
output = output.replace(htmlReplaceRegex, "").replace(/^[=\-]{2,}\s*$/g, "").replace(/\[\^.+?\](\: .*?$)?/g, "").replace(/\s{0,2}\[.*?\]: .*?$/g, "").replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, options.useImgAltText ? "$1" : "").replace(/\[([\s\S]*?)\]\s*[\(\[](.*?)[\)\]]/g, options.replaceLinksWithURL ? "$2" : "$1").replace(/^(\n)?\s{0,3}>\s?/gm, "$1").replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, "").replace(/^(\n)?\s{0,}#{1,6}\s*( (.+))? +#+$|^(\n)?\s{0,}#{1,6}\s*( (.+))?$/gm, "$1$3$4$6").replace(/([\*]+)(\S)(.*?\S)??\1/g, "$2$3").replace(/(^|\W)([_]+)(\S)(.*?\S)??\2($|\W)/g, "$1$3$4$5").replace(/(`{3,})(.*?)\1/gm, "$2").replace(/`(.+?)`/g, "$1").replace(/~(.*?)~/g, "$1");
|
|
48896
|
+
} catch (e) {
|
|
48897
|
+
if (options.throwError) throw e;
|
|
48898
|
+
console.error("remove-markdown encountered error: %s", e);
|
|
48899
|
+
return md;
|
|
48900
|
+
}
|
|
48901
|
+
return output;
|
|
48902
|
+
}
|
|
48903
|
+
const MAX_SENTENCE_LEN = 120;
|
|
48904
|
+
const CJK_TERMINATORS = /* @__PURE__ */ new Set(["。", "!", "?", ";", "…"]);
|
|
48905
|
+
const SPEAKABLE_RE = /[\p{L}\p{N}]/u;
|
|
48906
|
+
const FENCE_LINE_RE = /^\s{0,3}(`{3,}|~{3,})[A-Za-z0-9+#._-]*\s*$/;
|
|
48907
|
+
const RESIDUE_RE = new RegExp("[`*_~|\\u005B\\u005D]|\\p{Cf}", "gu");
|
|
48908
|
+
function sanitizeLine(line) {
|
|
48909
|
+
return removeMarkdown(line).replace(/https?:\/\/\S+/g, " ").replace(/^\s*\[[ xX]\]\s*/, "").replace(RESIDUE_RE, " ").replace(/\s+/g, " ").trim();
|
|
48910
|
+
}
|
|
48911
|
+
function createTtsTextSplitter() {
|
|
48912
|
+
let inFence = false;
|
|
48913
|
+
let lineBuf = "";
|
|
48914
|
+
let sentence = "";
|
|
48915
|
+
let pendingDot = false;
|
|
48916
|
+
const out = [];
|
|
48917
|
+
const pushSentence = (text) => {
|
|
48918
|
+
const trimmed = text.trim();
|
|
48919
|
+
if (!trimmed || !SPEAKABLE_RE.test(trimmed)) return;
|
|
48920
|
+
out.push(trimmed);
|
|
48921
|
+
};
|
|
48922
|
+
const flushSentence = () => {
|
|
48923
|
+
const text = sentence;
|
|
48924
|
+
sentence = "";
|
|
48925
|
+
pushSentence(text);
|
|
48926
|
+
};
|
|
48927
|
+
const splitLongSentence = () => {
|
|
48928
|
+
const from = Math.max(0, sentence.length - 60);
|
|
48929
|
+
let cut = -1;
|
|
48930
|
+
for (let i = sentence.length - 1; i >= from; i--) {
|
|
48931
|
+
if (",,;; ".includes(sentence[i])) {
|
|
48932
|
+
cut = i + 1;
|
|
48933
|
+
break;
|
|
48934
|
+
}
|
|
48935
|
+
}
|
|
48936
|
+
if (cut > 0) {
|
|
48937
|
+
pushSentence(sentence.slice(0, cut));
|
|
48938
|
+
sentence = sentence.slice(cut);
|
|
48939
|
+
} else {
|
|
48940
|
+
pushSentence(sentence.slice(0, MAX_SENTENCE_LEN));
|
|
48941
|
+
sentence = sentence.slice(MAX_SENTENCE_LEN);
|
|
48942
|
+
}
|
|
48943
|
+
};
|
|
48944
|
+
const scanChar = (ch) => {
|
|
48945
|
+
if (pendingDot) {
|
|
48946
|
+
pendingDot = false;
|
|
48947
|
+
if (!/[A-Za-z0-9]/.test(ch)) flushSentence();
|
|
48948
|
+
}
|
|
48949
|
+
if (CJK_TERMINATORS.has(ch) || ch === "!" || ch === "?") {
|
|
48950
|
+
sentence += ch;
|
|
48951
|
+
flushSentence();
|
|
48952
|
+
return;
|
|
48953
|
+
}
|
|
48954
|
+
if (ch === "." && /[A-Za-z]/.test(sentence.charAt(sentence.length - 1))) {
|
|
48955
|
+
sentence += ch;
|
|
48956
|
+
pendingDot = true;
|
|
48957
|
+
return;
|
|
48958
|
+
}
|
|
48959
|
+
sentence += ch;
|
|
48960
|
+
if (sentence.length > MAX_SENTENCE_LEN) splitLongSentence();
|
|
48961
|
+
};
|
|
48962
|
+
const processLine = (line) => {
|
|
48963
|
+
if (FENCE_LINE_RE.test(line)) {
|
|
48964
|
+
inFence = !inFence;
|
|
48965
|
+
return;
|
|
48966
|
+
}
|
|
48967
|
+
if (inFence) return;
|
|
48968
|
+
const sanitized = sanitizeLine(line);
|
|
48969
|
+
if (!SPEAKABLE_RE.test(sanitized)) return;
|
|
48970
|
+
if (sentence && !/\s$/.test(sentence)) sentence += " ";
|
|
48971
|
+
for (const ch of sanitized) scanChar(ch);
|
|
48972
|
+
};
|
|
48973
|
+
const lastCommitableTerminator = (text) => {
|
|
48974
|
+
for (let i = text.length - 1; i >= 0; i--) {
|
|
48975
|
+
const ch = text[i];
|
|
48976
|
+
if (CJK_TERMINATORS.has(ch) || ch === "!" || ch === "?") return i;
|
|
48977
|
+
if (ch === "." && i + 1 < text.length && /\s/.test(text[i + 1])) return i;
|
|
48978
|
+
}
|
|
48979
|
+
return -1;
|
|
48980
|
+
};
|
|
48981
|
+
const drainPartialLine = () => {
|
|
48982
|
+
const cut = lastCommitableTerminator(lineBuf);
|
|
48983
|
+
if (cut === -1) return;
|
|
48984
|
+
processLine(lineBuf.slice(0, cut + 1));
|
|
48985
|
+
lineBuf = lineBuf.slice(cut + 1);
|
|
48986
|
+
};
|
|
48987
|
+
return {
|
|
48988
|
+
feed(chunk) {
|
|
48989
|
+
out.length = 0;
|
|
48990
|
+
lineBuf += chunk;
|
|
48991
|
+
let idx;
|
|
48992
|
+
while ((idx = lineBuf.indexOf("\n")) !== -1) {
|
|
48993
|
+
processLine(lineBuf.slice(0, idx));
|
|
48994
|
+
lineBuf = lineBuf.slice(idx + 1);
|
|
48995
|
+
}
|
|
48996
|
+
drainPartialLine();
|
|
48997
|
+
return out.slice();
|
|
48998
|
+
},
|
|
48999
|
+
end() {
|
|
49000
|
+
out.length = 0;
|
|
49001
|
+
if (!inFence) processLine(lineBuf);
|
|
49002
|
+
lineBuf = "";
|
|
49003
|
+
pendingDot = false;
|
|
49004
|
+
flushSentence();
|
|
49005
|
+
return out.slice();
|
|
49006
|
+
}
|
|
49007
|
+
};
|
|
49008
|
+
}
|
|
49009
|
+
const START_RETRY_COOLDOWN_MS = 3e4;
|
|
49010
|
+
let audioSubscribed = false;
|
|
49011
|
+
let errorListener = null;
|
|
49012
|
+
const MANUAL_KEY = "manual";
|
|
49013
|
+
const suppressedAutoKeys = /* @__PURE__ */ new Set();
|
|
49014
|
+
const erroredSessions = /* @__PURE__ */ new Set();
|
|
49015
|
+
let liveTtsSessionId = null;
|
|
49016
|
+
let lastAutoKey = null;
|
|
49017
|
+
let startFailedAt = 0;
|
|
49018
|
+
let current = null;
|
|
49019
|
+
function ensureAudioSubscription() {
|
|
49020
|
+
if (audioSubscribed) return;
|
|
49021
|
+
audioSubscribed = true;
|
|
49022
|
+
subscribe.on("tts-audio", (detail2) => {
|
|
49023
|
+
if (detail2.ttsSessionId !== liveTtsSessionId) return;
|
|
49024
|
+
if (detail2.format !== "pcm") return;
|
|
49025
|
+
ttsPlayer.enqueueChunk({
|
|
49026
|
+
sessionId: detail2.ttsSessionId,
|
|
49027
|
+
audioB64: detail2.audioB64,
|
|
49028
|
+
sampleRate: detail2.sampleRate ?? 16e3
|
|
49029
|
+
});
|
|
49030
|
+
});
|
|
49031
|
+
subscribe.on("tts-closed", (detail2) => {
|
|
49032
|
+
const session2 = current;
|
|
49033
|
+
if (session2?.ttsSessionId === detail2.ttsSessionId) {
|
|
49034
|
+
session2.ttsSessionId = null;
|
|
49035
|
+
session2.dead = true;
|
|
49036
|
+
}
|
|
49037
|
+
});
|
|
49038
|
+
subscribe.on("tts-error", (detail2) => {
|
|
49039
|
+
const session2 = current;
|
|
49040
|
+
if (!session2 || session2.ttsSessionId !== detail2.ttsSessionId) return;
|
|
49041
|
+
if (erroredSessions.has(detail2.ttsSessionId)) return;
|
|
49042
|
+
erroredSessions.add(detail2.ttsSessionId);
|
|
49043
|
+
const ttsSessionId = detail2.ttsSessionId;
|
|
49044
|
+
session2.dead = true;
|
|
49045
|
+
session2.ttsSessionId = null;
|
|
49046
|
+
current = null;
|
|
49047
|
+
if (liveTtsSessionId === ttsSessionId) liveTtsSessionId = null;
|
|
49048
|
+
startFailedAt = Date.now();
|
|
49049
|
+
ttsPlayer.stop();
|
|
49050
|
+
errorListener?.(detail2.message);
|
|
49051
|
+
void request.endTts({ ttsSessionId }).catch(() => {
|
|
49052
|
+
});
|
|
49053
|
+
});
|
|
49054
|
+
}
|
|
49055
|
+
function onTtsError(listener) {
|
|
49056
|
+
errorListener = listener;
|
|
49057
|
+
}
|
|
49058
|
+
function newTtsSessionId() {
|
|
49059
|
+
return generateUUID().replace(/-/g, "").slice(0, 16);
|
|
49060
|
+
}
|
|
49061
|
+
function appendStep(session2, step) {
|
|
49062
|
+
session2.chain = session2.chain.then(step).catch(() => {
|
|
49063
|
+
});
|
|
49064
|
+
}
|
|
49065
|
+
async function ensureBackendSession(session2) {
|
|
49066
|
+
if (session2.ttsSessionId) return session2.ttsSessionId;
|
|
49067
|
+
if (session2.dead) return null;
|
|
49068
|
+
if (session2.respectCooldown && Date.now() - startFailedAt < START_RETRY_COOLDOWN_MS) return null;
|
|
49069
|
+
const ttsSessionId = newTtsSessionId();
|
|
49070
|
+
try {
|
|
49071
|
+
await request.startTts({ ttsSessionId });
|
|
49072
|
+
} catch (error) {
|
|
49073
|
+
session2.dead = true;
|
|
49074
|
+
erroredSessions.add(ttsSessionId);
|
|
49075
|
+
if (session2.respectCooldown) startFailedAt = Date.now();
|
|
49076
|
+
errorListener?.(error instanceof Error ? error.message : String(error));
|
|
49077
|
+
return null;
|
|
49078
|
+
}
|
|
49079
|
+
session2.ttsSessionId = ttsSessionId;
|
|
49080
|
+
if (session2.dead) return null;
|
|
49081
|
+
liveTtsSessionId = ttsSessionId;
|
|
49082
|
+
return ttsSessionId;
|
|
49083
|
+
}
|
|
49084
|
+
function appendSentence(session2, sentence) {
|
|
49085
|
+
appendStep(session2, async () => {
|
|
49086
|
+
if (session2.dead) return;
|
|
49087
|
+
const ttsSessionId = await ensureBackendSession(session2);
|
|
49088
|
+
if (!ttsSessionId) return;
|
|
49089
|
+
await request.speakTts({ ttsSessionId, text: sentence });
|
|
49090
|
+
});
|
|
49091
|
+
}
|
|
49092
|
+
function appendEnd(session2) {
|
|
49093
|
+
appendStep(session2, async () => {
|
|
49094
|
+
const ttsSessionId = session2.ttsSessionId;
|
|
49095
|
+
session2.ttsSessionId = null;
|
|
49096
|
+
if (!ttsSessionId) return;
|
|
49097
|
+
try {
|
|
49098
|
+
await request.endTts({ ttsSessionId });
|
|
49099
|
+
} finally {
|
|
49100
|
+
erroredSessions.delete(ttsSessionId);
|
|
49101
|
+
}
|
|
49102
|
+
});
|
|
49103
|
+
}
|
|
49104
|
+
function endSession(session2, options = {}) {
|
|
49105
|
+
if (session2.ended) return;
|
|
49106
|
+
session2.ended = true;
|
|
49107
|
+
if (!options.flushTail) {
|
|
49108
|
+
session2.dead = true;
|
|
49109
|
+
liveTtsSessionId = null;
|
|
49110
|
+
}
|
|
49111
|
+
if (options.flushTail && !session2.dead) {
|
|
49112
|
+
for (const sentence of session2.splitter.end()) appendSentence(session2, sentence);
|
|
49113
|
+
}
|
|
49114
|
+
appendEnd(session2);
|
|
49115
|
+
if (current === session2) current = null;
|
|
49116
|
+
}
|
|
49117
|
+
function startSession(key, respectCooldown) {
|
|
49118
|
+
liveTtsSessionId = null;
|
|
49119
|
+
if (current) endSession(current);
|
|
49120
|
+
ttsPlayer.stop();
|
|
49121
|
+
const session2 = {
|
|
49122
|
+
key,
|
|
49123
|
+
splitter: createTtsTextSplitter(),
|
|
49124
|
+
ttsSessionId: null,
|
|
49125
|
+
chain: Promise.resolve(),
|
|
49126
|
+
ended: false,
|
|
49127
|
+
dead: false,
|
|
49128
|
+
respectCooldown
|
|
49129
|
+
};
|
|
49130
|
+
current = session2;
|
|
49131
|
+
return session2;
|
|
49132
|
+
}
|
|
49133
|
+
function getOrCreateAutoSession(key) {
|
|
49134
|
+
if (current && current.key === key && !current.ended) return current;
|
|
49135
|
+
return startSession(key, true);
|
|
49136
|
+
}
|
|
49137
|
+
function feedTtsStream(key, rawText) {
|
|
49138
|
+
ensureAudioSubscription();
|
|
49139
|
+
lastAutoKey = key;
|
|
49140
|
+
if (suppressedAutoKeys.has(key)) return;
|
|
49141
|
+
const session2 = getOrCreateAutoSession(key);
|
|
49142
|
+
for (const sentence of session2.splitter.feed(rawText)) appendSentence(session2, sentence);
|
|
49143
|
+
}
|
|
49144
|
+
function endTtsStream(key) {
|
|
49145
|
+
suppressedAutoKeys.delete(key);
|
|
49146
|
+
const session2 = current;
|
|
49147
|
+
if (!session2 || session2.key !== key) return;
|
|
49148
|
+
endSession(session2, { flushTail: true });
|
|
49149
|
+
}
|
|
49150
|
+
function speakOnce(rawText) {
|
|
49151
|
+
ensureAudioSubscription();
|
|
49152
|
+
if (lastAutoKey) suppressedAutoKeys.add(lastAutoKey);
|
|
49153
|
+
const session2 = startSession(MANUAL_KEY, false);
|
|
49154
|
+
for (const sentence of session2.splitter.feed(rawText)) appendSentence(session2, sentence);
|
|
49155
|
+
endSession(session2, { flushTail: true });
|
|
49156
|
+
}
|
|
49157
|
+
function leaveTtsSession() {
|
|
49158
|
+
stopActiveTts();
|
|
49159
|
+
if (lastAutoKey) suppressedAutoKeys.delete(lastAutoKey);
|
|
49160
|
+
lastAutoKey = null;
|
|
49161
|
+
}
|
|
49162
|
+
function resetTtsForNewPrompt(key) {
|
|
49163
|
+
stopActiveTts();
|
|
49164
|
+
suppressedAutoKeys.delete(key);
|
|
49165
|
+
}
|
|
49166
|
+
function stopActiveTts() {
|
|
49167
|
+
if (lastAutoKey) suppressedAutoKeys.add(lastAutoKey);
|
|
49168
|
+
liveTtsSessionId = null;
|
|
49169
|
+
ttsPlayer.stop();
|
|
49170
|
+
if (current) endSession(current);
|
|
49171
|
+
}
|
|
47849
49172
|
var h = { name: "soft", baseFreq: 440, noiseColor: "pink", oscType: "sine", filterFreq: 3e3, filterQ: 2, attack: 2e-3, decay: 1, brightness: 2e3 }, D$1 = { name: "crisp", baseFreq: 523, noiseColor: "white", oscType: "triangle", filterFreq: 5e3, filterQ: 3, attack: 15e-4, decay: 0.6, brightness: 4e3 }, L$1 = { name: "arcade", baseFreq: 392, noiseColor: "white", oscType: "square", filterFreq: 2200, filterQ: 5, attack: 1e-3, decay: 0.5, brightness: 2800 }, P = { name: "glass", baseFreq: 660, noiseColor: "pink", oscType: "sine", filterFreq: 6500, filterQ: 6, attack: 4e-3, decay: 1.4, brightness: 5500 }, Q = { soft: h, crisp: D$1, arcade: L$1, glass: P };
|
|
47850
49173
|
function v$1(n) {
|
|
47851
49174
|
if (typeof n == "string") {
|
|
@@ -48138,26 +49461,25 @@ function D(t) {
|
|
|
48138
49461
|
}
|
|
48139
49462
|
const UPDATE_TOAST_ID = "fello-app-update";
|
|
48140
49463
|
function AppContent() {
|
|
48141
|
-
const
|
|
48142
|
-
|
|
48143
|
-
|
|
48144
|
-
|
|
48145
|
-
|
|
48146
|
-
|
|
48147
|
-
|
|
48148
|
-
|
|
48149
|
-
|
|
48150
|
-
|
|
48151
|
-
|
|
48152
|
-
|
|
48153
|
-
|
|
48154
|
-
|
|
48155
|
-
|
|
48156
|
-
|
|
48157
|
-
|
|
48158
|
-
|
|
48159
|
-
|
|
48160
|
-
} = useAppStore();
|
|
49464
|
+
const isMacApp = useAppStore((s) => s.isMacApp);
|
|
49465
|
+
const setSessions = useAppStore((s) => s.setSessions);
|
|
49466
|
+
const setProjects = useAppStore((s) => s.setProjects);
|
|
49467
|
+
const setConfiguredAgents = useAppStore((s) => s.setConfiguredAgents);
|
|
49468
|
+
const setConfiguredMcpServers = useAppStore((s) => s.setConfiguredMcpServers);
|
|
49469
|
+
const setWebUIStatus = useAppStore((s) => s.setWebUIStatus);
|
|
49470
|
+
const setTheme = useAppStore((s) => s.setTheme);
|
|
49471
|
+
const setI18n2 = useAppStore((s) => s.setI18n);
|
|
49472
|
+
const setEditor = useAppStore((s) => s.setEditor);
|
|
49473
|
+
const setSnippets = useAppStore((s) => s.setSnippets);
|
|
49474
|
+
const setImageGeneration = useAppStore((s) => s.setImageGeneration);
|
|
49475
|
+
const setSpeechProviders = useAppStore((s) => s.setSpeechProviders);
|
|
49476
|
+
const setVoiceInput = useAppStore((s) => s.setVoiceInput);
|
|
49477
|
+
const setShortcuts = useAppStore((s) => s.setShortcuts);
|
|
49478
|
+
const setPeripherals = useAppStore((s) => s.setPeripherals);
|
|
49479
|
+
const setProxy = useAppStore((s) => s.setProxy);
|
|
49480
|
+
const setIsFullScreen = useAppStore((s) => s.setIsFullScreen);
|
|
49481
|
+
const setIlinkStatus = useAppStore((s) => s.setIlinkStatus);
|
|
49482
|
+
const setActiveIlinkSessionId = useAppStore((s) => s.setActiveIlinkSessionId);
|
|
48161
49483
|
const shortcuts = useAppStore((state) => state.shortcuts);
|
|
48162
49484
|
const { resolvedTheme } = z();
|
|
48163
49485
|
const { i18n, t } = useTranslation();
|
|
@@ -48172,6 +49494,12 @@ function AppContent() {
|
|
|
48172
49494
|
reactExports.useEffect(() => {
|
|
48173
49495
|
activeSessionIdRef.current = activeSessionId;
|
|
48174
49496
|
}, [activeSessionId]);
|
|
49497
|
+
reactExports.useEffect(() => {
|
|
49498
|
+
onTtsError((message2) => {
|
|
49499
|
+
toast2.error(message2);
|
|
49500
|
+
});
|
|
49501
|
+
return () => onTtsError(null);
|
|
49502
|
+
}, [toast2]);
|
|
48175
49503
|
const navigate = useNavigate();
|
|
48176
49504
|
const [isReady, setIsReady] = reactExports.useState(false);
|
|
48177
49505
|
const pendingSessionNotificationRef = reactExports.useRef(
|
|
@@ -48209,9 +49537,10 @@ function AppContent() {
|
|
|
48209
49537
|
if (settings2.editor) setEditor(settings2.editor);
|
|
48210
49538
|
if (settings2.snippets) setSnippets(settings2.snippets);
|
|
48211
49539
|
if (settings2.imageGeneration) setImageGeneration(settings2.imageGeneration);
|
|
48212
|
-
if (settings2.
|
|
49540
|
+
if (settings2.speechProviders) setSpeechProviders(settings2.speechProviders);
|
|
48213
49541
|
if (settings2.voiceInput) setVoiceInput(settings2.voiceInput);
|
|
48214
49542
|
if (settings2.shortcuts) setShortcuts(settings2.shortcuts);
|
|
49543
|
+
if (settings2.peripherals) setPeripherals(settings2.peripherals);
|
|
48215
49544
|
for (const session2 of sessions ?? []) {
|
|
48216
49545
|
try {
|
|
48217
49546
|
const pending = await request.getPendingAskUserRequests({ sessionId: session2.id });
|
|
@@ -48244,9 +49573,10 @@ function AppContent() {
|
|
|
48244
49573
|
setEditor,
|
|
48245
49574
|
setSnippets,
|
|
48246
49575
|
setImageGeneration,
|
|
48247
|
-
|
|
49576
|
+
setSpeechProviders,
|
|
48248
49577
|
setVoiceInput,
|
|
48249
49578
|
setShortcuts,
|
|
49579
|
+
setPeripherals,
|
|
48250
49580
|
setProxy,
|
|
48251
49581
|
setIlinkStatus,
|
|
48252
49582
|
setActiveIlinkSessionId
|
|
@@ -48570,7 +49900,10 @@ function AppContent() {
|
|
|
48570
49900
|
] });
|
|
48571
49901
|
}
|
|
48572
49902
|
function App() {
|
|
48573
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ThemeProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(HashRouter, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(FocusTargetProvider, { children: /* @__PURE__ */ jsxRuntimeExports.
|
|
49903
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBoundary, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ThemeProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(HashRouter, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(FocusTargetProvider, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(VoicePanelProvider, { children: [
|
|
49904
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(AppContent, {}),
|
|
49905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(PeripheralRuntime, {})
|
|
49906
|
+
] }) }) }) }) }) });
|
|
48574
49907
|
}
|
|
48575
49908
|
clientExports.createRoot(document.getElementById("root")).render(
|
|
48576
49909
|
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) })
|
|
@@ -48608,201 +49941,222 @@ export {
|
|
|
48608
49941
|
ClockCheck as Z,
|
|
48609
49942
|
Badge as _,
|
|
48610
49943
|
useAppStore as a,
|
|
48611
|
-
|
|
49944
|
+
useHoverReferenceInteraction as a$,
|
|
48612
49945
|
CircleCheck as a0,
|
|
48613
|
-
|
|
48614
|
-
|
|
48615
|
-
|
|
48616
|
-
|
|
48617
|
-
|
|
48618
|
-
|
|
48619
|
-
|
|
48620
|
-
|
|
48621
|
-
|
|
48622
|
-
|
|
48623
|
-
|
|
48624
|
-
|
|
48625
|
-
|
|
48626
|
-
|
|
48627
|
-
|
|
48628
|
-
|
|
48629
|
-
|
|
48630
|
-
|
|
48631
|
-
|
|
48632
|
-
|
|
48633
|
-
|
|
48634
|
-
|
|
48635
|
-
|
|
48636
|
-
|
|
48637
|
-
|
|
48638
|
-
|
|
48639
|
-
|
|
48640
|
-
|
|
48641
|
-
|
|
48642
|
-
|
|
48643
|
-
|
|
48644
|
-
|
|
48645
|
-
|
|
48646
|
-
|
|
48647
|
-
|
|
48648
|
-
|
|
48649
|
-
|
|
48650
|
-
|
|
48651
|
-
|
|
48652
|
-
|
|
48653
|
-
|
|
48654
|
-
|
|
48655
|
-
|
|
48656
|
-
|
|
48657
|
-
|
|
48658
|
-
|
|
48659
|
-
|
|
48660
|
-
|
|
48661
|
-
|
|
48662
|
-
|
|
48663
|
-
|
|
48664
|
-
|
|
48665
|
-
|
|
48666
|
-
|
|
48667
|
-
|
|
48668
|
-
|
|
48669
|
-
|
|
48670
|
-
|
|
48671
|
-
|
|
48672
|
-
|
|
49946
|
+
ChevronRight as a1,
|
|
49947
|
+
EDITOR_LABELS as a2,
|
|
49948
|
+
L as a3,
|
|
49949
|
+
N as a4,
|
|
49950
|
+
_ as a5,
|
|
49951
|
+
D as a6,
|
|
49952
|
+
w as a7,
|
|
49953
|
+
SelectGroup as a8,
|
|
49954
|
+
SelectLabel as a9,
|
|
49955
|
+
popupStoreSelectors as aA,
|
|
49956
|
+
triggerHover as aB,
|
|
49957
|
+
triggerPress as aC,
|
|
49958
|
+
escapeKey as aD,
|
|
49959
|
+
attachPreventUnmountOnClose as aE,
|
|
49960
|
+
closePress as aF,
|
|
49961
|
+
PATIENT_CLICK_THRESHOLD as aG,
|
|
49962
|
+
focusOut as aH,
|
|
49963
|
+
createPopupOpenState as aI,
|
|
49964
|
+
createInitialPopupStoreState as aJ,
|
|
49965
|
+
Timeout as aK,
|
|
49966
|
+
PopupTriggerMap as aL,
|
|
49967
|
+
FloatingTree as aM,
|
|
49968
|
+
fastComponent as aN,
|
|
49969
|
+
usePopupRootSync as aO,
|
|
49970
|
+
useImplicitActiveTrigger as aP,
|
|
49971
|
+
useOpenStateTransitions as aQ,
|
|
49972
|
+
createChangeEventDetails as aR,
|
|
49973
|
+
imperativeAction as aS,
|
|
49974
|
+
PopupHandleAttachment as aT,
|
|
49975
|
+
usePopupRootStore as aU,
|
|
49976
|
+
useDismiss as aV,
|
|
49977
|
+
usePopupInteractionProps as aW,
|
|
49978
|
+
fastComponentRef as aX,
|
|
49979
|
+
usePopupHandleStore as aY,
|
|
49980
|
+
useBaseUiId as aZ,
|
|
49981
|
+
useTriggerDataForwarding as a_,
|
|
49982
|
+
RefreshCw as aa,
|
|
49983
|
+
cva as ab,
|
|
49984
|
+
Separator as ac,
|
|
49985
|
+
useRender as ad,
|
|
49986
|
+
mergeProps as ae,
|
|
49987
|
+
Bot as af,
|
|
49988
|
+
Globe as ag,
|
|
49989
|
+
MessageCircle as ah,
|
|
49990
|
+
resetAgent as ai,
|
|
49991
|
+
clearAgentSessions as aj,
|
|
49992
|
+
updateAgentSettings as ak,
|
|
49993
|
+
React as al,
|
|
49994
|
+
COMMAND_DEFINITIONS as am,
|
|
49995
|
+
getCommandShortcuts as an,
|
|
49996
|
+
shortcutPreviewFromKeyboardEvent as ao,
|
|
49997
|
+
shortcutFromKeyboardEvent as ap,
|
|
49998
|
+
findShortcutConflicts as aq,
|
|
49999
|
+
reactDomExports as ar,
|
|
50000
|
+
isPeripheralRuntimeAvailable as as,
|
|
50001
|
+
Info as at,
|
|
50002
|
+
BUILTIN_PERIPHERALS as au,
|
|
50003
|
+
RENDERER_PLATFORM as av,
|
|
50004
|
+
isPeripheralSupportedOnPlatform as aw,
|
|
50005
|
+
getDefaultExportFromCjs as ax,
|
|
48673
50006
|
formatErrorMessage as ay,
|
|
48674
|
-
|
|
50007
|
+
ReactStore as az,
|
|
48675
50008
|
useMessage as b,
|
|
48676
|
-
|
|
48677
|
-
|
|
48678
|
-
|
|
48679
|
-
|
|
48680
|
-
|
|
48681
|
-
|
|
48682
|
-
|
|
48683
|
-
|
|
48684
|
-
|
|
48685
|
-
|
|
48686
|
-
|
|
48687
|
-
|
|
48688
|
-
|
|
48689
|
-
|
|
48690
|
-
|
|
48691
|
-
|
|
48692
|
-
|
|
48693
|
-
|
|
48694
|
-
|
|
48695
|
-
|
|
48696
|
-
|
|
48697
|
-
|
|
48698
|
-
|
|
48699
|
-
|
|
48700
|
-
|
|
48701
|
-
|
|
48702
|
-
|
|
48703
|
-
|
|
48704
|
-
|
|
48705
|
-
|
|
48706
|
-
|
|
48707
|
-
|
|
48708
|
-
|
|
48709
|
-
|
|
48710
|
-
|
|
48711
|
-
|
|
48712
|
-
|
|
48713
|
-
|
|
48714
|
-
|
|
48715
|
-
|
|
48716
|
-
|
|
48717
|
-
|
|
48718
|
-
|
|
48719
|
-
|
|
48720
|
-
|
|
48721
|
-
|
|
48722
|
-
|
|
48723
|
-
|
|
48724
|
-
|
|
48725
|
-
|
|
48726
|
-
|
|
48727
|
-
|
|
48728
|
-
|
|
48729
|
-
|
|
48730
|
-
|
|
48731
|
-
|
|
48732
|
-
|
|
48733
|
-
|
|
48734
|
-
|
|
48735
|
-
|
|
48736
|
-
|
|
48737
|
-
|
|
48738
|
-
|
|
48739
|
-
|
|
50009
|
+
inputChange as b$,
|
|
50010
|
+
safePolygon as b0,
|
|
50011
|
+
useClick as b1,
|
|
50012
|
+
useOpenMethodTriggerProps as b2,
|
|
50013
|
+
useButton as b3,
|
|
50014
|
+
useTriggerFocusGuards as b4,
|
|
50015
|
+
useRenderElement as b5,
|
|
50016
|
+
CLICK_TRIGGER_IDENTIFIER as b6,
|
|
50017
|
+
FocusGuard as b7,
|
|
50018
|
+
pressableTriggerOpenStateMapping as b8,
|
|
50019
|
+
triggerOpenStateMapping as b9,
|
|
50020
|
+
useMergedRefs as bA,
|
|
50021
|
+
useValueAsRef as bB,
|
|
50022
|
+
AnimationFrame as bC,
|
|
50023
|
+
addEventListener as bD,
|
|
50024
|
+
getWindow as bE,
|
|
50025
|
+
none as bF,
|
|
50026
|
+
resolveStyle as bG,
|
|
50027
|
+
Tabs as bH,
|
|
50028
|
+
TabsList as bI,
|
|
50029
|
+
TabsTrigger as bJ,
|
|
50030
|
+
webUIBaseUrl as bK,
|
|
50031
|
+
reduceSessionNotification as bL,
|
|
50032
|
+
reduceFlushStreaming as bM,
|
|
50033
|
+
Clock as bN,
|
|
50034
|
+
Folder as bO,
|
|
50035
|
+
shimExports as bP,
|
|
50036
|
+
NOOP as bQ,
|
|
50037
|
+
useCSPContext as bR,
|
|
50038
|
+
clamp as bS,
|
|
50039
|
+
fieldValidityMapping as bT,
|
|
50040
|
+
useFormContext as bU,
|
|
50041
|
+
useFieldRootContext as bV,
|
|
50042
|
+
useLabelableContext as bW,
|
|
50043
|
+
useRegisterFieldControl as bX,
|
|
50044
|
+
useValueChanged as bY,
|
|
50045
|
+
areArraysEqual as bZ,
|
|
50046
|
+
keyboard as b_,
|
|
50047
|
+
FloatingPortal as ba,
|
|
50048
|
+
POPUP_COLLISION_AVOIDANCE as bb,
|
|
50049
|
+
useFloatingNodeId as bc,
|
|
50050
|
+
useAnimationsFinished as bd,
|
|
50051
|
+
useAnchorPositioning as be,
|
|
50052
|
+
useIsoLayoutEffect as bf,
|
|
50053
|
+
useAnchoredPopupScrollLock as bg,
|
|
50054
|
+
usePositioner as bh,
|
|
50055
|
+
InternalBackdrop as bi,
|
|
50056
|
+
inertValue as bj,
|
|
50057
|
+
FloatingNode as bk,
|
|
50058
|
+
useStableCallback as bl,
|
|
50059
|
+
useToolbarRootContext as bm,
|
|
50060
|
+
useOpenChangeComplete as bn,
|
|
50061
|
+
useHoverFloatingInteraction as bo,
|
|
50062
|
+
createDefaultInitialFocus as bp,
|
|
50063
|
+
FOCUSABLE_POPUP_PROPS as bq,
|
|
50064
|
+
COMPOSITE_KEYS as br,
|
|
50065
|
+
getDisabledMountTransitionStyles as bs,
|
|
50066
|
+
FloatingFocusManager as bt,
|
|
50067
|
+
isHTMLElement as bu,
|
|
50068
|
+
popupTransitionStateMapping as bv,
|
|
50069
|
+
useControlled as bw,
|
|
50070
|
+
useTransitionStatus as bx,
|
|
50071
|
+
startingStyle as by,
|
|
50072
|
+
transitionStatusMapping as bz,
|
|
48740
50073
|
createLucideIcon as c,
|
|
48741
|
-
|
|
48742
|
-
|
|
48743
|
-
|
|
48744
|
-
|
|
48745
|
-
|
|
48746
|
-
|
|
48747
|
-
|
|
48748
|
-
|
|
48749
|
-
|
|
48750
|
-
|
|
48751
|
-
|
|
48752
|
-
|
|
48753
|
-
|
|
48754
|
-
|
|
48755
|
-
|
|
48756
|
-
|
|
48757
|
-
|
|
48758
|
-
|
|
48759
|
-
|
|
48760
|
-
|
|
48761
|
-
|
|
48762
|
-
|
|
48763
|
-
|
|
48764
|
-
|
|
48765
|
-
|
|
48766
|
-
|
|
48767
|
-
|
|
48768
|
-
|
|
48769
|
-
|
|
48770
|
-
|
|
48771
|
-
|
|
48772
|
-
|
|
48773
|
-
|
|
48774
|
-
|
|
48775
|
-
|
|
48776
|
-
|
|
48777
|
-
|
|
48778
|
-
|
|
48779
|
-
|
|
48780
|
-
|
|
48781
|
-
|
|
48782
|
-
|
|
48783
|
-
|
|
48784
|
-
|
|
48785
|
-
|
|
48786
|
-
|
|
48787
|
-
|
|
48788
|
-
|
|
48789
|
-
|
|
48790
|
-
|
|
48791
|
-
|
|
48792
|
-
|
|
48793
|
-
|
|
48794
|
-
|
|
48795
|
-
|
|
48796
|
-
|
|
48797
|
-
|
|
48798
|
-
|
|
48799
|
-
|
|
48800
|
-
|
|
48801
|
-
|
|
48802
|
-
|
|
48803
|
-
|
|
48804
|
-
|
|
50074
|
+
Code as c$,
|
|
50075
|
+
createGenericEventDetails as c0,
|
|
50076
|
+
activeElement as c1,
|
|
50077
|
+
ownerDocument as c2,
|
|
50078
|
+
contains as c3,
|
|
50079
|
+
CompositeList as c4,
|
|
50080
|
+
getDefaultLabelId as c5,
|
|
50081
|
+
resolveAriaLabelledBy as c6,
|
|
50082
|
+
useDirection as c7,
|
|
50083
|
+
getTarget as c8,
|
|
50084
|
+
useAnimationFrame as c9,
|
|
50085
|
+
TooltipContent as cA,
|
|
50086
|
+
useFocusTarget as cB,
|
|
50087
|
+
formatDuration as cC,
|
|
50088
|
+
speakOnce as cD,
|
|
50089
|
+
ReactDOM as cE,
|
|
50090
|
+
useRealtimeAsr as cF,
|
|
50091
|
+
ChevronDown as cG,
|
|
50092
|
+
useVoicePanelTarget as cH,
|
|
50093
|
+
HoverCard as cI,
|
|
50094
|
+
HoverCardTrigger as cJ,
|
|
50095
|
+
HoverCardContent as cK,
|
|
50096
|
+
X as cL,
|
|
50097
|
+
useFocusTargetRegistry as cM,
|
|
50098
|
+
v as cN,
|
|
50099
|
+
DropdownMenuSub as cO,
|
|
50100
|
+
DropdownMenuSubTrigger as cP,
|
|
50101
|
+
DropdownMenuSubContent as cQ,
|
|
50102
|
+
CircleQuestionMark as cR,
|
|
50103
|
+
ChevronUp as cS,
|
|
50104
|
+
leaveTtsSession as cT,
|
|
50105
|
+
feedTtsStream as cU,
|
|
50106
|
+
resetTtsForNewPrompt as cV,
|
|
50107
|
+
endTtsStream as cW,
|
|
50108
|
+
AUDIO_EXTENSIONS as cX,
|
|
50109
|
+
VIDEO_EXTENSIONS as cY,
|
|
50110
|
+
z as cZ,
|
|
50111
|
+
__vitePreload as c_,
|
|
50112
|
+
isElement as ca,
|
|
50113
|
+
drag as cb,
|
|
50114
|
+
trackPress as cc,
|
|
50115
|
+
useLabelableId as cd,
|
|
50116
|
+
useCompositeListItem as ce,
|
|
50117
|
+
visuallyHidden as cf,
|
|
50118
|
+
PAGE_UP as cg,
|
|
50119
|
+
PAGE_DOWN as ch,
|
|
50120
|
+
HOME as ci,
|
|
50121
|
+
END as cj,
|
|
50122
|
+
ARROW_LEFT as ck,
|
|
50123
|
+
ARROW_DOWN as cl,
|
|
50124
|
+
ARROW_RIGHT as cm,
|
|
50125
|
+
ARROW_UP as cn,
|
|
50126
|
+
matchesFocusVisible as co,
|
|
50127
|
+
SessionConfigFields as cp,
|
|
50128
|
+
useTtsPlaybackStore as cq,
|
|
50129
|
+
stopActiveTts as cr,
|
|
50130
|
+
useTtsPrefsStore as cs,
|
|
50131
|
+
buttonVariants as ct,
|
|
50132
|
+
restartSession as cu,
|
|
50133
|
+
SessionLifecycleBusyError as cv,
|
|
50134
|
+
closeSession as cw,
|
|
50135
|
+
RestartSessionError as cx,
|
|
50136
|
+
Tooltip as cy,
|
|
50137
|
+
TooltipTrigger as cz,
|
|
48805
50138
|
Switch as d,
|
|
50139
|
+
MessageSquare as d0,
|
|
50140
|
+
isContextMenuKey as d1,
|
|
50141
|
+
openContextMenuFromKeyboard as d2,
|
|
50142
|
+
FolderPlus as d3,
|
|
50143
|
+
Eye as d4,
|
|
50144
|
+
useProjectState as d5,
|
|
50145
|
+
clientId as d6,
|
|
50146
|
+
TabsContent as d7,
|
|
50147
|
+
loadSession as d8,
|
|
50148
|
+
TriangleAlert as d9,
|
|
50149
|
+
Card as da,
|
|
50150
|
+
getBasename as db,
|
|
50151
|
+
isSubPath as dc,
|
|
50152
|
+
formatBytes as dd,
|
|
50153
|
+
isImageMimeType as de,
|
|
50154
|
+
getMediaKind as df,
|
|
50155
|
+
ALL_FEATURES as dg,
|
|
50156
|
+
FEATURE_I18N_KEYS as dh,
|
|
50157
|
+
twMerge as di,
|
|
50158
|
+
clsx as dj,
|
|
50159
|
+
getAugmentedNamespace as dk,
|
|
48806
50160
|
Copy as e,
|
|
48807
50161
|
request as f,
|
|
48808
50162
|
extractErrorMessage as g,
|