@saluzi/saluzi-edu 0.2.50 → 0.2.52
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/dist/cli.js +69 -64
- package/dist/guide/assets/{main-Ba71iEWV.js → main-BLaZPqcD.js} +1 -1
- package/dist/guide/guide-data.json +2 -2
- package/dist/guide/index.html +1 -1
- package/{packages/remote-control-server/web/dist/assets/AdminPanel-Ct9eK8PS.js → dist/rcs-web/assets/AdminPanel-BU_m2tTe.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/Claim-CupWsGys.js → dist/rcs-web/assets/Claim-76lutQis.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/Dashboard-MTKONPcB.js → dist/rcs-web/assets/Dashboard-B4nxTeft.js} +1 -1
- package/dist/rcs-web/assets/{Join-DLmnjsxE.js → Join-KIjSy6RI.js} +1 -1
- package/dist/rcs-web/assets/{Login-bCblCtbV.js → Login-BS8dN_pA.js} +1 -1
- package/dist/rcs-web/assets/{Register-DOgX4oH3.js → Register-DdWhmPwF.js} +1 -1
- package/dist/rcs-web/assets/{SessionDetail-CjsJ2Nqw.js → SessionDetail-B9zVxGG0.js} +1 -1
- package/dist/rcs-web/assets/{SessionVisibilityBadge-CtJcoGk_.js → SessionVisibilityBadge-Bkv-o3zy.js} +1 -1
- package/dist/rcs-web/assets/{Setup-CYE98qPs.js → Setup-Dh6nT2Cd.js} +1 -1
- package/dist/rcs-web/assets/{ShareLanding-CLKoEufZ.js → ShareLanding-AQyowQYz.js} +1 -1
- package/dist/rcs-web/assets/{TeamCreate-DmjFyCSj.js → TeamCreate-DStppJIa.js} +1 -1
- package/dist/rcs-web/assets/TeamDetail-DudkRM26.js +6 -0
- package/dist/rcs-web/assets/{TeamList-B7RrVPBl.js → TeamList-B2YF0znl.js} +1 -1
- package/dist/rcs-web/assets/{TeamSettings-EEPrvcmS.js → TeamSettings-BpHpHzUj.js} +1 -1
- package/dist/rcs-web/assets/{UserSearchInput-DvaOtWrz.js → UserSearchInput-DHCklRIF.js} +1 -1
- package/dist/rcs-web/assets/{UserSettings-C8uTbJo7.js → UserSettings-BWd6v4rQ.js} +1 -1
- package/dist/rcs-web/assets/{arc-BlkSVtQL.js → arc-BgGV491M.js} +1 -1
- package/dist/rcs-web/assets/{architectureDiagram-3BPJPVTR-DMFRRa4D.js → architectureDiagram-3BPJPVTR-DLhWu9K4.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-DuImWg6d.js → dist/rcs-web/assets/blockDiagram-GPEHLZMM-DejuGJUT.js} +1 -1
- package/dist/rcs-web/assets/{c4Diagram-AAUBKEIU-BR0t725Z.js → c4Diagram-AAUBKEIU-BJP-IVGK.js} +1 -1
- package/dist/rcs-web/assets/channel-6hQBS9Uq.js +1 -0
- package/dist/rcs-web/assets/{chunk-2J33WTMH-B0dCDVlO.js → chunk-2J33WTMH-yqGAlZsO.js} +1 -1
- package/dist/rcs-web/assets/{chunk-4BX2VUAB-_eu8ITLw.js → chunk-4BX2VUAB-C6xp5yYX.js} +1 -1
- package/dist/rcs-web/assets/{chunk-55IACEB6-CfhQXrYr.js → chunk-55IACEB6-BnoiueV2.js} +1 -1
- package/dist/rcs-web/assets/{chunk-727SXJPM-C4cV9vm4.js → chunk-727SXJPM-BAykCWKk.js} +1 -1
- package/dist/rcs-web/assets/{chunk-AQP2D5EJ--DhKQhEc.js → chunk-AQP2D5EJ-DeElJ5j7.js} +1 -1
- package/dist/rcs-web/assets/{chunk-FMBD7UC4-DZ1OrJK2.js → chunk-FMBD7UC4-jP0H_--k.js} +1 -1
- package/dist/rcs-web/assets/{chunk-ND2GUHAM-D9Z0Zh1p.js → chunk-ND2GUHAM-BGIpLa5_.js} +1 -1
- package/dist/rcs-web/assets/{chunk-QZHKN3VN-D3rtM6br.js → chunk-QZHKN3VN-Blt1Cg58.js} +1 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-BHUV1B5s.js +1 -0
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-BHUV1B5s.js +1 -0
- package/dist/rcs-web/assets/{code-block-IT6T5CEO-CaahNQzH.js → code-block-IT6T5CEO-BKTU2vHT.js} +1 -1
- package/dist/rcs-web/assets/{copy-BACa7KvX.js → copy-B2vFSPoy.js} +1 -1
- package/dist/rcs-web/assets/{cose-bilkent-S5V4N54A-BdonEvGn.js → cose-bilkent-S5V4N54A-ZuTAtm7Q.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/dagre-BM42HDAG-Dyc1_bNY.js → dist/rcs-web/assets/dagre-BM42HDAG-D56sKgGx.js} +1 -1
- package/dist/rcs-web/assets/{diagram-2AECGRRQ-Vx_n6aIe.js → diagram-2AECGRRQ-B9z0e8pz.js} +1 -1
- package/dist/rcs-web/assets/{diagram-5GNKFQAL-CwtEz5UH.js → diagram-5GNKFQAL-CHYkH5kc.js} +1 -1
- package/dist/rcs-web/assets/{diagram-KO2AKTUF-Dcwv972J.js → diagram-KO2AKTUF-B0fefELP.js} +1 -1
- package/dist/rcs-web/assets/{diagram-LMA3HP47-D3aJRasH.js → diagram-LMA3HP47-v_CNumDx.js} +1 -1
- package/dist/rcs-web/assets/{diagram-OG6HWLK6-Mpd2TxkR.js → diagram-OG6HWLK6-BiP-PzY3.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-BT4N2fdc.js → dist/rcs-web/assets/erDiagram-TEJ5UH35-CA-q3pz9.js} +1 -1
- package/dist/rcs-web/assets/{flowDiagram-I6XJVG4X-Cxnv-hUF.js → flowDiagram-I6XJVG4X-D0wxPgJk.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-D5khq5pQ.js → dist/rcs-web/assets/ganttDiagram-6RSMTGT7-D8tEhnvv.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-B2RQ2o9P.js → dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-Bx4dq1wL.js} +1 -1
- package/dist/rcs-web/assets/{infoDiagram-5YYISTIA-DvDKWoeM.js → infoDiagram-5YYISTIA-D9-sPGtp.js} +1 -1
- package/dist/rcs-web/assets/{ishikawaDiagram-YF4QCWOH-imaVzAh5.js → ishikawaDiagram-YF4QCWOH-DHC2gfHg.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/journeyDiagram-JHISSGLW-DchZFAta.js → dist/rcs-web/assets/journeyDiagram-JHISSGLW-CeWu1YkX.js} +1 -1
- package/dist/rcs-web/assets/{kanban-definition-UN3LZRKU-CGaZKyBi.js → kanban-definition-UN3LZRKU-CtbBamBO.js} +1 -1
- package/dist/rcs-web/assets/{linear-Bb3v4vs9.js → linear-WFGCU65A.js} +1 -1
- package/dist/rcs-web/assets/{main-BC1VOiGR.js → main-C6czI38s.js} +3 -3
- package/dist/rcs-web/assets/{mermaid-VLURNSYL-BCOb0kp0.js → mermaid-VLURNSYL-CJEG4DJA.js} +4 -4
- package/dist/rcs-web/assets/{mermaid.core-QYMkyCEt.js → mermaid.core-aZvgg4gM.js} +5 -5
- package/{packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-B48k7mv1.js → dist/rcs-web/assets/mindmap-definition-RKZ34NQL-CYrLhvPq.js} +1 -1
- package/dist/rcs-web/assets/{pieDiagram-4H26LBE5-DhghG1QC.js → pieDiagram-4H26LBE5-Cc9GCu8V.js} +1 -1
- package/dist/rcs-web/assets/{quadrantDiagram-W4KKPZXB-Dd4IfwVX.js → quadrantDiagram-W4KKPZXB-3VXRYoRB.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/requirementDiagram-4Y6WPE33-DC5ZTKl6.js → dist/rcs-web/assets/requirementDiagram-4Y6WPE33-DznaQwwS.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-DHi1SbAk.js → dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-B11xI8oj.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-B1_hgUxl.js → dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-CmUYXS5A.js} +1 -1
- package/dist/rcs-web/assets/{stateDiagram-AJRCARHV-DU0DNkMr.js → stateDiagram-AJRCARHV-CViWtNni.js} +1 -1
- package/dist/rcs-web/assets/{stateDiagram-v2-BHNVJYJU-CJQ1bhJ0.js → stateDiagram-v2-BHNVJYJU-DPQ0Q1PA.js} +1 -1
- package/dist/rcs-web/assets/{timeline-definition-PNZ67QCA-C4CW1u9S.js → timeline-definition-PNZ67QCA-CL0Ql3sZ.js} +1 -1
- package/{packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-CrcO6XWl.js → dist/rcs-web/assets/vennDiagram-CIIHVFJN-DEYqp1U8.js} +1 -1
- package/dist/rcs-web/assets/{wardleyDiagram-YWT4CUSO-CwuQo6e5.js → wardleyDiagram-YWT4CUSO-B9Pnv5gW.js} +1 -1
- package/dist/rcs-web/assets/{xychartDiagram-2RQKCTM6-D_UK1xKq.js → xychartDiagram-2RQKCTM6-DSPoLW7d.js} +1 -1
- package/dist/rcs-web/index.html +1 -1
- package/package.json +3 -1
- package/packages/remote-control-server/package.json +1 -0
- package/packages/remote-control-server/src/__tests__/teams.test.ts +25 -0
- package/packages/remote-control-server/src/routes/web/auth-routes.ts +32 -13
- package/packages/remote-control-server/src/services/disconnect-monitor.ts +7 -64
- package/{dist/rcs-web/assets/AdminPanel-Ct9eK8PS.js → packages/remote-control-server/web/dist/assets/AdminPanel-BU_m2tTe.js} +1 -1
- package/{dist/rcs-web/assets/Claim-CupWsGys.js → packages/remote-control-server/web/dist/assets/Claim-76lutQis.js} +1 -1
- package/{dist/rcs-web/assets/Dashboard-MTKONPcB.js → packages/remote-control-server/web/dist/assets/Dashboard-B4nxTeft.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Join-DLmnjsxE.js → Join-KIjSy6RI.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Login-bCblCtbV.js → Login-BS8dN_pA.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Register-DOgX4oH3.js → Register-DdWhmPwF.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{SessionDetail-CjsJ2Nqw.js → SessionDetail-B9zVxGG0.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{SessionVisibilityBadge-CtJcoGk_.js → SessionVisibilityBadge-Bkv-o3zy.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{Setup-CYE98qPs.js → Setup-Dh6nT2Cd.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ShareLanding-CLKoEufZ.js → ShareLanding-AQyowQYz.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamCreate-DmjFyCSj.js → TeamCreate-DStppJIa.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/TeamDetail-DudkRM26.js +6 -0
- package/packages/remote-control-server/web/dist/assets/{TeamList-B7RrVPBl.js → TeamList-B2YF0znl.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{TeamSettings-EEPrvcmS.js → TeamSettings-BpHpHzUj.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{UserSearchInput-DvaOtWrz.js → UserSearchInput-DHCklRIF.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{UserSettings-C8uTbJo7.js → UserSettings-BWd6v4rQ.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{arc-BlkSVtQL.js → arc-BgGV491M.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{architectureDiagram-3BPJPVTR-DMFRRa4D.js → architectureDiagram-3BPJPVTR-DLhWu9K4.js} +1 -1
- package/{dist/rcs-web/assets/blockDiagram-GPEHLZMM-DuImWg6d.js → packages/remote-control-server/web/dist/assets/blockDiagram-GPEHLZMM-DejuGJUT.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{c4Diagram-AAUBKEIU-BR0t725Z.js → c4Diagram-AAUBKEIU-BJP-IVGK.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/channel-6hQBS9Uq.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{chunk-2J33WTMH-B0dCDVlO.js → chunk-2J33WTMH-yqGAlZsO.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-4BX2VUAB-_eu8ITLw.js → chunk-4BX2VUAB-C6xp5yYX.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-55IACEB6-CfhQXrYr.js → chunk-55IACEB6-BnoiueV2.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-727SXJPM-C4cV9vm4.js → chunk-727SXJPM-BAykCWKk.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-AQP2D5EJ--DhKQhEc.js → chunk-AQP2D5EJ-DeElJ5j7.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-FMBD7UC4-DZ1OrJK2.js → chunk-FMBD7UC4-jP0H_--k.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-ND2GUHAM-D9Z0Zh1p.js → chunk-ND2GUHAM-BGIpLa5_.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{chunk-QZHKN3VN-D3rtM6br.js → chunk-QZHKN3VN-Blt1Cg58.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-BHUV1B5s.js +1 -0
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-BHUV1B5s.js +1 -0
- package/packages/remote-control-server/web/dist/assets/{code-block-IT6T5CEO-CaahNQzH.js → code-block-IT6T5CEO-BKTU2vHT.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{copy-BACa7KvX.js → copy-B2vFSPoy.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{cose-bilkent-S5V4N54A-BdonEvGn.js → cose-bilkent-S5V4N54A-ZuTAtm7Q.js} +1 -1
- package/{dist/rcs-web/assets/dagre-BM42HDAG-Dyc1_bNY.js → packages/remote-control-server/web/dist/assets/dagre-BM42HDAG-D56sKgGx.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-2AECGRRQ-Vx_n6aIe.js → diagram-2AECGRRQ-B9z0e8pz.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-5GNKFQAL-CwtEz5UH.js → diagram-5GNKFQAL-CHYkH5kc.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-KO2AKTUF-Dcwv972J.js → diagram-KO2AKTUF-B0fefELP.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-LMA3HP47-D3aJRasH.js → diagram-LMA3HP47-v_CNumDx.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{diagram-OG6HWLK6-Mpd2TxkR.js → diagram-OG6HWLK6-BiP-PzY3.js} +1 -1
- package/{dist/rcs-web/assets/erDiagram-TEJ5UH35-BT4N2fdc.js → packages/remote-control-server/web/dist/assets/erDiagram-TEJ5UH35-CA-q3pz9.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{flowDiagram-I6XJVG4X-Cxnv-hUF.js → flowDiagram-I6XJVG4X-D0wxPgJk.js} +1 -1
- package/{dist/rcs-web/assets/ganttDiagram-6RSMTGT7-D5khq5pQ.js → packages/remote-control-server/web/dist/assets/ganttDiagram-6RSMTGT7-D8tEhnvv.js} +1 -1
- package/{dist/rcs-web/assets/gitGraphDiagram-PVQCEYII-B2RQ2o9P.js → packages/remote-control-server/web/dist/assets/gitGraphDiagram-PVQCEYII-Bx4dq1wL.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{infoDiagram-5YYISTIA-DvDKWoeM.js → infoDiagram-5YYISTIA-D9-sPGtp.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{ishikawaDiagram-YF4QCWOH-imaVzAh5.js → ishikawaDiagram-YF4QCWOH-DHC2gfHg.js} +1 -1
- package/{dist/rcs-web/assets/journeyDiagram-JHISSGLW-DchZFAta.js → packages/remote-control-server/web/dist/assets/journeyDiagram-JHISSGLW-CeWu1YkX.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{kanban-definition-UN3LZRKU-CGaZKyBi.js → kanban-definition-UN3LZRKU-CtbBamBO.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{linear-Bb3v4vs9.js → linear-WFGCU65A.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{main-BC1VOiGR.js → main-C6czI38s.js} +3 -3
- package/packages/remote-control-server/web/dist/assets/{mermaid-VLURNSYL-BCOb0kp0.js → mermaid-VLURNSYL-CJEG4DJA.js} +4 -4
- package/packages/remote-control-server/web/dist/assets/{mermaid.core-QYMkyCEt.js → mermaid.core-aZvgg4gM.js} +5 -5
- package/{dist/rcs-web/assets/mindmap-definition-RKZ34NQL-B48k7mv1.js → packages/remote-control-server/web/dist/assets/mindmap-definition-RKZ34NQL-CYrLhvPq.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{pieDiagram-4H26LBE5-DhghG1QC.js → pieDiagram-4H26LBE5-Cc9GCu8V.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{quadrantDiagram-W4KKPZXB-Dd4IfwVX.js → quadrantDiagram-W4KKPZXB-3VXRYoRB.js} +1 -1
- package/{dist/rcs-web/assets/requirementDiagram-4Y6WPE33-DC5ZTKl6.js → packages/remote-control-server/web/dist/assets/requirementDiagram-4Y6WPE33-DznaQwwS.js} +1 -1
- package/{dist/rcs-web/assets/sankeyDiagram-5OEKKPKP-DHi1SbAk.js → packages/remote-control-server/web/dist/assets/sankeyDiagram-5OEKKPKP-B11xI8oj.js} +1 -1
- package/{dist/rcs-web/assets/sequenceDiagram-3UESZ5HK-B1_hgUxl.js → packages/remote-control-server/web/dist/assets/sequenceDiagram-3UESZ5HK-CmUYXS5A.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{stateDiagram-AJRCARHV-DU0DNkMr.js → stateDiagram-AJRCARHV-CViWtNni.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{stateDiagram-v2-BHNVJYJU-CJQ1bhJ0.js → stateDiagram-v2-BHNVJYJU-DPQ0Q1PA.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{timeline-definition-PNZ67QCA-C4CW1u9S.js → timeline-definition-PNZ67QCA-CL0Ql3sZ.js} +1 -1
- package/{dist/rcs-web/assets/vennDiagram-CIIHVFJN-CrcO6XWl.js → packages/remote-control-server/web/dist/assets/vennDiagram-CIIHVFJN-DEYqp1U8.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{wardleyDiagram-YWT4CUSO-CwuQo6e5.js → wardleyDiagram-YWT4CUSO-B9Pnv5gW.js} +1 -1
- package/packages/remote-control-server/web/dist/assets/{xychartDiagram-2RQKCTM6-D_UK1xKq.js → xychartDiagram-2RQKCTM6-DSPoLW7d.js} +1 -1
- package/packages/remote-control-server/web/dist/index.html +1 -1
- package/dist/rcs-web/assets/TeamDetail-DIL1NQNr.js +0 -6
- package/dist/rcs-web/assets/channel-B25SKqAo.js +0 -1
- package/dist/rcs-web/assets/classDiagram-4FO5ZUOK-Dg1j1aBA.js +0 -1
- package/dist/rcs-web/assets/classDiagram-v2-Q7XG4LA2-Dg1j1aBA.js +0 -1
- package/packages/remote-control-server/web/dist/assets/TeamDetail-DIL1NQNr.js +0 -6
- package/packages/remote-control-server/web/dist/assets/channel-B25SKqAo.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-4FO5ZUOK-Dg1j1aBA.js +0 -1
- package/packages/remote-control-server/web/dist/assets/classDiagram-v2-Q7XG4LA2-Dg1j1aBA.js +0 -1
|
@@ -164,4 +164,4 @@ import{c as e,l as t,o as n,s as r}from"./streamdown-nMT_aKRc.js";import{t as i}
|
|
|
164
164
|
`,R=(0,f.lazy)(async()=>({default:(await a(()=>import(`./streamdown-nMT_aKRc.js`).then(e=>e.n),__vite__mapDeps([0,1,2]))).Streamdown}));function z(e){let t=e.split(`
|
|
165
165
|
`),n=[],r=!1,i=``;for(let e=0;e<t.length;e++){let a=t[e],o=a.trim(),s=/^(`{3}|~{3})/.exec(o);if(s){r?o.startsWith(i.repeat(3))&&(r=!1,i=``):(r=!0,i=s[1][0]),n.push(a);continue}if(r){n.push(a);continue}if(o===``||/^#{1,6} /.test(o)||o.startsWith(`|`)||/^[-*+]\s/.test(o)||/^\d+\.\s/.test(o)||o.startsWith(`>`)||/^(-{3,}|\*{3,}|_{3,})$/.test(o)||o.startsWith("```")){n.push(a);continue}let c=(n[n.length-1]??``).trim();c!==``&&!/^#{1,6} /.test(c)&&!c.startsWith(`|`)&&!/^[-*+]\s/.test(c)&&!/^\d+\.\s/.test(c)&&!c.startsWith(`>`)&&!/^(-{3,}|\*{3,}|_{3,})$/.test(c)&&!c.startsWith("```")&&n.push(``),n.push(a)}return n.join(`
|
|
166
166
|
`)}var B=`::parade-preview::`;function V(e){return e.replace(/[*_`~]/g,``).replace(/[^\p{L}\p{N}\s-]/gu,``).trim().toLowerCase().replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``)}function H(e){let t=e.split(`
|
|
167
|
-
`),n=[],r=!1,i=``;for(let e of t){let t=e.trim(),a=/^(`{3}|~{3})/.exec(t);if(a){r?t.startsWith(i.repeat(3))&&(r=!1,i=``):(r=!0,i=a[1][0]);continue}if(r)continue;let o=/^(#{2,3})\s+(.+?)\s*$/.exec(t);if(!o)continue;let s=o[1].length,c=o[2],l=V(c);l&&n.push({level:s,text:c,slug:l})}let a=new Map;return n.map(e=>{let t=a.get(e.slug)??0;return a.set(e.slug,t+1),t===0?e:{...e,slug:`${e.slug}-${t}`}})}function U(e){let t=[],n=e.split(B);for(let e=0;e<n.length;e++)n[e]&&t.push({kind:`md`,content:z(n[e])}),e<n.length-1&&t.push({kind:`parade-preview`});return t}function W({chapter:e,path:t,onNavigate:n}){let r=e.frontmatter.title??t,i=(0,f.useRef)(null),a=(0,f.useRef)(null),[o,s]=(0,f.useState)(null),c=(0,f.useMemo)(()=>U(e.content.replace(/^\{\/\*[\s\S]*?\*\/\}\s*\n/gm,``).replace(/^\{\/\*[\s\S]*?\*\/\}/gm,``)),[e.content]),l=(0,f.useMemo)(()=>H(e.content),[e.content]);(0,f.useEffect)(()=>{if(!i.current||l.length===0)return;let e=i.current,t=()=>{e.querySelectorAll(`h2, h3`).forEach((e,t)=>{let n=l[t];n&&(e.id!==n.slug&&(e.id=n.slug),e.style.scrollMarginTop!==`5rem`&&(e.style.scrollMarginTop=`5rem`))})};t();let n=new MutationObserver(()=>t());return n.observe(e,{childList:!0,subtree:!0}),()=>n.disconnect()},[l,c]),(0,f.useEffect)(()=>{if(!i.current)return;let e=i.current.parentElement;for(;e&&getComputedStyle(e).overflowY!==`auto`;)e=e.parentElement;a.current=e},[]),(0,f.useEffect)(()=>{let e=a.current;if(!e||l.length===0)return;let t=()=>{let t=e.scrollTop,n=null;for(let e of l){let r=document.getElementById(e.slug);if(r)if(r.offsetTop-120<=t)n=e;else break}s(n?.slug??null)};return t(),e.addEventListener(`scroll`,t,{passive:!0}),()=>e.removeEventListener(`scroll`,t)},[l]);function u(e){if(!n)return null;if(e.startsWith(`docs/`))return e;let r=e.replace(/^(?:\.\.\/|\.\/|\/)+/,``);return r=r.replace(/\.(md|mdx)$/,``),r?`${t.split(`/`).slice(0,-1).join(`/`)}/${r}`:null}function d(e){if(!n)return;let t=e.target.closest(`a`);if(!t)return;let r=t.getAttribute(`href`);if(!r||/^(https?:|mailto:|#)/.test(r))return;let i=u(r);i&&(e.preventDefault(),n(i))}function p(e){let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:`smooth`,block:`start`}),s(e);return}let n=0,r=window.setInterval(()=>{n+=1;let t=document.getElementById(e);t?(window.clearInterval(r),t.scrollIntoView({behavior:`smooth`,block:`start`}),s(e)):n>=20&&window.clearInterval(r)},50)}let m=l.length>=2;return(0,S.jsx)(`div`,{className:`mx-auto max-w-5xl px-6 py-12 sm:px-10 sm:py-16`,children:(0,S.jsxs)(`div`,{className:`flex gap-10`,children:[(0,S.jsxs)(`article`,{ref:i,className:`min-w-0 max-w-2xl flex-1 px-2 sm:px-4`,onClick:d,children:[(0,S.jsxs)(`header`,{className:`mb-12 border-b border-border pb-8`,children:[(0,S.jsx)(`h1`,{className:`font-display text-4xl font-bold leading-tight tracking-tight text-foreground`,children:r}),e.frontmatter.description?(0,S.jsx)(`p`,{className:`mt-4 font-serif text-lg leading-relaxed text-muted-foreground`,children:e.frontmatter.description}):null,e.frontmatter.keywords?.length?(0,S.jsx)(`div`,{className:`mt-6 flex flex-wrap gap-2`,children:e.frontmatter.keywords.map(e=>(0,S.jsx)(`span`,{className:`rounded-full border border-border-light bg-muted px-3 py-1 text-xs font-medium text-muted-foreground`,children:e},e))}):null]}),(0,S.jsx)(`div`,{className:`chapter-content max-w-none`,children:(0,S.jsx)(f.Suspense,{fallback:(0,S.jsx)(`div`,{className:`py-8 text-sm text-muted-foreground`,children:`Loading content…`}),children:c.map((e,t)=>e.kind===`parade-preview`?(0,S.jsx)(I,{},`pp-${t}`):(0,S.jsx)(R,{children:e.content},`md-${t}`))})})]}),m?(0,S.jsx)(`aside`,{className:`sticky top-4 hidden h-[calc(100vh-2rem)] w-56 shrink-0 self-start overflow-y-auto lg:block`,children:(0,S.jsxs)(`nav`,{"aria-label":`章节目录`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground`,children:`本章目录`}),(0,S.jsx)(`ul`,{className:`space-y-1 border-l border-border-light`,children:l.map(e=>{let t=o===e.slug;return(0,S.jsx)(`li`,{className:e.level===3?`ml-3`:``,children:(0,S.jsx)(`button`,{type:`button`,onClick:()=>p(e.slug),className:`block w-full border-l-2 py-1 pl-3 text-left text-xs leading-relaxed transition-colors `+(t?`border-primary text-primary`:`border-transparent text-muted-foreground hover:text-foreground`),style:{marginLeft:`-1px`},children:e.text})},e.slug)})})]})}):null]})})}var G=null;async function K(){if(G)return G;let e=await fetch(`./guide-data.json`);if(!e.ok)throw Error(`Failed to load guide-data.json: ${e.status}`);return G=await e.json(),G}function q(){let e=window.location.hash.replace(/^#\/?/,``);return e?e===`commands`?{kind:`commands`}:{kind:`chapter`,path:e}:{kind:`home`}}function J(e){return e.kind===`home`?`#/`:e.kind===`commands`?`#/commands`:`#/${e.path}`}function Y(){let[e,t]=(0,f.useState)(null),[n,r]=(0,f.useState)(null),[i,a]=(0,f.useState)(()=>q());if((0,f.useEffect)(()=>{K().then(t).catch(e=>r(e.message??String(e)))},[]),(0,f.useEffect)(()=>{let e=()=>a(q());return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]),n)return(0,S.jsx)(`div`,{className:`flex h-screen items-center justify-center`,children:(0,S.jsxs)(`div`,{className:`max-w-md rounded-xl border border-destructive bg-card p-8 text-center`,children:[(0,S.jsx)(`h1`,{className:`font-display text-xl font-bold text-destructive`,children:`加载失败`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:n}),(0,S.jsxs)(`p`,{className:`mt-2 text-xs text-muted-foreground`,children:[`请确认 guide-data.json 已生成(运行 `,(0,S.jsx)(`code`,{children:`npm run build:guide`}),`)。`]})]})});if(!e)return(0,S.jsx)(`div`,{className:`flex h-screen items-center justify-center text-muted-foreground`,children:`Loading guide…`});let o=e=>{let t=e===`__commands__`?{kind:`commands`}:{kind:`chapter`,path:e},n=J(t);window.location.hash!==n&&window.history.pushState(null,``,n),a(t)};return(0,S.jsxs)(`div`,{className:`flex h-screen w-screen overflow-hidden bg-background text-foreground`,children:[(0,S.jsx)(C,{navigation:e.navigation,selected:i.kind===`chapter`?i.path:i.kind===`commands`?`__commands__`:null,onSelect:o,onHome:()=>{let e=J({kind:`home`});window.location.hash!==e&&window.history.pushState(null,``,e),a({kind:`home`})}}),(0,S.jsxs)(`main`,{className:`flex flex-1 flex-col overflow-hidden`,children:[(0,S.jsx)(`header`,{className:`flex h-16 items-center justify-end border-b border-border bg-background/80 px-8 backdrop-blur-sm`,children:(0,S.jsx)(M,{})}),(0,S.jsx)(`div`,{className:`flex-1 overflow-y-auto`,children:i.kind===`home`?(0,S.jsx)(X,{data:e,onSelect:o}):i.kind===`commands`?(0,S.jsx)(Z,{data:e}):(0,S.jsx)(Q,{data:e,path:i.path,onSelect:o})})]})]})}function X({data:e,onSelect:t}){return(0,S.jsxs)(`div`,{className:`mx-auto max-w-5xl px-10 py-16 sm:px-16 sm:py-20`,children:[(0,S.jsxs)(`header`,{className:`mb-16`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-primary`,children:`Saluzi Guide`}),(0,S.jsx)(`h1`,{className:`font-display text-5xl font-bold leading-tight tracking-tight text-foreground`,children:`使用指南`}),(0,S.jsx)(`p`,{className:`mt-5 max-w-2xl font-serif text-lg leading-relaxed text-muted-foreground`,children:`Terminal-native agentic coding system · 终端原生的 AI 编程系统。 从新手入门到 Saluzi 特色,按你的节奏探索。`})]}),(0,S.jsxs)(`section`,{className:`mb-20`,children:[(0,S.jsxs)(`div`,{className:`mb-8 flex items-baseline justify-between border-b border-border pb-3`,children:[(0,S.jsx)(`h2`,{className:`font-display text-2xl font-semibold text-foreground`,children:`新手 Top 8 工作流`}),(0,S.jsx)(`span`,{className:`text-xs uppercase tracking-wider text-muted-foreground`,children:`按推荐顺序`})]}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-5 md:grid-cols-2`,children:N.map(e=>(0,S.jsx)(P,{workflow:e,onSelect:t},e.id))})]}),(0,S.jsxs)(`section`,{children:[(0,S.jsxs)(`div`,{className:`mb-8 flex items-baseline justify-between border-b border-border pb-3`,children:[(0,S.jsx)(`h2`,{className:`font-display text-2xl font-semibold text-foreground`,children:`Saluzi 特色`}),(0,S.jsx)(`span`,{className:`text-xs uppercase tracking-wider text-muted-foreground`,children:`saluzi 独有`})]}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.navigation.find(e=>e.group===`Saluzi 特色`)?.pages.flatMap(e=>e.pages?e.pages:[e]).filter(e=>e.path).map(e=>(0,S.jsxs)(`button`,{type:`button`,onClick:()=>e.path&&t(e.path),className:`group flex items-center justify-between rounded-xl border border-border bg-card p-4 text-left transition-shadow hover:shadow-md`,children:[(0,S.jsx)(`span`,{className:`font-display text-base font-medium text-foreground`,children:e.title??e.path}),(0,S.jsx)(h,{className:`h-4 w-4 text-muted-foreground transition-transform group-hover:translate-x-1`})]},e.path))??null})]})]})}function Z({data:e}){return(0,S.jsxs)(`div`,{className:`mx-auto max-w-4xl px-10 py-16 sm:px-14 sm:py-20`,children:[(0,S.jsxs)(`header`,{className:`mb-14 border-b border-border pb-8`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-primary`,children:`Command Dictionary`}),(0,S.jsx)(`h1`,{className:`font-display text-4xl font-bold tracking-tight text-foreground`,children:`命令字典`}),(0,S.jsxs)(`p`,{className:`mt-4 font-serif text-base leading-relaxed text-muted-foreground`,children:[`按分类列出所有可用命令(共 `,Object.keys(e.commands).length,` 条)。每个卡片包含命令名称与描述,部分含别名。`]})]}),e.categories.map(e=>(0,S.jsxs)(`section`,{className:`mb-14`,children:[(0,S.jsx)(`h2`,{className:`mb-6 font-display text-xl font-semibold text-primary`,children:e.titleZh??e.title}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.commands.map(e=>(0,S.jsx)(F,{command:e},e.name))})]},e.id))]})}function Q({data:e,path:t,onSelect:n}){let r=e.chapters[t];return r?(0,S.jsx)(W,{chapter:r,path:t,onNavigate:n}):(0,S.jsxs)(`div`,{className:`mx-auto max-w-2xl px-10 py-16`,children:[(0,S.jsx)(`h1`,{className:`font-display text-3xl font-bold text-foreground`,children:`未找到章节`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:`该章节可能已移除或重命名。`})]})}var $=document.getElementById(`root`);if(!$)throw Error(`root element not found`);(0,b.createRoot)($).render((0,S.jsx)(f.StrictMode,{children:(0,S.jsx)(Y,{})}));
|
|
167
|
+
`),n=[],r=!1,i=``;for(let e of t){let t=e.trim(),a=/^(`{3}|~{3})/.exec(t);if(a){r?t.startsWith(i.repeat(3))&&(r=!1,i=``):(r=!0,i=a[1][0]);continue}if(r)continue;let o=/^(#{2,3})\s+(.+?)\s*$/.exec(t);if(!o)continue;let s=o[1].length,c=o[2],l=V(c);l&&n.push({level:s,text:c,slug:l})}let a=new Map;return n.map(e=>{let t=a.get(e.slug)??0;return a.set(e.slug,t+1),t===0?e:{...e,slug:`${e.slug}-${t}`}})}function U(e){let t=[],n=e.split(B);for(let e=0;e<n.length;e++)n[e]&&t.push({kind:`md`,content:z(n[e])}),e<n.length-1&&t.push({kind:`parade-preview`});return t}function W({chapter:e,path:t,onNavigate:n}){let r=e.frontmatter.title??t,i=(0,f.useRef)(null),a=(0,f.useRef)(null),[o,s]=(0,f.useState)(null),c=(0,f.useMemo)(()=>U(e.content.replace(/^\{\/\*[\s\S]*?\*\/\}\s*\n/gm,``).replace(/^\{\/\*[\s\S]*?\*\/\}/gm,``)),[e.content]),l=(0,f.useMemo)(()=>H(e.content),[e.content]);(0,f.useEffect)(()=>{if(!i.current||l.length===0)return;let e=i.current,t=()=>{e.querySelectorAll(`h2, h3`).forEach((e,t)=>{let n=l[t];n&&(e.id!==n.slug&&(e.id=n.slug),e.style.scrollMarginTop!==`5rem`&&(e.style.scrollMarginTop=`5rem`))})};t();let n=new MutationObserver(()=>t());return n.observe(e,{childList:!0,subtree:!0}),()=>n.disconnect()},[l,c]),(0,f.useEffect)(()=>{if(!i.current)return;let e=i.current.parentElement;for(;e&&getComputedStyle(e).overflowY!==`auto`;)e=e.parentElement;a.current=e},[]),(0,f.useEffect)(()=>{let e=a.current;if(!e||l.length===0)return;let t=()=>{let t=e.scrollTop,n=null;for(let e of l){let r=document.getElementById(e.slug);if(r)if(r.offsetTop-120<=t)n=e;else break}s(n?.slug??null)};return t(),e.addEventListener(`scroll`,t,{passive:!0}),()=>e.removeEventListener(`scroll`,t)},[l]);function u(e){if(!n)return null;if(e.startsWith(`docs/`))return e;let r=e.replace(/^(?:\.\.\/|\.\/|\/)+/,``);return r=r.replace(/\.(md|mdx)$/,``),r?`${t.split(`/`).slice(0,-1).join(`/`)}/${r}`:null}function d(e){if(!n)return;let t=e.target.closest(`a`);if(!t)return;let r=t.getAttribute(`href`);if(!r||/^(https?:|mailto:|#)/.test(r))return;let i=u(r);i&&(e.preventDefault(),n(i))}function p(e){let t=document.getElementById(e);if(t){t.scrollIntoView({behavior:`smooth`,block:`start`}),s(e);return}let n=0,r=window.setInterval(()=>{n+=1;let t=document.getElementById(e);t?(window.clearInterval(r),t.scrollIntoView({behavior:`smooth`,block:`start`}),s(e)):n>=20&&window.clearInterval(r)},50)}let m=l.length>=2;return(0,S.jsx)(`div`,{className:`mx-auto max-w-5xl px-6 py-12 sm:px-10 sm:py-16`,children:(0,S.jsxs)(`div`,{className:`flex gap-10`,children:[(0,S.jsxs)(`article`,{ref:i,className:`min-w-0 max-w-2xl flex-1 px-2 sm:px-4`,onClick:d,children:[(0,S.jsxs)(`header`,{className:`mb-12 border-b border-border pb-8`,children:[(0,S.jsx)(`h1`,{className:`font-display text-4xl font-bold leading-tight tracking-tight text-foreground`,children:r}),e.frontmatter.description?(0,S.jsx)(`p`,{className:`mt-4 font-serif text-lg leading-relaxed text-muted-foreground`,children:e.frontmatter.description}):null,e.frontmatter.keywords?.length?(0,S.jsx)(`div`,{className:`mt-6 flex flex-wrap gap-2`,children:e.frontmatter.keywords.map(e=>(0,S.jsx)(`span`,{className:`rounded-full border border-border-light bg-muted px-3 py-1 text-xs font-medium text-muted-foreground`,children:e},e))}):null]}),(0,S.jsx)(`div`,{className:`chapter-content max-w-none`,children:(0,S.jsx)(f.Suspense,{fallback:(0,S.jsx)(`div`,{className:`py-8 text-sm text-muted-foreground`,children:`Loading content…`}),children:c.map((e,t)=>e.kind===`parade-preview`?(0,S.jsx)(I,{},`pp-${t}`):(0,S.jsx)(R,{children:e.content},`md-${t}`))})})]}),m?(0,S.jsx)(`aside`,{className:`sticky top-4 hidden h-[calc(100vh-2rem)] w-56 shrink-0 self-start overflow-y-auto lg:block`,children:(0,S.jsxs)(`nav`,{"aria-label":`章节目录`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-wider text-muted-foreground`,children:`本章目录`}),(0,S.jsx)(`ul`,{className:`space-y-1 border-l border-border-light`,children:l.map(e=>{let t=o===e.slug;return(0,S.jsx)(`li`,{className:e.level===3?`ml-3`:``,children:(0,S.jsx)(`button`,{type:`button`,onClick:()=>p(e.slug),className:`block w-full border-l-2 py-1 pl-3 text-left text-xs leading-relaxed transition-colors `+(t?`border-primary text-primary`:`border-transparent text-muted-foreground hover:text-foreground`),style:{marginLeft:`-1px`},children:e.text})},e.slug)})})]})}):null]})})}var G=null;async function K(){if(G)return G;let e=await fetch(`./guide-data.json`);if(!e.ok)throw Error(`Failed to load guide-data.json: ${e.status}`);return G=await e.json(),G}function q(){let e=window.location.hash.replace(/^#\/?/,``);return e?e===`commands`?{kind:`commands`}:{kind:`chapter`,path:e}:{kind:`home`}}function J(e){return e.kind===`home`?`#/`:e.kind===`commands`?`#/commands`:`#/${e.path}`}function Y(){let[e,t]=(0,f.useState)(null),[n,r]=(0,f.useState)(null),[i,a]=(0,f.useState)(()=>q()),o=(0,f.useRef)(null);if((0,f.useEffect)(()=>{K().then(t).catch(e=>r(e.message??String(e)))},[]),(0,f.useEffect)(()=>{let e=()=>a(q());return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]),(0,f.useEffect)(()=>{o.current?.scrollTo(0,0)},[i]),n)return(0,S.jsx)(`div`,{className:`flex h-screen items-center justify-center`,children:(0,S.jsxs)(`div`,{className:`max-w-md rounded-xl border border-destructive bg-card p-8 text-center`,children:[(0,S.jsx)(`h1`,{className:`font-display text-xl font-bold text-destructive`,children:`加载失败`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:n}),(0,S.jsxs)(`p`,{className:`mt-2 text-xs text-muted-foreground`,children:[`请确认 guide-data.json 已生成(运行 `,(0,S.jsx)(`code`,{children:`npm run build:guide`}),`)。`]})]})});if(!e)return(0,S.jsx)(`div`,{className:`flex h-screen items-center justify-center text-muted-foreground`,children:`Loading guide…`});let s=e=>{let t=e===`__commands__`?{kind:`commands`}:{kind:`chapter`,path:e},n=J(t);window.location.hash!==n&&window.history.pushState(null,``,n),a(t)};return(0,S.jsxs)(`div`,{className:`flex h-screen w-screen overflow-hidden bg-background text-foreground`,children:[(0,S.jsx)(C,{navigation:e.navigation,selected:i.kind===`chapter`?i.path:i.kind===`commands`?`__commands__`:null,onSelect:s,onHome:()=>{let e=J({kind:`home`});window.location.hash!==e&&window.history.pushState(null,``,e),a({kind:`home`})}}),(0,S.jsxs)(`main`,{className:`flex flex-1 flex-col overflow-hidden`,children:[(0,S.jsx)(`header`,{className:`flex h-16 items-center justify-end border-b border-border bg-background/80 px-8 backdrop-blur-sm`,children:(0,S.jsx)(M,{})}),(0,S.jsx)(`div`,{ref:o,className:`flex-1 overflow-y-auto`,children:i.kind===`home`?(0,S.jsx)(X,{data:e,onSelect:s}):i.kind===`commands`?(0,S.jsx)(Z,{data:e}):(0,S.jsx)(Q,{data:e,path:i.path,onSelect:s})})]})]})}function X({data:e,onSelect:t}){return(0,S.jsxs)(`div`,{className:`mx-auto max-w-5xl px-10 py-16 sm:px-16 sm:py-20`,children:[(0,S.jsxs)(`header`,{className:`mb-16`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-primary`,children:`Saluzi Guide`}),(0,S.jsx)(`h1`,{className:`font-display text-5xl font-bold leading-tight tracking-tight text-foreground`,children:`使用指南`}),(0,S.jsx)(`p`,{className:`mt-5 max-w-2xl font-serif text-lg leading-relaxed text-muted-foreground`,children:`Terminal-native agentic coding system · 终端原生的 AI 编程系统。 从新手入门到 Saluzi 特色,按你的节奏探索。`})]}),(0,S.jsxs)(`section`,{className:`mb-20`,children:[(0,S.jsxs)(`div`,{className:`mb-8 flex items-baseline justify-between border-b border-border pb-3`,children:[(0,S.jsx)(`h2`,{className:`font-display text-2xl font-semibold text-foreground`,children:`新手 Top 8 工作流`}),(0,S.jsx)(`span`,{className:`text-xs uppercase tracking-wider text-muted-foreground`,children:`按推荐顺序`})]}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-5 md:grid-cols-2`,children:N.map(e=>(0,S.jsx)(P,{workflow:e,onSelect:t},e.id))})]}),(0,S.jsxs)(`section`,{children:[(0,S.jsxs)(`div`,{className:`mb-8 flex items-baseline justify-between border-b border-border pb-3`,children:[(0,S.jsx)(`h2`,{className:`font-display text-2xl font-semibold text-foreground`,children:`Saluzi 特色`}),(0,S.jsx)(`span`,{className:`text-xs uppercase tracking-wider text-muted-foreground`,children:`saluzi 独有`})]}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.navigation.find(e=>e.group===`Saluzi 特色`)?.pages.flatMap(e=>e.pages?e.pages:[e]).filter(e=>e.path).map(e=>(0,S.jsxs)(`button`,{type:`button`,onClick:()=>e.path&&t(e.path),className:`group flex items-center justify-between rounded-xl border border-border bg-card p-4 text-left transition-shadow hover:shadow-md`,children:[(0,S.jsx)(`span`,{className:`font-display text-base font-medium text-foreground`,children:e.title??e.path}),(0,S.jsx)(h,{className:`h-4 w-4 text-muted-foreground transition-transform group-hover:translate-x-1`})]},e.path))??null})]})]})}function Z({data:e}){return(0,S.jsxs)(`div`,{className:`mx-auto max-w-4xl px-10 py-16 sm:px-14 sm:py-20`,children:[(0,S.jsxs)(`header`,{className:`mb-14 border-b border-border pb-8`,children:[(0,S.jsx)(`p`,{className:`mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-primary`,children:`Command Dictionary`}),(0,S.jsx)(`h1`,{className:`font-display text-4xl font-bold tracking-tight text-foreground`,children:`命令字典`}),(0,S.jsxs)(`p`,{className:`mt-4 font-serif text-base leading-relaxed text-muted-foreground`,children:[`按分类列出所有可用命令(共 `,Object.keys(e.commands).length,` 条)。每个卡片包含命令名称与描述,部分含别名。`]})]}),e.categories.map(e=>(0,S.jsxs)(`section`,{className:`mb-14`,children:[(0,S.jsx)(`h2`,{className:`mb-6 font-display text-xl font-semibold text-primary`,children:e.titleZh??e.title}),(0,S.jsx)(`div`,{className:`grid grid-cols-1 gap-3 md:grid-cols-2`,children:e.commands.map(e=>(0,S.jsx)(F,{command:e},e.name))})]},e.id))]})}function Q({data:e,path:t,onSelect:n}){let r=e.chapters[t];return r?(0,S.jsx)(W,{chapter:r,path:t,onNavigate:n}):(0,S.jsxs)(`div`,{className:`mx-auto max-w-2xl px-10 py-16`,children:[(0,S.jsx)(`h1`,{className:`font-display text-3xl font-bold text-foreground`,children:`未找到章节`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:`该章节可能已移除或重命名。`})]})}var $=document.getElementById(`root`);if(!$)throw Error(`root element not found`);(0,b.createRoot)($).render((0,S.jsx)(f.StrictMode,{children:(0,S.jsx)(Y,{})}));
|
|
@@ -3075,7 +3075,7 @@
|
|
|
3075
3075
|
"成本优化"
|
|
3076
3076
|
]
|
|
3077
3077
|
},
|
|
3078
|
-
"content": "\n## 为什么需要 MOM\n\n单模型对话有几类常见痛点,MOM 正是为解决它们而生:\n\n| 痛点 | 单模型表现 | MOM 解决方式 |\n|------|-----------|-------------|\n| 重要决策缺第二意见 | 一个模型说了算,错了也只能事后发现 | 多顾问并行给方案,主机综合后行动 |\n| 简单任务烧钱 | 用 Max 处理「重命名变量」大材小用 | 弱模型先试,简单任务不消耗强模型 token |\n| 复杂任务欠深度 | Std/Pro 推理深度不够,硬上又怕漏 | 强模型带完整工具循环兜底 |\n| 单一模型有盲区 | 不同模型擅长不同领域,只能赌一个 | 多 provider 顾问互补(如 Claude + Gemini + Grok) |\n| 关键改动无人审查 | 自己写自己改,bug 容易溜过去 | 顾问作为「审查者」给出反对意见 |\n\n一句话:**MOM 不是为了「更强」,而是为了「更稳 + 更省」**。它让简单任务便宜跑、关键决策有交叉验证、不同 provider 的模型互补盲区。\n\n## MOM 的两种内置模式\n\nMOM 是一个统称,下面注册了多个具名模式。每个模式 ID 同时也是虚拟模型名(可以直接 `/model mom-avg` 切换)和一次性命令名(`/mom-avg \"...\"`)。\n\n### mom-avg:并行顾问 + 主机综合\n\n工作流:\n\n```\n用户输入\n │\n ├──► 顾问 1(只读,text-only)──┐\n ├──► 顾问 2(只读,text-only)──┤\n ├──► 顾问 N(只读,text-only)──┤\n │ │\n ▼ ▼\n 主机模型 ◄──综合所有顾问建议──┘\n │\n ▼\n最终输出(带工具调用、文件编辑等完整能力)\n```\n\n关键点:\n\n- **顾问只读**:顾问不携带工具,只看对话历史给出建议文本,不能改文件、不能跑命令。这意味着顾问调用很快、很便宜(一次 text completion)。\n- **主机有完整能力**:主机收到所有顾问的建议后,作为「主持人」综合并执行——它可以读文件、改代码、跑测试,和普通对话完全一样。\n- **fanout 控制频率**:顾问不需要每轮都跑。默认 `user_turn`(每个用户消息跑一次,后续工具迭代复用同一份建议),也可设 `per_iteration`(每轮都跑,成本高)或 `every_n:N`(每 N 轮跑一次)。\n\n适合:**关键决策**——架构设计、安全审查、复杂 bug 方案选型。需要多角度意见时。\n\n### mom-stair:阶梯式弱→强升级\n\n工作流:\n\n```\n用户输入\n │\n ▼\n弱模型(带只读工具:Read/Grep/Glob)\n │
|
|
3078
|
+
"content": "\n## 为什么需要 MOM\n\n单模型对话有几类常见痛点,MOM 正是为解决它们而生:\n\n| 痛点 | 单模型表现 | MOM 解决方式 |\n|------|-----------|-------------|\n| 重要决策缺第二意见 | 一个模型说了算,错了也只能事后发现 | 多顾问并行给方案,主机综合后行动 |\n| 简单任务烧钱 | 用 Max 处理「重命名变量」大材小用 | 弱模型先试,简单任务不消耗强模型 token |\n| 复杂任务欠深度 | Std/Pro 推理深度不够,硬上又怕漏 | 强模型带完整工具循环兜底 |\n| 单一模型有盲区 | 不同模型擅长不同领域,只能赌一个 | 多 provider 顾问互补(如 Claude + Gemini + Grok) |\n| 关键改动无人审查 | 自己写自己改,bug 容易溜过去 | 顾问作为「审查者」给出反对意见 |\n\n一句话:**MOM 不是为了「更强」,而是为了「更稳 + 更省」**。它让简单任务便宜跑、关键决策有交叉验证、不同 provider 的模型互补盲区。\n\n## MOM 的两种内置模式\n\nMOM 是一个统称,下面注册了多个具名模式。每个模式 ID 同时也是虚拟模型名(可以直接 `/model mom-avg` 切换)和一次性命令名(`/mom-avg \"...\"`)。\n\n### mom-avg:并行顾问 + 主机综合\n\n工作流:\n\n```\n用户输入\n │\n ├──► 顾问 1(只读,text-only)──┐\n ├──► 顾问 2(只读,text-only)──┤\n ├──► 顾问 N(只读,text-only)──┤\n │ │\n ▼ ▼\n 主机模型 ◄──综合所有顾问建议──┘\n │\n ▼\n最终输出(带工具调用、文件编辑等完整能力)\n```\n\n关键点:\n\n- **顾问只读**:顾问不携带工具,只看对话历史给出建议文本,不能改文件、不能跑命令。这意味着顾问调用很快、很便宜(一次 text completion)。\n- **主机有完整能力**:主机收到所有顾问的建议后,作为「主持人」综合并执行——它可以读文件、改代码、跑测试,和普通对话完全一样。\n- **fanout 控制频率**:顾问不需要每轮都跑。默认 `user_turn`(每个用户消息跑一次,后续工具迭代复用同一份建议),也可设 `per_iteration`(每轮都跑,成本高)或 `every_n:N`(每 N 轮跑一次)。\n\n适合:**关键决策**——架构设计、安全审查、复杂 bug 方案选型。需要多角度意见时。\n\n### mom-stair:阶梯式弱→强升级\n\n工作流:\n\n```\n用户输入\n │\n ▼\n弱模型(带只读工具:Read/Grep/Glob)\n │ 可选末尾输出 CONFIDENCE: 0-1\n │\n ├── 答案充实且接地 ──► 直接交付答案,跳过强模型\n │ (置信度 ≥ 阈值时可额外确认,非必须)\n │\n └── 答案过短 / 用了工具但无接地发现\n │ 或显式低置信度\n ──► 升级到下一阶段\n │\n ▼\n 强模型(完整工具循环)\n 接收弱模型的草稿 + 发现作为引导\n 但**不接收**置信度/推理(自评不可靠)\n │\n ▼\n 最终输出\n```\n\n关键点:\n\n- **弱模型先试**:用 Std 或轻量模型尝试回答,可用只读工具(读文件、搜索代码)做基础调研。\n- **简化协议**:弱模型可在答案末尾输出一行 `CONFIDENCE: 0.7`(0-1 数字,也支持 `high`/`medium`/`low` 等词),无需 JSON/XML 嵌套格式——格式遵从率大幅提升。\n- **置信度是软信号**:模型未输出置信度时**不视为失败**——升级决策基于客观信号(答案厚度、工具接地)。解析失败也不再标记为 failed,弱模型产出始终保留。\n- **多因素门控**:升级决策综合考量:置信度(如有)、答案是否过短、以及(当使用了工具时)是否有接地发现(file:line 引用)。这弥补了低等模型自评分方差的不足。\n- **自评不传递**:置信度/推理仅在内部用于门控,**不传递给强模型**。强模型只接收草稿答案 + 接地发现,避免被不可靠的自评分误导。\n- **不丢弃弱模型产出**:弱模型的原始文本始终作为草稿传递给强模型,避免重复劳动。\n\n适合:**日常开发**——大部分任务用弱模型就能搞定,遇到真复杂的才升级到强模型。成本优化首选。\n\n## 三种使用方式\n\n### 1. 一次性 MOM 回合\n\n```bash\n# 用默认 MOM 模式跑一次,结束后自动恢复原模型\n> /mom 帮我设计一个端口冲突处理策略\n\n# 指定具体模式\n> /mom-avg 这段并发代码有什么竞态风险?\n> /mom-stair 重构这个 800 行的函数\n```\n\n特点:**不修改全局配置**,仅本次消息走 MOM 流程,下一条消息自动回到之前的模型。适合偶尔在关键节点用一下。\n\n### 2. 切换会话到 MOM 模式\n\n```bash\n> /model mom-avg\n```\n\n把当前会话的模型切到 `mom-avg`,后续所有消息都走 MOM 流程,直到再次 `/model` 切回。和切普通模型完全一样——MOM 模式 ID 在 `/model` 选择器里就能看到。\n\n### 3. 设为默认模式\n\n在 `/mom` 配置卡里把某个模式(如 `mom-stair`)设为 default,所有新会话默认走该模式。适合希望日常开发都享受成本优化的用户。\n\n## 配置 MOM\n\n```bash\n> /mom\n```\n\n打开 MOM 配置卡。这是一个多页 Ink 卡片:\n\n- **首页**:总开关、隐私过滤模式、模式列表(mom-avg / mom-stair)、模型池、默认模式\n- **每个模式一页**:顾问槽位、主机槽位、参数(fanout、超时、温度等)\n\n操作键:`Tab` 切页、`j/k` 上下导航、`←/→` 切区域、`Enter` 确认、`s` 保存、`Esc` 关闭。每个模式下都有底部快捷键提示,只显示当前可用的操作。\n\n### 模型池(modelPool)\n\n模型池是 MOM 可用的所有模型清单。每个条目有三种来源:\n\n| 类型 | 说明 | 适合场景 |\n|------|------|---------|\n| `preset` | 预设别名:`max`、`pro`、`std`、`subagent` | 最简,开箱即用 |\n| `key` | 引用 `/keys` 里绑定的 API Key(可指定该 Key 下的具体 modelName) | 多 provider 混搭,如一个 Claude Key + 一个 Gemini Key |\n| `custom` | 自定义 provider + baseUrl + apiKey + model | 接入自部署模型、第三方兼容端点 |\n\n顾问和主机都从池里引用。配一个 `preset:std` 和一个 `key:my-gemini-key` 进池,就能让 mom-avg 的两个顾问分别是 Saluzi Std 和 Gemini。\n\n### 关键参数\n\n| 参数 | 作用 | 推荐值 |\n|------|------|--------|\n| `fanout` | 顾问调用频率:`user_turn` / `per_iteration` / `every_n:N` | `user_turn`(默认,省钱);只有真正需要每轮都参考意见时才用 `per_iteration` |\n| `privacyFilter` | 顾问输出脱敏:`off` / `display`(仅显示脱敏)/ `full`(连主机也看不到原话) | `off`(默认);处理敏感代码时用 `display` 或 `full` |\n| `degradedReferencePolicy` | 顾问失败时:`loud`(报错)/ `silent`(静默忽略) | `loud`(默认,能发现问题);成本敏感且可容忍漏掉顾问时用 `silent` |\n| `referenceMaxTokens` | 单个顾问最大输出 token | 2000~4000,避免顾问长篇大论 |\n| `referenceTimeout` | 顾问调用超时(秒) | 30~60,慢 provider 别拖死整个回合 |\n| `temperature` | 顾问采样温度 | 0.3~0.5(建议更有条理);想多角度发散可调高 |\n| `hostTemperature` | 主机采样温度 | 默认即可,主机需要稳定执行 |\n| `confidenceThreshold` | 仅 mom-stair:弱模型自评分低于此值则升级 | 0.7(默认);任务对准确度要求高可调到 0.8,省钱可调到 0.5 |\n\n## 推荐配置场景\n\n### 场景 1:日常开发(成本优先)\n\n```yaml\n默认模式: mom-stair\n弱模型: preset:std\n强模型: preset:pro\n置信度阈值: 0.6 # 稍低,更多任务用弱模型搞定\n```\n\n效果:80% 的简单任务由 Std 处理(便宜),剩下 20% 升级到 Pro。整体成本比纯 Pro 低 40~60%。\n\n### 场景 2:架构设计(质量优先)\n\n```yaml\n一次性调用: /mom-avg 帮我设计这个微服务拆分方案\n主机: preset:pro\n顾问 1: preset:max # 深度推理\n顾问 2: key:my-gemini-key # 不同视角\nfanout: user_turn\nreferenceMaxTokens: 4000\n```\n\n效果:Max 给出深思熟虑的方案,Gemini 提供不同训练集带来的视角差异,Pro 综合后执行。一次性使用,不污染日常对话。\n\n### 场景 3:安全审查(严格交叉验证)\n\n```yaml\n一次性调用: /mom-avg 审查这段处理用户输入的代码\n主机: preset:max\n顾问 1: preset:pro\n顾问 2: preset:pro # 两个 Pro 独立审查\nprivacyFilter: display # 显示时脱敏,避免敏感数据被多个 provider 看到\ndegradedReferencePolicy: loud # 任何一个顾问失败都要提示\n```\n\n效果:多个模型独立审查同一份代码,主机汇总所有发现。任何模型漏掉的漏洞都有可能被另一个发现。\n\n### 场景 4:复杂 bug(深度+广度)\n\n```yaml\n会话切换: /model mom-stair\n弱模型: preset:std # 先快速定位\n强模型: preset:max # 升级时用 Max 深度推理\n置信度阈值: 0.8 # 严格,避免弱模型误判\n```\n\n效果:Std 先用只读工具快速探索代码、给出初步判断。如果是简单 bug(如拼写错误),Std 直接修复;如果是涉及多模块的复杂 bug,升级到 Max 带完整工具循环深挖。\n\n## 成本控制要点\n\nMOM 用得不好可能比单模型还贵。几个原则:\n\n- **简单任务不要用 mom-avg**:mom-avg 至少调用 N+1 次模型(N 个顾问 + 1 个主机)。改个变量名用 mom-avg 是浪费。\n- **日常用 mom-stair 而非 mom-avg**:stair 只在弱模型搞不定时才升级,平均成本远低于 avg 的「每次都全员上场」。\n- **设 referenceMaxTokens**:顾问容易啰嗦,限制输出长度能直接省钱。\n- **fanout 用 user_turn**:除非真的需要每轮都参考意见,否则别用 `per_iteration`。\n- **关键决策用一次性 `/mom-avg`**:而不是把整个会话切到 mom-avg 模式。\n- **用 `/cost` 监控**:MOM 开启后会看到顾问调用的 token 消耗,发现异常及时调整。\n- **`/poor` 节约模式不影响 MOM**:`/poor` 只关记忆提取和提示建议,MOM 仍按配置运行。要省 MOM 的钱得调 `referenceMaxTokens` 和 `fanout`。\n\n## 与普通对话的对比\n\n| 维度 | 普通对话 | mom-stair | mom-avg |\n|------|---------|-----------|---------|\n| 模型调用次数 | 1 次 / 轮 | 1 次(简单)或 2+ 次(复杂) | N+1 次 / 用户回合 |\n| 简单任务成本 | 基准 | 低 30~50% | 高 2~5 倍 |\n| 复杂任务成本 | 基准 | 接近基准 | 高 2~5 倍 |\n| 决策质量 | 单模型 | 弱模型搞定时一般;升级后接近强模型 | 多角度交叉验证 |\n| 响应速度 | 最快 | 简单任务快;复杂任务稍慢 | 最慢(要等所有顾问) |\n| 适合场景 | 日常常规 | 日常开发 + 偶尔复杂 | 关键决策、安全审查 |\n\n## 常见误区\n\n**误区 1:MOM 一定比单模型好**\n不是。MOM 的并行调用本身有成本,简单任务用单模型更快更便宜。MOM 的价值在「关键决策有第二意见」和「简单任务不烧强模型」。\n\n**误区 2:顾问越多越好**\n顾问越多 token 越贵,且主机综合成本也上升。2~3 个互补顾问(如不同 provider、不同规模)通常比 5 个同质顾问效果好。\n\n**误区 3:把整个会话切到 mom-avg 就高枕无忧**\n会让每条消息都跑多顾问,成本爆炸。mom-avg 更适合用 `/mom-avg \"...\"` 一次性调用。\n\n**误区 4:mom-stair 的弱模型能解决一切**\n弱模型只有只读工具,不能改文件。它判定「我能搞定」时只是给出答案文本,真正的执行还得主机接力。所以 stair 的省钱逻辑是「简单咨询类问题」,不是「简单执行类问题」。\n\n**误区 5:自定义 provider 任何模型都能接**\ncustom entry 需要映射到 openai/anthropic/gemini/grok 之一的 SDK。Bedrock/Vertex 等需要专属 SDK 的 provider 暂时不能作为 MOM 主机(可作为顾问,但仍受相同限制)。\n\n## 下一步\n\n- [模型选择与切换](./model-selection) — `/model`、`/effort` 与 MOM 的关系\n- [查看消耗](./cost-usage) — `/cost` 监控 MOM 的顾问开销\n- [API Key 绑定](./keys-binding) — `/keys` 多 Key 调度,给 MOM 配多 provider 顾问\n- [对话基础](./conversation-basics) — 多轮对话与流式输出\n"
|
|
3079
3079
|
},
|
|
3080
3080
|
"docs/guide/saluzi-home": {
|
|
3081
3081
|
"frontmatter": {
|
|
@@ -3123,7 +3123,7 @@
|
|
|
3123
3123
|
"省 token"
|
|
3124
3124
|
]
|
|
3125
3125
|
},
|
|
3126
|
-
"content": "\n## 为什么需要 Token 节约模式\n\nSaluzi 默认开启大量「让 AI 更聪明」的后台机制:自动记忆提取、提示建议、会话记忆整合、验证 Agent、相关记忆预取、Agent 摘要……这些机制各自只消耗少量 token,但叠在一起会让每次对话的「隐性开销」相当可观。\n\n当你处于以下场景时,这些开销就是纯浪费:\n\n- **API Key 按量计费**,想压到最低\n- **弱模型 / 小上下文窗口**,每一段 prompt 都很贵\n- **一次性脚本任务**,不需要长期记忆\n- **清晰的单文件修改**,不需要多角度验证\n\n两种节约模式就是为这些场景设计的开关,按「砍多少」分档:\n\n| 模式 | 砍掉的范围 | 工具集 | System Prompt | 适合 |\n|------|-----------|--------|--------------|------|\n| **Poor** | 5 项后台副作用 | 全部保留 | 完整 | 日常开发省 token |\n| **SA** | 全部后台 + 工具收敛 | 仅 4 核心 | ~20 行极简 | 极限省 token / 弱模型 |\n\nSA 是 Poor 的**严格超集**——Poor 关掉的一切,SA 也关掉;SA 还额外砍掉工具和 prompt。两者的关系类似「省电模式」与「飞行模式」。\n\n## Poor 节约模式\n\n### 是什么\n\n`/poor` 切换 Poor 模式。开启后 Saluzi 跳过 5 类后台副作用任务,并对若干辅助模型调用降级。**主对话的工具集与 system prompt 完全不变**——你只是少了一些「后台 whisper」。\n\n### 关闭了什么\n\n| 被关闭的子系统 | 位置 | 原本做什么 |\n|---------------|------|-----------|\n| extract_memories | Stop hook | 每轮结束后从对话提取记忆写入 MEMORY.md |\n| prompt_suggestion | Stop hook | 给用户猜测「下一步可能想问什么」 |\n| autoDream | Stop hook | 后台整合/蒸馏历史记忆 |\n| AgentSummary | 后台 | 给子 Agent 生成摘要 |\n| 验证 Agent | System prompt | 非平凡改动后强制独立审查 |\n\n同时这些**辅助模型调用降级**(不影响主模型):\n\n| 调用点 | 原模型 | Poor 后 |\n|--------|--------|---------|\n| autoMode critique | MainLoop | SmallFast |\n| permission explainer | MainLoop | SmallFast |\n| universal classifier | MainLoop | DefaultPro |\n| yolo classifier | MainLoop | DefaultPro |\n\n降级意味着权限分类、自动模式批评等「辅助判断」用更便宜的模型跑,质量略降但成本显著下降。主对话模型不变。\n\n### 优势\n\n- **工具集完整**:Read/Edit/Write/Bash/Glob/Grep/WebFetch/Task/MCP……全部照常\n- **System prompt 完整**:项目记忆、CodeGraph、技能、SALUZI.md 仍然注入\n- **可逆且持久**:`/poor` 再按一次关闭;状态写入 `settings.json` 的 `poorMode` 字段,重启后保留\n- **粒度温和**:只砍「后台 whisper」,主循环质量基本无损\n\n### 劣势\n\n- **不再自动积累记忆**:MEMORY.md 不会自动更新,需要手动 `/memory` 编辑\n- **无提示建议**:终端不再显示「你可能想问……」的快捷建议\n- **无验证 Agent**:复杂改动后没有独立审查兜底,需要自己跑测试\n- **辅助分类降级**:权限判断、自动模式批评的精度略降\n\n## SA 极简模式\n\n### 是什么\n\n`/sa` 切换 SA 模式(极简风格 minimal harness)。开启后 Saluzi 收敛到「最小可用 harness」:\n\n- **System prompt 收缩到 ~20 行**:只有角色定义 + 4 个工具说明 + 基本准则 + cwd + 日期。没有动态段落、没有项目记忆、没有 CodeGraph、没有 MCP 说明、没有会话指导。\n- **工具收敛到 4 个核心**:Read / Edit / Write / Bash。其余工具(Glob、Grep、WebFetch、Task、TodoWrite、MCP、Skill……)全部移除。\n- **所有后台副作用归零**:Poor 关掉的 5 项 + 会话记忆 + 相关记忆预取,全部跳过。\n\n这是「把 Saluzi 当成一个极简的 Read/Edit/Write/Bash 编码助手」的开关——类似极简 harness 的体验。\n\n### SA 的 System Prompt 长什么样\n\n完整内容就这些:\n\n```\nYou are an expert coding assistant operating inside Saluzi, a coding agent harness.\nYou help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n- Read: Read file contents from the filesystem\n- Edit: Make targeted edits to existing files\n- Write: Create new files or overwrite existing files\n- Bash: Execute shell commands\n\nGuidelines:\n- Be concise in your responses\n- Show file paths clearly when working with files\n- Use file_path:line_number format when referencing code locations\n- Do not use a colon before tool calls\n- Ask the user before making significant architectural decisions\n\nCurrent working directory: <cwd>\nDate: <date>\n```\n\n对比默认 prompt 的数千字(项目记忆 + CodeGraph + 技能 + 会话指导 + 工具说明 + 安全规则……),SA prompt 几乎是零开销。\n\n### 关闭了什么\n\nSA 关闭 = Poor 的全部 + 以下额外项:\n\n| 额外关闭项 | 位置 | 原本做什么 |\n|-----------|------|-----------|\n| 会话记忆提取 | sessionMemory | 跨会话蒸馏项目级记忆 |\n| 相关记忆预取 | attachments | 每轮用户消息后 side-query 检索相关记忆 |\n| 全部工具(除 4 核心) | tools | Glob/Grep/Task/WebFetch/MCP/Skill 等 |\n| 完整 system prompt | prompts | 替换为 20 行极简版 |\n\n### 优势\n\n- **极限省 token**:prompt 从数千字降到 ~20 行,每轮省下大量输入 token\n- **弱模型友好**:小上下文窗口 / 弱模型不会被巨型 prompt 挤占空间\n- **响应快**:没有后台 side-query 拖慢首字节\n- **行为可预测**:AI 只有 4 个工具,不会偷偷跑 WebFetch / Task / MCP,调试简单\n- **可逆且持久**:`/sa` 再按一次关闭;状态写入 `settings.json` 的 `saMode` 字段\n\n### 劣势\n\n- **没有 Glob/Grep**:AI 找文件只能用 `Bash(ls/find)` + `Read`,搜索效率低\n- **没有 Task/TodoWrite**:无法拆分多步任务、不能 spawn 子 Agent\n- **没有 WebFetch/WebSearch**:不能查文档、不能上网\n- **没有 MCP/Skill**:所有 MCP 服务器工具、自定义技能全部不可用\n- **没有项目记忆**:SALUZI.md、MEMORY.md、CodeGraph 知识都不注入,AI 对项目「无记忆」\n- **没有验证 Agent**:同 Poor\n- **AI 不知道自己的完整能力**:极简 prompt 不说明权限模式、安全规则、提交规范等,复杂工作流需要你手动提示\n\n> 简言之:SA 模式适合「我就让 AI 改这一个文件」「跑个脚本看看」这类窄任务,不适合复杂架构重构或需要项目上下文的工作。\n\n## 两种模式的完整对比\n\n| 维度 | 默认 | Poor | SA |\n|------|------|------|-----|\n| System prompt | 数千字(完整动态) | 数千字(完整动态) | ~20 行(极简) |\n| 工具集 | 全部 | 全部 | 4 核心(Read/Edit/Write/Bash) |\n| extract_memories | ✅ | ❌ | ❌ |\n| prompt_suggestion | ✅ | ❌ | ❌ |\n| autoDream | ✅ | ❌ | ❌ |\n| AgentSummary | ✅ | ❌ | ❌ |\n| 验证 Agent | ✅ | ❌ | ❌ |\n| 会话记忆提取 | ✅ | ✅ | ❌ |\n| 相关记忆预取 | ✅ | ✅ | ❌ |\n| 项目记忆注入 (SALUZI.md) | ✅ | ✅ | ❌ |\n| CodeGraph | ✅ | ✅ | ❌ |\n| MCP 工具 | ✅ | ✅ | ❌ |\n| Skill 工具 | ✅ | ✅ | ❌ |\n| Glob/Grep/WebFetch/Task | ✅ | ✅ | ❌ |\n| 辅助分类模型 | MainLoop | Pro/SmallFast | Pro/SmallFast |\n| 主对话模型 | 不变 | 不变 | 不变 |\n| 输入 token / 轮 | 基准 | 略低(少后台 side-query) | 显著低(prompt 极小) |\n| 适合场景 | 日常全功能 | 日常省 token | 极限省 / 弱模型 / 窄任务 |\n\n## 与其他功能的兼容性\n\n这是最关键的部分——开了节约模式后,你常用的那些 Saluzi 特色还能不能用。\n\n### MOM 混合模型\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ✅ 完全兼容 | Poor 不触碰 MOM 配置,顾问与主机按 `/mom` 设置正常运行 |\n| SA | ⚠️ 受限兼容 | MOM 仍可运行,但**主机只有 4 个工具**(Read/Edit/Write/Bash);顾问本就是 text-only 不受影响 |\n\n> 如果在 SA 模式下用 mom-stair,弱模型顾问(text-only)正常工作;升级到主机后主机也只能用 4 工具执行——不能 Glob/Grep/WebFetch。建议 SA + MOM 时把主机任务限定在文件读写 + 命令执行。\n\n### CodeGraph 代码智能\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ✅ 完全兼容 | CodeGraph 工具与 prompt 段落照常注入 |\n| SA | ❌ 不可用 | 工具被收敛到 4 核心(无 CodeGraph 工具),prompt 也不含 CodeGraph 段落 |\n\n### 记忆系统 (Memory V2 / SALUZI.md)\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ⚠️ 只读不写 | 已有记忆仍注入 prompt;但 extract_memories/autoDream 关闭,不再自动积累新记忆 |\n| SA | ❌ 完全隔离 | 既不注入(极简 prompt 无记忆段),也不提取(session memory 关闭) |\n\n### 验证 Agent (Verification Agent)\n\n| 模式 | 兼容性 |\n|------|--------|\n| Poor | ❌ 跳过 |\n| SA | ❌ 跳过 |\n\n两种模式都跳过验证 Agent。需要独立审查时请关闭节约模式后再跑,或手动 spawn 子 Agent(SA 模式下无 Task 工具,需先关 SA)。\n\n### Plan 模式 / Sandbox / Hooks\n\n| 模式 | Plan | Sandbox | Hooks |\n|------|------|---------|-------|\n| Poor | ✅ | ✅ | ✅ |\n| SA | ✅ | ✅ | ✅ |\n\n权限模式、沙箱、hooks 都是工具执行层机制,与节约模式正交,完全不受影响。\n\n### MCP 服务器 / Skill\n\n| 模式 | MCP | Skill |\n|------|-----|-------|\n| Poor | ✅ | ✅ |\n| SA | ❌ 工具被移除 | ❌ 工具被移除 |\n\nSA 模式下 MCP 服务器仍可连接(连接层不变),但 MCP 提供的工具不在 4 核心之列,不会被注入工具列表。\n\n### Auto Mode (/auto)\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ⚠️ 降级 | autoMode 仍运行,但 critique 步骤用 SmallFast 模型 |\n| SA | ⚠️ 降级 | 同 Poor;且主机工具受限 |\n\n### Buddy 伴侣 / Proactive 主动助手\n\n| 模式 | 兼容性 |\n|------|--------|\n| Poor | ✅ Buddy/Proactive 不在 Poor 的关闭清单内 |\n| SA | ⚠️ SA 的设计哲学是「零后台副作用」,建议关闭 Buddy/Proactive 以获得最纯净体验 |\n\n## 权限模式与安全风险\n\n> 用户最关心的问题:**开了节约模式,AI 会不会偷偷执行 `rm -rf /`、`drop database` 这类删库命令?**\n>\n> 简短回答:**节约模式本身不改变权限策略,不会让危险命令「更容易跑」**。真正的风险来自你选的**权限模式**(`default` / `acceptEdits` / `bypassPermissions` / `auto`),而不是 Poor/SA。但 Poor/SA 会把权限分类器降级到更便宜的模型,在 `bypassPermissions`/`auto` 模式下**理论上**误判概率略升。下面逐层拆解。\n\n### 权限模式与节约模式正交\n\n权限模式由 `/permissions` 或 `settings.json` 的 `permissions.defaultMode` 控制,**与 Poor/SA 完全独立**。开 Poor 或 SA 不会切换你的权限模式:\n\n| 权限模式 | Bash 危险命令会怎样 | Poor/SA 影响 |\n|---------|---------------------|-------------|\n| `default` | 每条命令弹确认,`rm -rf` 类必问你 | 无——该问还是问 |\n| `acceptEdits` | 只自动放行文件编辑,**Bash 仍逐条问** | 无——Bash 仍问 |\n| `plan` | 只读,不能执行任何写操作 | 无——根本跑不了 |\n| `bypassPermissions` | 分类器自动判断,不问你 | ⚠️ 分类器降级(见下) |\n| `auto` | autoMode 分类器自动判断 | ⚠️ 分类器降级(见下) |\n\n**结论**:在 `default` / `acceptEdits` / `plan` 这三种模式下,无论开不开 Poor/SA,危险命令都必须经过你手动确认——**不存在「开了 SA 就自动删库」的情况**。\n\n### SA 模式仍执行 deny 规则\n\nSA 模式收敛工具集时调用的是 `filterToolsByDenyRules`——也就是说你在 `settings.json` 里配的 `permissions.deny` 规则**在 SA 模式下照常生效**:\n\n```json\n{\n \"permissions\": {\n \"deny\": [\n \"Bash(rm -rf:*)\",\n \"Bash(rm -rf /*:*)\",\n \"Bash(drop database:*)\",\n \"Bash(git push --force:*)\",\n \"Bash(:(){ :|:& };:)\",\n \"Bash(mkfs*:*)\"\n ]\n }\n}\n```\n\n这些规则会在工具列表阶段就**直接屏蔽**匹配的命令——AI 根本看不到这些工具能跑这类命令,分类器也不会被调用。这是比分类器更硬的防线,且**不受 Poor/SA 影响**。\n\n> 强烈建议:无论用不用节约模式,都把 `rm -rf /`、`drop database`、`mkfs`、fork 炸弹等不可逆命令写进 `deny`。这是「物理隔离」级别的一刀切。\n\n### 分类器降级:风险有多大\n\n在 `bypassPermissions` 或 `auto` 模式下,命令是否自动放行由**分类器**(yoloClassifier / universalClassifier)决定。Saluzi 的分类器 prompt 明确把以下列为 **Irreversible Local Destruction(不可逆本地破坏)**:\n\n- `rm -rf` 递归强制删除非平凡路径\n- `Remove-Item -Recurse -Force`(PowerShell 等价物)\n- `> file` 截断已有文件为空\n- `drop database` 删库\n- `git push --force`(视上下文)\n\nPoor/SA 模式下分类器模型降级:\n\n| 模式 | 分类器模型 | 影响 |\n|------|-----------|------|\n| 默认 | MainLoop(如 Max/Pro 主模型) | 精度最高 |\n| Poor/SA | DefaultPro | 略低,但仍是 Pro 级模型 |\n\n**关键点**:\n\n- 分类器**仍然运行**——Poor/SA 没有关闭分类器,只是让它用更便宜的模型跑。\n- Pro 级模型对 `rm -rf /` 这种明显的破坏性命令识别能力依然很强——这不是「盲放」。\n- 降级影响的是**边界模糊**的命令(如 `rm -rf ./build` 这种有歧义的)的判断精度,不是放行 `rm -rf /`。\n\n**所以「删库」风险的真实情况**:\n\n1. `default` / `acceptEdits` / `plan` 模式:**零风险**,必须你确认。\n2. `bypassPermissions` / `auto` + 默认:**低风险**,分类器(MainLoop)会拦。\n3. `bypassPermissions` / `auto` + Poor/SA:**略升的边界风险**,分类器(Pro)对明显破坏命令仍拦,但对模糊命令误判概率略高。\n4. 任何模式 + 配了 `deny` 规则:**零风险**,物理屏蔽。\n\n### SA 模式的特殊风险面\n\nSA 模式只保留 4 个工具(Read/Edit/Write/Bash),这反而**缩小**了攻击面:\n\n- **没有 WebFetch/WebSearch**:AI 不能下载并执行远程脚本。\n- **没有 Task**:不能 spawn 子 Agent 绕过主循环审查。\n- **没有 MCP 工具**:外部 MCP 服务器不能注入未审查的工具。\n- **没有 Skill**:自定义技能不会被执行。\n\n但 **Bash 仍在**——这是 SA 模式下唯一的「能干坏事」的入口。只要 Bash 的权限策略到位(`default` 模式或 `deny` 规则),SA 模式的整体风险面比默认模式**更小**,不是更大。\n\n### 安全使用建议\n\n| 建议 | 原因 |\n|------|------|\n| 默认用 `default` 或 `acceptEdits` 权限模式 | Bash 逐条确认,物理安全 |\n| 在 `settings.json` 配 `permissions.deny` 屏蔽 `rm -rf /`、`drop database`、`mkfs`、fork 炸弹 | 一刀切物理隔离,不受任何模式影响 |\n| 开启沙箱(`sandbox.enabled: true`)| 限制写入路径与网络访问,`rm -rf /` 直接失败 |\n| 避免 `bypassPermissions` + Poor/SA 组合 | 分类器降级 + 不问你 = 信任分类器,边界命令风险略升 |\n| SA 模式下尤其盯紧 Bash 输出 | 没有验证 Agent 兜底,需要你自己看命令 |\n| 用 `/permissions` 临时切 `plan` 模式做危险探索 | 只读,根本不能执行写操作 |\n\n### 一句话总结\n\n**Poor/SA 不会让 Saluzi「更敢删库」**——它们只砍后台副作用和工具数量,不动权限策略与 deny 规则。真正的删库风险来自 `bypassPermissions`/`auto` 权限模式本身;要彻底消除风险,配 `deny` 规则 + 开沙箱 + 用 `default` 模式,这三道防线与节约模式正交,同时开启完全安全。\n\n## 如何开启 / 关闭\n\n### 命令切换\n\n```\n> /poor # 切换 Poor 模式(开↔关)\n> /sa # 切换 SA 模式(开↔关)\n```\n\n输出会确认当前状态,例如:\n\n```\nSA mode ON — minimal prompt, 4 tools (Read/Edit/Write/Bash), all background tasks disabled\n```\n\n### 配置面板\n\n`/config` → 找到 `SA mode (minimal harness)` 与 `poor mode` 开关,`Enter` 切换。\n\n### settings.json\n\n直接编辑 `~/.saluzi-edu/settings.json`:\n\n```json\n{\n \"poorMode\": true,\n \"saMode\": true\n}\n```\n\n两个字段都可选,`true` 开启、省略或 `false` 关闭。重启 Saluzi 后生效。\n\n> **不要同时开 Poor 和 SA**。SA 是 Poor 的严格超集,同时开启只是冗余——工具集与 prompt 都按 SA 走,Poor 的标志位不起额外作用。需要极限省 token 就直接开 SA;需要保留全部工具就开 Poor。\n\n## 何时该用哪个\n\n| 你的情况 | 推荐 |\n|---------|------|\n| 日常开发,想省点 token,但还要用 Glob/Grep/MOM/CodeGraph | **Poor** |\n| API Key 按量计费,想压到最低 | **Poor**(日常)或 **SA**(窄任务) |\n| 用弱模型 / 小上下文窗口 | **SA** |\n| 一次性脚本:改一个文件、跑个命令 | **SA** |\n| 复杂架构重构、需要项目记忆与多步任务 | **关闭**(用默认) |\n| 需要 MOM 多顾问交叉验证 | **Poor**(保留工具)或 **关闭** |\n| 调试时想要「AI 不要偷偷干别的」 | **SA** |\n| 长期挂着的会话,不想后台烧 token | **Poor** |\n\n## 节约效果怎么看\n\n开启后用 `/cost` 观察单轮 token:\n\n```\n> /cost\n```\n\n重点看**输入 token**——SA 模式下每轮输入 token 会显著下降(因为 prompt 从数千字缩到 ~20 行)。后台 side-query 的输出 token 也归零。多轮对比即可看到差异。\n\n## 下一步\n\n- [MOM 混合模型](./mom-mixed-models) — 节约模式下 MOM 如何运行\n- [模型选择与切换](./model-selection) — `/poor` 命令的简述与模型降级\n- [查看消耗](./cost-usage) — `/cost` 监控节约效果\n- [记忆系统](./memory-system) — Poor/SA 对记忆的影响\n"
|
|
3126
|
+
"content": "\n## 为什么需要 Token 节约模式\n\nSaluzi 默认开启大量「让 AI 更聪明」的后台机制:自动记忆提取、提示建议、会话记忆整合、验证 Agent、相关记忆预取、Agent 摘要……这些机制各自只消耗少量 token,但叠在一起会让每次对话的「隐性开销」相当可观。\n\n当你处于以下场景时,这些开销就是纯浪费:\n\n- **API Key 按量计费**,想压到最低\n- **弱模型 / 小上下文窗口**,每一段 prompt 都很贵\n- **一次性脚本任务**,不需要长期记忆\n- **清晰的单文件修改**,不需要多角度验证\n\n两种节约模式就是为这些场景设计的开关,按「砍多少」分档:\n\n| 模式 | 砍掉的范围 | 工具集 | System Prompt | 适合 |\n|------|-----------|--------|--------------|------|\n| **Poor** | 5 项后台副作用 | 全部保留 | 完整 | 日常开发省 token |\n| **SA** | 全部后台 + 工具收敛 | 仅 4 核心 | ~20 行极简 | 极限省 token / 弱模型 |\n\nSA 是 Poor 的**严格超集**——Poor 关掉的一切,SA 也关掉;SA 还额外砍掉工具和 prompt。两者的关系类似「省电模式」与「飞行模式」。\n\n## Poor 节约模式\n\n### 是什么\n\n`/poor` 切换 Poor 模式。开启后 Saluzi 跳过 5 类后台副作用任务,并对若干辅助模型调用降级。**主对话的工具集与 system prompt 完全不变**——你只是少了一些「后台 whisper」。\n\n### 关闭了什么\n\n| 被关闭的子系统 | 位置 | 原本做什么 |\n|---------------|------|-----------|\n| extract_memories | Stop hook | 每轮结束后从对话提取记忆写入 MEMORY.md |\n| prompt_suggestion | Stop hook | 给用户猜测「下一步可能想问什么」 |\n| autoDream | Stop hook | 后台整合/蒸馏历史记忆 |\n| AgentSummary | 后台 | 给子 Agent 生成摘要 |\n| 验证 Agent | System prompt | 非平凡改动后强制独立审查 |\n\n同时这些**辅助模型调用降级**(不影响主模型):\n\n| 调用点 | 原模型 | Poor 后 |\n|--------|--------|---------|\n| autoMode critique | MainLoop | SmallFast |\n| permission explainer | MainLoop | SmallFast |\n| universal classifier | MainLoop | DefaultPro |\n| yolo classifier | MainLoop | DefaultPro |\n\n降级意味着权限分类、自动模式批评等「辅助判断」用更便宜的模型跑,质量略降但成本显著下降。主对话模型不变。\n\n### 优势\n\n- **工具集完整**:Read/Edit/Write/Bash/Glob/Grep/WebFetch/Task/MCP……全部照常\n- **System prompt 完整**:项目记忆、CodeGraph、技能、SALUZI.md 仍然注入\n- **可逆且持久**:`/poor` 再按一次关闭;状态写入 `settings.json` 的 `poorMode` 字段,重启后保留\n- **粒度温和**:只砍「后台 whisper」,主循环质量基本无损\n\n### 劣势\n\n- **不再自动积累记忆**:MEMORY.md 不会自动更新,需要手动 `/memory` 编辑\n- **无提示建议**:终端不再显示「你可能想问……」的快捷建议\n- **无验证 Agent**:复杂改动后没有独立审查兜底,需要自己跑测试\n- **辅助分类降级**:权限判断、自动模式批评的精度略降\n\n## SA 极简模式\n\n### 是什么\n\n`/sa` 切换 SA 模式(极简风格 minimal harness)。开启后 Saluzi 收敛到「最小可用 harness」:\n\n- **System prompt 收缩到 ~20 行**:只有角色定义 + 4 个工具说明 + 基本准则 + cwd + 日期。没有动态段落、没有项目记忆、没有 CodeGraph、没有 MCP 说明、没有会话指导。\n- **工具收敛到 4 个核心**:Read / Edit / Write / Bash。其余工具(Glob、Grep、WebFetch、Task、TodoWrite、MCP、Skill……)全部移除。\n- **所有后台副作用归零**:Poor 关掉的 5 项 + 会话记忆 + 相关记忆预取,全部跳过。\n\n这是「把 Saluzi 当成一个极简的 Read/Edit/Write/Bash 编码助手」的开关——类似极简 harness 的体验。\n\n### SA 的 System Prompt 长什么样\n\n完整内容就这些:\n\n```\nYou are an expert coding assistant operating inside Saluzi, a coding agent harness.\nYou help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n- Read: Read file contents from the filesystem\n- Edit: Make targeted edits to existing files\n- Write: Create new files or overwrite existing files\n- Bash: Execute shell commands\n\nGuidelines:\n- Be concise in your responses\n- Show file paths clearly when working with files\n- Use file_path:line_number format when referencing code locations\n- Do not use a colon before tool calls\n- Ask the user before making significant architectural decisions\n\nCurrent working directory: <cwd>\nDate: <date>\n```\n\n对比默认 prompt 的数千字(项目记忆 + CodeGraph + 技能 + 会话指导 + 工具说明 + 安全规则……),SA prompt 几乎是零开销。\n\n### 关闭了什么\n\nSA 关闭 = Poor 的全部 + 以下额外项:\n\n| 额外关闭项 | 位置 | 原本做什么 |\n|-----------|------|-----------|\n| 会话记忆提取 | sessionMemory | 跨会话蒸馏项目级记忆 |\n| 相关记忆预取 | attachments | 每轮用户消息后 side-query 检索相关记忆 |\n| 全部工具(除 4 核心) | tools | Glob/Grep/Task/WebFetch/MCP/Skill 等 |\n| 完整 system prompt | prompts | 替换为 20 行极简版 |\n\n### 优势\n\n- **极限省 token**:prompt 从数千字降到 ~20 行,每轮省下大量输入 token\n- **弱模型友好**:小上下文窗口 / 弱模型不会被巨型 prompt 挤占空间\n- **响应快**:没有后台 side-query 拖慢首字节\n- **行为可预测**:AI 只有 4 个工具,不会偷偷跑 WebFetch / Task / MCP,调试简单\n- **可逆且持久**:`/sa` 再按一次关闭;状态写入 `settings.json` 的 `saMode` 字段\n\n### 劣势\n\n- **没有 Glob/Grep**:AI 找文件只能用 `Bash(ls/find)` + `Read`,搜索效率低\n- **没有 Task/TodoWrite**:无法拆分多步任务、不能 spawn 子 Agent\n- **没有 WebFetch/WebSearch**:不能查文档、不能上网\n- **没有 MCP/Skill**:所有 MCP 服务器工具、自定义技能全部不可用\n- **没有项目记忆**:SALUZI.md、MEMORY.md、CodeGraph 知识都不注入,AI 对项目「无记忆」\n- **没有验证 Agent**:同 Poor\n- **AI 不知道自己的完整能力**:极简 prompt 不说明权限模式、安全规则、提交规范等,复杂工作流需要你手动提示\n\n> 简言之:SA 模式适合「我就让 AI 改这一个文件」「跑个脚本看看」这类窄任务,不适合复杂架构重构或需要项目上下文的工作。\n\n## 两种模式的完整对比\n\n| 维度 | 默认 | Poor | SA |\n|------|------|------|-----|\n| System prompt | 数千字(完整动态) | 数千字(完整动态) | ~20 行(极简) |\n| 工具集 | 全部 | 全部 | 4 核心(Read/Edit/Write/Bash) |\n| extract_memories | ✅ | ❌ | ❌ |\n| prompt_suggestion | ✅ | ❌ | ❌ |\n| autoDream | ✅ | ❌ | ❌ |\n| AgentSummary | ✅ | ❌ | ❌ |\n| 验证 Agent | ✅ | ❌ | ❌ |\n| 会话记忆提取 | ✅ | ✅ | ❌ |\n| 相关记忆预取 | ✅ | ✅ | ❌ |\n| 项目记忆注入 (SALUZI.md) | ✅ | ✅ | ❌ |\n| CodeGraph | ✅ | ✅ | ❌ |\n| MCP 工具 | ✅ | ✅ | ❌ |\n| Skill 工具 | ✅ | ✅ | ❌ |\n| Glob/Grep/WebFetch/Task | ✅ | ✅ | ❌ |\n| 辅助分类模型 | MainLoop | Pro/SmallFast | Pro/SmallFast |\n| 主对话模型 | 不变 | 不变 | 不变 |\n| 输入 token / 轮 | 基准 | 略低(少后台 side-query) | 显著低(prompt 极小) |\n| 适合场景 | 日常全功能 | 日常省 token | 极限省 / 弱模型 / 窄任务 |\n\n## 与其他功能的兼容性\n\n这是最关键的部分——开了节约模式后,你常用的那些 Saluzi 特色还能不能用。\n\n### MOM 混合模型\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ✅ 完全兼容 | Poor 不触碰 MOM 配置,顾问与主机按 `/mom` 设置正常运行 |\n| SA | ⚠️ 受限兼容 | MOM 仍可运行,但**主机只有 4 个工具**(Read/Edit/Write/Bash);顾问本就是 text-only 不受影响 |\n\n> 如果在 SA 模式下用 mom-stair,弱模型顾问(text-only)正常工作;升级到主机后主机也只能用 4 工具执行——不能 Glob/Grep/WebFetch。建议 SA + MOM 时把主机任务限定在文件读写 + 命令执行。\n\n### CodeGraph 代码智能\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ✅ 完全兼容 | CodeGraph 工具与 prompt 段落照常注入 |\n| SA | ❌ 不可用 | 工具被收敛到 4 核心(无 CodeGraph 工具),prompt 也不含 CodeGraph 段落 |\n\n### 记忆系统 (Memory V2 / SALUZI.md)\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ⚠️ 只读不写 | 已有记忆仍注入 prompt;但 extract_memories/autoDream 关闭,不再自动积累新记忆 |\n| SA | ❌ 完全隔离 | 既不注入(极简 prompt 无记忆段),也不提取(session memory 关闭) |\n\n### 验证 Agent (Verification Agent)\n\n| 模式 | 兼容性 |\n|------|--------|\n| Poor | ❌ 跳过 |\n| SA | ❌ 跳过 |\n\n两种模式都跳过验证 Agent。需要独立审查时请关闭节约模式后再跑,或手动 spawn 子 Agent(SA 模式下无 Task 工具,需先关 SA)。\n\n### Plan 模式 / Sandbox / Hooks\n\n| 模式 | Plan | Sandbox | Hooks |\n|------|------|---------|-------|\n| Poor | ✅ | ✅ | ✅ |\n| SA | ✅ | ✅ | ✅ |\n\n权限模式、沙箱、hooks 都是工具执行层机制,与节约模式正交,完全不受影响。\n\n### MCP 服务器 / Skill\n\n| 模式 | MCP | Skill |\n|------|-----|-------|\n| Poor | ✅ | ✅ |\n| SA | ❌ 工具被移除 | ❌ 工具被移除 |\n\nSA 模式下 MCP 服务器仍可连接(连接层不变),但 MCP 提供的工具不在 4 核心之列,不会被注入工具列表。\n\n### Auto Mode (/auto)\n\n| 模式 | 兼容性 | 说明 |\n|------|--------|------|\n| Poor | ⚠️ 降级 | autoMode 仍运行,但 critique 步骤用 SmallFast 模型 |\n| SA | ⚠️ 降级 | 同 Poor;且主机工具受限 |\n\n## 权限模式与安全风险\n\n> 用户最关心的问题:**开了节约模式,AI 会不会偷偷执行 `rm -rf /`、`drop database` 这类删库命令?**\n>\n> 简短回答:**节约模式本身不改变权限策略,不会让危险命令「更容易跑」**。真正的风险来自你选的**权限模式**(`default` / `acceptEdits` / `bypassPermissions` / `auto`),而不是 Poor/SA。但 Poor/SA 会把权限分类器降级到更便宜的模型,在 `bypassPermissions`/`auto` 模式下**理论上**误判概率略升。下面逐层拆解。\n\n### 权限模式与节约模式正交\n\n权限模式由 `/permissions` 或 `settings.json` 的 `permissions.defaultMode` 控制,**与 Poor/SA 完全独立**。开 Poor 或 SA 不会切换你的权限模式:\n\n| 权限模式 | Bash 危险命令会怎样 | Poor/SA 影响 |\n|---------|---------------------|-------------|\n| `default` | 每条命令弹确认,`rm -rf` 类必问你 | 无——该问还是问 |\n| `acceptEdits` | 只自动放行文件编辑,**Bash 仍逐条问** | 无——Bash 仍问 |\n| `plan` | 只读,不能执行任何写操作 | 无——根本跑不了 |\n| `bypassPermissions` | 分类器自动判断,不问你 | ⚠️ 分类器降级(见下) |\n| `auto` | autoMode 分类器自动判断 | ⚠️ 分类器降级(见下) |\n\n**结论**:在 `default` / `acceptEdits` / `plan` 这三种模式下,无论开不开 Poor/SA,危险命令都必须经过你手动确认——**不存在「开了 SA 就自动删库」的情况**。\n\n### SA 模式仍执行 deny 规则\n\nSA 模式收敛工具集时调用的是 `filterToolsByDenyRules`——也就是说你在 `settings.json` 里配的 `permissions.deny` 规则**在 SA 模式下照常生效**:\n\n```json\n{\n \"permissions\": {\n \"deny\": [\n \"Bash(rm -rf:*)\",\n \"Bash(rm -rf /*:*)\",\n \"Bash(drop database:*)\",\n \"Bash(git push --force:*)\",\n \"Bash(:(){ :|:& };:)\",\n \"Bash(mkfs*:*)\"\n ]\n }\n}\n```\n\n这些规则会在工具列表阶段就**直接屏蔽**匹配的命令——AI 根本看不到这些工具能跑这类命令,分类器也不会被调用。这是比分类器更硬的防线,且**不受 Poor/SA 影响**。\n\n> 强烈建议:无论用不用节约模式,都把 `rm -rf /`、`drop database`、`mkfs`、fork 炸弹等不可逆命令写进 `deny`。这是「物理隔离」级别的一刀切。\n\n### 分类器降级:风险有多大\n\n在 `bypassPermissions` 或 `auto` 模式下,命令是否自动放行由**分类器**(yoloClassifier / universalClassifier)决定。Saluzi 的分类器 prompt 明确把以下列为 **Irreversible Local Destruction(不可逆本地破坏)**:\n\n- `rm -rf` 递归强制删除非平凡路径\n- `Remove-Item -Recurse -Force`(PowerShell 等价物)\n- `> file` 截断已有文件为空\n- `drop database` 删库\n- `git push --force`(视上下文)\n\nPoor/SA 模式下分类器模型降级:\n\n| 模式 | 分类器模型 | 影响 |\n|------|-----------|------|\n| 默认 | MainLoop(如 Max/Pro 主模型) | 精度最高 |\n| Poor/SA | DefaultPro | 略低,但仍是 Pro 级模型 |\n\n**关键点**:\n\n- 分类器**仍然运行**——Poor/SA 没有关闭分类器,只是让它用更便宜的模型跑。\n- Pro 级模型对 `rm -rf /` 这种明显的破坏性命令识别能力依然很强——这不是「盲放」。\n- 降级影响的是**边界模糊**的命令(如 `rm -rf ./build` 这种有歧义的)的判断精度,不是放行 `rm -rf /`。\n\n**所以「删库」风险的真实情况**:\n\n1. `default` / `acceptEdits` / `plan` 模式:**零风险**,必须你确认。\n2. `bypassPermissions` / `auto` + 默认:**低风险**,分类器(MainLoop)会拦。\n3. `bypassPermissions` / `auto` + Poor/SA:**略升的边界风险**,分类器(Pro)对明显破坏命令仍拦,但对模糊命令误判概率略高。\n4. 任何模式 + 配了 `deny` 规则:**零风险**,物理屏蔽。\n\n### SA 模式的特殊风险面\n\nSA 模式只保留 4 个工具(Read/Edit/Write/Bash),这反而**缩小**了攻击面:\n\n- **没有 WebFetch/WebSearch**:AI 不能下载并执行远程脚本。\n- **没有 Task**:不能 spawn 子 Agent 绕过主循环审查。\n- **没有 MCP 工具**:外部 MCP 服务器不能注入未审查的工具。\n- **没有 Skill**:自定义技能不会被执行。\n\n但 **Bash 仍在**——这是 SA 模式下唯一的「能干坏事」的入口。只要 Bash 的权限策略到位(`default` 模式或 `deny` 规则),SA 模式的整体风险面比默认模式**更小**,不是更大。\n\n### 安全使用建议\n\n| 建议 | 原因 |\n|------|------|\n| 默认用 `default` 或 `acceptEdits` 权限模式 | Bash 逐条确认,物理安全 |\n| 在 `settings.json` 配 `permissions.deny` 屏蔽 `rm -rf /`、`drop database`、`mkfs`、fork 炸弹 | 一刀切物理隔离,不受任何模式影响 |\n| 开启沙箱(`sandbox.enabled: true`)| 限制写入路径与网络访问,`rm -rf /` 直接失败 |\n| 避免 `bypassPermissions` + Poor/SA 组合 | 分类器降级 + 不问你 = 信任分类器,边界命令风险略升 |\n| SA 模式下尤其盯紧 Bash 输出 | 没有验证 Agent 兜底,需要你自己看命令 |\n| 用 `/permissions` 临时切 `plan` 模式做危险探索 | 只读,根本不能执行写操作 |\n\n### 一句话总结\n\n**Poor/SA 不会让 Saluzi「更敢删库」**——它们只砍后台副作用和工具数量,不动权限策略与 deny 规则。真正的删库风险来自 `bypassPermissions`/`auto` 权限模式本身;要彻底消除风险,配 `deny` 规则 + 开沙箱 + 用 `default` 模式,这三道防线与节约模式正交,同时开启完全安全。\n\n## 如何开启 / 关闭\n\n### 命令切换\n\n```\n> /poor # 切换 Poor 模式(开↔关)\n> /sa # 切换 SA 模式(开↔关)\n```\n\n输出会确认当前状态,例如:\n\n```\nSA mode ON — minimal prompt, 4 tools (Read/Edit/Write/Bash), all background tasks disabled\n```\n\n### 配置面板\n\n`/config` → 找到 `SA mode (minimal harness)` 与 `poor mode` 开关,`Enter` 切换。\n\n### settings.json\n\n直接编辑 `~/.saluzi-edu/settings.json`:\n\n```json\n{\n \"poorMode\": true,\n \"saMode\": true\n}\n```\n\n两个字段都可选,`true` 开启、省略或 `false` 关闭。重启 Saluzi 后生效。\n\n> **不要同时开 Poor 和 SA**。SA 是 Poor 的严格超集,同时开启只是冗余——工具集与 prompt 都按 SA 走,Poor 的标志位不起额外作用。需要极限省 token 就直接开 SA;需要保留全部工具就开 Poor。\n\n## 何时该用哪个\n\n| 你的情况 | 推荐 |\n|---------|------|\n| 日常开发,想省点 token,但还要用 Glob/Grep/MOM/CodeGraph | **Poor** |\n| API Key 按量计费,想压到最低 | **Poor**(日常)或 **SA**(窄任务) |\n| 用弱模型 / 小上下文窗口 | **SA** |\n| 一次性脚本:改一个文件、跑个命令 | **SA** |\n| 复杂架构重构、需要项目记忆与多步任务 | **关闭**(用默认) |\n| 需要 MOM 多顾问交叉验证 | **Poor**(保留工具)或 **关闭** |\n| 调试时想要「AI 不要偷偷干别的」 | **SA** |\n| 长期挂着的会话,不想后台烧 token | **Poor** |\n\n## 节约效果怎么看\n\n开启后用 `/cost` 观察单轮 token:\n\n```\n> /cost\n```\n\n重点看**输入 token**——SA 模式下每轮输入 token 会显著下降(因为 prompt 从数千字缩到 ~20 行)。后台 side-query 的输出 token 也归零。多轮对比即可看到差异。\n\n## 下一步\n\n- [MOM 混合模型](./mom-mixed-models) — 节约模式下 MOM 如何运行\n- [模型选择与切换](./model-selection) — `/poor` 命令的简述与模型降级\n- [查看消耗](./cost-usage) — `/cost` 监控节约效果\n- [记忆系统](./memory-system) — Poor/SA 对记忆的影响\n"
|
|
3127
3127
|
},
|
|
3128
3128
|
"docs/guide/assistant-proactive": {
|
|
3129
3129
|
"frontmatter": {
|
package/dist/guide/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
|
12
12
|
rel="stylesheet"
|
|
13
13
|
/>
|
|
14
|
-
<script type="module" crossorigin src="/assets/main-
|
|
14
|
+
<script type="module" crossorigin src="/assets/main-BLaZPqcD.js"></script>
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-S-ySWqyJ.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/assets/shiki-CMaUdEs0.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/streamdown-nMT_aKRc.js">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{ac as x,ad as o,E as m,a7 as s,a1 as l,t as u}from"./main-
|
|
1
|
+
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{ac as x,ad as o,E as m,a7 as s,a1 as l,t as u}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){x();const[a,i]=d.useState([]),{myTeams:r,isLoading:c}=o(),n=d.useCallback(async()=>{try{const t=await m();i(t||[])}catch(t){console.error("Admin: failed to load sessions",t)}},[]);return d.useEffect(()=>{n()},[n]),e.jsx("div",{className:"flex-1 overflow-y-auto",children:e.jsxs("div",{className:"mx-auto max-w-5xl px-4 py-8",children:[e.jsx("h1",{className:"mb-6 font-display text-2xl font-semibold text-text-primary",children:s("admin.title")}),e.jsxs("section",{className:"mb-10",children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.teams")," (",r.length,")"]}),c?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("common.loading")}):r.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noTeams")}):e.jsx("div",{className:"space-y-2",children:r.map(t=>e.jsxs("a",{href:`/teams/${t.slug}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"font-medium text-text-primary",children:t.name}),e.jsx("span",{className:"ml-2 text-xs text-text-muted",children:t.slug})]}),e.jsx("span",{className:"text-xs text-text-muted",children:l(new Date(t.created_at).getTime()/1e3)})]},t.id))})]}),e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-4 font-display text-lg font-semibold text-text-primary",children:[s("admin.sessions")," (",a.length,")"]}),a.length===0?e.jsx("div",{className:"rounded-xl border border-border bg-surface-1 p-4 text-center text-text-muted",children:s("admin.noSessions")}):e.jsx("div",{className:"space-y-2",children:a.map(t=>e.jsxs("a",{href:`/code/${t.id}`,className:"flex items-center justify-between rounded-xl border border-border bg-surface-1 px-4 py-3 no-underline transition-colors hover:border-border-light hover:bg-surface-2",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.title||t.id}),e.jsx("span",{className:"rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-muted",children:t.source||"unknown"})]}),e.jsx("div",{className:"truncate text-xs text-text-muted",children:t.id})]}),e.jsxs("div",{className:"ml-4 flex items-center gap-3",children:[e.jsx(u,{status:t.status}),e.jsx("span",{className:"text-xs text-text-muted",children:l(t.updated_at||t.created_at)})]})]},t.id))})]})]})})}export{j as AdminPanel};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{x}from"./main-
|
|
1
|
+
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{x}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function f(){const r=window.location.pathname.split("/"),t=r[r.length-1]||"",[i,s]=a.useState("idle"),[o,c]=a.useState(null),[m,l]=a.useState(null);return a.useEffect(()=>{if(!t||!t.startsWith("clm_")){c("Invalid claim token"),s("error");return}s("claiming"),x(t).then(n=>{l(n.environment_id),s("success")}).catch(n=>{c(n instanceof Error?n.message:"Claim failed"),s("error")})},[t]),i==="claiming"?e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsx("p",{className:"text-sm text-text-muted",children:"Claiming environment..."})}):i==="error"?e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsx("p",{className:"text-sm text-destructive",children:o}),e.jsx("a",{href:"/code",className:"mt-4 inline-block text-accent hover:underline",children:"Back to dashboard"})]}):e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:"Environment claimed"}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:"You are now the owner of this environment."})]}),e.jsxs("div",{className:"space-y-4",children:[m&&e.jsx("p",{className:"font-mono text-xs text-text-muted",children:m}),e.jsx("a",{href:"/code",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 transition-colors",children:"Go to dashboard"})]})]})}export{f as Claim};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as e,e as o}from"./vendor-DE_-CLIE.js";import{_ as O,Z as _,ad as E,ab as T,t as P,ac as L,a7 as a,a1 as A,o as $,q as W,e as H,p as V,d as I,a4 as Z,y as q,E as R,F as U,B as z}from"./main-
|
|
1
|
+
import{j as e,e as o}from"./vendor-DE_-CLIE.js";import{_ as O,Z as _,ad as E,ab as T,t as P,ac as L,a7 as a,a1 as A,o as $,q as W,e as H,p as V,d as I,a4 as Z,y as q,E as R,F as U,B as z}from"./main-C6czI38s.js";import{g as D}from"./workerType-Bd-zteMi.js";import{S as G,D as J,a as K,c as Q,d as X,b as Y}from"./SessionVisibilityBadge-Bkv-o3zy.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as v,a7 as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as v,a7 as t}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function E({onSuccess:b,onInvalidInvite:l}){const{join:h}=v(),[u,f]=r.useState(""),[d,j]=r.useState(""),[o,w]=r.useState(""),[c,g]=r.useState(""),[m,n]=r.useState(""),[x,p]=r.useState(!1);r.useEffect(()=>{const a=new URLSearchParams(window.location.search).get("invite");a?f(a):l()},[l]);const y=async s=>{if(s.preventDefault(),n(""),o.length<8){n(t("auth.setup.passwordTooShort"));return}if(o!==c){n(t("auth.setup.passwordMismatch"));return}p(!0);try{await h(u,d,o),b()}catch(a){const i=a instanceof Error?a.message:"Join failed";if(i.includes("Invalid invitation")||i.includes("expired")||i.includes("already used")){l();return}n(i)}finally{p(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.join.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.join.welcome")}),e.jsx("p",{className:"mt-1 text-sm text-text-muted",children:t("auth.join.description")})]}),e.jsxs("form",{onSubmit:y,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.username")}),e.jsx("input",{type:"text",value:d,onChange:s=>j(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),m&&e.jsx("p",{className:"text-sm text-status-error",children:m}),e.jsx("button",{type:"submit",disabled:x||!u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:x?t("common.loading"):t("auth.join.submit")})]})]})})}export{E as Join};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as f,a7 as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as f,a7 as t}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function N({onSuccess:d,onNavigateRegister:c}){const{login:m,registrationAllowed:x}=f(),[a,p]=r.useState(""),[o,b]=r.useState(""),[l,n]=r.useState(""),[i,u]=r.useState(!1),h=async s=>{s.preventDefault(),n(""),u(!0);try{await m(a,o),d()}catch{n(t("auth.login.failed"))}finally{u(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.login.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.login.description")})]}),e.jsxs("form",{onSubmit:h,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:a,onChange:s=>p(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:o,onChange:s=>b(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),l&&e.jsx("p",{className:"text-sm text-status-error",children:l}),e.jsx("button",{type:"submit",disabled:i,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:i?t("common.loading"):t("auth.login.submit")})]}),x&&e.jsx("button",{type:"button",onClick:c,className:"w-full text-center text-sm text-text-muted hover:text-text-primary transition-colors",children:t("auth.login.register")})]})})}export{N as Login};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as y,a7 as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as y,a7 as t}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S({onSuccess:m,onBack:x}){const{register:p}=y(),[n,b]=r.useState(""),[a,h]=r.useState(""),[l,f]=r.useState(""),[i,o]=r.useState(""),[u,d]=r.useState(!1),g=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==l){o(t("auth.setup.passwordMismatch"));return}d(!0);try{await p(n,a),m()}catch(c){o(c instanceof Error?c.message:t("auth.register.failed"))}finally{d(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.register.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.register.description")})]}),e.jsxs("form",{onSubmit:g,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.username")}),e.jsx("input",{type:"text",value:n,onChange:s=>b(s.target.value),required:!0,autoComplete:"username",autoFocus:!0,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.login.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>h(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.join.confirmPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>f(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:u,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:u?t("common.loading"):t("auth.register.submit")})]}),e.jsx("button",{type:"button",onClick:x,className:"w-full text-center text-sm text-text-muted hover:text-text-primary transition-colors",children:t("auth.register.backToLogin")})]})})}export{S as Register};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var pe=Object.defineProperty;var he=(s,t,n)=>t in s?pe(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var $=(s,t,n)=>he(s,typeof t!="symbol"?t+"":t,n);import{e as x,j as e}from"./vendor-DE_-CLIE.js";import{_ as P,H as fe,Q as ye,a2 as ge,N as O,I as be,t as se,a1 as ne,L as re,v as je,s as we,a0 as I,Z as L,d as Ne,a8 as ke,J as ve,z as _e,M as Se,ac as ae,a7 as g,A as Ce,a3 as Me,a9 as Ee,$ as $e,B as Te,u as oe,c as Ae,C as Ie,G as Pe,a5 as Re,D as De,a as qe}from"./main-
|
|
1
|
+
var pe=Object.defineProperty;var he=(s,t,n)=>t in s?pe(s,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):s[t]=n;var $=(s,t,n)=>he(s,typeof t!="symbol"?t+"":t,n);import{e as x,j as e}from"./vendor-DE_-CLIE.js";import{_ as P,H as fe,Q as ye,a2 as ge,N as O,I as be,t as se,a1 as ne,L as re,v as je,s as we,a0 as I,Z as L,d as Ne,a8 as ke,J as ve,z as _e,M as Se,ac as ae,a7 as g,A as Ce,a3 as Me,a9 as Ee,$ as $e,B as Te,u as oe,c as Ae,C as Ie,G as Pe,a5 as Re,D as De,a as qe}from"./main-C6czI38s.js";import{g as Ue}from"./workerType-Bd-zteMi.js";import{D as ie,a as le,c as ce,d as de,b as Fe,S as Oe}from"./SessionVisibilityBadge-Bkv-o3zy.js";import{U as Le}from"./UserSearchInput-DHCklRIF.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as t}from"./vendor-DE_-CLIE.js";import{_ as l,R as c,g as d,f as g,X as u,Z as o,T as x,r as f,O as m,U as p}from"./main-
|
|
1
|
+
import{j as t}from"./vendor-DE_-CLIE.js";import{_ as l,R as c,g as d,f as g,X as u,Z as o,T as x,r as f,O as m,U as p}from"./main-C6czI38s.js";/**
|
|
2
2
|
* @license lucide-react v0.555.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as v,a7 as t}from"./main-
|
|
1
|
+
import{e as r,j as e}from"./vendor-DE_-CLIE.js";import{ab as v,a7 as t}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function q({onSuccess:p,onAlreadyDone:b}){const{setup:f}=v(),[n,h]=r.useState(""),[l,y]=r.useState(""),[a,g]=r.useState(""),[d,w]=r.useState(""),[i,o]=r.useState(""),[c,m]=r.useState(!1),j=async s=>{if(s.preventDefault(),o(""),a.length<8){o(t("auth.setup.passwordTooShort"));return}if(a!==d){o(t("auth.setup.passwordMismatch"));return}m(!0);try{await f(n,l,a),p()}catch(x){const u=x instanceof Error?x.message:"Setup failed";if(u.includes("already")||u.includes("409")){b();return}o(u)}finally{m(!1)}};return e.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-0 px-4",children:e.jsxs("div",{className:"w-full max-w-sm space-y-6",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold text-text-primary",children:t("auth.setup.title")}),e.jsx("p",{className:"mt-2 text-sm text-text-muted",children:t("auth.setup.description")})]}),e.jsxs("form",{onSubmit:j,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.apiKey")}),e.jsx("input",{type:"password",value:n,onChange:s=>h(s.target.value),required:!0,autoComplete:"off",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.username")}),e.jsx("input",{type:"text",value:l,onChange:s=>y(s.target.value),required:!0,autoComplete:"username",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.password")}),e.jsx("input",{type:"password",value:a,onChange:s=>g(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-1 block text-sm font-medium text-text-secondary",children:t("auth.setup.confirmPassword")}),e.jsx("input",{type:"password",value:d,onChange:s=>w(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"})]}),i&&e.jsx("p",{className:"text-sm text-status-error",children:i}),e.jsx("button",{type:"submit",disabled:c,className:"w-full rounded-lg bg-brand px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-light disabled:cursor-not-allowed disabled:opacity-50",children:c?t("common.loading"):t("auth.setup.submit")})]})]})})}export{q as Setup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{K as m,b as h}from"./main-
|
|
1
|
+
import{e as d,j as e}from"./vendor-DE_-CLIE.js";import{K as m,b as h}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function j(){const[t,r]=d.useState("loading"),[i,a]=d.useState(""),l=(typeof window<"u"?window.location.pathname:"").match(/\/code\/s\/([^/?]+)/),o=l?l[1]:null;return d.useEffect(()=>{if(!o){r("invalid"),a("Share link is invalid — no token found.");return}if(!o.startsWith("shr_")){r("invalid"),a("Invalid share token format.");return}let n=!1;async function c(){try{const s=await m(o);if(n)return;window.location.href=`/code/${s.id}`}catch(s){if(n)return;s instanceof h?s.status===401&&s.message.toLowerCase().includes("expired")?(r("expired"),a("This share has expired.")):s.status===404?s.message.toLowerCase().includes("session")?(r("not_found"),a("Session not found.")):(r("invalid"),a("Share not found or has been revoked.")):s.status===403?(r("invalid"),a("You do not have permission to access this share.")):(r("error"),a(s.message||"Failed to resolve share.")):(r("error"),a(s instanceof Error?s.message:"Failed to resolve share."))}}return c(),()=>{n=!0}},[o]),d.useEffect(()=>{if(t!=="loading"&&t!=="error"){const n=setTimeout(()=>{window.location.href="/code"},3e3);return()=>clearTimeout(n)}},[t]),t==="loading"?e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-muted",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"animate-spin h-8 w-8 border-2 border-brand border-t-transparent rounded-full mx-auto mb-3"}),e.jsx("p",{children:"Resolving share link..."})]})}):e.jsx("div",{className:"flex h-screen items-center justify-center bg-surface-0 text-text-primary",children:e.jsxs("div",{className:"text-center max-w-md px-4",children:[t==="expired"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Share Expired"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share has expired."})]}),t==="invalid"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Invalid Share"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"This share link is invalid or has been revoked."})]}),t==="not_found"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Not Found"}),e.jsx("p",{className:"text-text-muted mb-4",children:i||"The session could not be found."})]}),t==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("h2",{className:"font-display text-xl font-semibold mb-2",children:"Error"}),e.jsx("p",{className:"text-status-error mb-4",children:i})]}),e.jsx("a",{href:"/code",className:"text-brand hover:underline",children:"← Back to Dashboard"})]})})}export{j as ShareLanding};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{ac as f,ad as y,a7 as r}from"./main-
|
|
1
|
+
import{e as a,j as e}from"./vendor-DE_-CLIE.js";import{ac as f,ad as y,a7 as r}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function S(){f();const{createTeam:u}=y(),[o,p]=a.useState(""),[s,c]=a.useState(""),[i,b]=a.useState(""),[m,l]=a.useState(null),[d,x]=a.useState(!1),h=t=>{p(t),s||c(t.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-"))},g=async t=>{t.preventDefault(),l(null),x(!0);try{const n=await u({name:o,slug:s,description:i||void 0});window.location.href=`/teams/${n.slug}`}catch(n){l(n instanceof Error?n.message:"Failed to create team")}finally{x(!1)}};return e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsx("h1",{className:"mb-10 font-display text-2xl font-semibold tracking-tight text-text-primary",children:r("team.create.title")}),e.jsxs("form",{onSubmit:g,className:"max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.name")}),e.jsx("input",{id:"name",type:"text",required:!0,value:o,onChange:t=>h(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"Engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.nameHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"slug",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.slug")}),e.jsx("input",{id:"slug",type:"text",required:!0,value:s,onChange:t=>c(t.target.value),pattern:"^[a-z0-9-]{3,32}$",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",placeholder:"engineering"}),e.jsx("p",{className:"mt-1.5 text-xs text-text-muted",children:r("team.create.slugHint")})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:r("team.create.description")}),e.jsx("textarea",{id:"description",value:i,onChange:t=>b(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),m&&e.jsx("p",{className:"text-sm text-destructive",children:m}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:r("common.cancel")}),e.jsx("button",{type:"submit",disabled:d||!o||!s,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:d?r("common.creating"):r("team.create.submit")})]})]})]})})}export{S as TeamCreate};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{_ as H,w as T,ac as P,a7 as i,d as O,X as G,t as I,F as W,W as z,V as q,ab as V,S as X,Z as Y,h as Z,m as J,P as K,i as Q,k as ee,j as M,l as te,v as se}from"./main-C6czI38s.js";import{U as ae}from"./UserSearchInput-DHCklRIF.js";import{C as D}from"./copy-B2vFSPoy.js";import{g as ne}from"./workerType-Bd-zteMi.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";/**
|
|
2
|
+
* @license lucide-react v0.555.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const re=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]],ie=H("user-plus",re);function B(a){const[m,r]=n.useState([]),[N,j]=n.useState(!1),c=n.useCallback(async()=>{if(a){j(!0);try{const u=await T("GET",`/web/teams/${a}/members`);r(u)}catch{r([])}finally{j(!1)}}},[a]);n.useEffect(()=>{c()},[c]);const p=n.useCallback(async(u,f)=>{await T("POST",`/web/teams/${a}/members`,{userId:u,role:f}),await c()},[a,c]),x=n.useCallback(async u=>{await T("DELETE",`/web/teams/${a}/members/${u}`),await c()},[a,c]),l=n.useCallback(async(u,f)=>{await T("PATCH",`/web/teams/${a}/members/${u}`,{role:f}),await c()},[a,c]);return{members:m,isLoading:N,addMember:p,removeMember:x,updateRole:l,refetch:c}}function oe(a){const[m,r]=n.useState([]),N=n.useCallback(async c=>{if(!a)return null;const p=await T("POST",`/web/teams/${a}/invitations`,c);return r(x=>[...x,p]),p},[a]),j=n.useCallback(async c=>{a&&(await T("DELETE",`/web/teams/${a}/invitations/${c}`),r(p=>p.filter(x=>x.token!==c)))},[a]);return{invitations:m,createInvitation:N,revokeInvitation:j}}function ce({teamId:a,canManage:m}){P();const{invitations:r,createInvitation:N,revokeInvitation:j}=oe(a),{addMember:c}=B(a),[p,x]=n.useState(!1),[l,u]=n.useState(null),[f,E]=n.useState("member"),[d,g]=n.useState(!1),[y,b]=n.useState("member"),[v,L]=n.useState(null),[$,_]=n.useState(!1),[s,t]=n.useState(!1),[h,w]=n.useState(!1),S=async()=>{x(!0);try{const o=await N({role:f,expiresIn:86400,maxUses:5});o&&u(o.token||o.inviteToken||null)}catch{}finally{x(!1)}},R=async()=>{if(!l)return;const o=`${window.location.origin}/join?invite=${l}`;let k=!1;try{navigator.clipboard&&window.isSecureContext&&(await navigator.clipboard.writeText(o),k=!0)}catch{}if(!k){const C=document.createElement("textarea");C.value=o,C.style.position="fixed",C.style.top="0",C.style.opacity="0",document.body.appendChild(C),C.focus(),C.select(),C.setSelectionRange(0,o.length);try{k=document.execCommand("copy")}catch{k=!1}document.body.removeChild(C)}k?(w(!1),t(!0),setTimeout(()=>t(!1),2e3)):(t(!1),w(!0),setTimeout(()=>w(!1),4e3))},A=async o=>{_(!0),L(null);try{await c(o,y),g(!1)}catch(k){L(k instanceof Error?k.message:"Failed to add user")}finally{_(!1)}};return e.jsxs("div",{className:"space-y-5",children:[m&&e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("select",{className:"rounded-md border border-border bg-surface-2 px-2.5 py-1.5 text-xs text-text-primary focus:border-accent focus:outline-none",value:f,onChange:o=>E(o.target.value),children:[e.jsx("option",{value:"member",children:i("invitation.member")}),e.jsx("option",{value:"admin",children:i("invitation.admin")})]}),e.jsx("button",{type:"button",onClick:S,disabled:p,className:"rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-accent/90 disabled:opacity-50",children:p?i("invitation.creating"):i("invitation.create")}),e.jsxs("button",{type:"button",onClick:()=>g(!d),className:"inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-surface-2",title:i("invitation.addExistingHint"),children:[e.jsx(ie,{className:"h-3.5 w-3.5"}),i("invitation.addExisting")]})]}),d&&m&&e.jsxs("div",{className:"space-y-3 rounded border border-border bg-surface-2 p-3",children:[e.jsx("p",{className:"text-xs text-text-muted",children:i("invitation.addExistingHint")}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs("select",{className:"rounded border border-border bg-surface-1 px-2 py-1.5 text-sm",value:y,onChange:o=>b(o.target.value),children:[e.jsx("option",{value:"member",children:i("invitation.member")}),e.jsx("option",{value:"admin",children:i("invitation.admin")})]})}),v&&e.jsx("p",{className:"text-xs text-destructive",children:v}),e.jsx(ae,{onSelect:A,actionDisabled:$,placeholder:i("invitation.searchUser")})]}),l&&e.jsxs("div",{className:"space-y-1.5 rounded border border-accent/40 bg-accent/5 p-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"flex-1 text-xs text-text-primary break-all",children:`${window.location.origin}/join?invite=${l}`}),e.jsx("button",{type:"button",onClick:R,className:s?"text-status-active":"text-text-muted hover:text-text-primary",title:s?i("share.copied"):i("share.copy"),children:s?e.jsx(O,{className:"h-4 w-4"}):e.jsx(D,{className:"h-4 w-4"})}),e.jsx("button",{type:"button",onClick:()=>u(null),className:"text-text-muted hover:text-text-primary",children:e.jsx(G,{className:"h-4 w-4"})})]}),s&&e.jsx("p",{className:"text-xs text-status-active",children:i("share.copied")}),h&&e.jsx("p",{className:"text-xs text-status-error",children:i("share.copyFailed")})]}),r.length>0&&e.jsx("ul",{className:"space-y-2",children:r.map(o=>e.jsxs("li",{className:"flex items-center justify-between rounded border border-border/60 bg-surface-2 p-2 text-sm",children:[e.jsxs("span",{className:"text-text-muted",children:[o.role," — expires ",new Date(o.expiresAt).toLocaleDateString()]}),m&&e.jsx("button",{type:"button",onClick:()=>j(o.token),className:"text-sm text-destructive hover:underline",children:i("invitation.revoke")})]},o.token))})]})}function le({teamId:a,canManage:m}){const[r,N]=n.useState([]),[j,c]=n.useState(!0),[p,x]=n.useState(null),[l,u]=n.useState(""),[f,E]=n.useState(null),[d,g]=n.useState(!1),y=async()=>{try{const s=await W();N(s||[])}catch(s){x(s instanceof Error?s.message:"Failed to load environments")}finally{c(!1)}};n.useEffect(()=>{y()},[]);const b=n.useMemo(()=>r.filter(s=>s.team_id===a),[r,a]),v=n.useMemo(()=>r.filter(s=>!s.team_id),[r]),L=async()=>{if(l){E(null);try{await q(l,a),u(""),await y()}catch(s){E(s instanceof Error?s.message:"Failed to link environment")}}},$=async s=>{if(window.confirm("Unlink this environment from the team? It will revert to personal scope.")){E(null);try{await z(a,s),await y()}catch(t){E(t instanceof Error?t.message:"Failed to unlink environment")}}},_=async()=>{const s=`slz rc --team-id ${a}`;try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(s),g(!0),setTimeout(()=>g(!1),2e3);return}}catch{}const t=document.createElement("textarea");t.value=s,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select();try{document.execCommand("copy"),g(!0),setTimeout(()=>g(!1),2e3)}catch{}document.body.removeChild(t)};return j?e.jsx("p",{className:"text-sm text-text-muted",children:"Loading environments..."}):p?e.jsx("p",{className:"text-sm text-destructive",children:p}):e.jsxs("div",{className:"space-y-8",children:[e.jsx("ul",{className:"space-y-3",children:b.length===0?e.jsx("li",{className:"text-sm text-text-muted",children:"No environments linked to this team yet."}):b.map(s=>{const t=ne(s.worker_type);return e.jsxs("li",{className:"text-sm",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text-primary",children:s.machine_name||s.id}),e.jsx("span",{className:`rounded-full px-2 py-0.5 text-xs font-medium ${t.colorClass}`,children:t.shortLabel}),e.jsx(I,{status:s.status}),m&&e.jsx("button",{type:"button",onClick:()=>$(s.id),className:"ml-2 text-xs text-text-muted underline-offset-2 transition-colors hover:text-destructive hover:underline",children:"Unlink"})]}),e.jsxs("div",{className:"mt-1 font-mono text-xs text-text-muted",children:[s.directory||""," ",s.branch?`· ${s.branch}`:""]})]},s.id)})}),m&&e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm text-text-muted",children:"Register a new worker to this team:"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("code",{className:"rounded-md border border-border bg-surface-2 px-3 py-1.5 font-mono text-xs text-text-primary",children:["slz rc --team-id ",a]}),e.jsx("button",{type:"button",onClick:_,className:"text-text-muted transition-colors hover:text-text-primary","aria-label":"Copy command",children:e.jsx(D,{className:"h-3.5 w-3.5"})}),d&&e.jsx("span",{className:"text-xs text-status-active",children:"Copied"})]})]}),v.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"text-sm text-text-muted",children:"Link an existing personal environment:"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("select",{value:l,onChange:s=>u(s.target.value),className:"max-w-md rounded-md border border-border bg-surface-2 px-3 py-1.5 text-sm text-text-primary focus:border-accent focus:outline-none",children:[e.jsx("option",{value:"",children:"Select environment..."}),v.map(s=>e.jsxs("option",{value:s.id,children:[s.machine_name||s.id," ",s.branch?`· ${s.branch}`:""]},s.id))]}),e.jsx("button",{type:"button",onClick:L,disabled:!l,className:"rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:"Link"})]})]}),f&&e.jsx("p",{className:"text-sm text-destructive",children:f})]})]})}async function de(a){try{const m=a.startsWith("team_")?`/web/teams/${a}`:`/web/teams/by-slug/${a}`;return await T("GET",m)}catch{return null}}const me={owner:"team.member.roleOwner",admin:"team.member.roleAdmin",member:"team.member.roleMember"},U={owner:"border-brand/30 bg-brand/10 text-brand",admin:"border-accent/30 bg-accent/10 text-accent",member:"border-border/60 bg-surface-2 text-text-muted"};function F(a){return i(me[a]||"team.member.roleMember")}function ve(){P();const a=window.location.pathname.split("/"),m=a[a.length-1]||"",[r,N]=n.useState(null),[j,c]=n.useState(!0),[p,x]=n.useState(!1),{members:l,isLoading:u,updateRole:f,removeMember:E}=B((r==null?void 0:r.id)||null),{user:d}=V(),[g,y]=n.useState("");if(n.useEffect(()=>{m&&(c(!0),de(m).then(t=>{N(t),c(!1)}))},[m]),j)return e.jsx("div",{className:"px-6 py-16 text-sm text-text-muted",children:"Loading..."});if(!r)return e.jsx("div",{className:"px-6 py-16 sm:px-10",children:e.jsxs("div",{className:"max-w-3xl",children:[e.jsx("p",{className:"text-text-muted",children:"Team not found."}),e.jsx("a",{href:"/teams",className:"text-accent hover:underline",children:"Back to teams"})]})});const b=l.find(t=>t.user_id===(d==null?void 0:d.userId)),v=(d==null?void 0:d.role)==="admin"||(b==null?void 0:b.role)==="owner"||(b==null?void 0:b.role)==="admin",L=(d==null?void 0:d.role)==="admin"||(b==null?void 0:b.role)==="owner",$=async()=>{const t=r.id;try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(t),x(!0),setTimeout(()=>x(!1),2e3);return}}catch{}const h=document.createElement("textarea");h.value=t,h.style.position="fixed",h.style.opacity="0",document.body.appendChild(h),h.select();try{document.execCommand("copy"),x(!0),setTimeout(()=>x(!1),2e3)}catch{}document.body.removeChild(h)},_=async(t,h)=>{if(t.role!==h){y("");try{await f(t.user_id,h)}catch(w){y(w instanceof Error?w.message:i("team.member.updateFailed"))}}},s=async t=>{const h=t.username||t.user_id;if(window.confirm(i("team.member.removeConfirm").replace("{name}",h))){y("");try{await E(t.user_id)}catch(S){y(S instanceof Error?S.message:i("team.member.updateFailed"))}}};return e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:r.name}),e.jsxs("p",{className:"mt-2 font-mono text-xs text-text-muted",children:["/",r.slug]}),r.description&&e.jsx("p",{className:"mt-5 max-w-2xl text-sm leading-relaxed text-text-muted",children:r.description}),e.jsxs("div",{className:"mt-4 flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-xs text-text-muted",children:r.id}),e.jsx("button",{type:"button",onClick:$,className:"text-text-muted transition-colors hover:text-text-primary","aria-label":"Copy team ID",children:e.jsx(D,{className:"h-3.5 w-3.5"})}),p&&e.jsx("span",{className:"text-xs text-status-active",children:"Copied"}),v&&e.jsx("a",{href:`/teams/${r.slug}/settings`,className:"ml-1 text-text-muted transition-colors hover:text-text-primary","aria-label":"Team settings",title:"Team settings",children:e.jsx(X,{className:"h-4 w-4"})})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("div",{className:"mb-6 flex items-baseline justify-between",children:e.jsxs("h2",{className:"text-sm font-medium text-text-primary",children:[i("team.detail.members")," (",l.length,")"]})}),g&&e.jsx("div",{className:"mb-4 rounded-md bg-destructive/10 px-3 py-2 text-sm text-status-error",children:g}),u?e.jsx("p",{className:"text-sm text-text-muted",children:"Loading members..."}):l.length===0?e.jsx("p",{className:"text-sm text-text-muted",children:"No members."}):e.jsx("ul",{className:"space-y-2",children:l.map(t=>{const h=t.user_id===(d==null?void 0:d.userId),w=t.role==="owner"||t.role==="admin",S=v&&(!w||L),R=S&&!(t.role==="owner"&&l.filter(o=>o.role==="owner").length<=1),A=["owner","admin","member"];return e.jsxs("li",{className:"flex items-center justify-between gap-3 rounded-xl border border-border bg-surface-1 px-4 py-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-text-primary",children:t.username||t.user_id}),h&&e.jsx("span",{className:"text-xs text-text-muted",children:i("team.member.you")}),e.jsx("span",{className:Y("shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-medium",U[t.role]||U.member),children:F(t.role)})]}),e.jsx("div",{className:"mt-0.5 truncate font-mono text-xs text-text-muted",children:t.user_id})]}),v&&e.jsxs(Z,{children:[e.jsx(J,{asChild:!0,children:e.jsx("button",{type:"button",disabled:!S,className:"shrink-0 rounded-md p-1.5 text-text-muted transition-colors hover:bg-surface-2 hover:text-text-primary disabled:opacity-40 disabled:hover:bg-transparent","aria-label":i("team.member.changeRole"),title:i("team.member.changeRole"),children:e.jsx(K,{className:"h-4 w-4"})})}),e.jsxs(Q,{align:"end",className:"w-48",children:[e.jsx(ee,{className:"text-xs text-text-muted",children:i("team.member.changeRole")}),A.map(o=>e.jsxs(M,{onSelect:()=>_(t,o),className:"flex items-center justify-between",children:[e.jsx("span",{children:F(o)}),t.role===o&&e.jsx(O,{className:"h-3.5 w-3.5 text-brand"})]},o)),e.jsx(te,{}),e.jsxs(M,{variant:"destructive",disabled:!R,onSelect:()=>s(t),className:"flex items-center gap-2",children:[e.jsx(se,{className:"h-3.5 w-3.5"}),e.jsx("span",{children:i("team.member.remove")})]})]})]})]},t.user_id)})})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-6 text-sm font-medium text-text-primary",children:i("team.detail.environments")}),e.jsx(le,{teamId:r.id,canManage:v})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-6 text-sm font-medium text-text-primary",children:i("team.detail.invitations")}),e.jsx(ce,{teamId:r.id,canManage:v})]})]})}export{ve as TeamDetail};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./vendor-DE_-CLIE.js";import{ad as l,n as a}from"./main-
|
|
1
|
+
import{j as e}from"./vendor-DE_-CLIE.js";import{ad as l,n as a}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function c(){const{myTeams:t,isLoading:i}=l();return i?e.jsx("div",{className:"px-6 py-20 sm:px-10",children:e.jsxs("div",{className:"max-w-4xl",children:[e.jsx("div",{className:"h-8 w-32 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"mt-12 space-y-10",children:[0,1,2].map(s=>e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"h-6 w-48 animate-pulse rounded bg-surface-2"}),e.jsx("div",{className:"h-4 w-32 animate-pulse rounded bg-surface-2"})]},s))})]})}):e.jsxs("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-3xl font-semibold tracking-tight text-text-primary sm:text-4xl",children:"Teams"}),e.jsx("p",{className:"mt-3 text-sm text-text-muted",children:t.length===0?"Create your first team to start collaborating.":`${t.length} ${t.length===1?"team":"teams"}`})]}),t.length===0?e.jsx("div",{className:"py-8",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md bg-accent px-5 py-2.5 text-sm font-medium text-white transition-all hover:bg-accent/90 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"Create team"]})}):e.jsx("ul",{className:"space-y-10",children:t.map(s=>e.jsx("li",{children:e.jsxs("a",{href:`/teams/${s.slug}`,className:"group block",children:[e.jsxs("div",{className:"flex items-baseline gap-4",children:[e.jsx("h2",{className:"font-display text-xl font-medium tracking-tight text-text-primary transition-colors group-hover:text-accent",children:s.name}),e.jsxs("span",{className:"font-mono text-xs text-text-muted",children:["/",s.slug]})]}),s.description?e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-relaxed text-text-muted",children:s.description}):e.jsx("p",{className:"mt-2 text-sm italic text-text-muted/60",children:"No description"})]})},s.id))}),t.length>0&&e.jsx("div",{className:"mt-16",children:e.jsxs("a",{href:"/teams/new",className:"inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-text-primary transition-all hover:bg-surface-2 active:translate-y-px",children:[e.jsx(a,{className:"h-4 w-4"}),"New team"]})})]})}export{c as TeamList};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{w as c}from"./main-
|
|
1
|
+
import{e as n,j as e}from"./vendor-DE_-CLIE.js";import{w as c}from"./main-C6czI38s.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";async function j(s){try{const r=s.startsWith("team_")?`/web/teams/${s}`:`/web/teams/by-slug/${s}`;return await c("GET",r)}catch{return null}}async function w(s,r){await c("PATCH",`/web/teams/${s}`,r)}async function N(s){await c("DELETE",`/web/teams/${s}`)}function k(){const s=window.location.pathname.split("/"),r=s[s.length-2]||"",[a,h]=n.useState(null),[b,y]=n.useState(!0),[i,m]=n.useState(""),[l,d]=n.useState(""),[u,o]=n.useState(null),[x,p]=n.useState(!1);n.useEffect(()=>{r&&j(r).then(t=>{t&&(h(t),m(t.name),d(t.description||"")),y(!1)})},[r]);const g=async t=>{if(t.preventDefault(),!!a){o(null),p(!0);try{await w(a.id,{name:i,description:l}),window.location.href=`/teams/${a.slug}`}catch(f){o(f instanceof Error?f.message:"Failed to update")}finally{p(!1)}}},v=async()=>{if(a&&window.confirm("Delete this team? Environments must be transferred first."))try{await N(a.id),window.location.href="/teams"}catch(t){o(t instanceof Error?t.message:"Failed to delete")}};return b?e.jsx("div",{className:"flex items-center justify-center py-12 text-text-muted",children:"Loading..."}):a?e.jsx("div",{className:"px-6 py-12 sm:px-10 sm:py-16",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-12",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:a.name}),e.jsxs("p",{className:"mt-1 font-mono text-xs text-text-muted",children:["/",a.slug]})]}),e.jsxs("form",{onSubmit:g,className:"mb-16 max-w-md space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"name",className:"block text-sm font-medium text-text-primary mb-2",children:"Team Name"}),e.jsx("input",{id:"name",type:"text",required:!0,value:i,onChange:t=>m(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"description",className:"block text-sm font-medium text-text-primary mb-2",children:"Description"}),e.jsx("textarea",{id:"description",value:l,onChange:t=>d(t.target.value),className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",rows:3})]}),u&&e.jsx("p",{className:"text-sm text-destructive",children:u}),e.jsxs("div",{className:"flex gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:()=>window.history.back(),className:"rounded-md border border-border px-4 py-2 text-sm text-text-primary hover:bg-surface-2 transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:x||!i,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90 disabled:opacity-50 transition-colors",children:x?"Saving...":"Save Changes"})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-3 text-sm font-medium text-destructive",children:"Delete team"}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Deleting a team requires all environments to be transferred first."}),e.jsx("button",{type:"button",onClick:v,className:"rounded-md border border-destructive/60 px-4 py-2 text-sm font-medium text-destructive hover:bg-destructive/10 transition-colors",children:"Delete Team"})]})]})}):e.jsxs("div",{className:"mx-auto max-w-lg px-4 py-8",children:[e.jsx("p",{className:"text-text-muted",children:"Team not found."}),e.jsx("a",{href:"/teams",className:"text-accent hover:underline",children:"Back to teams"})]})}export{k as TeamSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{ac as v,a7 as l,w as S}from"./main-
|
|
1
|
+
import{e as a,j as t}from"./vendor-DE_-CLIE.js";import{ac as v,a7 as l,w as S}from"./main-C6czI38s.js";function C({onSelect:o,excludeUserIds:x=[],placeholder:u,actionLabel:m,actionDisabled:h=!1,className:p}){v();const[n,c]=a.useState(""),[b,s]=a.useState([]),[i,d]=a.useState(!1),f=async e=>{if(c(e),e.trim().length<2){s([]);return}d(!0);try{const N=await S("GET",`/web/users/search?q=${encodeURIComponent(e.trim())}`);s(N)}catch{s([])}finally{d(!1)}},y=e=>{o(e),c(""),s([])},r=b.filter(e=>!x.includes(e.id)),g=m??l("invitation.add"),j=u??l("invitation.searchUser");return t.jsxs("div",{className:p,children:[t.jsx("input",{type:"text",value:n,onChange:e=>f(e.target.value),placeholder:j,className:"w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-brand focus:outline-none"}),i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"Searching..."}),r.length>0&&t.jsx("ul",{className:"mt-2 divide-y divide-border rounded border border-border bg-surface-1",children:r.map(e=>t.jsxs("li",{className:"flex items-center justify-between px-3 py-2 text-sm",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsx("div",{className:"text-text-primary",children:e.username}),t.jsx("div",{className:"truncate font-mono text-xs text-text-muted",children:e.id})]}),t.jsx("button",{type:"button",onClick:()=>y(e.id),disabled:h,className:"rounded bg-accent px-2 py-1 text-xs text-white hover:bg-accent/90 disabled:opacity-50",children:g})]},e.id))}),n.trim().length>=2&&r.length===0&&!i&&t.jsx("p",{className:"mt-1 text-xs text-text-muted",children:"No users found."})]})}export{C as U};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as o,j as e}from"./vendor-DE_-CLIE.js";import{ab as C,ac as P,a7 as t,a6 as S}from"./main-
|
|
1
|
+
import{e as o,j as e}from"./vendor-DE_-CLIE.js";import{ab as C,ac as P,a7 as t,a6 as S}from"./main-C6czI38s.js";import{C as k}from"./copy-B2vFSPoy.js";import"./shiki-mEP5vQQu.js";import"./motion-BILbV7YQ.js";function L(){const{user:n,logout:f}=C(),w=P(),[l,u]=o.useState(""),[c,m]=o.useState(""),[x,p]=o.useState(""),[h,b]=o.useState(""),[g,a]=o.useState(""),[y,d]=o.useState(!1);if(!n)return null;const j=async()=>{const s=n.userId;try{if(navigator.clipboard&&window.isSecureContext){await navigator.clipboard.writeText(s),d(!0),setTimeout(()=>d(!1),2e3);return}}catch{}const r=document.createElement("textarea");r.value=s,r.style.position="fixed",r.style.opacity="0",document.body.appendChild(r),r.select();try{document.execCommand("copy"),d(!0),setTimeout(()=>d(!1),2e3)}catch{}document.body.removeChild(r)},N=async s=>{if(s.preventDefault(),a(""),b(""),c.length<8){a(t("auth.setup.passwordTooShort"));return}if(c!==x){a(t("auth.setup.passwordMismatch"));return}try{const r=await fetch("/web/auth/change-password",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json","X-Requested-With":"XMLHttpRequest"},body:JSON.stringify({currentPassword:l,newPassword:c})});if(!r.ok){const i=await r.json();throw new Error(i.error||t("user.settings.changeFailed"))}b(t("user.settings.passwordChanged")),u(""),m(""),p("")}catch(r){const i=r instanceof Error?r.message:t("user.settings.changeFailed");a(i)}},v=async()=>{try{if(!(await fetch("/web/auth/logout-all",{method:"POST",credentials:"include",headers:{"X-Requested-With":"XMLHttpRequest"}})).ok){a(t("common.error"));return}await f()}catch{a(t("common.error"))}};return e.jsx("div",{className:"px-6 py-16 sm:px-10 sm:py-20",children:e.jsxs("div",{children:[e.jsxs("header",{className:"mb-16",children:[e.jsx("h1",{className:"font-display text-2xl font-semibold tracking-tight text-text-primary",children:n.username}),e.jsxs("div",{className:"mt-3 flex items-center gap-2",children:[e.jsx("code",{className:"font-mono text-xs text-text-muted",children:n.userId}),e.jsx("button",{type:"button",onClick:j,className:"text-text-muted transition-colors hover:text-text-primary","aria-label":"Copy user ID",children:e.jsx(k,{className:"h-3.5 w-3.5"})}),y&&e.jsx("span",{className:"text-xs text-status-active",children:t("share.copied")}),e.jsx("span",{className:"text-text-muted/40",children:"·"}),e.jsx("span",{className:"text-xs text-text-muted",children:n.role})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.language")}),e.jsxs("select",{value:w,onChange:s=>S(s.target.value),className:"rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent focus:outline-none",children:[e.jsx("option",{value:"zh",children:"中文"}),e.jsx("option",{value:"en",children:"English"})]})]}),e.jsxs("section",{className:"mb-16",children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-text-primary",children:t("user.settings.changePassword")}),e.jsxs("form",{onSubmit:N,className:"max-w-md space-y-6",children:[e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.currentPassword")}),e.jsx("input",{type:"password",value:l,onChange:s=>u(s.target.value),required:!0,autoComplete:"current-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.newPassword")}),e.jsx("input",{type:"password",value:c,onChange:s=>m(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"mb-2 block text-sm font-medium text-text-primary",children:t("user.settings.confirmNewPassword")}),e.jsx("input",{type:"password",value:x,onChange:s=>p(s.target.value),required:!0,autoComplete:"new-password",className:"w-full rounded-md border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-muted focus:border-accent focus:outline-none"})]}),g&&e.jsx("p",{className:"text-sm text-status-error",children:g}),h&&e.jsx("p",{className:"text-sm text-status-active",children:h}),e.jsx("div",{className:"pt-2",children:e.jsx("button",{type:"submit",className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-accent/90",children:t("user.settings.submit")})})]})]}),e.jsxs("section",{children:[e.jsx("h2",{className:"mb-5 text-sm font-medium text-destructive",children:t("user.settings.logoutAll")}),e.jsx("p",{className:"mb-4 text-sm text-text-muted",children:"Revoke sessions on all devices."}),e.jsx("button",{onClick:v,className:"rounded-md border border-status-error/30 px-4 py-2 text-sm font-medium text-status-error transition-colors hover:bg-status-error/10",children:t("user.settings.logoutAll")})]})]})})}export{L as UserSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{bl as ln,aO as an,H as z,b8 as w,F as G,ah as un,W as y,bd as tn,b9 as J,aI as _,c as rn,m as o,aG as on,j as sn,d as fn}from"./mermaid.core-
|
|
1
|
+
import{bl as ln,aO as an,H as z,b8 as w,F as G,ah as un,W as y,bd as tn,b9 as J,aI as _,c as rn,m as o,aG as on,j as sn,d as fn}from"./mermaid.core-aZvgg4gM.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,j,I,v,A,H,a){var q=j-l,i=I-h,n=H-v,d=a-A,u=d*q-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*q,h+u*i]}function U(l,h,j,I,v,A,H){var a=l-j,q=h-I,i=(H?A:-A)/J(a*a+q*q),n=i*q,d=-i*a,u=l+n,s=h+d,f=j+n,c=I+d,S=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,D=(g<0?-1:1)*J(on(0,T*T*R-P*P)),E=(P*g-m*D)/R,F=(-P*m-g*D)/R,b=(P*g+m*D)/R,p=(-P*m+g*D)/R,x=E-S,e=F-t,r=b-S,W=p-t;return x*x+e*e>r*r+W*W&&(E=b,F=p),{cx:E,cy:F,x01:-n,y01:-d,x11:E*(v/T-1),y11:F*(v/T-1)}}function hn(){var l=cn,h=yn,j=G(0),I=null,v=gn,A=dn,H=mn,a=null,q=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,S=rn(c-f),t=c>f;if(a||(a=n=q()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(S>tn-y)a.moveTo(s*z(f),s*w(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*z(c),u*w(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=S,D=S,E=H.apply(this,arguments)/2,F=E>y&&(I?+I.apply(this,arguments):J(u*u+s*s)),b=_(rn(s-u)/2,+j.apply(this,arguments)),p=b,x=b,e,r;if(F>y){var W=sn(F/u*w(E)),K=sn(F/s*w(E));(P-=W*2)>y?(W*=t?1:-1,R+=W,T-=W):(P=0,R=T=(f+c)/2),(D-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(D=0,m=g=(f+c)/2)}var B=s*z(m),C=s*w(m),L=u*z(T),M=u*w(T);if(b>y){var N=s*z(g),Q=s*w(g),V=u*z(R),X=u*w(R),O;if(S<an)if(O=pn(B,C,V,X,N,Q,L,M)){var Y=B-O[0],Z=C-O[1],$=N-O[0],k=Q-O[1],nn=1/w(fn((Y*$+Z*k)/(J(Y*Y+Z*Z)*J($*$+k*k)))/2),en=J(O[0]*O[0]+O[1]*O[1]);p=_(b,(u-en)/(nn-1)),x=_(b,(s-en)/(nn+1))}else p=x=0}D>y?x>y?(e=U(V,X,B,C,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<b?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(B,C),a.arc(0,0,s,m,g,!t)):a.moveTo(B,C),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(B,C,V,X,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<b?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[z(d)*n,w(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:G(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:G(+n),i):h},i.cornerRadius=function(n){return arguments.length?(j=typeof n=="function"?n:G(+n),i):j},i.padRadius=function(n){return arguments.length?(I=n==null?null:typeof n=="function"?n:G(+n),i):I},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:G(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:G(+n),i):A},i.padAngle=function(n){return arguments.length?(H=typeof n=="function"?n:G(+n),i):H},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|