agent-whiteboard 1.0.3 → 1.1.0
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/CHANGELOG.md +59 -0
- package/README.md +13 -2
- package/dist/client/assets/abnfDiagram-VCTEODGH-CcuBIZ5h.js +1 -0
- package/dist/client/assets/{arc-4691b008.js → arc-Aq92EeUK.js} +1 -1
- package/dist/client/assets/architectureDiagram-5GKGNRK7-CpMRoWIY.js +36 -0
- package/dist/client/assets/blockDiagram-I7D4REHJ-Dee0m4lz.js +129 -0
- package/dist/client/assets/{bootstrap.min-21652813.js → bootstrap.min-UtnB-TxT.js} +1 -2
- package/dist/client/assets/c4Diagram-7LVT6UL2-D_qs3YTM.js +38 -0
- package/dist/client/assets/channel-9qggtmY_.js +1 -0
- package/dist/client/assets/{chunk-QZHKN3VN-0f554985.js → chunk-2Q5K7J3B-CBwQ-uNF.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-23d48b24.js → chunk-5VM5RSS4-yGvVHapR.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-1104c326.js → chunk-F27PBJKO-BzFUf98n.js} +1 -1
- package/dist/client/assets/chunk-IMKFNOWR-D-Zj1GaL.js +231 -0
- package/dist/client/assets/{chunk-4BX2VUAB-3c93511d.js → chunk-JWPE2WC7-C8Aj4MVR.js} +1 -1
- package/dist/client/assets/chunk-POPQ4Y6H-DZP2a-yV.js +1 -0
- package/dist/client/assets/chunk-SVP7TREG-COihS1MQ.js +88 -0
- package/dist/client/assets/chunk-TICWLB2K-DNZTRqyJ.js +206 -0
- package/dist/client/assets/{chunk-55IACEB6-0243aefd.js → chunk-XXDRQBXY-BC_9L4PF.js} +1 -1
- package/dist/client/assets/classDiagram-ZZMXUADV-BUnGzX-0.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BUnGzX-0.js +1 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-DrJ8c1cV.js +1 -0
- package/dist/client/assets/cynefin-OW5HDTMX-CMVAR4fd.js +178 -0
- package/dist/client/assets/cynefinDiagram-5FMLGOSQ-CdAQ0Lst.js +62 -0
- package/dist/client/assets/cytoscape.esm-C5JX3QLV.js +331 -0
- package/dist/client/assets/dagre-GXQ25YYZ-CybK0L_u.js +4 -0
- package/dist/client/assets/diagram-S7CK7UJ4-CHjTv5Sr.js +30 -0
- package/dist/client/assets/diagram-UQ7AKVKN-DfypPsGR.js +41 -0
- package/dist/client/assets/{diagram-KO2AKTUF-81f42eeb.js → diagram-VSXAHHWV-DHsmmCug.js} +3 -3
- package/dist/client/assets/diagram-VX7I27RA-CHZoTi9k.js +24 -0
- package/dist/client/assets/diagram-Z3DM3KII-Ceb2h13y.js +24 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-BlZ247wB.js +1 -0
- package/dist/client/assets/embed-DcNeILcO.js +211 -0
- package/dist/client/assets/erDiagram-RLTQ6QDP-BQdw-U-S.js +99 -0
- package/dist/client/assets/flowDiagram-HODETNUW-DjUWHA94.js +168 -0
- package/dist/client/assets/ganttDiagram-EL5Y4UJY-CXu2s5vq.js +292 -0
- package/dist/client/assets/gitGraphDiagram-WWUBYQGX-CwlsB28k.js +106 -0
- package/dist/client/assets/index-CFelVSRu.js +19 -0
- package/dist/client/assets/index-GF8Uj64S.css +1 -0
- package/dist/client/assets/infoDiagram-27XIBGKW-C7nvTbsQ.js +2 -0
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-50b43d03.js → ishikawaDiagram-5VMMS53U-DGFXG874.js} +2 -2
- package/dist/client/assets/{journeyDiagram-JHISSGLW-dce41bdf.js → journeyDiagram-3NMN7TZE-BDdRMcmq.js} +4 -4
- package/dist/client/assets/{kanban-definition-UN3LZRKU-92401a86.js → kanban-definition-UXKFOSKX-C3fnvfeO.js} +1 -1
- package/dist/client/assets/{katex-4c9ea27f.js → katex-BTI-AXqd.js} +3 -3
- package/dist/client/assets/{katex-0cba7652.js → katex-C5jXJg4s.js} +3 -3
- package/dist/client/assets/layout-BfegUiqt.js +1 -0
- package/dist/client/assets/linear-D1EL1Azg.js +1 -0
- package/dist/client/assets/mermaid.core-DioArgDk.js +310 -0
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-66fe4544.js → mindmap-definition-YA3MSWOX-CFCbAUC0.js} +12 -12
- package/dist/client/assets/{ordinal-db88ae6f.js → ordinal-BeghXfj9.js} +1 -1
- package/dist/client/assets/pegDiagram-XKGWAZYB-B1ULJH6S.js +1 -0
- package/dist/client/assets/pieDiagram-E7YTZNPT-B9H3HosU.js +39 -0
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-f64a7ed7.js → quadrantDiagram-AXDQQJYC-eWc3HHkM.js} +4 -4
- package/dist/client/assets/railroadDiagram-O6MQD6OU-DT7c-KwW.js +1 -0
- package/dist/client/assets/requirementDiagram-BXWQKSXE-Dk1yVWV5.js +84 -0
- package/dist/client/assets/sankeyDiagram-P5KCCOFB-B5a__hiX.js +40 -0
- package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CkCIByRS.js +162 -0
- package/dist/client/assets/sizeCapture-INFHLROL-CnZIW94r.js +1 -0
- package/dist/client/assets/stateDiagram-D77RDMKH-89Sfaoz9.js +1 -0
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CP--cdl-.js +1 -0
- package/dist/client/assets/step-BEQzeS8V.js +1 -0
- package/dist/client/assets/swimlanes-42K2YHIH-C7m88XIh.js +1 -0
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DmG2scPu.js +8 -0
- package/dist/client/assets/{time-043b3464.js → time-BaoZouO5.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-b0c81243.js → timeline-definition-24CTP7MA-BHKHgHq9.js} +10 -10
- package/dist/client/assets/vennDiagram-4TSXK5OY-BqKaRdWu.js +34 -0
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-8d4d7626.js → wardleyDiagram-VM6X3IG4-XiDVRZV5.js} +3 -3
- package/dist/client/assets/xychartDiagram-S5SC5T6Z-CxP4dIVd.js +7 -0
- package/dist/client/index.html +2 -3
- package/dist/server/app.js +29 -397
- package/dist/server/channel.js +5 -3
- package/dist/server/export-html.js +26 -60
- package/dist/server/export-zip.js +83 -0
- package/dist/server/import-zip.js +196 -0
- package/dist/server/index.js +2 -1
- package/dist/server/mcp.js +9 -9
- package/dist/server/port.js +18 -0
- package/dist/server/render-core.js +5 -5
- package/dist/server/routes/export.js +95 -0
- package/dist/server/routes/import.js +24 -0
- package/dist/server/routes/render.js +184 -0
- package/dist/server/routes/slideshow.js +52 -0
- package/dist/server/routes/snapshots.js +119 -0
- package/dist/server/snapshot-reader.js +58 -20
- package/dist/server/snapshot-writer.js +18 -16
- package/dist/server/viewport-cache.js +97 -25
- package/package.json +13 -7
- package/dist/client/assets/architecture-7EHR7CIX-1221aa61.js +0 -1
- package/dist/client/assets/architectureDiagram-3BPJPVTR-1eef4d3c.js +0 -36
- package/dist/client/assets/blockDiagram-GPEHLZMM-313fb06c.js +0 -132
- package/dist/client/assets/c4Diagram-AAUBKEIU-92b023ad.js +0 -10
- package/dist/client/assets/channel-5ee4a8a7.js +0 -1
- package/dist/client/assets/chunk-2J33WTMH-fb021fdc.js +0 -1
- package/dist/client/assets/chunk-727SXJPM-8e0e0228.js +0 -206
- package/dist/client/assets/chunk-AQP2D5EJ-2ccc13c2.js +0 -231
- package/dist/client/assets/classDiagram-4FO5ZUOK-42ffecb6.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-42ffecb6.js +0 -1
- package/dist/client/assets/cose-bilkent-S5V4N54A-45ec2e52.js +0 -1
- package/dist/client/assets/cytoscape.esm-1491e259.js +0 -331
- package/dist/client/assets/dagre-BM42HDAG-ed748885.js +0 -4
- package/dist/client/assets/diagram-2AECGRRQ-ccc0ddec.js +0 -43
- package/dist/client/assets/diagram-5GNKFQAL-342efdea.js +0 -10
- package/dist/client/assets/diagram-LMA3HP47-39e66739.js +0 -24
- package/dist/client/assets/diagram-OG6HWLK6-b3e61903.js +0 -24
- package/dist/client/assets/embed-2b4adf34.js +0 -201
- package/dist/client/assets/erDiagram-TEJ5UH35-281f5cc7.js +0 -85
- package/dist/client/assets/eventmodeling-FCH6USID-6508120e.js +0 -1
- package/dist/client/assets/flowDiagram-I6XJVG4X-c3a4269e.js +0 -162
- package/dist/client/assets/ganttDiagram-6RSMTGT7-013b07ec.js +0 -292
- package/dist/client/assets/gitGraph-WXDBUCRP-02827359.js +0 -1
- package/dist/client/assets/gitGraphDiagram-PVQCEYII-de184acb.js +0 -106
- package/dist/client/assets/graph-f3dfaf53.js +0 -1
- package/dist/client/assets/index-d674a6a4.css +0 -1
- package/dist/client/assets/index-ffc5af4b.js +0 -5
- package/dist/client/assets/info-J43DQDTF-81e32294.js +0 -1
- package/dist/client/assets/infoDiagram-5YYISTIA-196101ee.js +0 -2
- package/dist/client/assets/layout-3a4eff80.js +0 -1
- package/dist/client/assets/linear-fed00341.js +0 -1
- package/dist/client/assets/mermaid-parser.core-52f9cd92.js +0 -173
- package/dist/client/assets/mermaid.core-7dfc221a.js +0 -306
- package/dist/client/assets/packet-YPE3B663-278a272a.js +0 -1
- package/dist/client/assets/pie-LRSECV5Y-2e55d9ae.js +0 -1
- package/dist/client/assets/pieDiagram-4H26LBE5-65b1bcbd.js +0 -30
- package/dist/client/assets/radar-GUYGQ44K-608e459f.js +0 -1
- package/dist/client/assets/requirementDiagram-4Y6WPE33-90ebf889.js +0 -84
- package/dist/client/assets/sankeyDiagram-5OEKKPKP-2d1a83b3.js +0 -40
- package/dist/client/assets/sequenceDiagram-3UESZ5HK-aece3633.js +0 -162
- package/dist/client/assets/stateDiagram-AJRCARHV-9bd5b5f4.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-7c16c251.js +0 -1
- package/dist/client/assets/step-171ad54a.js +0 -1
- package/dist/client/assets/treeView-BLDUP644-e54b9ddb.js +0 -1
- package/dist/client/assets/treemap-LRROVOQU-6a81775b.js +0 -1
- package/dist/client/assets/vennDiagram-CIIHVFJN-8eaf0464.js +0 -34
- package/dist/client/assets/wardley-L42UT6IY-7abd921f.js +0 -1
- package/dist/client/assets/xychartDiagram-2RQKCTM6-450f333c.js +0 -7
- /package/dist/client/assets/{KaTeX_AMS-Regular-0cdd387c.woff2 → KaTeX_AMS-Regular-BQhdFMY1.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_AMS-Regular-30da91e8.woff → KaTeX_AMS-Regular-DMm9YOAa.woff} +0 -0
- /package/dist/client/assets/{KaTeX_AMS-Regular-68534840.ttf → KaTeX_AMS-Regular-DRggAlZN.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-07d8e303.ttf → KaTeX_Caligraphic-Bold-ATXxdsX0.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-1ae6bd74.woff → KaTeX_Caligraphic-Bold-BEiXGLvX.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Bold-de7701e4.woff2 → KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-3398dd02.woff → KaTeX_Caligraphic-Regular-CTRA-rTL.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-5d53e70a.woff2 → KaTeX_Caligraphic-Regular-Di6jR-x-.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Caligraphic-Regular-ed0b7437.ttf → KaTeX_Caligraphic-Regular-wX97UBjC.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-9163df9c.ttf → KaTeX_Fraktur-Bold-BdnERNNW.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-9be7ceb8.woff → KaTeX_Fraktur-Bold-BsDP51OF.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Bold-74444efd.woff2 → KaTeX_Fraktur-Bold-CL6g_b3V.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-1e6f9579.ttf → KaTeX_Fraktur-Regular-CB_wures.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-51814d27.woff2 → KaTeX_Fraktur-Regular-CTYiF6lA.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Fraktur-Regular-5e28753b.woff → KaTeX_Fraktur-Regular-Dxdc4cR9.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-0f60d1b8.woff2 → KaTeX_Main-Bold-Cx986IdX.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-c76c5d69.woff → KaTeX_Main-Bold-Jm3AIy58.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Bold-138ac28d.ttf → KaTeX_Main-Bold-waoOVXN0.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-99cd42a3.woff2 → KaTeX_Main-BoldItalic-DxDJ3AOS.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-70ee1f64.ttf → KaTeX_Main-BoldItalic-DzxPMmG6.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-BoldItalic-a6f7ec0d.woff → KaTeX_Main-BoldItalic-SpSLRI95.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-0d85ae7c.ttf → KaTeX_Main-Italic-3WenGoN9.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-f1d6ef86.woff → KaTeX_Main-Italic-BMLOBm91.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Italic-97479ca6.woff2 → KaTeX_Main-Italic-NWA7e6Wa.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-c2342cd8.woff2 → KaTeX_Main-Regular-B22Nviop.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-c6368d87.woff → KaTeX_Main-Regular-Dr94JaBh.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Main-Regular-d0332f52.ttf → KaTeX_Main-Regular-ypZvNtVU.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-f9377ab0.ttf → KaTeX_Math-BoldItalic-B3XSjfu4.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-dc47344d.woff2 → KaTeX_Math-BoldItalic-CZnvNsCZ.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Math-BoldItalic-850c0af5.woff → KaTeX_Math-BoldItalic-iY-2wyZ7.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-8a8d2445.woff → KaTeX_Math-Italic-DA0__PXp.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-08ce98e5.ttf → KaTeX_Math-Italic-flOr_0UB.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Math-Italic-7af58c5e.woff2 → KaTeX_Math-Italic-t53AETM-.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-1ece03f7.ttf → KaTeX_SansSerif-Bold-CFMepnvq.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-e99ae511.woff2 → KaTeX_SansSerif-Bold-D1sUS0GD.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Bold-ece03cfd.woff → KaTeX_SansSerif-Bold-DbIhKOiC.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-00b26ac8.woff2 → KaTeX_SansSerif-Italic-C3H0VqGB.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-91ee6750.woff → KaTeX_SansSerif-Italic-DN2j7dab.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Italic-3931dd81.ttf → KaTeX_SansSerif-Italic-YYjJ1zSn.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-f36ea897.ttf → KaTeX_SansSerif-Regular-BNo7hRIc.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-11e4dc8a.woff → KaTeX_SansSerif-Regular-CS6fqUqJ.woff} +0 -0
- /package/dist/client/assets/{KaTeX_SansSerif-Regular-68e8c73e.woff2 → KaTeX_SansSerif-Regular-DDBCnlJ7.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-1c67f068.ttf → KaTeX_Script-Regular-C5JkGWo-.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-036d4e95.woff2 → KaTeX_Script-Regular-D3wIWfF6.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Script-Regular-d96cdf2b.woff → KaTeX_Script-Regular-D5yQViql.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-c943cc98.woff → KaTeX_Size1-Regular-C195tn64.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-95b6d2f1.ttf → KaTeX_Size1-Regular-Dbsnue_I.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size1-Regular-6b47c401.woff2 → KaTeX_Size1-Regular-mCD8mA8B.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-a6b2099f.ttf → KaTeX_Size2-Regular-B7gKUWhC.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-d04c5421.woff2 → KaTeX_Size2-Regular-Dy4dx90m.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Size2-Regular-2014c523.woff → KaTeX_Size2-Regular-oD1tc_U0.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size3-Regular-6ab6b62e.woff → KaTeX_Size3-Regular-CTq5MqoE.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size3-Regular-500e04d5.ttf → KaTeX_Size3-Regular-DgpXs0kz.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-99f9c675.woff → KaTeX_Size4-Regular-BF-4gkZK.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-c647367d.ttf → KaTeX_Size4-Regular-DWFBv043.ttf} +0 -0
- /package/dist/client/assets/{KaTeX_Size4-Regular-a4af7d41.woff2 → KaTeX_Size4-Regular-Dl5lxZxV.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-e14fed02.woff → KaTeX_Typewriter-Regular-C0xS9mPB.woff} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-71d517d6.woff2 → KaTeX_Typewriter-Regular-CO6r4hn1.woff2} +0 -0
- /package/dist/client/assets/{KaTeX_Typewriter-Regular-f01f3e87.ttf → KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf} +0 -0
- /package/dist/client/assets/{colors-98f238a0.js → colors-Cc3OSVma.js} +0 -0
- /package/dist/client/assets/{defaultLocale-a8476f12.js → defaultLocale-CzDG__Ur.js} +0 -0
- /package/dist/client/assets/{index-a1656aec.js → index-Bi7T_FA4.js} +0 -0
- /package/dist/client/assets/{init-a5b10ee5.js → init-Dmth1JHB.js} +0 -0
- /package/dist/client/assets/{range-6bc2a9a0.js → range-OtVwhkKS.js} +0 -0
|
@@ -4,19 +4,37 @@
|
|
|
4
4
|
// step-frames sequence persists its own manual viewport independently, consistent
|
|
5
5
|
// with each frame now getting its own auto-fit trigger (was a bare `id` key,
|
|
6
6
|
// shared across a whole sequence, pre-v0.26.1).
|
|
7
|
-
|
|
7
|
+
//
|
|
8
|
+
// NF49 (v1.4): reads/writes go through fs/promises instead of blocking the event
|
|
9
|
+
// loop, and the on-disk file is treated as a write-back cache — kept in memory
|
|
10
|
+
// after the first load and flushed to disk on a coalesced delay (see
|
|
11
|
+
// `scheduleFlush()`) instead of a full synchronous read-modify-write per
|
|
12
|
+
// zoom/pan event.
|
|
13
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
8
14
|
import { join } from "path";
|
|
9
15
|
import { getSnapshotsRoot } from "./paths.js";
|
|
10
16
|
function cachePath() {
|
|
11
17
|
return join(getSnapshotsRoot(), "viewport-cache.json");
|
|
12
18
|
}
|
|
13
|
-
function
|
|
19
|
+
function cacheKey(id, frameIndex) {
|
|
20
|
+
return `${id}:${frameIndex}`;
|
|
21
|
+
}
|
|
22
|
+
// In-memory cache, lazily loaded on first access. `cachedForPath` guards
|
|
23
|
+
// against a stale in-memory cache surviving a change to the underlying
|
|
24
|
+
// snapshots root (WHITEBOARD_SNAPSHOTS_DIR) — reloads transparently if the
|
|
25
|
+
// resolved cache path differs from the one currently held in memory.
|
|
26
|
+
let cache;
|
|
27
|
+
let cachedForPath;
|
|
28
|
+
async function loadCache() {
|
|
29
|
+
const path = cachePath();
|
|
30
|
+
if (cache !== undefined && cachedForPath === path)
|
|
31
|
+
return cache;
|
|
14
32
|
try {
|
|
15
|
-
const raw =
|
|
33
|
+
const raw = await readFile(path, "utf-8");
|
|
16
34
|
const parsed = JSON.parse(raw);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
35
|
+
cache = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
|
|
36
|
+
? parsed
|
|
37
|
+
: {};
|
|
20
38
|
}
|
|
21
39
|
catch (err) {
|
|
22
40
|
// ENOENT (no cache file yet, e.g. first run) is expected and not logged.
|
|
@@ -25,45 +43,99 @@ function readCache() {
|
|
|
25
43
|
if (err?.code !== "ENOENT") {
|
|
26
44
|
console.error("[agent-whiteboard] viewport-cache read failed, resetting cache:", err instanceof Error ? err.message : String(err));
|
|
27
45
|
}
|
|
28
|
-
|
|
46
|
+
cache = {};
|
|
29
47
|
}
|
|
48
|
+
cachedForPath = path;
|
|
49
|
+
return cache;
|
|
30
50
|
}
|
|
31
|
-
function
|
|
51
|
+
async function flushCache() {
|
|
52
|
+
if (cache === undefined)
|
|
53
|
+
return;
|
|
32
54
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
await mkdir(getSnapshotsRoot(), { recursive: true });
|
|
56
|
+
await writeFile(cachePath(), JSON.stringify(cache, null, 2), "utf-8");
|
|
35
57
|
}
|
|
36
58
|
catch (err) {
|
|
37
59
|
console.error("[agent-whiteboard] viewport-cache write failed:", err instanceof Error ? err.message : String(err));
|
|
38
60
|
}
|
|
39
61
|
}
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Delay before a scheduled flush fires. Exported so tests can advance fake
|
|
64
|
+
* timers by exactly this amount instead of hardcoding a duplicate constant.
|
|
65
|
+
*/
|
|
66
|
+
export const VIEWPORT_CACHE_FLUSH_DELAY_MS = 250;
|
|
67
|
+
let flushTimer;
|
|
68
|
+
/**
|
|
69
|
+
* Coalesces bursts of writes (continuous zoom/pan produces many `setViewport`
|
|
70
|
+
* calls in quick succession) into a single disk write roughly
|
|
71
|
+
* `VIEWPORT_CACHE_FLUSH_DELAY_MS` after the first update in a burst, instead
|
|
72
|
+
* of a full synchronous rewrite per update. A timer already pending absorbs
|
|
73
|
+
* every subsequent call in the same burst — it is not reset per call, so a
|
|
74
|
+
* sustained stream of updates still flushes periodically rather than being
|
|
75
|
+
* postponed indefinitely.
|
|
76
|
+
*/
|
|
77
|
+
function scheduleFlush() {
|
|
78
|
+
if (flushTimer !== undefined)
|
|
79
|
+
return;
|
|
80
|
+
flushTimer = setTimeout(() => {
|
|
81
|
+
flushTimer = undefined;
|
|
82
|
+
void flushCache();
|
|
83
|
+
}, VIEWPORT_CACHE_FLUSH_DELAY_MS);
|
|
84
|
+
}
|
|
85
|
+
export async function getViewport(id, frameIndex) {
|
|
86
|
+
const c = await loadCache();
|
|
87
|
+
return c[cacheKey(id, frameIndex)];
|
|
42
88
|
}
|
|
43
|
-
export function
|
|
44
|
-
|
|
89
|
+
export async function setViewport(id, frameIndex, viewport) {
|
|
90
|
+
const c = await loadCache();
|
|
91
|
+
c[cacheKey(id, frameIndex)] = viewport;
|
|
92
|
+
scheduleFlush();
|
|
45
93
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Immediately flushes the in-memory cache to disk, bypassing (and cancelling)
|
|
96
|
+
* any pending debounced flush. Not needed in production — `setViewport`'s
|
|
97
|
+
* own scheduled flush is sufficient — but lets tests assert on-disk state
|
|
98
|
+
* deterministically without waiting on the real debounce delay or racing
|
|
99
|
+
* fake timers against real fs/promises I/O.
|
|
100
|
+
*/
|
|
101
|
+
export async function flushViewportCacheNow() {
|
|
102
|
+
if (flushTimer !== undefined) {
|
|
103
|
+
clearTimeout(flushTimer);
|
|
104
|
+
flushTimer = undefined;
|
|
105
|
+
}
|
|
106
|
+
await flushCache();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Drops the in-memory cache and cancels any pending flush, forcing the next
|
|
110
|
+
* call to reload from disk. Not needed in production (the snapshots root
|
|
111
|
+
* doesn't change at runtime); exists for tests whose fixtures recreate the
|
|
112
|
+
* snapshots directory on the same path between cases (`cachedForPath`'s
|
|
113
|
+
* path-based invalidation can't detect that on its own).
|
|
114
|
+
*/
|
|
115
|
+
export function resetViewportCacheForTest() {
|
|
116
|
+
cache = undefined;
|
|
117
|
+
cachedForPath = undefined;
|
|
118
|
+
if (flushTimer !== undefined) {
|
|
119
|
+
clearTimeout(flushTimer);
|
|
120
|
+
flushTimer = undefined;
|
|
121
|
+
}
|
|
50
122
|
}
|
|
51
|
-
export function deleteViewport(id) {
|
|
52
|
-
deleteViewports([id]);
|
|
123
|
+
export async function deleteViewport(id) {
|
|
124
|
+
await deleteViewports([id]);
|
|
53
125
|
}
|
|
54
126
|
/** Removes every per-frame entry for each given snapshot id (prefix match on "<id>:"). */
|
|
55
|
-
export function deleteViewports(ids) {
|
|
127
|
+
export async function deleteViewports(ids) {
|
|
56
128
|
if (ids.length === 0)
|
|
57
129
|
return;
|
|
58
|
-
const
|
|
130
|
+
const c = await loadCache();
|
|
59
131
|
const prefixes = ids.map((id) => `${id}:`);
|
|
60
132
|
let changed = false;
|
|
61
|
-
for (const key of Object.keys(
|
|
133
|
+
for (const key of Object.keys(c)) {
|
|
62
134
|
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
63
|
-
delete
|
|
135
|
+
delete c[key];
|
|
64
136
|
changed = true;
|
|
65
137
|
}
|
|
66
138
|
}
|
|
67
139
|
if (changed)
|
|
68
|
-
|
|
140
|
+
scheduleFlush();
|
|
69
141
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-whiteboard",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A domain-agnostic interactive whiteboard for AI teacher agents — render diagrams, math, charts, and HTML to a local browser tab via MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,16 +48,21 @@
|
|
|
48
48
|
"test": "vitest run",
|
|
49
49
|
"test:e2e": "playwright test",
|
|
50
50
|
"lint": "eslint .",
|
|
51
|
-
"lint:fix": "eslint . --fix"
|
|
51
|
+
"lint:fix": "eslint . --fix",
|
|
52
|
+
"prepublishOnly": "npm run build"
|
|
52
53
|
},
|
|
53
54
|
"dependencies": {
|
|
54
55
|
"@hono/node-server": "^1.13.7",
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
57
|
+
"@types/archiver": "^7.0.0",
|
|
56
58
|
"@types/dompurify": "^3.2.0",
|
|
59
|
+
"archiver": "^7.0.1",
|
|
57
60
|
"bootstrap": "^5.3.8",
|
|
58
|
-
"dompurify": "^3.4.
|
|
59
|
-
"
|
|
61
|
+
"dompurify": "^3.4.15",
|
|
62
|
+
"extract-zip": "^2.0.1",
|
|
60
63
|
"hono": "^4.7.11",
|
|
64
|
+
"jsdom": "^26.1.0",
|
|
65
|
+
"jszip": "^3.10.1",
|
|
61
66
|
"katex": "^0.17.0",
|
|
62
67
|
"mermaid": "^11.15.0",
|
|
63
68
|
"open": "^10.1.2",
|
|
@@ -69,10 +74,11 @@
|
|
|
69
74
|
"devDependencies": {
|
|
70
75
|
"@eslint/js": "^10.0.1",
|
|
71
76
|
"@playwright/test": "^1.60.0",
|
|
72
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
77
|
+
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
|
73
78
|
"@testing-library/jest-dom": "^6.9.1",
|
|
74
79
|
"@testing-library/svelte": "^4.2.3",
|
|
75
80
|
"@tsconfig/svelte": "^5.0.4",
|
|
81
|
+
"@types/jsdom": "^30.0.0",
|
|
76
82
|
"@types/node": "^20.17.57",
|
|
77
83
|
"@types/ws": "^8.18.1",
|
|
78
84
|
"concurrently": "^9.1.2",
|
|
@@ -85,8 +91,8 @@
|
|
|
85
91
|
"tsx": "^3.14.0",
|
|
86
92
|
"typescript": "^5.8.3",
|
|
87
93
|
"typescript-eslint": "^8.62.1",
|
|
88
|
-
"vite": "^4.
|
|
89
|
-
"vitest": "^
|
|
94
|
+
"vite": "^5.4.21",
|
|
95
|
+
"vitest": "^3.2.7",
|
|
90
96
|
"wait-on": "^8.0.3"
|
|
91
97
|
}
|
|
92
98
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as c,f as i}from"./mermaid-parser.core-52f9cd92.js";import"./index-ffc5af4b.js";export{c as ArchitectureModule,i as createArchitectureServices};
|