@shaykec/bridge 0.4.20 → 0.4.21
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/README.md +2 -2
- package/canvas-dist/assets/{_basePickBy-CWoeT3J7.js → _basePickBy-BovdgFIW.js} +1 -1
- package/canvas-dist/assets/_basePickBy-BtkHe2u_.js +1 -0
- package/canvas-dist/assets/_basePickBy-C0936578.js +1 -0
- package/canvas-dist/assets/_basePickBy-CE2Qvuh7.js +1 -0
- package/canvas-dist/assets/_basePickBy-DV6sX4CG.js +1 -0
- package/canvas-dist/assets/_basePickBy-DZX6ZNMT.js +1 -0
- package/canvas-dist/assets/{_baseUniq-Dtuvtwtn.js → _baseUniq-B7dN28TM.js} +1 -1
- package/canvas-dist/assets/_baseUniq-Cl23fCdR.js +1 -0
- package/canvas-dist/assets/_baseUniq-CojWFw7B.js +1 -0
- package/canvas-dist/assets/_baseUniq-DA640BJl.js +1 -0
- package/canvas-dist/assets/_baseUniq-Ds-62CCj.js +1 -0
- package/canvas-dist/assets/_baseUniq-KG7SRw9H.js +1 -0
- package/canvas-dist/assets/{arc-YYWnrNJU.js → arc-7E9FFKlC.js} +1 -1
- package/canvas-dist/assets/arc-BSMfRZtt.js +1 -0
- package/canvas-dist/assets/arc-C6nT-koR.js +1 -0
- package/canvas-dist/assets/arc-D_fOnjmo.js +1 -0
- package/canvas-dist/assets/arc-Khfvgkr3.js +1 -0
- package/canvas-dist/assets/arc-ieS-i42x.js +1 -0
- package/canvas-dist/assets/{architectureDiagram-VXUJARFQ-CegbV-RR.js → architectureDiagram-VXUJARFQ-DF4t6GQD.js} +1 -1
- package/canvas-dist/assets/architectureDiagram-VXUJARFQ-DXgSlsio.js +36 -0
- package/canvas-dist/assets/architectureDiagram-VXUJARFQ-DiomxPB4.js +36 -0
- package/canvas-dist/assets/architectureDiagram-VXUJARFQ-DnFaxvXD.js +36 -0
- package/canvas-dist/assets/architectureDiagram-VXUJARFQ-Dt38C0LJ.js +36 -0
- package/canvas-dist/assets/architectureDiagram-VXUJARFQ-egbtMwua.js +36 -0
- package/canvas-dist/assets/{blockDiagram-VD42YOAC-C2e_j6ry.js → blockDiagram-VD42YOAC-CUNKQd-b.js} +1 -1
- package/canvas-dist/assets/blockDiagram-VD42YOAC-D-NiLXxd.js +122 -0
- package/canvas-dist/assets/blockDiagram-VD42YOAC-Dx6Dh9gg.js +122 -0
- package/canvas-dist/assets/blockDiagram-VD42YOAC-_r-PmlQy.js +122 -0
- package/canvas-dist/assets/blockDiagram-VD42YOAC-bvYKZLMc.js +122 -0
- package/canvas-dist/assets/blockDiagram-VD42YOAC-l85QT9Ig.js +122 -0
- package/canvas-dist/assets/{c4Diagram-YG6GDRKO-rIpnAud9.js → c4Diagram-YG6GDRKO-BWKCTyQi.js} +1 -1
- package/canvas-dist/assets/c4Diagram-YG6GDRKO-CbXs2xzC.js +10 -0
- package/canvas-dist/assets/c4Diagram-YG6GDRKO-CjiS-GNK.js +10 -0
- package/canvas-dist/assets/c4Diagram-YG6GDRKO-D7SnLlHp.js +10 -0
- package/canvas-dist/assets/c4Diagram-YG6GDRKO-RTTCSVf2.js +10 -0
- package/canvas-dist/assets/c4Diagram-YG6GDRKO-yvqJ_AqX.js +10 -0
- package/canvas-dist/assets/channel-CSXq7GP6.js +1 -0
- package/canvas-dist/assets/channel-CvujjGiJ.js +1 -0
- package/canvas-dist/assets/channel-D959Iony.js +1 -0
- package/canvas-dist/assets/channel-DOSwCnrB.js +1 -0
- package/canvas-dist/assets/channel-sw61LzxF.js +1 -0
- package/canvas-dist/assets/channel-vZVnNhOK.js +1 -0
- package/canvas-dist/assets/{chunk-4BX2VUAB-CpZGetnU.js → chunk-4BX2VUAB-BBjuAwXr.js} +1 -1
- package/canvas-dist/assets/chunk-4BX2VUAB-BXRNyucU.js +1 -0
- package/canvas-dist/assets/chunk-4BX2VUAB-Bgq5Z77T.js +1 -0
- package/canvas-dist/assets/chunk-4BX2VUAB-BuoMCMCr.js +1 -0
- package/canvas-dist/assets/chunk-4BX2VUAB-COD5n7vg.js +1 -0
- package/canvas-dist/assets/chunk-4BX2VUAB-K8DepKJO.js +1 -0
- package/canvas-dist/assets/{chunk-55IACEB6-L0OhcFdd.js → chunk-55IACEB6-Bic_bMrQ.js} +1 -1
- package/canvas-dist/assets/chunk-55IACEB6-DEy2QUDq.js +1 -0
- package/canvas-dist/assets/chunk-55IACEB6-Dcgbmfzg.js +1 -0
- package/canvas-dist/assets/chunk-55IACEB6-DfmuNm_E.js +1 -0
- package/canvas-dist/assets/chunk-55IACEB6-DlQRcczm.js +1 -0
- package/canvas-dist/assets/chunk-55IACEB6-p2qMY-fm.js +1 -0
- package/canvas-dist/assets/{chunk-B4BG7PRW-Cv9vsAzg.js → chunk-B4BG7PRW-BpbyxBP2.js} +1 -1
- package/canvas-dist/assets/chunk-B4BG7PRW-CCPqvPrP.js +165 -0
- package/canvas-dist/assets/chunk-B4BG7PRW-CEeDPAki.js +165 -0
- package/canvas-dist/assets/chunk-B4BG7PRW-D2UFN_2M.js +165 -0
- package/canvas-dist/assets/chunk-B4BG7PRW-DFI5h6HC.js +165 -0
- package/canvas-dist/assets/chunk-B4BG7PRW-DKOiFGMU.js +165 -0
- package/canvas-dist/assets/{chunk-DI55MBZ5-B3p1mU43.js → chunk-DI55MBZ5-BV6nHjNQ.js} +1 -1
- package/canvas-dist/assets/chunk-DI55MBZ5-CEZJmC0E.js +220 -0
- package/canvas-dist/assets/chunk-DI55MBZ5-DOZT99Ek.js +220 -0
- package/canvas-dist/assets/chunk-DI55MBZ5-DmC2LoG2.js +220 -0
- package/canvas-dist/assets/chunk-DI55MBZ5-DpkcJdZP.js +220 -0
- package/canvas-dist/assets/chunk-DI55MBZ5-fVTGx0zh.js +220 -0
- package/canvas-dist/assets/{chunk-FMBD7UC4-JCLAHw5x.js → chunk-FMBD7UC4-BOCyQpI7.js} +1 -1
- package/canvas-dist/assets/chunk-FMBD7UC4-C76FrRL8.js +15 -0
- package/canvas-dist/assets/chunk-FMBD7UC4-CAq-btWc.js +15 -0
- package/canvas-dist/assets/chunk-FMBD7UC4-CidVsej6.js +15 -0
- package/canvas-dist/assets/chunk-FMBD7UC4-DPpfskdX.js +15 -0
- package/canvas-dist/assets/chunk-FMBD7UC4-DnLtclge.js +15 -0
- package/canvas-dist/assets/{chunk-QN33PNHL-C9arKEVq.js → chunk-QN33PNHL-BclpCUi8.js} +1 -1
- package/canvas-dist/assets/chunk-QN33PNHL-DDUw8IU1.js +1 -0
- package/canvas-dist/assets/chunk-QN33PNHL-DdJFAUXw.js +1 -0
- package/canvas-dist/assets/chunk-QN33PNHL-DjV4jUn9.js +1 -0
- package/canvas-dist/assets/chunk-QN33PNHL-N-HTycqU.js +1 -0
- package/canvas-dist/assets/chunk-QN33PNHL-sd8p21DW.js +1 -0
- package/canvas-dist/assets/{chunk-QZHKN3VN-Bs1r3d9U.js → chunk-QZHKN3VN-B6mT-JkP.js} +1 -1
- package/canvas-dist/assets/chunk-QZHKN3VN-BCo8pc7x.js +1 -0
- package/canvas-dist/assets/chunk-QZHKN3VN-C8IIu6es.js +1 -0
- package/canvas-dist/assets/chunk-QZHKN3VN-D9FF492U.js +1 -0
- package/canvas-dist/assets/chunk-QZHKN3VN-DWMbUjXT.js +1 -0
- package/canvas-dist/assets/chunk-QZHKN3VN-l5FBJ77g.js +1 -0
- package/canvas-dist/assets/{chunk-TZMSLE5B-_Ye6r84Y.js → chunk-TZMSLE5B-BASt-UWt.js} +1 -1
- package/canvas-dist/assets/chunk-TZMSLE5B-BCfaZWLT.js +1 -0
- package/canvas-dist/assets/chunk-TZMSLE5B-BKIk_hBR.js +1 -0
- package/canvas-dist/assets/chunk-TZMSLE5B-C4pt-Ir8.js +1 -0
- package/canvas-dist/assets/chunk-TZMSLE5B-DwGlELvo.js +1 -0
- package/canvas-dist/assets/chunk-TZMSLE5B-jJKG-WvJ.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-B7YQfPU4.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-BZ61MaHY.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-CGseYor2.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-CKzOc99J.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-Ce_LPjwW.js +1 -0
- package/canvas-dist/assets/classDiagram-2ON5EDUG-DorPdibv.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-B7YQfPU4.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-BZ61MaHY.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-CGseYor2.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-CKzOc99J.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-Ce_LPjwW.js +1 -0
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-DorPdibv.js +1 -0
- package/canvas-dist/assets/clone-74KSto7H.js +1 -0
- package/canvas-dist/assets/clone-CJQgAYVe.js +1 -0
- package/canvas-dist/assets/clone-DLeTuhHE.js +1 -0
- package/canvas-dist/assets/clone-D_IHK_lQ.js +1 -0
- package/canvas-dist/assets/clone-DxMUv1L9.js +1 -0
- package/canvas-dist/assets/clone-UNKf_nED.js +1 -0
- package/canvas-dist/assets/{cose-bilkent-S5V4N54A-2O2oovOj.js → cose-bilkent-S5V4N54A-BTyQiCkr.js} +1 -1
- package/canvas-dist/assets/cose-bilkent-S5V4N54A-BtPAe24N.js +1 -0
- package/canvas-dist/assets/cose-bilkent-S5V4N54A-DIjE7V3m.js +1 -0
- package/canvas-dist/assets/cose-bilkent-S5V4N54A-DKL_BGvE.js +1 -0
- package/canvas-dist/assets/cose-bilkent-S5V4N54A-LZ4OsCLU.js +1 -0
- package/canvas-dist/assets/cose-bilkent-S5V4N54A-XWeJtgga.js +1 -0
- package/canvas-dist/assets/{dagre-6UL2VRFP-gRmGLrEW.js → dagre-6UL2VRFP-BJ2vcFwR.js} +1 -1
- package/canvas-dist/assets/dagre-6UL2VRFP-C1FlE5s8.js +4 -0
- package/canvas-dist/assets/dagre-6UL2VRFP-C3BWFgl6.js +4 -0
- package/canvas-dist/assets/dagre-6UL2VRFP-CUnx73Rf.js +4 -0
- package/canvas-dist/assets/dagre-6UL2VRFP-Do10BY1y.js +4 -0
- package/canvas-dist/assets/dagre-6UL2VRFP-rOZEkrsg.js +4 -0
- package/canvas-dist/assets/{diagram-PSM6KHXK-B7Li-xxw.js → diagram-PSM6KHXK-BGi_qzbq.js} +1 -1
- package/canvas-dist/assets/diagram-PSM6KHXK-C3Nv7h_j.js +24 -0
- package/canvas-dist/assets/diagram-PSM6KHXK-CsMy-r0n.js +24 -0
- package/canvas-dist/assets/diagram-PSM6KHXK-Dj8g7kGt.js +24 -0
- package/canvas-dist/assets/diagram-PSM6KHXK-Dxb1w_7r.js +24 -0
- package/canvas-dist/assets/diagram-PSM6KHXK-kVMBkEyV.js +24 -0
- package/canvas-dist/assets/{diagram-QEK2KX5R-B_NNUAm3.js → diagram-QEK2KX5R-4bsrr1WZ.js} +1 -1
- package/canvas-dist/assets/diagram-QEK2KX5R-Bv7BmKfI.js +43 -0
- package/canvas-dist/assets/diagram-QEK2KX5R-C_FLN6hv.js +43 -0
- package/canvas-dist/assets/diagram-QEK2KX5R-Csuk5L3z.js +43 -0
- package/canvas-dist/assets/diagram-QEK2KX5R-D5Aszgz4.js +43 -0
- package/canvas-dist/assets/diagram-QEK2KX5R-DX58f87l.js +43 -0
- package/canvas-dist/assets/{diagram-S2PKOQOG-NcK-KHaA.js → diagram-S2PKOQOG-1Q7hwiSd.js} +1 -1
- package/canvas-dist/assets/diagram-S2PKOQOG-Bz9Vxi5V.js +24 -0
- package/canvas-dist/assets/diagram-S2PKOQOG-CdWgZIIc.js +24 -0
- package/canvas-dist/assets/diagram-S2PKOQOG-DBicbKFU.js +24 -0
- package/canvas-dist/assets/diagram-S2PKOQOG-DsXKwPtU.js +24 -0
- package/canvas-dist/assets/diagram-S2PKOQOG-L_SMHLXs.js +24 -0
- package/canvas-dist/assets/{erDiagram-Q2GNP2WA-CG7dqzk3.js → erDiagram-Q2GNP2WA-BYu7fh6H.js} +1 -1
- package/canvas-dist/assets/erDiagram-Q2GNP2WA-CvnQ69BF.js +60 -0
- package/canvas-dist/assets/erDiagram-Q2GNP2WA-D3xm-Tdm.js +60 -0
- package/canvas-dist/assets/erDiagram-Q2GNP2WA-DIPpD8sj.js +60 -0
- package/canvas-dist/assets/erDiagram-Q2GNP2WA-DNgu6dMd.js +60 -0
- package/canvas-dist/assets/erDiagram-Q2GNP2WA-Decm8aB4.js +60 -0
- package/canvas-dist/assets/{flowDiagram-NV44I4VS-CBzCj5D6.js → flowDiagram-NV44I4VS-2ymk2kw2.js} +1 -1
- package/canvas-dist/assets/flowDiagram-NV44I4VS-BEPFOt6U.js +162 -0
- package/canvas-dist/assets/flowDiagram-NV44I4VS-BwqXYGfK.js +162 -0
- package/canvas-dist/assets/flowDiagram-NV44I4VS-CS1jax_z.js +162 -0
- package/canvas-dist/assets/flowDiagram-NV44I4VS-DQz5bf7r.js +162 -0
- package/canvas-dist/assets/flowDiagram-NV44I4VS-KW4T1sqF.js +162 -0
- package/canvas-dist/assets/{ganttDiagram-JELNMOA3-CHw-4qJC.js → ganttDiagram-JELNMOA3-B811prZt.js} +1 -1
- package/canvas-dist/assets/ganttDiagram-JELNMOA3-C75pWm7X.js +267 -0
- package/canvas-dist/assets/ganttDiagram-JELNMOA3-CWsbo0fn.js +267 -0
- package/canvas-dist/assets/ganttDiagram-JELNMOA3-CbJozPBN.js +267 -0
- package/canvas-dist/assets/ganttDiagram-JELNMOA3-Co0cFt4c.js +267 -0
- package/canvas-dist/assets/ganttDiagram-JELNMOA3-I4PDqrRh.js +267 -0
- package/canvas-dist/assets/{gitGraphDiagram-V2S2FVAM-Dqrc4wUs.js → gitGraphDiagram-V2S2FVAM-B-z0cLPt.js} +1 -1
- package/canvas-dist/assets/gitGraphDiagram-V2S2FVAM-Be40z-LF.js +65 -0
- package/canvas-dist/assets/gitGraphDiagram-V2S2FVAM-BejNaAVm.js +65 -0
- package/canvas-dist/assets/gitGraphDiagram-V2S2FVAM-BqWDYr0X.js +65 -0
- package/canvas-dist/assets/gitGraphDiagram-V2S2FVAM-DSvWGY-e.js +65 -0
- package/canvas-dist/assets/gitGraphDiagram-V2S2FVAM-HLYbyNJ5.js +65 -0
- package/canvas-dist/assets/{graph-X9Kzu-pf.js → graph-BE8KKsdf.js} +1 -1
- package/canvas-dist/assets/graph-D6DzzszU.js +1 -0
- package/canvas-dist/assets/graph-DFR8Y_8s.js +1 -0
- package/canvas-dist/assets/graph-Da385cDY.js +1 -0
- package/canvas-dist/assets/graph-MU7gZz2B.js +1 -0
- package/canvas-dist/assets/graph-wjSBJwnf.js +1 -0
- package/canvas-dist/assets/index--ztw-8Rw.js +647 -0
- package/canvas-dist/assets/{index-BQFKo-II.js → index-5TpIM6B1.js} +1 -1
- package/canvas-dist/assets/index-6GBZ9nXN.css +32 -0
- package/canvas-dist/assets/index-BSswTuBk.js +11 -0
- package/canvas-dist/assets/index-BVvhMmjs.js +11 -0
- package/canvas-dist/assets/index-BY92Mj5g.js +572 -0
- package/canvas-dist/assets/index-CV7palC3.js +572 -0
- package/canvas-dist/assets/index-D9bmQGsB.js +11 -0
- package/canvas-dist/assets/index-DDIKkGv8.js +592 -0
- package/canvas-dist/assets/index-Dyo0NkPb.js +574 -0
- package/canvas-dist/assets/index-iQWajCow.js +572 -0
- package/canvas-dist/assets/index-m68YlAMU.js +11 -0
- package/canvas-dist/assets/index-mEoP57az.js +11 -0
- package/canvas-dist/assets/{infoDiagram-HS3SLOUP-CflnZPsm.js → infoDiagram-HS3SLOUP--9BirqgJ.js} +1 -1
- package/canvas-dist/assets/infoDiagram-HS3SLOUP-CSJVED2y.js +2 -0
- package/canvas-dist/assets/infoDiagram-HS3SLOUP-D68HIb2t.js +2 -0
- package/canvas-dist/assets/infoDiagram-HS3SLOUP-DK2VLGGz.js +2 -0
- package/canvas-dist/assets/infoDiagram-HS3SLOUP-PaFhn4yD.js +2 -0
- package/canvas-dist/assets/infoDiagram-HS3SLOUP-zLNG47sU.js +2 -0
- package/canvas-dist/assets/{journeyDiagram-XKPGCS4Q-D2gkCipQ.js → journeyDiagram-XKPGCS4Q-Bue2dR2X.js} +1 -1
- package/canvas-dist/assets/journeyDiagram-XKPGCS4Q-CrgZfpdU.js +139 -0
- package/canvas-dist/assets/journeyDiagram-XKPGCS4Q-DUxWmkkC.js +139 -0
- package/canvas-dist/assets/journeyDiagram-XKPGCS4Q-OTFkv4pd.js +139 -0
- package/canvas-dist/assets/journeyDiagram-XKPGCS4Q-eK2_Zuu3.js +139 -0
- package/canvas-dist/assets/journeyDiagram-XKPGCS4Q-uds5Tz8D.js +139 -0
- package/canvas-dist/assets/{kanban-definition-3W4ZIXB7-CtLLz4o8.js → kanban-definition-3W4ZIXB7-BETdiI7I.js} +1 -1
- package/canvas-dist/assets/kanban-definition-3W4ZIXB7-BdVh7KdN.js +89 -0
- package/canvas-dist/assets/kanban-definition-3W4ZIXB7-Cxl8UM9S.js +89 -0
- package/canvas-dist/assets/kanban-definition-3W4ZIXB7-DVPlx3I2.js +89 -0
- package/canvas-dist/assets/kanban-definition-3W4ZIXB7-LtNWeoYB.js +89 -0
- package/canvas-dist/assets/kanban-definition-3W4ZIXB7-uvhEMvyE.js +89 -0
- package/canvas-dist/assets/{layout-CjvV_Dms.js → layout-1OzszN14.js} +1 -1
- package/canvas-dist/assets/layout-CJSupFcF.js +1 -0
- package/canvas-dist/assets/layout-DFRmxN_c.js +1 -0
- package/canvas-dist/assets/layout-DSu-zk7y.js +1 -0
- package/canvas-dist/assets/layout-TGcrvApd.js +1 -0
- package/canvas-dist/assets/layout-eStc8SYK.js +1 -0
- package/canvas-dist/assets/{linear-D3cIYHoS.js → linear-9qlE6xa7.js} +1 -1
- package/canvas-dist/assets/linear-CBfFWnLD.js +1 -0
- package/canvas-dist/assets/linear-Cv4ai8Hq.js +1 -0
- package/canvas-dist/assets/linear-DDzz65E6.js +1 -0
- package/canvas-dist/assets/linear-wbIqhwDf.js +1 -0
- package/canvas-dist/assets/linear-wyNKl76F.js +1 -0
- package/canvas-dist/assets/{mindmap-definition-VGOIOE7T-DSgjVg-P.js → mindmap-definition-VGOIOE7T-3l4YzhEM.js} +1 -1
- package/canvas-dist/assets/mindmap-definition-VGOIOE7T-B-KkpNlw.js +68 -0
- package/canvas-dist/assets/mindmap-definition-VGOIOE7T-DHMHWgmT.js +68 -0
- package/canvas-dist/assets/mindmap-definition-VGOIOE7T-Dqfyg4Z2.js +68 -0
- package/canvas-dist/assets/mindmap-definition-VGOIOE7T-NeRYOzsq.js +68 -0
- package/canvas-dist/assets/mindmap-definition-VGOIOE7T-xyu628P9.js +68 -0
- package/canvas-dist/assets/{pieDiagram-ADFJNKIX-B_lYaGFj.js → pieDiagram-ADFJNKIX-BWNzVAGj.js} +1 -1
- package/canvas-dist/assets/pieDiagram-ADFJNKIX-Bm3PXYs-.js +30 -0
- package/canvas-dist/assets/pieDiagram-ADFJNKIX-BvvN7VvQ.js +30 -0
- package/canvas-dist/assets/pieDiagram-ADFJNKIX-BwU7AN7W.js +30 -0
- package/canvas-dist/assets/pieDiagram-ADFJNKIX-CHgwWCaM.js +30 -0
- package/canvas-dist/assets/pieDiagram-ADFJNKIX-DlZc8YOh.js +30 -0
- package/canvas-dist/assets/{quadrantDiagram-AYHSOK5B-DLZLTJe3.js → quadrantDiagram-AYHSOK5B-B-Zd8OFp.js} +1 -1
- package/canvas-dist/assets/quadrantDiagram-AYHSOK5B-B1CnJyxI.js +7 -0
- package/canvas-dist/assets/quadrantDiagram-AYHSOK5B-C0Qo00b9.js +7 -0
- package/canvas-dist/assets/quadrantDiagram-AYHSOK5B-C9bx3nEJ.js +7 -0
- package/canvas-dist/assets/quadrantDiagram-AYHSOK5B-UHENkiRO.js +7 -0
- package/canvas-dist/assets/quadrantDiagram-AYHSOK5B-jKfurTPU.js +7 -0
- package/canvas-dist/assets/{requirementDiagram-UZGBJVZJ-CZE26rhL.js → requirementDiagram-UZGBJVZJ-BPpNNusD.js} +1 -1
- package/canvas-dist/assets/requirementDiagram-UZGBJVZJ-BwZF1NIK.js +64 -0
- package/canvas-dist/assets/requirementDiagram-UZGBJVZJ-CaT3Frtk.js +64 -0
- package/canvas-dist/assets/requirementDiagram-UZGBJVZJ-Dfoz7R_7.js +64 -0
- package/canvas-dist/assets/requirementDiagram-UZGBJVZJ-DsrX4TT-.js +64 -0
- package/canvas-dist/assets/requirementDiagram-UZGBJVZJ-dmouSXOl.js +64 -0
- package/canvas-dist/assets/{sankeyDiagram-TZEHDZUN-DQMRJAPV.js → sankeyDiagram-TZEHDZUN-BEy-A1Fu.js} +1 -1
- package/canvas-dist/assets/sankeyDiagram-TZEHDZUN-BViMBiAQ.js +10 -0
- package/canvas-dist/assets/sankeyDiagram-TZEHDZUN-BqrM-qWN.js +10 -0
- package/canvas-dist/assets/sankeyDiagram-TZEHDZUN-DRkRC9qB.js +10 -0
- package/canvas-dist/assets/sankeyDiagram-TZEHDZUN-DbuzKCtn.js +10 -0
- package/canvas-dist/assets/sankeyDiagram-TZEHDZUN-_aHMKbpw.js +10 -0
- package/canvas-dist/assets/{sequenceDiagram-WL72ISMW-BY723FEn.js → sequenceDiagram-WL72ISMW-B8FOaL2Q.js} +1 -1
- package/canvas-dist/assets/sequenceDiagram-WL72ISMW-C02NQwOB.js +145 -0
- package/canvas-dist/assets/sequenceDiagram-WL72ISMW-CgyHivPj.js +145 -0
- package/canvas-dist/assets/sequenceDiagram-WL72ISMW-CzW1WaEm.js +145 -0
- package/canvas-dist/assets/sequenceDiagram-WL72ISMW-DJhHI1pe.js +145 -0
- package/canvas-dist/assets/sequenceDiagram-WL72ISMW-VFkpAeoG.js +145 -0
- package/canvas-dist/assets/{stateDiagram-FKZM4ZOC-C_UdOFhy.js → stateDiagram-FKZM4ZOC-BSqFX4PJ.js} +1 -1
- package/canvas-dist/assets/stateDiagram-FKZM4ZOC-BnXhhxkN.js +1 -0
- package/canvas-dist/assets/stateDiagram-FKZM4ZOC-ClARVrvt.js +1 -0
- package/canvas-dist/assets/stateDiagram-FKZM4ZOC-CuC6xesY.js +1 -0
- package/canvas-dist/assets/stateDiagram-FKZM4ZOC-DcAiGjph.js +1 -0
- package/canvas-dist/assets/stateDiagram-FKZM4ZOC-aBg0hjTp.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-8fib9ftc.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-B-DO0ZqO.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-BksbsE4k.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-C2DJCNPK.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-CeA5jba6.js +1 -0
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-zsAyq0tK.js +1 -0
- package/canvas-dist/assets/{timeline-definition-IT6M3QCI-DkrJqww0.js → timeline-definition-IT6M3QCI-BaHdYD2h.js} +1 -1
- package/canvas-dist/assets/timeline-definition-IT6M3QCI-Bl2hg8IM.js +61 -0
- package/canvas-dist/assets/timeline-definition-IT6M3QCI-CrVwLiGm.js +61 -0
- package/canvas-dist/assets/timeline-definition-IT6M3QCI-DrXGRjnB.js +61 -0
- package/canvas-dist/assets/timeline-definition-IT6M3QCI-cYAwshf6.js +61 -0
- package/canvas-dist/assets/timeline-definition-IT6M3QCI-flyL0y-3.js +61 -0
- package/canvas-dist/assets/{treemap-GDKQZRPO-B-6bMZqD.js → treemap-GDKQZRPO-C4Hg8kJ_.js} +1 -1
- package/canvas-dist/assets/treemap-GDKQZRPO-DVY2G9qY.js +162 -0
- package/canvas-dist/assets/treemap-GDKQZRPO-DpLWPA1z.js +162 -0
- package/canvas-dist/assets/treemap-GDKQZRPO-Ds86cUVw.js +162 -0
- package/canvas-dist/assets/treemap-GDKQZRPO-DwmoI6tH.js +162 -0
- package/canvas-dist/assets/treemap-GDKQZRPO-SsGFkgVd.js +162 -0
- package/canvas-dist/assets/{xychartDiagram-PRI3JC2R-DkBhUy_D.js → xychartDiagram-PRI3JC2R-B9c1iLBf.js} +1 -1
- package/canvas-dist/assets/xychartDiagram-PRI3JC2R-BpX6MPWa.js +7 -0
- package/canvas-dist/assets/xychartDiagram-PRI3JC2R-CEgW_j0p.js +7 -0
- package/canvas-dist/assets/xychartDiagram-PRI3JC2R-CSEFGEQX.js +7 -0
- package/canvas-dist/assets/xychartDiagram-PRI3JC2R-CnG4XoMc.js +7 -0
- package/canvas-dist/assets/xychartDiagram-PRI3JC2R-Dftj3Bt3.js +7 -0
- package/canvas-dist/index.html +3 -2
- package/package.json +2 -1
- package/src/protocol.js +1 -1
- package/src/protocol.test.js +1 -1
- package/src/pty-manager.js +281 -0
- package/src/pty-manager.test.js +212 -0
- package/src/router.js +31 -1
- package/src/router.test.js +1 -1
- package/src/sdk-e2e.test.js +101 -0
- package/src/server.e2e.test.js +804 -138
- package/src/server.js +1273 -137
- package/src/session-store.js +260 -0
- package/src/session-store.test.js +235 -0
- package/src/templates.js +1 -1
- package/src/templates.test.js +1 -1
- package/src/terminal.js +3 -3
- package/src/terminal.test.js +12 -12
- package/src/visual-interceptor.js +450 -0
- package/src/visual-interceptor.test.js +943 -0
- package/src/workshop-parser.js +251 -0
- package/src/workshop-parser.test.js +179 -0
- package/templates/celebrate.html +1 -1
- package/templates/code-playground.html +1 -1
- package/templates/dashboard.html +7 -8
- package/templates/diagram-architecture.html +1 -1
- package/templates/diagram-flow.html +1 -1
- package/templates/diagram-mermaid.html +1 -1
- package/templates/game-speed-round.html +1 -1
- package/templates/quiz-drag-order.html +1 -1
- package/templates/quiz-fill-blank.html +1 -1
- package/templates/quiz-matching.html +1 -1
- package/templates/quiz-timed-choice.html +1 -1
- package/templates/welcome.html +7 -7
- package/canvas-dist/assets/channel-BzJVlie3.js +0 -1
- package/canvas-dist/assets/classDiagram-2ON5EDUG-BTs-zEmB.js +0 -1
- package/canvas-dist/assets/classDiagram-v2-WZHVMYZB-BTs-zEmB.js +0 -1
- package/canvas-dist/assets/clone-CXEfuXmc.js +0 -1
- package/canvas-dist/assets/index-DJ49c6u-.js +0 -426
- package/canvas-dist/assets/stateDiagram-v2-4FDKWEC3-DXIiFh0L.js +0 -1
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionStore — persistent session storage for Socrates.
|
|
3
|
+
*
|
|
4
|
+
* Stores session metadata + full message history as one JSON file per session
|
|
5
|
+
* in the .socrates-sessions/ directory (project-local, alongside .socrates-progress.yaml).
|
|
6
|
+
*
|
|
7
|
+
* File format: .socrates-sessions/<sessionId>.json
|
|
8
|
+
* {
|
|
9
|
+
* sessionId, title, module, topic, created, lastActive,
|
|
10
|
+
* pinned, messageCount, messages: [{ id, role, text, data, timestamp }]
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, unlinkSync, renameSync } from 'fs';
|
|
15
|
+
import { join, resolve } from 'path';
|
|
16
|
+
import { randomUUID } from 'crypto';
|
|
17
|
+
|
|
18
|
+
const SESSION_DIR_NAME = '.socrates-sessions';
|
|
19
|
+
const MAX_SESSIONS = 100;
|
|
20
|
+
|
|
21
|
+
let _sessionsDir = null;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Resolve and return the sessions directory path.
|
|
25
|
+
* Creates it if it doesn't exist. Adds to .gitignore if needed.
|
|
26
|
+
*/
|
|
27
|
+
export function getSessionsDir() {
|
|
28
|
+
if (_sessionsDir) return _sessionsDir;
|
|
29
|
+
_sessionsDir = resolve(process.cwd(), SESSION_DIR_NAME);
|
|
30
|
+
ensureSessionsDir();
|
|
31
|
+
return _sessionsDir;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Override sessions dir (for testing). */
|
|
35
|
+
export function setSessionsDir(dir) {
|
|
36
|
+
_sessionsDir = dir;
|
|
37
|
+
ensureSessionsDir();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function ensureSessionsDir() {
|
|
41
|
+
if (!existsSync(_sessionsDir)) {
|
|
42
|
+
mkdirSync(_sessionsDir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
// Best-effort: add to .gitignore
|
|
45
|
+
try {
|
|
46
|
+
const gitignore = resolve(process.cwd(), '.gitignore');
|
|
47
|
+
if (existsSync(gitignore)) {
|
|
48
|
+
const content = readFileSync(gitignore, 'utf-8');
|
|
49
|
+
if (!content.includes(SESSION_DIR_NAME)) {
|
|
50
|
+
writeFileSync(gitignore, content.trimEnd() + '\n' + SESSION_DIR_NAME + '/\n');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch { /* ignore */ }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function sessionPath(sessionId) {
|
|
57
|
+
return join(getSessionsDir(), `${sessionId}.json`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function readSessionFile(sessionId) {
|
|
61
|
+
const fp = sessionPath(sessionId);
|
|
62
|
+
if (!existsSync(fp)) return null;
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(readFileSync(fp, 'utf-8'));
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function writeSessionFile(sessionId, data) {
|
|
71
|
+
const fp = sessionPath(sessionId);
|
|
72
|
+
const tmp = fp + '.tmp';
|
|
73
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2));
|
|
74
|
+
renameSync(tmp, fp);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* List all sessions (metadata only, no messages).
|
|
79
|
+
* Sorted by lastActive descending.
|
|
80
|
+
*/
|
|
81
|
+
export function listSessions() {
|
|
82
|
+
const dir = getSessionsDir();
|
|
83
|
+
if (!existsSync(dir)) return [];
|
|
84
|
+
|
|
85
|
+
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
86
|
+
const sessions = [];
|
|
87
|
+
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
try {
|
|
90
|
+
const data = JSON.parse(readFileSync(join(dir, file), 'utf-8'));
|
|
91
|
+
sessions.push({
|
|
92
|
+
sessionId: data.sessionId,
|
|
93
|
+
title: data.title || 'Untitled',
|
|
94
|
+
module: data.module || null,
|
|
95
|
+
topic: data.topic || null,
|
|
96
|
+
created: data.created,
|
|
97
|
+
lastActive: data.lastActive,
|
|
98
|
+
pinned: data.pinned || false,
|
|
99
|
+
messageCount: data.messageCount || 0,
|
|
100
|
+
firstMessage: data.messages?.[0]?.text?.slice(0, 100) || null,
|
|
101
|
+
});
|
|
102
|
+
} catch { /* skip corrupt files */ }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
sessions.sort((a, b) => {
|
|
106
|
+
if (a.pinned !== b.pinned) return a.pinned ? -1 : 1;
|
|
107
|
+
return new Date(b.lastActive) - new Date(a.lastActive);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return sessions;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get a full session including all messages.
|
|
115
|
+
*/
|
|
116
|
+
export function getSession(sessionId) {
|
|
117
|
+
return readSessionFile(sessionId);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a new session. Returns the created session object.
|
|
122
|
+
*/
|
|
123
|
+
export function createSession(sessionId, meta = {}) {
|
|
124
|
+
const now = new Date().toISOString();
|
|
125
|
+
const session = {
|
|
126
|
+
sessionId,
|
|
127
|
+
title: meta.title || 'New conversation',
|
|
128
|
+
module: meta.module || null,
|
|
129
|
+
topic: meta.topic || null,
|
|
130
|
+
created: now,
|
|
131
|
+
lastActive: now,
|
|
132
|
+
pinned: false,
|
|
133
|
+
messageCount: 0,
|
|
134
|
+
messages: [],
|
|
135
|
+
};
|
|
136
|
+
writeSessionFile(sessionId, session);
|
|
137
|
+
pruneOldSessions();
|
|
138
|
+
return session;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Append a message to a session. Creates the session if it doesn't exist.
|
|
143
|
+
*/
|
|
144
|
+
export function appendMessage(sessionId, message) {
|
|
145
|
+
let session = readSessionFile(sessionId);
|
|
146
|
+
if (!session) {
|
|
147
|
+
session = createSession(sessionId);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const msg = {
|
|
151
|
+
id: message.id || `msg-${Date.now()}-${randomUUID().slice(0, 8)}`,
|
|
152
|
+
role: message.role,
|
|
153
|
+
text: message.text || null,
|
|
154
|
+
data: message.data || null,
|
|
155
|
+
timestamp: message.timestamp || Date.now(),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
session.messages.push(msg);
|
|
159
|
+
session.messageCount = session.messages.length;
|
|
160
|
+
session.lastActive = new Date().toISOString();
|
|
161
|
+
writeSessionFile(sessionId, session);
|
|
162
|
+
return msg;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Update session metadata (title, module, topic, pinned).
|
|
167
|
+
*/
|
|
168
|
+
export function updateMeta(sessionId, fields) {
|
|
169
|
+
const session = readSessionFile(sessionId);
|
|
170
|
+
if (!session) return null;
|
|
171
|
+
|
|
172
|
+
const allowed = ['title', 'module', 'topic', 'pinned'];
|
|
173
|
+
for (const key of allowed) {
|
|
174
|
+
if (fields[key] !== undefined) {
|
|
175
|
+
session[key] = fields[key];
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
session.lastActive = new Date().toISOString();
|
|
179
|
+
writeSessionFile(sessionId, session);
|
|
180
|
+
return session;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Delete a single session.
|
|
185
|
+
*/
|
|
186
|
+
export function deleteSession(sessionId) {
|
|
187
|
+
const fp = sessionPath(sessionId);
|
|
188
|
+
if (existsSync(fp)) {
|
|
189
|
+
unlinkSync(fp);
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Delete all sessions (purge).
|
|
197
|
+
*/
|
|
198
|
+
export function purgeAll() {
|
|
199
|
+
const dir = getSessionsDir();
|
|
200
|
+
if (!existsSync(dir)) return 0;
|
|
201
|
+
|
|
202
|
+
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
203
|
+
for (const file of files) {
|
|
204
|
+
try {
|
|
205
|
+
unlinkSync(join(dir, file));
|
|
206
|
+
} catch { /* ignore */ }
|
|
207
|
+
}
|
|
208
|
+
return files.length;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Auto-detect module/topic from user message text.
|
|
213
|
+
* Returns { module, topic, title } or null if no command detected.
|
|
214
|
+
*/
|
|
215
|
+
export function detectSessionTag(text) {
|
|
216
|
+
if (!text || typeof text !== 'string') return null;
|
|
217
|
+
|
|
218
|
+
const teachMatch = text.match(/^\/teach\s+([\w-]+)/);
|
|
219
|
+
if (teachMatch) {
|
|
220
|
+
const mod = teachMatch[1];
|
|
221
|
+
return { module: mod, topic: null, title: `Teaching: ${mod}` };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const learnMatch = text.match(/^\/learn\s+(.+)/);
|
|
225
|
+
if (learnMatch) {
|
|
226
|
+
const topic = learnMatch[1].trim().slice(0, 60);
|
|
227
|
+
return { module: null, topic, title: `Learning: ${topic}` };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Generate a short title from assistant response text.
|
|
235
|
+
*/
|
|
236
|
+
export function generateTitle(text) {
|
|
237
|
+
if (!text || typeof text !== 'string') return 'New conversation';
|
|
238
|
+
const clean = text
|
|
239
|
+
.replace(/[#*_`~]/g, '')
|
|
240
|
+
.replace(/[\u2500-\u257F\u2580-\u259F\u25A0-\u25FF]/g, '')
|
|
241
|
+
.trim();
|
|
242
|
+
const lines = clean.split('\n').map(l => l.trim()).filter(l => l.length > 0);
|
|
243
|
+
const firstLine = lines[0] || 'New conversation';
|
|
244
|
+
if (firstLine.length <= 50) return firstLine;
|
|
245
|
+
return firstLine.slice(0, 47) + '...';
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Prune sessions beyond MAX_SESSIONS, removing oldest unpinned.
|
|
250
|
+
*/
|
|
251
|
+
function pruneOldSessions() {
|
|
252
|
+
const sessions = listSessions();
|
|
253
|
+
if (sessions.length <= MAX_SESSIONS) return;
|
|
254
|
+
|
|
255
|
+
const unpinned = sessions.filter(s => !s.pinned);
|
|
256
|
+
const toRemove = unpinned.slice(MAX_SESSIONS - sessions.filter(s => s.pinned).length);
|
|
257
|
+
for (const s of toRemove) {
|
|
258
|
+
deleteSession(s.sessionId);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdirSync, rmSync, existsSync, readdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
import {
|
|
7
|
+
setSessionsDir,
|
|
8
|
+
listSessions,
|
|
9
|
+
getSession,
|
|
10
|
+
createSession,
|
|
11
|
+
appendMessage,
|
|
12
|
+
updateMeta,
|
|
13
|
+
deleteSession,
|
|
14
|
+
purgeAll,
|
|
15
|
+
detectSessionTag,
|
|
16
|
+
generateTitle,
|
|
17
|
+
} from './session-store.js';
|
|
18
|
+
|
|
19
|
+
let testDir;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
testDir = join(tmpdir(), `teach-sessions-test-${randomUUID()}`);
|
|
23
|
+
mkdirSync(testDir, { recursive: true });
|
|
24
|
+
setSessionsDir(testDir);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('createSession', () => {
|
|
32
|
+
it('creates a session file with default values', () => {
|
|
33
|
+
const session = createSession('test-1');
|
|
34
|
+
expect(session.sessionId).toBe('test-1');
|
|
35
|
+
expect(session.title).toBe('New conversation');
|
|
36
|
+
expect(session.messages).toEqual([]);
|
|
37
|
+
expect(session.messageCount).toBe(0);
|
|
38
|
+
expect(session.module).toBeNull();
|
|
39
|
+
expect(session.pinned).toBe(false);
|
|
40
|
+
expect(existsSync(join(testDir, 'test-1.json'))).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('creates a session with custom metadata', () => {
|
|
44
|
+
const session = createSession('test-2', { title: 'My session', module: 'git' });
|
|
45
|
+
expect(session.title).toBe('My session');
|
|
46
|
+
expect(session.module).toBe('git');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('getSession', () => {
|
|
51
|
+
it('returns null for nonexistent session', () => {
|
|
52
|
+
expect(getSession('nonexistent')).toBeNull();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('returns full session with messages', () => {
|
|
56
|
+
createSession('s1');
|
|
57
|
+
appendMessage('s1', { role: 'user', text: 'hello' });
|
|
58
|
+
const session = getSession('s1');
|
|
59
|
+
expect(session.sessionId).toBe('s1');
|
|
60
|
+
expect(session.messages).toHaveLength(1);
|
|
61
|
+
expect(session.messages[0].text).toBe('hello');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('appendMessage', () => {
|
|
66
|
+
it('appends a message to an existing session', () => {
|
|
67
|
+
createSession('s1');
|
|
68
|
+
const msg = appendMessage('s1', { role: 'user', text: 'hello' });
|
|
69
|
+
expect(msg.role).toBe('user');
|
|
70
|
+
expect(msg.text).toBe('hello');
|
|
71
|
+
expect(msg.id).toBeTruthy();
|
|
72
|
+
expect(msg.timestamp).toBeGreaterThan(0);
|
|
73
|
+
|
|
74
|
+
const session = getSession('s1');
|
|
75
|
+
expect(session.messages).toHaveLength(1);
|
|
76
|
+
expect(session.messageCount).toBe(1);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('auto-creates session if it does not exist', () => {
|
|
80
|
+
appendMessage('auto-created', { role: 'user', text: 'hi' });
|
|
81
|
+
const session = getSession('auto-created');
|
|
82
|
+
expect(session).not.toBeNull();
|
|
83
|
+
expect(session.messages).toHaveLength(1);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('preserves existing messages when appending', () => {
|
|
87
|
+
createSession('s1');
|
|
88
|
+
appendMessage('s1', { role: 'user', text: 'first' });
|
|
89
|
+
appendMessage('s1', { role: 'assistant', text: 'second' });
|
|
90
|
+
const session = getSession('s1');
|
|
91
|
+
expect(session.messages).toHaveLength(2);
|
|
92
|
+
expect(session.messages[0].text).toBe('first');
|
|
93
|
+
expect(session.messages[1].text).toBe('second');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('listSessions', () => {
|
|
98
|
+
it('returns empty array when no sessions exist', () => {
|
|
99
|
+
expect(listSessions()).toEqual([]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('lists sessions sorted by lastActive descending', () => {
|
|
103
|
+
createSession('s1', { title: 'First' });
|
|
104
|
+
createSession('s2', { title: 'Second' });
|
|
105
|
+
appendMessage('s1', { role: 'user', text: 'bump' });
|
|
106
|
+
const list = listSessions();
|
|
107
|
+
expect(list).toHaveLength(2);
|
|
108
|
+
expect(list[0].sessionId).toBe('s1');
|
|
109
|
+
expect(list[1].sessionId).toBe('s2');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('puts pinned sessions first', () => {
|
|
113
|
+
createSession('s1', { title: 'Unpinned' });
|
|
114
|
+
createSession('s2', { title: 'Pinned' });
|
|
115
|
+
updateMeta('s2', { pinned: true });
|
|
116
|
+
const list = listSessions();
|
|
117
|
+
expect(list[0].sessionId).toBe('s2');
|
|
118
|
+
expect(list[0].pinned).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('excludes message content from list results', () => {
|
|
122
|
+
createSession('s1');
|
|
123
|
+
appendMessage('s1', { role: 'user', text: 'secret message' });
|
|
124
|
+
const list = listSessions();
|
|
125
|
+
expect(list[0].messages).toBeUndefined();
|
|
126
|
+
expect(list[0].messageCount).toBe(1);
|
|
127
|
+
expect(list[0].firstMessage).toBe('secret message');
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('updateMeta', () => {
|
|
132
|
+
it('updates title', () => {
|
|
133
|
+
createSession('s1');
|
|
134
|
+
updateMeta('s1', { title: 'Renamed' });
|
|
135
|
+
expect(getSession('s1').title).toBe('Renamed');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('updates module and topic', () => {
|
|
139
|
+
createSession('s1');
|
|
140
|
+
updateMeta('s1', { module: 'git', topic: 'branching' });
|
|
141
|
+
const session = getSession('s1');
|
|
142
|
+
expect(session.module).toBe('git');
|
|
143
|
+
expect(session.topic).toBe('branching');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('toggles pinned', () => {
|
|
147
|
+
createSession('s1');
|
|
148
|
+
updateMeta('s1', { pinned: true });
|
|
149
|
+
expect(getSession('s1').pinned).toBe(true);
|
|
150
|
+
updateMeta('s1', { pinned: false });
|
|
151
|
+
expect(getSession('s1').pinned).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('returns null for nonexistent session', () => {
|
|
155
|
+
expect(updateMeta('nope', { title: 'x' })).toBeNull();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('ignores disallowed fields', () => {
|
|
159
|
+
createSession('s1');
|
|
160
|
+
updateMeta('s1', { messages: [], sessionId: 'hacked' });
|
|
161
|
+
const session = getSession('s1');
|
|
162
|
+
expect(session.sessionId).toBe('s1');
|
|
163
|
+
expect(session.messages).toEqual([]);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('deleteSession', () => {
|
|
168
|
+
it('deletes an existing session', () => {
|
|
169
|
+
createSession('s1');
|
|
170
|
+
expect(deleteSession('s1')).toBe(true);
|
|
171
|
+
expect(getSession('s1')).toBeNull();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('returns false for nonexistent session', () => {
|
|
175
|
+
expect(deleteSession('nope')).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('purgeAll', () => {
|
|
180
|
+
it('deletes all sessions', () => {
|
|
181
|
+
createSession('s1');
|
|
182
|
+
createSession('s2');
|
|
183
|
+
createSession('s3');
|
|
184
|
+
const count = purgeAll();
|
|
185
|
+
expect(count).toBe(3);
|
|
186
|
+
expect(listSessions()).toEqual([]);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('returns 0 when no sessions exist', () => {
|
|
190
|
+
expect(purgeAll()).toBe(0);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('detectSessionTag', () => {
|
|
195
|
+
it('detects /teach command', () => {
|
|
196
|
+
const tag = detectSessionTag('/teach git');
|
|
197
|
+
expect(tag.module).toBe('git');
|
|
198
|
+
expect(tag.title).toBe('Teaching: git');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('detects /learn command', () => {
|
|
202
|
+
const tag = detectSessionTag('/learn React hooks');
|
|
203
|
+
expect(tag.topic).toBe('React hooks');
|
|
204
|
+
expect(tag.title).toBe('Learning: React hooks');
|
|
205
|
+
expect(tag.module).toBeNull();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('returns null for regular messages', () => {
|
|
209
|
+
expect(detectSessionTag('hello world')).toBeNull();
|
|
210
|
+
expect(detectSessionTag('')).toBeNull();
|
|
211
|
+
expect(detectSessionTag(null)).toBeNull();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('generateTitle', () => {
|
|
216
|
+
it('generates title from short text', () => {
|
|
217
|
+
expect(generateTitle('Welcome to Git')).toBe('Welcome to Git');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('truncates long text', () => {
|
|
221
|
+
const long = 'A'.repeat(100);
|
|
222
|
+
const title = generateTitle(long);
|
|
223
|
+
expect(title.length).toBeLessThanOrEqual(50);
|
|
224
|
+
expect(title.endsWith('...')).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('strips markdown formatting', () => {
|
|
228
|
+
expect(generateTitle('# Hello **World**')).toBe('Hello World');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('returns default for empty input', () => {
|
|
232
|
+
expect(generateTitle('')).toBe('New conversation');
|
|
233
|
+
expect(generateTitle(null)).toBe('New conversation');
|
|
234
|
+
});
|
|
235
|
+
});
|
package/src/templates.js
CHANGED
package/src/templates.test.js
CHANGED
package/src/terminal.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Terminal session manager for
|
|
2
|
+
* Terminal session manager for Socrates canvas terminal.
|
|
3
3
|
* Executes user commands via child_process with cwd tracking,
|
|
4
4
|
* safety limits, and session lifecycle management.
|
|
5
5
|
*/
|
|
@@ -60,10 +60,10 @@ export async function createSession(initialCwd) {
|
|
|
60
60
|
await access(initialCwd);
|
|
61
61
|
cwd = resolve(initialCwd);
|
|
62
62
|
} catch {
|
|
63
|
-
cwd = await mkdtemp(join(tmpdir(), '
|
|
63
|
+
cwd = await mkdtemp(join(tmpdir(), 'socrates-'));
|
|
64
64
|
}
|
|
65
65
|
} else {
|
|
66
|
-
cwd = await mkdtemp(join(tmpdir(), '
|
|
66
|
+
cwd = await mkdtemp(join(tmpdir(), 'socrates-'));
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
sessionCounter += 1;
|
package/src/terminal.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tests for
|
|
2
|
+
* Tests for Socrates bridge terminal session manager.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
@@ -45,12 +45,12 @@ describe('Terminal session manager', () => {
|
|
|
45
45
|
it('falls back to temp dir if provided cwd does not exist', async () => {
|
|
46
46
|
const { cwd } = await createSession('/nonexistent/path/xyz');
|
|
47
47
|
expect(cwd).not.toBe('/nonexistent/path/xyz');
|
|
48
|
-
expect(cwd).toContain('
|
|
48
|
+
expect(cwd).toContain('socrates-');
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
it('creates a temp dir with the
|
|
51
|
+
it('creates a temp dir with the socrates- prefix when no cwd given', async () => {
|
|
52
52
|
const { cwd } = await createSession();
|
|
53
|
-
expect(cwd).toContain('
|
|
53
|
+
expect(cwd).toContain('socrates-');
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
it('resolves provided cwd to an absolute path', async () => {
|
|
@@ -202,11 +202,11 @@ describe('Terminal session manager', () => {
|
|
|
202
202
|
|
|
203
203
|
it('handles relative cd paths', async () => {
|
|
204
204
|
const { sessionId } = await createSession('/tmp');
|
|
205
|
-
await execCommand(sessionId, 'mkdir -p /tmp/
|
|
206
|
-
await execCommand(sessionId, 'cd
|
|
205
|
+
await execCommand(sessionId, 'mkdir -p /tmp/socrates-test-cd');
|
|
206
|
+
await execCommand(sessionId, 'cd socrates-test-cd');
|
|
207
207
|
const info = getSession(sessionId);
|
|
208
|
-
expect(info.cwd).toBe('/tmp/
|
|
209
|
-
await execCommand(sessionId, 'rm -rf /tmp/
|
|
208
|
+
expect(info.cwd).toBe('/tmp/socrates-test-cd');
|
|
209
|
+
await execCommand(sessionId, 'rm -rf /tmp/socrates-test-cd');
|
|
210
210
|
});
|
|
211
211
|
|
|
212
212
|
it('returns an error for cd to a nonexistent directory', async () => {
|
|
@@ -325,15 +325,15 @@ describe('Terminal session manager', () => {
|
|
|
325
325
|
|
|
326
326
|
it('allows normal rm commands', async () => {
|
|
327
327
|
const { sessionId } = await createSession('/tmp');
|
|
328
|
-
await execCommand(sessionId, 'touch /tmp/
|
|
329
|
-
const result = await execCommand(sessionId, 'rm /tmp/
|
|
328
|
+
await execCommand(sessionId, 'touch /tmp/socrates-test-rm');
|
|
329
|
+
const result = await execCommand(sessionId, 'rm /tmp/socrates-test-rm');
|
|
330
330
|
expect(result.exitCode).toBe(0);
|
|
331
331
|
});
|
|
332
332
|
|
|
333
333
|
it('allows rm -rf on a subdirectory', async () => {
|
|
334
334
|
const { sessionId } = await createSession('/tmp');
|
|
335
|
-
await execCommand(sessionId, 'mkdir -p /tmp/
|
|
336
|
-
const result = await execCommand(sessionId, 'rm -rf /tmp/
|
|
335
|
+
await execCommand(sessionId, 'mkdir -p /tmp/socrates-test-rmdir/sub');
|
|
336
|
+
const result = await execCommand(sessionId, 'rm -rf /tmp/socrates-test-rmdir');
|
|
337
337
|
expect(result.exitCode).toBe(0);
|
|
338
338
|
});
|
|
339
339
|
|