@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,450 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response interceptor — scans Claude's chat:assistant messages for
|
|
3
|
+
* mermaid fenced code blocks and media URLs, routing them as visual
|
|
4
|
+
* envelopes to connected canvas clients.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createEnvelope, MSG_CHAT_SUGGESTIONS } from '@shaykec/shared';
|
|
8
|
+
|
|
9
|
+
const MERMAID_FENCE_RE = /```mermaid\s*\n([\s\S]*?)```/g;
|
|
10
|
+
const CANVAS_CMD_RE = /<!--\s*(canvas:\w[\w-]*):\s*(\{[\s\S]*?\})\s*-->/g;
|
|
11
|
+
const VALID_CANVAS_TYPES = new Set([
|
|
12
|
+
'canvas:quiz', 'canvas:game', 'canvas:terminal', 'canvas:code',
|
|
13
|
+
'canvas:html', 'canvas:web-embed', 'canvas:celebrate',
|
|
14
|
+
'canvas:dashboard', 'canvas:real-terminal', 'canvas:workshop',
|
|
15
|
+
]);
|
|
16
|
+
const SUGGESTIONS_RE = /<!--\s*suggestions:\s*(\[[\s\S]*?\])\s*-->/;
|
|
17
|
+
const BUTTONS_RE = /<!--\s*buttons:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
18
|
+
const VALID_BUTTON_TYPES = ['single', 'multi', 'rating'];
|
|
19
|
+
|
|
20
|
+
const LIST_RE = /<!--\s*list:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
21
|
+
const PROGRESS_RE = /<!--\s*progress:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
22
|
+
const CARD_RE = /<!--\s*card:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
23
|
+
const CODE_BLOCK_RE = /<!--\s*code:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
24
|
+
const STEPS_RE = /<!--\s*steps:\s*(\{[\s\S]*?\})\s*-->/g;
|
|
25
|
+
const VALID_LIST_STYLES = ['cards', 'numbered', 'checklist', 'compact'];
|
|
26
|
+
const VALID_PROGRESS_STYLES = ['bar', 'steps', 'ring'];
|
|
27
|
+
const VALID_CARD_TYPES = ['tip', 'warning', 'error', 'success', 'concept'];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Auto-enhance plain markdown responses with smart components.
|
|
31
|
+
* Only runs when the message contains NO existing smart component comments.
|
|
32
|
+
* Wrapped in try/catch so a regex failure never crashes the bridge.
|
|
33
|
+
*/
|
|
34
|
+
let enhanceCounter = 0;
|
|
35
|
+
function nextId(prefix) { return `${prefix}-auto-${++enhanceCounter}`; }
|
|
36
|
+
|
|
37
|
+
const HAS_SMART_COMMENT_RE = /<!--\s*(buttons|list|progress|card|code|steps|suggestions):/;
|
|
38
|
+
|
|
39
|
+
export function enhanceWithSmartComponents(text) {
|
|
40
|
+
if (!text || typeof text !== 'string') return text;
|
|
41
|
+
if (HAS_SMART_COMMENT_RE.test(text)) return text;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
let enhanced = text;
|
|
45
|
+
|
|
46
|
+
// Blockquote tips: > **Pro Tip:** ... or > **💡 Tip:** ...
|
|
47
|
+
enhanced = enhanced.replace(
|
|
48
|
+
/(?:^|\n)>\s*\*\*((?:💡|🔑|✅|⚡|📌)\s*)?(?:(?:Pro\s*)?Tip|Best Practice|Remember|Key Insight|Key Takeaway)[:\s!]*\*\*\s*([^\n]+(?:\n>\s*[^\n]+)*)/gi,
|
|
49
|
+
(_, _icon, content) => {
|
|
50
|
+
const clean = content.replace(/\n>\s*/g, ' ').trim();
|
|
51
|
+
if (clean.length < 10) return _;
|
|
52
|
+
return `\n<!-- card: ${JSON.stringify({ id: nextId('card'), type: 'tip', title: 'Pro Tip', content: clean })} -->`;
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// Blockquote warnings: > **⚠️ Warning:** ...
|
|
57
|
+
enhanced = enhanced.replace(
|
|
58
|
+
/(?:^|\n)>\s*\*\*((?:⚠️|🚫|❌)\s*)?(?:Warning|Caution|Watch Out|Common Mistake|Pitfall|Anti-Pattern)[:\s!]*\*\*\s*([^\n]+(?:\n>\s*[^\n]+)*)/gi,
|
|
59
|
+
(_, _icon, content) => {
|
|
60
|
+
const clean = content.replace(/\n>\s*/g, ' ').trim();
|
|
61
|
+
if (clean.length < 10) return _;
|
|
62
|
+
return `\n<!-- card: ${JSON.stringify({ id: nextId('card'), type: 'warning', title: 'Watch Out', content: clean })} -->`;
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Numbered lists with bold titles: 1. **Title** — description
|
|
67
|
+
const numberedListMatch = enhanced.match(/(?:^|\n)((?:\d+\.\s+\*\*[^*]+\*\*[^\n]*\n?){3,})/);
|
|
68
|
+
if (numberedListMatch) {
|
|
69
|
+
const items = numberedListMatch[1].trim().split('\n')
|
|
70
|
+
.map(l => l.trim()).filter(Boolean)
|
|
71
|
+
.map(line => {
|
|
72
|
+
const m = line.replace(/^\d+\.\s+/, '').match(/^\*\*([^*]+)\*\*\s*[-—:]*\s*(.*)/);
|
|
73
|
+
return m ? { title: m[1].trim(), description: m[2].trim() || undefined } : null;
|
|
74
|
+
}).filter(Boolean);
|
|
75
|
+
if (items.length >= 3) {
|
|
76
|
+
enhanced = enhanced.replace(numberedListMatch[0],
|
|
77
|
+
`\n<!-- list: ${JSON.stringify({ id: nextId('list'), style: 'numbered', items })} -->`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Bullet lists with bold titles: - **Title** — description
|
|
82
|
+
const bulletListMatch = enhanced.match(/(?:^|\n)((?:[-*]\s+\*\*[^*]+\*\*[^\n]*\n?){3,})/);
|
|
83
|
+
if (bulletListMatch) {
|
|
84
|
+
const items = bulletListMatch[1].trim().split('\n')
|
|
85
|
+
.map(l => l.trim()).filter(Boolean)
|
|
86
|
+
.map(line => {
|
|
87
|
+
const m = line.replace(/^[-*]\s+/, '').match(/^\*\*([^*]+)\*\*\s*[-—:]*\s*(.*)/);
|
|
88
|
+
return m ? { title: m[1].trim(), description: m[2].trim() || undefined } : null;
|
|
89
|
+
}).filter(Boolean);
|
|
90
|
+
if (items.length >= 3) {
|
|
91
|
+
enhanced = enhanced.replace(bulletListMatch[0],
|
|
92
|
+
`\n<!-- list: ${JSON.stringify({ id: nextId('list'), style: 'cards', items })} -->`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return enhanced;
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error('[visual-interceptor] enhanceWithSmartComponents error:', err.message);
|
|
99
|
+
return text;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const YOUTUBE_RE = /(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{11})/;
|
|
104
|
+
const VIMEO_RE = /vimeo\.com\/(\d+)/;
|
|
105
|
+
const IMAGE_EXT_RE = /\.(png|jpe?g|gif|svg|webp|avif)(\?[^#\s]*)?$/i;
|
|
106
|
+
const VIDEO_EXT_RE = /\.(mp4|webm|ogg|mov)(\?[^#\s]*)?$/i;
|
|
107
|
+
const CODE_FENCE_RE = /```[\s\S]*?```/g;
|
|
108
|
+
const URL_RE = /https?:\/\/[^\s)<>"]+/g;
|
|
109
|
+
const MAX_AUTO_MEDIA = 3;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Extract mermaid code blocks from text and broadcast each as a
|
|
113
|
+
* canvas:diagram envelope via the tier manager.
|
|
114
|
+
*
|
|
115
|
+
* @param {string} text - The full assistant message text
|
|
116
|
+
* @param {object} tierManager - Bridge tier manager (broadcastWs/broadcastSse)
|
|
117
|
+
* @param {object} router - Event router (routeVisualCommand)
|
|
118
|
+
*/
|
|
119
|
+
export function extractAndRouteVisuals(text, tierManager, router) {
|
|
120
|
+
if (!text || typeof text !== 'string') return;
|
|
121
|
+
|
|
122
|
+
const blocks = [];
|
|
123
|
+
let match;
|
|
124
|
+
while ((match = MERMAID_FENCE_RE.exec(text)) !== null) {
|
|
125
|
+
const content = match[1].trim();
|
|
126
|
+
if (content) blocks.push(content);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (const content of blocks) {
|
|
130
|
+
const envelope = createEnvelope('canvas:diagram', {
|
|
131
|
+
format: 'mermaid',
|
|
132
|
+
content,
|
|
133
|
+
autoRouted: true,
|
|
134
|
+
}, 'bridge');
|
|
135
|
+
router.routeVisualCommand(envelope);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
CANVAS_CMD_RE.lastIndex = 0;
|
|
139
|
+
let cmdMatch;
|
|
140
|
+
while ((cmdMatch = CANVAS_CMD_RE.exec(text)) !== null) {
|
|
141
|
+
const type = cmdMatch[1];
|
|
142
|
+
if (!VALID_CANVAS_TYPES.has(type)) continue;
|
|
143
|
+
try {
|
|
144
|
+
const payload = JSON.parse(cmdMatch[2]);
|
|
145
|
+
payload.autoRouted = true;
|
|
146
|
+
const envelope = createEnvelope(type, payload, 'bridge');
|
|
147
|
+
router.routeVisualCommand(envelope);
|
|
148
|
+
} catch { /* malformed JSON — skip */ }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Extract suggestion chips from an assistant message.
|
|
154
|
+
* Format: <!-- suggestions: [{"label":"Quiz me","text":"/teach --quiz-only"},...] -->
|
|
155
|
+
*
|
|
156
|
+
* @param {string} text - The full assistant message text
|
|
157
|
+
* @param {object} tierManager - Bridge tier manager (broadcastWs/broadcastSse)
|
|
158
|
+
*/
|
|
159
|
+
export function extractAndRouteSuggestions(text, tierManager) {
|
|
160
|
+
if (!text || typeof text !== 'string') return;
|
|
161
|
+
|
|
162
|
+
const match = SUGGESTIONS_RE.exec(text);
|
|
163
|
+
if (!match) return;
|
|
164
|
+
|
|
165
|
+
let suggestions;
|
|
166
|
+
try {
|
|
167
|
+
suggestions = JSON.parse(match[1]);
|
|
168
|
+
} catch {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!Array.isArray(suggestions) || suggestions.length === 0) return;
|
|
173
|
+
|
|
174
|
+
const valid = suggestions.filter(s =>
|
|
175
|
+
s && typeof s.label === 'string' && typeof s.text === 'string'
|
|
176
|
+
);
|
|
177
|
+
if (valid.length === 0) return;
|
|
178
|
+
|
|
179
|
+
const envelope = createEnvelope(MSG_CHAT_SUGGESTIONS, { suggestions: valid }, 'bridge');
|
|
180
|
+
const data = JSON.stringify(envelope);
|
|
181
|
+
tierManager.broadcastWs(data);
|
|
182
|
+
tierManager.broadcastSse(data);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Extract inline smart button blocks from an assistant message.
|
|
187
|
+
* Format: <!-- buttons: {"id":"x","type":"single","options":[{"label":"A","value":"a"}]} -->
|
|
188
|
+
*
|
|
189
|
+
* Supports multiple button blocks per message. Each block is stripped from the
|
|
190
|
+
* text and returned as a parsed object. Invalid blocks are silently dropped.
|
|
191
|
+
*
|
|
192
|
+
* @param {string} text - The full assistant message text
|
|
193
|
+
* @returns {{ cleanText: string, buttons: object[] }}
|
|
194
|
+
*/
|
|
195
|
+
export function extractButtons(text) {
|
|
196
|
+
if (!text || typeof text !== 'string') return { cleanText: '', buttons: [] };
|
|
197
|
+
|
|
198
|
+
const buttons = [];
|
|
199
|
+
let cleanText = text;
|
|
200
|
+
|
|
201
|
+
// Reset regex state for global matching
|
|
202
|
+
BUTTONS_RE.lastIndex = 0;
|
|
203
|
+
const matches = [...text.matchAll(BUTTONS_RE)];
|
|
204
|
+
|
|
205
|
+
for (const match of matches) {
|
|
206
|
+
let parsed;
|
|
207
|
+
try {
|
|
208
|
+
parsed = JSON.parse(match[1]);
|
|
209
|
+
} catch {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!parsed || typeof parsed !== 'object') continue;
|
|
214
|
+
if (typeof parsed.id !== 'string' || !parsed.id) continue;
|
|
215
|
+
if (!VALID_BUTTON_TYPES.includes(parsed.type)) continue;
|
|
216
|
+
if (!Array.isArray(parsed.options) || parsed.options.length === 0) continue;
|
|
217
|
+
|
|
218
|
+
const validOptions = parsed.options.filter(o =>
|
|
219
|
+
o && typeof o.label === 'string' && typeof o.value === 'string'
|
|
220
|
+
);
|
|
221
|
+
if (validOptions.length === 0) continue;
|
|
222
|
+
|
|
223
|
+
buttons.push({
|
|
224
|
+
id: parsed.id,
|
|
225
|
+
type: parsed.type,
|
|
226
|
+
prompt: typeof parsed.prompt === 'string' ? parsed.prompt : undefined,
|
|
227
|
+
options: validOptions,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
cleanText = cleanText.replace(match[0], '');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return { cleanText: cleanText.trim(), buttons };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Extract inline block controls (list, progress, card, code, steps) from assistant text.
|
|
238
|
+
* Each block type uses an HTML comment: <!-- type: {...} -->
|
|
239
|
+
* Returns cleaned text with comments removed and an array of validated block objects.
|
|
240
|
+
*
|
|
241
|
+
* @param {string} text - The full assistant message text
|
|
242
|
+
* @returns {{ cleanText: string, blocks: object[] }}
|
|
243
|
+
*/
|
|
244
|
+
export function extractInlineBlocks(text) {
|
|
245
|
+
if (!text || typeof text !== 'string') return { cleanText: '', blocks: [] };
|
|
246
|
+
|
|
247
|
+
const blocks = [];
|
|
248
|
+
let cleanText = text;
|
|
249
|
+
|
|
250
|
+
const extractors = [
|
|
251
|
+
{ re: LIST_RE, type: 'list', validate: validateList },
|
|
252
|
+
{ re: PROGRESS_RE, type: 'progress', validate: validateProgress },
|
|
253
|
+
{ re: CARD_RE, type: 'card', validate: validateCard },
|
|
254
|
+
{ re: CODE_BLOCK_RE, type: 'code', validate: validateCode },
|
|
255
|
+
{ re: STEPS_RE, type: 'steps', validate: validateSteps },
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
for (const { re, type, validate } of extractors) {
|
|
259
|
+
re.lastIndex = 0;
|
|
260
|
+
for (const match of [...text.matchAll(re)]) {
|
|
261
|
+
let parsed;
|
|
262
|
+
try { parsed = JSON.parse(match[1]); } catch { continue; }
|
|
263
|
+
if (!parsed || typeof parsed !== 'object') continue;
|
|
264
|
+
if (typeof parsed.id !== 'string' || !parsed.id) continue;
|
|
265
|
+
|
|
266
|
+
const block = validate(parsed);
|
|
267
|
+
if (!block) continue;
|
|
268
|
+
|
|
269
|
+
blocks.push({ blockType: type, ...block });
|
|
270
|
+
cleanText = cleanText.replace(match[0], '');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return { cleanText: cleanText.trim(), blocks };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function validateList(p) {
|
|
278
|
+
if (!Array.isArray(p.items) || p.items.length === 0) return null;
|
|
279
|
+
const items = p.items.filter(i => i && typeof i.title === 'string');
|
|
280
|
+
if (items.length === 0) return null;
|
|
281
|
+
return {
|
|
282
|
+
id: p.id,
|
|
283
|
+
style: VALID_LIST_STYLES.includes(p.style) ? p.style : 'cards',
|
|
284
|
+
items: items.map(i => ({
|
|
285
|
+
icon: typeof i.icon === 'string' ? i.icon : undefined,
|
|
286
|
+
title: i.title,
|
|
287
|
+
description: typeof i.description === 'string' ? i.description : undefined,
|
|
288
|
+
action: typeof i.action === 'string' ? i.action : undefined,
|
|
289
|
+
})),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function validateProgress(p) {
|
|
294
|
+
if (typeof p.current !== 'number' || typeof p.total !== 'number') return null;
|
|
295
|
+
if (p.total <= 0) return null;
|
|
296
|
+
return {
|
|
297
|
+
id: p.id,
|
|
298
|
+
label: typeof p.label === 'string' ? p.label : undefined,
|
|
299
|
+
current: p.current,
|
|
300
|
+
total: p.total,
|
|
301
|
+
style: VALID_PROGRESS_STYLES.includes(p.style) ? p.style : 'bar',
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function validateCard(p) {
|
|
306
|
+
if (typeof p.content !== 'string' || !p.content) return null;
|
|
307
|
+
return {
|
|
308
|
+
id: p.id,
|
|
309
|
+
type: VALID_CARD_TYPES.includes(p.type) ? p.type : 'tip',
|
|
310
|
+
title: typeof p.title === 'string' ? p.title : undefined,
|
|
311
|
+
content: p.content,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function validateCode(p) {
|
|
316
|
+
if (typeof p.code !== 'string' || !p.code) return null;
|
|
317
|
+
return {
|
|
318
|
+
id: p.id,
|
|
319
|
+
language: typeof p.language === 'string' ? p.language : 'text',
|
|
320
|
+
filename: typeof p.filename === 'string' ? p.filename : undefined,
|
|
321
|
+
code: p.code,
|
|
322
|
+
highlight: Array.isArray(p.highlight) ? p.highlight.filter(n => typeof n === 'number') : [],
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function validateSteps(p) {
|
|
327
|
+
if (!Array.isArray(p.steps) || p.steps.length === 0) return null;
|
|
328
|
+
const validStatuses = ['done', 'active', 'pending'];
|
|
329
|
+
const steps = p.steps.filter(s => s && typeof s.label === 'string');
|
|
330
|
+
if (steps.length === 0) return null;
|
|
331
|
+
return {
|
|
332
|
+
id: p.id,
|
|
333
|
+
current: typeof p.current === 'number' ? p.current : undefined,
|
|
334
|
+
steps: steps.map(s => ({
|
|
335
|
+
label: s.label,
|
|
336
|
+
status: validStatuses.includes(s.status) ? s.status : 'pending',
|
|
337
|
+
})),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Detect the media type of a URL.
|
|
343
|
+
* @returns {'youtube'|'vimeo'|'image'|'video'|'link'}
|
|
344
|
+
*/
|
|
345
|
+
export function detectMediaUrl(url) {
|
|
346
|
+
if (YOUTUBE_RE.test(url)) return 'youtube';
|
|
347
|
+
if (VIMEO_RE.test(url)) return 'vimeo';
|
|
348
|
+
if (IMAGE_EXT_RE.test(url)) return 'image';
|
|
349
|
+
if (VIDEO_EXT_RE.test(url)) return 'video';
|
|
350
|
+
return 'link';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function escapeHtml(str) {
|
|
354
|
+
if (!str) return '';
|
|
355
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function buildMediaHtml(url, type) {
|
|
359
|
+
const safe = escapeHtml(url);
|
|
360
|
+
switch (type) {
|
|
361
|
+
case 'youtube': {
|
|
362
|
+
const m = url.match(YOUTUBE_RE);
|
|
363
|
+
if (!m) return null;
|
|
364
|
+
return {
|
|
365
|
+
html: `<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;"><iframe src="https://www.youtube.com/embed/${m[1]}?rel=0" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;border-radius:8px;" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe></div><p style="margin-top:12px;text-align:center;"><a href="${safe}" target="_blank" rel="noopener noreferrer" style="font-size:13px;">Open on YouTube ↗</a></p>`,
|
|
366
|
+
title: 'YouTube Video',
|
|
367
|
+
subtype: 'youtube',
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
case 'vimeo': {
|
|
371
|
+
const m = url.match(VIMEO_RE);
|
|
372
|
+
if (!m) return null;
|
|
373
|
+
return {
|
|
374
|
+
html: `<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;"><iframe src="https://player.vimeo.com/video/${m[1]}" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;border-radius:8px;" allow="autoplay;fullscreen;picture-in-picture" allowfullscreen></iframe></div><p style="margin-top:12px;text-align:center;"><a href="${safe}" target="_blank" rel="noopener noreferrer" style="font-size:13px;">Open on Vimeo ↗</a></p>`,
|
|
375
|
+
title: 'Vimeo Video',
|
|
376
|
+
subtype: 'vimeo',
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
case 'image':
|
|
380
|
+
return {
|
|
381
|
+
html: `<div style="text-align:center;padding:16px 0;"><img src="${safe}" style="max-width:100%;max-height:80vh;border-radius:8px;" /><p style="margin-top:12px;"><a href="${safe}" target="_blank" rel="noopener noreferrer" style="font-size:13px;">Open full size ↗</a></p></div>`,
|
|
382
|
+
title: 'Image',
|
|
383
|
+
subtype: 'image',
|
|
384
|
+
};
|
|
385
|
+
case 'video':
|
|
386
|
+
return {
|
|
387
|
+
html: `<div style="text-align:center;"><video controls style="max-width:100%;border-radius:8px;"><source src="${safe}" /></video><p style="margin-top:12px;"><a href="${safe}" target="_blank" rel="noopener noreferrer" style="font-size:13px;">Download video ↗</a></p></div>`,
|
|
388
|
+
title: 'Video',
|
|
389
|
+
subtype: 'video',
|
|
390
|
+
};
|
|
391
|
+
default:
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Strip code fences from text so URLs inside code blocks aren't auto-routed.
|
|
398
|
+
*/
|
|
399
|
+
function stripCodeFences(text) {
|
|
400
|
+
return text.replace(CODE_FENCE_RE, '');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Remove `<!-- canvas:TYPE {...} -->` comments from text so they don't
|
|
405
|
+
* render as raw HTML in the chat bubble.
|
|
406
|
+
*/
|
|
407
|
+
export function stripCanvasCommands(text) {
|
|
408
|
+
if (!text || typeof text !== 'string') return text;
|
|
409
|
+
return text.replace(CANVAS_CMD_RE, '').replace(/\n{3,}/g, '\n\n').trim();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Scan assistant text for media URLs and route them as canvas:html envelopes.
|
|
414
|
+
* Only routes embeddable media (YouTube, Vimeo, images, videos) — not generic links.
|
|
415
|
+
* Deduplicates via the seenUrls set to avoid re-routing the same URL.
|
|
416
|
+
*
|
|
417
|
+
* @param {string} text - The full assistant message text
|
|
418
|
+
* @param {object} router - Event router (routeVisualCommand)
|
|
419
|
+
* @param {Set} seenUrls - URLs already routed in this session
|
|
420
|
+
*/
|
|
421
|
+
export function extractAndRouteMedia(text, router, seenUrls) {
|
|
422
|
+
if (!text || typeof text !== 'string') return;
|
|
423
|
+
|
|
424
|
+
const cleaned = stripCodeFences(text);
|
|
425
|
+
const urls = cleaned.match(URL_RE);
|
|
426
|
+
if (!urls) return;
|
|
427
|
+
|
|
428
|
+
let count = 0;
|
|
429
|
+
for (const url of urls) {
|
|
430
|
+
if (count >= MAX_AUTO_MEDIA) break;
|
|
431
|
+
if (seenUrls.has(url)) continue;
|
|
432
|
+
|
|
433
|
+
const type = detectMediaUrl(url);
|
|
434
|
+
if (type === 'link') continue;
|
|
435
|
+
|
|
436
|
+
const media = buildMediaHtml(url, type);
|
|
437
|
+
if (!media) continue;
|
|
438
|
+
|
|
439
|
+
seenUrls.add(url);
|
|
440
|
+
count++;
|
|
441
|
+
|
|
442
|
+
const envelope = createEnvelope('canvas:html', {
|
|
443
|
+
html: media.html,
|
|
444
|
+
title: media.title,
|
|
445
|
+
subtype: media.subtype,
|
|
446
|
+
autoRouted: true,
|
|
447
|
+
}, 'bridge');
|
|
448
|
+
router.routeVisualCommand(envelope);
|
|
449
|
+
}
|
|
450
|
+
}
|