strikethroo 3.25.0 → 4.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/README.md +14 -0
- package/dist/cli.js +18 -0
- package/dist/cli.js.map +1 -1
- package/dist/export-profile.d.ts +6 -0
- package/dist/export-profile.d.ts.map +1 -1
- package/dist/export-profile.js +46 -4
- package/dist/export-profile.js.map +1 -1
- package/dist/metadata.d.ts +11 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +75 -11
- package/dist/metadata.js.map +1 -1
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +52 -7
- package/dist/profiles.js.map +1 -1
- package/dist/serve/config-write.d.ts +6 -3
- package/dist/serve/config-write.d.ts.map +1 -1
- package/dist/serve/config-write.js +20 -21
- package/dist/serve/config-write.js.map +1 -1
- package/dist/serve/events.d.ts +37 -8
- package/dist/serve/events.d.ts.map +1 -1
- package/dist/serve/events.js +114 -28
- package/dist/serve/events.js.map +1 -1
- package/dist/serve/self-review.d.ts +37 -7
- package/dist/serve/self-review.d.ts.map +1 -1
- package/dist/serve/self-review.js +93 -33
- package/dist/serve/self-review.js.map +1 -1
- package/dist/serve/server.d.ts +107 -0
- package/dist/serve/server.d.ts.map +1 -1
- package/dist/serve/server.js +502 -135
- package/dist/serve/server.js.map +1 -1
- package/dist/serve/workspace-model.d.ts.map +1 -1
- package/dist/serve/workspace-model.js +36 -34
- package/dist/serve/workspace-model.js.map +1 -1
- package/dist/skill-scripts/shared/safe-fs.d.ts +89 -0
- package/dist/skill-scripts/shared/safe-fs.d.ts.map +1 -0
- package/dist/skill-scripts/shared/safe-fs.js +324 -0
- package/dist/skill-scripts/shared/safe-fs.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +13 -1
- package/dist/types.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +15 -1
- package/dist/update.js.map +1 -1
- package/dist-web/assets/abnfDiagram-VCTEODGH-BCoAyQ8y.js +1 -0
- package/dist-web/assets/apl-gfMMiTNf.js +1 -0
- package/dist-web/assets/arc-Pry-7G1_.js +1 -0
- package/dist-web/assets/architecture-7GRP2DOG-C2Oj1AcH.js +1 -0
- package/dist-web/assets/architectureDiagram-5GKGNRK7-BbYvyste.js +36 -0
- package/dist-web/assets/array-BifhSqXX.js +1 -0
- package/dist-web/assets/asciiarmor-C_eisQCp.js +1 -0
- package/dist-web/assets/asn1-DCl_8MCW.js +1 -0
- package/dist-web/assets/asterisk-BEn0Cwpx.js +1 -0
- package/dist-web/assets/blockDiagram-I7D4REHJ-CGYIKoI0.js +129 -0
- package/dist-web/assets/brainfuck-D5EjA2JK.js +1 -0
- package/dist-web/assets/c4Diagram-7LVT6UL2-Cpat9Q1R.js +38 -0
- package/dist-web/assets/channel-Da0Eg5hZ.js +1 -0
- package/dist-web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist-web/assets/chunk-4HAMMTFA-D1PXshWJ.js +62 -0
- package/dist-web/assets/{chunk-FMBD7UC4-BxPfAX5i.js → chunk-5VM5RSS4-ZNzvKenW.js} +2 -2
- package/dist-web/assets/chunk-75Z2AOVW-C19f30iG.js +2 -0
- package/dist-web/assets/chunk-DU6HZSFF-CV-KOPc1.js +125 -0
- package/dist-web/assets/chunk-F27PBJKO-DMfX40T1.js +1 -0
- package/dist-web/assets/chunk-FOHPRMQF-DzxwRta7.js +161 -0
- package/dist-web/assets/chunk-GMAD6QVW-Nd9kACgc.js +72 -0
- package/dist-web/assets/chunk-GVQU2GXP-3G8ojGFe.js +1 -0
- package/dist-web/assets/chunk-IMKFNOWR-CmhGyHNd.js +231 -0
- package/dist-web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist-web/assets/chunk-L3NEJ4N5-Dsa1ER8Q.js +1 -0
- package/dist-web/assets/chunk-OSK3NFVY-ObCj9P3B.js +10 -0
- package/dist-web/assets/chunk-P2QGCYS3-CfNHqVGX.js +1 -0
- package/dist-web/assets/chunk-POPQ4Y6H-Cg5tk8by.js +1 -0
- package/dist-web/assets/chunk-PWAF6VOD-e6XMS-JR.js +1 -0
- package/dist-web/assets/chunk-SHT3W25Y-B1M0HI76.js +168 -0
- package/dist-web/assets/chunk-SVP7TREG-XLNHY4Z2.js +88 -0
- package/dist-web/assets/chunk-TICWLB2K-Bpm0S7rI.js +206 -0
- package/dist-web/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
- package/dist-web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist-web/assets/classDiagram-ZZMXUADV-CZI086hK.js +1 -0
- package/dist-web/assets/classDiagram-v2-VYDZK3BY-CZI086hK.js +1 -0
- package/dist-web/assets/clike-D_6L3tnO.js +1 -0
- package/dist-web/assets/clojure-BflJGmDX.js +1 -0
- package/dist-web/assets/cmake-84nbDH0I.js +1 -0
- package/dist-web/assets/cobol-DHLQUbN7.js +1 -0
- package/dist-web/assets/coffeescript-De_zI4J0.js +1 -0
- package/dist-web/assets/commonlisp-DgAKBe0r.js +1 -0
- package/dist-web/assets/cose-bilkent-JH36ORCC-BEpcWcmK.js +1 -0
- package/dist-web/assets/crystal-Bsdphhtm.js +1 -0
- package/dist-web/assets/css-CnaYoQib.js +1 -0
- package/dist-web/assets/cynefin-OW5HDTMX-B5ohibc7.js +1 -0
- package/dist-web/assets/cynefinDiagram-5FMLGOSQ-C1202n-x.js +62 -0
- package/dist-web/assets/cypher-p9eYesGn.js +1 -0
- package/dist-web/assets/cytoscape.esm-Yq6u8L66.js +321 -0
- package/dist-web/assets/d-DWkQyNnU.js +1 -0
- package/dist-web/assets/dagre-C-rnJpZF.js +1 -0
- package/dist-web/assets/dagre-GXQ25YYZ-CQlKKJXg.js +4 -0
- package/dist-web/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist-web/assets/diagram-S7CK7UJ4-DRf7iTH9.js +30 -0
- package/dist-web/assets/diagram-UQ7AKVKN-CxSX3b2_.js +41 -0
- package/dist-web/assets/diagram-VSXAHHWV-D9vrB5je.js +3 -0
- package/dist-web/assets/diagram-VX7I27RA-DTOqcpBV.js +24 -0
- package/dist-web/assets/diagram-Z3DM3KII-mlhRA4lR.js +24 -0
- package/dist-web/assets/diff-ChtP43wD.js +1 -0
- package/dist-web/assets/dist-B-O4eZD_.js +1 -0
- package/dist-web/assets/dist-B27L6oW0.js +1 -0
- package/dist-web/assets/dist-BKXbBuAc.js +1 -0
- package/dist-web/assets/dist-BPcC0hnc.js +9 -0
- package/dist-web/assets/dist-BgwxV8e_.js +1 -0
- package/dist-web/assets/dist-BlG40nRw.js +1 -0
- package/dist-web/assets/dist-Bqc6e86z.js +1 -0
- package/dist-web/assets/dist-BsvASXHG.js +1 -0
- package/dist-web/assets/dist-C15GN054.js +1 -0
- package/dist-web/assets/dist-C4QRmcTO.js +1 -0
- package/dist-web/assets/dist-C4lZy0XG.js +6 -0
- package/dist-web/assets/dist-CFLbFzpB.js +23 -0
- package/dist-web/assets/dist-CP6AUVtv.js +1 -0
- package/dist-web/assets/dist-CpYnHHz6.js +1 -0
- package/dist-web/assets/dist-DHnGmK79.js +1 -0
- package/dist-web/assets/dist-DYmIHv0n.js +13 -0
- package/dist-web/assets/dist-DauRO0RO.js +1 -0
- package/dist-web/assets/dist-Day7i26p.js +1 -0
- package/dist-web/assets/dist-Do_t70vA.js +1 -0
- package/dist-web/assets/dist-DqTG_rhR.js +2 -0
- package/dist-web/assets/dist-G8nWWSie.js +11 -0
- package/dist-web/assets/dist-QfYLz_N1.js +1 -0
- package/dist-web/assets/dist-TZhb2tj2.js +1 -0
- package/dist-web/assets/dist-Wr2Wo_KE.js +1 -0
- package/dist-web/assets/dist-kYRo7Db1.js +1 -0
- package/dist-web/assets/dist-kfqV1Lu-.js +2 -0
- package/dist-web/assets/dist-v5Q1xZ2K.js +1 -0
- package/dist-web/assets/dockerfile-DJkHQgkl.js +1 -0
- package/dist-web/assets/dtd-DTF72YNO.js +1 -0
- package/dist-web/assets/dylan-BCDoL_-p.js +1 -0
- package/dist-web/assets/ebnf-D4c0_ac3.js +1 -0
- package/dist-web/assets/ebnfDiagram-PWID7BFC-BhB_RJPM.js +1 -0
- package/dist-web/assets/ecl-BVIeWmwY.js +1 -0
- package/dist-web/assets/eiffel-BEjRio4Q.js +1 -0
- package/dist-web/assets/elm-Cshzl8qu.js +1 -0
- package/dist-web/assets/erDiagram-RLTQ6QDP-0wE1kPYz.js +99 -0
- package/dist-web/assets/erlang-BV0c4Hdn.js +1 -0
- package/dist-web/assets/esm-COEoxUhE.js +2 -0
- package/dist-web/assets/eventmodeling-NTZA5JFV-DzkXb9nA.js +1 -0
- package/dist-web/assets/factor-LKH5gN8L.js +1 -0
- package/dist-web/assets/fcl-ClOhbFR7.js +1 -0
- package/dist-web/assets/flowDiagram-HODETNUW-cgl8ipSt.js +1 -0
- package/dist-web/assets/forth-D6RzAl64.js +1 -0
- package/dist-web/assets/fortran-Bt6PBEDR.js +1 -0
- package/dist-web/assets/ganttDiagram-EL5Y4UJY-BsvlpHPt.js +292 -0
- package/dist-web/assets/gas-BHEdbvp9.js +1 -0
- package/dist-web/assets/gherkin-oBAE_ms0.js +1 -0
- package/dist-web/assets/gitGraph-4MIJSDKK-Dm82FCqy.js +1 -0
- package/dist-web/assets/gitGraphDiagram-WWUBYQGX-OPit_3vA.js +106 -0
- package/dist-web/assets/graphlib-DS17s2tU.js +1 -0
- package/dist-web/assets/groovy-CUpZ7dEl.js +1 -0
- package/dist-web/assets/haskell-BRsoo5mP.js +1 -0
- package/dist-web/assets/haxe-DjVOVvNP.js +1 -0
- package/dist-web/assets/http-CLVgA2GD.js +1 -0
- package/dist-web/assets/idl-BUZw3wgd.js +1 -0
- package/dist-web/assets/index-6XzOqB6r.js +103 -0
- package/dist-web/assets/index-CgIHUWsX.css +2 -0
- package/dist-web/assets/info-A6RAGUB7-8sl1XQWq.js +1 -0
- package/dist-web/assets/infoDiagram-27XIBGKW-DIpdnB7L.js +2 -0
- package/dist-web/assets/init-C-OQMol4.js +1 -0
- package/dist-web/assets/ishikawaDiagram-5VMMS53U-DpoLDWpF.js +70 -0
- package/dist-web/assets/javascript-Bu8mWwtz.js +1 -0
- package/dist-web/assets/journeyDiagram-3NMN7TZE-BAEbJ33U.js +139 -0
- package/dist-web/assets/julia-CQfgDRfP.js +1 -0
- package/dist-web/assets/kanban-definition-UXKFOSKX-CqzyUA0g.js +89 -0
- package/dist-web/assets/katex-ZlcWpGUi.js +257 -0
- package/dist-web/assets/line-CQRHrtV_.js +1 -0
- package/dist-web/assets/linear-SzVmGSw4.js +1 -0
- package/dist-web/assets/livescript-BXxG0Yva.js +1 -0
- package/dist-web/assets/lua-DPCEkfD_.js +1 -0
- package/dist-web/assets/mathematica-u8YMmbU0.js +1 -0
- package/dist-web/assets/mbox-BEMVcqjs.js +1 -0
- package/dist-web/assets/mermaid-parser.core-XlEvAPi2.js +7 -0
- package/dist-web/assets/mermaid.core-CvFTFi5O.js +44 -0
- package/dist-web/assets/mindmap-definition-YA3MSWOX-Ch0vW4Mc.js +96 -0
- package/dist-web/assets/{mirc-CjQqDB4T.js → mirc-C9zpzAZU.js} +1 -1
- package/dist-web/assets/mllike-B45xgp2S.js +1 -0
- package/dist-web/assets/modelica-CqHI_q-D.js +1 -0
- package/dist-web/assets/mscgen-qgSLujhx.js +1 -0
- package/dist-web/assets/mumps-BSzj6Xyz.js +1 -0
- package/dist-web/assets/{nginx-DdIZxoE0.js → nginx-8H7HVH4w.js} +1 -1
- package/dist-web/assets/nsis-CfSuhXs5.js +1 -0
- package/dist-web/assets/ntriples-B9h1VB_g.js +1 -0
- package/dist-web/assets/octave-D2Q8cUp1.js +1 -0
- package/dist-web/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist-web/assets/oz-BwTct_5T.js +1 -0
- package/dist-web/assets/packet-AYTQ26CC-lk-QU-qZ.js +1 -0
- package/dist-web/assets/pascal-Dp_KdFgX.js +1 -0
- package/dist-web/assets/path-fybaL0A-.js +1 -0
- package/dist-web/assets/pegDiagram-XKGWAZYB-Cgf4CYg-.js +1 -0
- package/dist-web/assets/perl-BkSkiI9m.js +1 -0
- package/dist-web/assets/pie-WAS4IAKB-dWyVjg9O.js +1 -0
- package/dist-web/assets/pieDiagram-E7YTZNPT-BDZxWO8n.js +39 -0
- package/dist-web/assets/pig-AF4Hwhju.js +1 -0
- package/dist-web/assets/powershell-BcIto6Sf.js +1 -0
- package/dist-web/assets/properties-C357ku5U.js +1 -0
- package/dist-web/assets/protobuf-D1ij_kNL.js +1 -0
- package/dist-web/assets/pug-3K-JMW4g.js +1 -0
- package/dist-web/assets/puppet-BZyAS7I4.js +1 -0
- package/dist-web/assets/python-B_1Jd8HM.js +1 -0
- package/dist-web/assets/q-B9NhS7L_.js +1 -0
- package/dist-web/assets/quadrantDiagram-AXDQQJYC-DCu9cx1_.js +7 -0
- package/dist-web/assets/r-CxDmU1I4.js +1 -0
- package/dist-web/assets/radar-RG4KPBEZ-CphwvESj.js +1 -0
- package/dist-web/assets/railroad-74A4TZTK-COTrvtXu.js +1 -0
- package/dist-web/assets/railroad-abnf-HS5TGJTU-CYfpugMj.js +1 -0
- package/dist-web/assets/railroad-ebnf-LZEXJU2U--Ui_4jm6.js +1 -0
- package/dist-web/assets/railroad-peg-WCYAUIDC-DzcveMan.js +1 -0
- package/dist-web/assets/railroadDiagram-O6MQD6OU-S9ZI1Adi.js +1 -0
- package/dist-web/assets/requirementDiagram-BXWQKSXE-a_3FElqS.js +84 -0
- package/dist-web/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/dist-web/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist-web/assets/rpm-gpDK5sbt.js +1 -0
- package/dist-web/assets/ruby-BjXV7-Qa.js +1 -0
- package/dist-web/assets/sankeyDiagram-P5KCCOFB-D-i6r8wy.js +40 -0
- package/dist-web/assets/{sas-B4kiWyti.js → sas-C2OyD2Y6.js} +1 -1
- package/dist-web/assets/scheme-D9qYN0V5.js +1 -0
- package/dist-web/assets/sequenceDiagram-WJ2MYXX4-D8hA2m0U.js +162 -0
- package/dist-web/assets/shell-DwuoZtxw.js +1 -0
- package/dist-web/assets/sieve-tLWDfEkZ.js +1 -0
- package/dist-web/assets/simple-mode-DXiLM1-G.js +1 -0
- package/dist-web/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/dist-web/assets/smalltalk-BLp5-jwC.js +1 -0
- package/dist-web/assets/solr-B78wSQJQ.js +1 -0
- package/dist-web/assets/sparql-Dz-mlCAC.js +1 -0
- package/dist-web/assets/spreadsheet-CTIncYxj.js +1 -0
- package/dist-web/assets/sql-DuQMFDvy.js +1 -0
- package/dist-web/assets/src-B6xuSHsQ.js +1 -0
- package/dist-web/assets/stateDiagram-D77RDMKH-C14W-8zT.js +1 -0
- package/dist-web/assets/stateDiagram-v2-MP3YSRHH-Dhuhsub3.js +1 -0
- package/dist-web/assets/stex-DNzd62Q_.js +1 -0
- package/dist-web/assets/stylus-BOVgKnng.js +1 -0
- package/dist-web/assets/swift-DKB6_1j6.js +1 -0
- package/dist-web/assets/swimlanes-42K2YHIH-FMv8YLkC.js +1 -0
- package/dist-web/assets/swimlanesDiagram-VR7AAH4N-O94a9jW3.js +8 -0
- package/dist-web/assets/tcl-BGfruO1u.js +1 -0
- package/dist-web/assets/textile-C4jVoHG1.js +1 -0
- package/dist-web/assets/tiddlywiki-VlUiK86J.js +1 -0
- package/dist-web/assets/tiki-AK6FwT8q.js +1 -0
- package/dist-web/assets/timeline-definition-24CTP7MA-DmBN45fY.js +120 -0
- package/dist-web/assets/toml-BPTmHmyx.js +1 -0
- package/dist-web/assets/treeView-Q6P3EWNA-C5-PUnPN.js +1 -0
- package/dist-web/assets/treemap-WGGIJYW6-C_veVYMi.js +1 -0
- package/dist-web/assets/troff-C2dAgh7P.js +1 -0
- package/dist-web/assets/ttcn-PPSTk1ow.js +1 -0
- package/dist-web/assets/ttcn-cfg-2b4Gb5sE.js +1 -0
- package/dist-web/assets/turtle-Cx3rYX2g.js +1 -0
- package/dist-web/assets/vb-BthdM_4N.js +1 -0
- package/dist-web/assets/vbscript-D9f6rSsU.js +1 -0
- package/dist-web/assets/velocity-CqftRsjg.js +1 -0
- package/dist-web/assets/vennDiagram-4TSXK5OY-CiWHjSVc.js +34 -0
- package/dist-web/assets/verilog-CjI9Y6RI.js +1 -0
- package/dist-web/assets/vhdl-kS471soi.js +1 -0
- package/dist-web/assets/wardley-WFR3VGLG-FOCO1NlU.js +1 -0
- package/dist-web/assets/wardleyDiagram-VM6X3IG4-Da3kkvxV.js +78 -0
- package/dist-web/assets/webidl-D5jiJvOU.js +1 -0
- package/dist-web/assets/xquery-BKJx4mf9.js +1 -0
- package/dist-web/assets/xychartDiagram-S5SC5T6Z-DPxie1fH.js +7 -0
- package/dist-web/assets/yacas-CXXgtw0p.js +1 -0
- package/dist-web/assets/z80-Co3PbHdE.js +1 -0
- package/dist-web/index.html +6 -18
- package/dist-web/theme-guard.js +21 -0
- package/package.json +29 -24
- package/templates/strikethroo/config/config.yaml +7 -4
- package/dist-web/assets/apl-B4CMkyY2.js +0 -1
- package/dist-web/assets/arc-D8anvcX-.js +0 -1
- package/dist-web/assets/architectureDiagram-3BPJPVTR-CGfqArN_.js +0 -36
- package/dist-web/assets/asciiarmor-Df11BRmG.js +0 -1
- package/dist-web/assets/asn1-EdZsLKOL.js +0 -1
- package/dist-web/assets/asterisk-B-8jnY81.js +0 -1
- package/dist-web/assets/blockDiagram-GPEHLZMM-CHzLIPZe.js +0 -132
- package/dist-web/assets/brainfuck-C4LP7Hcl.js +0 -1
- package/dist-web/assets/c4Diagram-AAUBKEIU-9rRidvsm.js +0 -10
- package/dist-web/assets/channel-DgcCmM1I.js +0 -1
- package/dist-web/assets/chunk-2J33WTMH-C39TKr_M.js +0 -1
- package/dist-web/assets/chunk-4BX2VUAB-C2djuG3T.js +0 -1
- package/dist-web/assets/chunk-55IACEB6-DWqTM520.js +0 -1
- package/dist-web/assets/chunk-727SXJPM-rovNVJJP.js +0 -206
- package/dist-web/assets/chunk-AQP2D5EJ-CHH1etIO.js +0 -231
- package/dist-web/assets/chunk-ND2GUHAM-C8MhIE2B.js +0 -1
- package/dist-web/assets/chunk-QZHKN3VN-63gK6NbV.js +0 -1
- package/dist-web/assets/classDiagram-4FO5ZUOK-C0z0eFyi.js +0 -1
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-C0z0eFyi.js +0 -1
- package/dist-web/assets/clike-B9uivgTg.js +0 -1
- package/dist-web/assets/clojure-BMjYHr_A.js +0 -1
- package/dist-web/assets/cmake-BQqOBYOt.js +0 -1
- package/dist-web/assets/cobol-CWcv1MsR.js +0 -1
- package/dist-web/assets/coffeescript-S37ZYGWr.js +0 -1
- package/dist-web/assets/commonlisp-DBKNyK5s.js +0 -1
- package/dist-web/assets/cose-bilkent-S5V4N54A-COtPU2p7.js +0 -1
- package/dist-web/assets/crystal-SjHAIU92.js +0 -1
- package/dist-web/assets/css-BnMrqG3P.js +0 -1
- package/dist-web/assets/cypher-C_CwsFkJ.js +0 -1
- package/dist-web/assets/cytoscape.esm-BHYC38rz.js +0 -331
- package/dist-web/assets/d-pRatUO7H.js +0 -1
- package/dist-web/assets/dagre-BM42HDAG-Av_BDeN2.js +0 -4
- package/dist-web/assets/defaultLocale-CrowFXzY.js +0 -1
- package/dist-web/assets/diagram-2AECGRRQ-TPYX18Ua.js +0 -43
- package/dist-web/assets/diagram-5GNKFQAL-DtQI3PSq.js +0 -10
- package/dist-web/assets/diagram-KO2AKTUF-DNXbi8Vg.js +0 -3
- package/dist-web/assets/diagram-LMA3HP47-Bl0b9O4C.js +0 -24
- package/dist-web/assets/diagram-OG6HWLK6-DboL6tB3.js +0 -24
- package/dist-web/assets/diff-DbItnlRl.js +0 -1
- package/dist-web/assets/dockerfile-BKs6k2Af.js +0 -1
- package/dist-web/assets/dtd-DF_7sFjM.js +0 -1
- package/dist-web/assets/dylan-DwRh75JA.js +0 -1
- package/dist-web/assets/ebnf-CDyGwa7X.js +0 -1
- package/dist-web/assets/ecl-Cabwm37j.js +0 -1
- package/dist-web/assets/eiffel-CnydiIhH.js +0 -1
- package/dist-web/assets/elm-vLlmbW-K.js +0 -1
- package/dist-web/assets/erDiagram-TEJ5UH35-BbYxGrzg.js +0 -85
- package/dist-web/assets/erlang-BNw1qcRV.js +0 -1
- package/dist-web/assets/factor-kuTfRLto.js +0 -1
- package/dist-web/assets/fcl-Kvtd6kyn.js +0 -1
- package/dist-web/assets/flowDiagram-I6XJVG4X-bgw4_MAe.js +0 -162
- package/dist-web/assets/forth-Ffai-XNe.js +0 -1
- package/dist-web/assets/fortran-DYz_wnZ1.js +0 -1
- package/dist-web/assets/ganttDiagram-6RSMTGT7-D_LznzPz.js +0 -292
- package/dist-web/assets/gas-Bneqetm1.js +0 -1
- package/dist-web/assets/gherkin-heZmZLOM.js +0 -1
- package/dist-web/assets/gitGraphDiagram-PVQCEYII-DIsJhn0o.js +0 -106
- package/dist-web/assets/graph-Dqkl27Ch.js +0 -1
- package/dist-web/assets/groovy-D9Dt4D0W.js +0 -1
- package/dist-web/assets/haskell-BWDZoCOh.js +0 -1
- package/dist-web/assets/haxe-H-WmDvRZ.js +0 -1
- package/dist-web/assets/http-DBlCnlav.js +0 -1
- package/dist-web/assets/idl-BEugSyMb.js +0 -1
- package/dist-web/assets/index-B-KlYMEI.js +0 -1
- package/dist-web/assets/index-B0a4C4Lb.js +0 -1
- package/dist-web/assets/index-B90tvIxG.js +0 -3
- package/dist-web/assets/index-BLXIwDvb.js +0 -1
- package/dist-web/assets/index-BdEHUYQj.js +0 -169
- package/dist-web/assets/index-BjZYUODU.js +0 -1
- package/dist-web/assets/index-BmsczLPZ.js +0 -1
- package/dist-web/assets/index-BpU7RpGz.js +0 -1
- package/dist-web/assets/index-C53NKwQ5.js +0 -1
- package/dist-web/assets/index-C73riuQN.js +0 -1
- package/dist-web/assets/index-C9RcHSPW.js +0 -1
- package/dist-web/assets/index-CEBV-m_B.js +0 -1
- package/dist-web/assets/index-CG1O2Vjg.js +0 -1
- package/dist-web/assets/index-CQ8MJGW7.js +0 -2
- package/dist-web/assets/index-CddJufqj.js +0 -1
- package/dist-web/assets/index-CrzBaw1K.css +0 -1
- package/dist-web/assets/index-CuBsNWzH.js +0 -13
- package/dist-web/assets/index-CuCAyRTw.js +0 -7
- package/dist-web/assets/index-CuUh3dvS.js +0 -1
- package/dist-web/assets/index-CwPWc9jQ.js +0 -1
- package/dist-web/assets/index-DHBbud_j.js +0 -1
- package/dist-web/assets/index-LLaxWDbg.js +0 -1
- package/dist-web/assets/index-XOpAvr0E.js +0 -13
- package/dist-web/assets/index-lkaAPBmM.js +0 -6
- package/dist-web/assets/index-pUkuW0EP.js +0 -1
- package/dist-web/assets/index-sbfqG9cy.js +0 -1
- package/dist-web/assets/index-udFbjSlZ.js +0 -2
- package/dist-web/assets/index-uwcaE2d7.js +0 -2
- package/dist-web/assets/index-yjEPVwyN.js +0 -1
- package/dist-web/assets/infoDiagram-5YYISTIA-DUEtO7Ix.js +0 -2
- package/dist-web/assets/init-Gi6I4Gst.js +0 -1
- package/dist-web/assets/ishikawaDiagram-YF4QCWOH-Ctv84Jbw.js +0 -70
- package/dist-web/assets/javascript-qCveANmP.js +0 -1
- package/dist-web/assets/journeyDiagram-JHISSGLW-DILNkNlL.js +0 -139
- package/dist-web/assets/julia-DuME0IfC.js +0 -1
- package/dist-web/assets/kanban-definition-UN3LZRKU-BO7sq2cF.js +0 -89
- package/dist-web/assets/katex-C5jXJg4s.js +0 -257
- package/dist-web/assets/layout-DO9UvE1P.js +0 -1
- package/dist-web/assets/linear-DOC1-cx3.js +0 -1
- package/dist-web/assets/livescript-BwQOo05w.js +0 -1
- package/dist-web/assets/lua-VAEuO923.js +0 -1
- package/dist-web/assets/mathematica-DTrFuWx2.js +0 -1
- package/dist-web/assets/mbox-CNhZ1qSd.js +0 -1
- package/dist-web/assets/mermaid.core-DqgK5FaN.js +0 -307
- package/dist-web/assets/mindmap-definition-RKZ34NQL-BnOJs-M5.js +0 -96
- package/dist-web/assets/mllike-CXdrOF99.js +0 -1
- package/dist-web/assets/modelica-Dc1JOy9r.js +0 -1
- package/dist-web/assets/mscgen-BA5vi2Kp.js +0 -1
- package/dist-web/assets/mumps-BT43cFF4.js +0 -1
- package/dist-web/assets/nsis-LdVXkNf5.js +0 -1
- package/dist-web/assets/ntriples-BfvgReVJ.js +0 -1
- package/dist-web/assets/octave-Ck1zUtKM.js +0 -1
- package/dist-web/assets/ordinal-Cboi1Yqb.js +0 -1
- package/dist-web/assets/oz-BzwKVEFT.js +0 -1
- package/dist-web/assets/pascal--L3eBynH.js +0 -1
- package/dist-web/assets/perl-CdXCOZ3F.js +0 -1
- package/dist-web/assets/pieDiagram-4H26LBE5-CscOm59p.js +0 -30
- package/dist-web/assets/pig-CevX1Tat.js +0 -1
- package/dist-web/assets/powershell-CFHJl5sT.js +0 -1
- package/dist-web/assets/properties-C78fOPTZ.js +0 -1
- package/dist-web/assets/protobuf-ChK-085T.js +0 -1
- package/dist-web/assets/pug-DukmZTjD.js +0 -1
- package/dist-web/assets/puppet-DMA9R1ak.js +0 -1
- package/dist-web/assets/python-BuPzkPfP.js +0 -1
- package/dist-web/assets/q-pXgVlZs6.js +0 -1
- package/dist-web/assets/quadrantDiagram-W4KKPZXB-IVu2Npzf.js +0 -7
- package/dist-web/assets/r-DUYO_cvP.js +0 -1
- package/dist-web/assets/requirementDiagram-4Y6WPE33-BbDNPPBQ.js +0 -84
- package/dist-web/assets/rpm-CTu-6PCP.js +0 -1
- package/dist-web/assets/ruby-B2Rjki9n.js +0 -1
- package/dist-web/assets/sankeyDiagram-5OEKKPKP-DcjXnlMj.js +0 -40
- package/dist-web/assets/scheme-C41bIUwD.js +0 -1
- package/dist-web/assets/sequenceDiagram-3UESZ5HK-B_Jw3NhT.js +0 -162
- package/dist-web/assets/shell-CjFT_Tl9.js +0 -1
- package/dist-web/assets/sieve-C3Gn_uJK.js +0 -1
- package/dist-web/assets/simple-mode-GW_nhZxv.js +0 -1
- package/dist-web/assets/smalltalk-CnHTOXQT.js +0 -1
- package/dist-web/assets/solr-DehyRSwq.js +0 -1
- package/dist-web/assets/sparql-DkYu6x3z.js +0 -1
- package/dist-web/assets/spreadsheet-BCZA_wO0.js +0 -1
- package/dist-web/assets/sql-D0XecflT.js +0 -1
- package/dist-web/assets/stateDiagram-AJRCARHV-CyQirMnx.js +0 -1
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-o71gojBr.js +0 -1
- package/dist-web/assets/stex-C3f8Ysf7.js +0 -1
- package/dist-web/assets/stylus-B533Al4x.js +0 -1
- package/dist-web/assets/swift-BzpIVaGY.js +0 -1
- package/dist-web/assets/tcl-DVfN8rqt.js +0 -1
- package/dist-web/assets/textile-CnDTJFAw.js +0 -1
- package/dist-web/assets/tiddlywiki-DO-Gjzrf.js +0 -1
- package/dist-web/assets/tiki-DGYXhP31.js +0 -1
- package/dist-web/assets/timeline-definition-PNZ67QCA-0X5ctUMy.js +0 -120
- package/dist-web/assets/toml-Bm5Em-hy.js +0 -1
- package/dist-web/assets/troff-wAsdV37c.js +0 -1
- package/dist-web/assets/ttcn-CfJYG6tj.js +0 -1
- package/dist-web/assets/ttcn-cfg-B9xdYoR4.js +0 -1
- package/dist-web/assets/turtle-B1tBg_DP.js +0 -1
- package/dist-web/assets/vb-CmGdzxic.js +0 -1
- package/dist-web/assets/vbscript-BuJXcnF6.js +0 -1
- package/dist-web/assets/velocity-D8B20fx6.js +0 -1
- package/dist-web/assets/vennDiagram-CIIHVFJN-BbO0uHQQ.js +0 -34
- package/dist-web/assets/verilog-C6RDOZhf.js +0 -1
- package/dist-web/assets/vhdl-lSbBsy5d.js +0 -1
- package/dist-web/assets/wardley-L42UT6IY-maQQ80J4.js +0 -173
- package/dist-web/assets/wardleyDiagram-YWT4CUSO-BIswUO4D.js +0 -78
- package/dist-web/assets/webidl-ZXfAyPTL.js +0 -1
- package/dist-web/assets/xquery-CQfU5ijd.js +0 -1
- package/dist-web/assets/xychartDiagram-2RQKCTM6-DUBe_cWp.js +0 -7
- package/dist-web/assets/yacas-BJ4BC0dw.js +0 -1
- package/dist-web/assets/z80-Hz9HOZM7.js +0 -1
|
@@ -15,9 +15,12 @@
|
|
|
15
15
|
* to the workspace's structured configuration file `config/config.yaml` (the
|
|
16
16
|
* file behind the Customize section's Config form). In every case the target
|
|
17
17
|
* file must ALREADY exist (this never creates a new file). When the guards
|
|
18
|
-
* pass it overwrites the file content verbatim
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* pass it overwrites the file content verbatim through the shared containment
|
|
19
|
+
* helper, so a symlinked file or directory anywhere below the workspace root
|
|
20
|
+
* (or a non-regular file at the target) is refused as `not-found` rather than
|
|
21
|
+
* followed. It never deletes or renames the target itself. Expected guard
|
|
22
|
+
* failures are returned as a typed result, not thrown; only an unexpected
|
|
23
|
+
* filesystem error surfaces as `fs-error`. Node built-ins only.
|
|
21
24
|
*/
|
|
22
25
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
26
|
if (k2 === undefined) k2 = k;
|
|
@@ -54,8 +57,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
54
57
|
})();
|
|
55
58
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
59
|
exports.writeConfigFile = void 0;
|
|
57
|
-
const fs = __importStar(require("fs"));
|
|
58
60
|
const path = __importStar(require("path"));
|
|
61
|
+
const safe_fs_1 = require("../skill-scripts/shared/safe-fs");
|
|
59
62
|
/** The directory-backed config kinds that may be written. */
|
|
60
63
|
const KINDS = new Set(['hooks', 'templates']);
|
|
61
64
|
/**
|
|
@@ -66,14 +69,15 @@ const KINDS = new Set(['hooks', 'templates']);
|
|
|
66
69
|
* performs zero filesystem changes on any guard failure.
|
|
67
70
|
*/
|
|
68
71
|
const writeConfigFile = async (root, kind, id, content) => {
|
|
69
|
-
|
|
72
|
+
/** Target path relative to `root`; the helper does the on-disk containment. */
|
|
73
|
+
let relTarget;
|
|
70
74
|
if (kind === 'workspace') {
|
|
71
75
|
// The workspace's single structured config file. No id namespace exists
|
|
72
76
|
// here — `config` is the only valid id, fixed to config/config.yaml.
|
|
73
77
|
if (id !== 'config') {
|
|
74
78
|
return { ok: false, reason: 'invalid-id', message: 'Invalid config file id.' };
|
|
75
79
|
}
|
|
76
|
-
|
|
80
|
+
relTarget = path.join('config', 'config.yaml');
|
|
77
81
|
}
|
|
78
82
|
else {
|
|
79
83
|
if (!KINDS.has(kind)) {
|
|
@@ -84,30 +88,25 @@ const writeConfigFile = async (root, kind, id, content) => {
|
|
|
84
88
|
return { ok: false, reason: 'invalid-id', message: 'Invalid config file id.' };
|
|
85
89
|
}
|
|
86
90
|
const dir = path.resolve(root, 'config', kind);
|
|
87
|
-
target = path.resolve(dir, `${id}.md`);
|
|
88
|
-
//
|
|
91
|
+
const target = path.resolve(dir, `${id}.md`);
|
|
92
|
+
// Lexical containment: the resolved target must be a direct, flat child of
|
|
93
|
+
// `dir`. The on-disk walk below is what rejects links and special files.
|
|
89
94
|
const withinDir = target.startsWith(dir + path.sep);
|
|
90
95
|
const isFlatChild = path.dirname(target) === dir;
|
|
91
96
|
if (!withinDir || !isFlatChild) {
|
|
92
97
|
return { ok: false, reason: 'invalid-id', message: 'Invalid config file id.' };
|
|
93
98
|
}
|
|
99
|
+
relTarget = path.join('config', kind, `${id}.md`);
|
|
94
100
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (!stat.isFile()) {
|
|
98
|
-
return { ok: false, reason: 'not-found', message: 'Config file not found.' };
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return { ok: false, reason: 'not-found', message: 'Config file not found.' };
|
|
103
|
-
}
|
|
104
|
-
try {
|
|
105
|
-
await fs.promises.writeFile(target, content, 'utf8');
|
|
101
|
+
const written = await (0, safe_fs_1.writeFileAtomic)(root, relTarget, content, { mustExist: true });
|
|
102
|
+
if (!('error' in written))
|
|
106
103
|
return { ok: true };
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
// Anything the helper refused to resolve (missing, linked, special, escaped)
|
|
105
|
+
// is reported as absent; only a genuine I/O failure is an fs-error.
|
|
106
|
+
if (written.error === 'fs-error' || written.error === 'too-large') {
|
|
109
107
|
return { ok: false, reason: 'fs-error', message: 'Failed to write config file.' };
|
|
110
108
|
}
|
|
109
|
+
return { ok: false, reason: 'not-found', message: 'Config file not found.' };
|
|
111
110
|
};
|
|
112
111
|
exports.writeConfigFile = writeConfigFile;
|
|
113
112
|
//# sourceMappingURL=config-write.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-write.js","sourceRoot":"","sources":["../../src/serve/config-write.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"config-write.js","sourceRoot":"","sources":["../../src/serve/config-write.ts"],"names":[],"mappings":"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"}
|
package/dist/serve/events.d.ts
CHANGED
|
@@ -3,15 +3,30 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides `GET /api/events`: a `text/event-stream` that broadcasts a single
|
|
5
5
|
* coalesced `changed` ping whenever the workspace mutates on disk. The event
|
|
6
|
-
* carries no diff payload — clients refetch the affected API data
|
|
7
|
-
* consumer is a later plan).
|
|
6
|
+
* carries no diff payload — clients refetch the affected API data.
|
|
8
7
|
*
|
|
9
8
|
* Exposes an {@link EventsHub} that owns the connected-client set and the
|
|
10
9
|
* workspace watcher, plus an `ApiHandler` the server registers so this module
|
|
11
|
-
* stays decoupled from routing.
|
|
12
|
-
*
|
|
10
|
+
* stays decoupled from routing. Delivery is bounded per session: at most
|
|
11
|
+
* {@link MAX_SSE_CLIENTS} streams are admitted, a client whose socket stops
|
|
12
|
+
* accepting data is written to only once more (one coalesced `changed` on
|
|
13
|
+
* `drain`), and one still blocked after {@link BLOCKED_TIMEOUT_MS} is ended and
|
|
14
|
+
* removed. Disconnect and {@link EventsHub.close} release every per-client
|
|
15
|
+
* timer and listener so nothing leaks. Node built-ins only.
|
|
13
16
|
*/
|
|
14
17
|
import * as http from 'http';
|
|
18
|
+
/** Keep-alive comment interval (ms) to hold idle proxies/streams open. */
|
|
19
|
+
export declare const KEEP_ALIVE_MS = 15000;
|
|
20
|
+
/** Upper bound on concurrently connected SSE clients per hub. */
|
|
21
|
+
export declare const MAX_SSE_CLIENTS = 16;
|
|
22
|
+
/** How long (ms) a client may stay blocked on backpressure before it is dropped. */
|
|
23
|
+
export declare const BLOCKED_TIMEOUT_MS = 30000;
|
|
24
|
+
/** The compiled bounds; tests shorten them through the constructor. */
|
|
25
|
+
export interface EventsHubLimits {
|
|
26
|
+
maxClients: number;
|
|
27
|
+
blockedTimeoutMs: number;
|
|
28
|
+
keepAliveMs: number;
|
|
29
|
+
}
|
|
15
30
|
/**
|
|
16
31
|
* Owns the SSE client set and the workspace watcher. One hub per server. Start
|
|
17
32
|
* the watcher with {@link start} after the server is listening; release it with
|
|
@@ -22,16 +37,30 @@ export declare class EventsHub {
|
|
|
22
37
|
private readonly debounceMs?;
|
|
23
38
|
private readonly clients;
|
|
24
39
|
private watcher;
|
|
25
|
-
|
|
40
|
+
private readonly limits;
|
|
41
|
+
constructor(workspaceDir: string, debounceMs?: number | undefined, limits?: Partial<EventsHubLimits>);
|
|
26
42
|
/** Begins watching the workspace; coalesced changes broadcast to all clients. */
|
|
27
43
|
start(): void;
|
|
28
44
|
/** Stops the watcher and ends every open client connection. */
|
|
29
45
|
close(): void;
|
|
30
46
|
/** Number of currently connected SSE clients (used by tests). */
|
|
31
47
|
get clientCount(): number;
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
/**
|
|
48
|
+
/** Number of connected clients currently held back by backpressure. */
|
|
49
|
+
get blockedClientCount(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Sends a single coalesced `changed` event to every connected client. A
|
|
52
|
+
* blocked client is owed exactly one `changed` on `drain`, however many
|
|
53
|
+
* broadcasts it misses. Called by the watcher; public so tests can drive the
|
|
54
|
+
* stream without touching disk.
|
|
55
|
+
*/
|
|
56
|
+
broadcast(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Writes one chunk, honoring backpressure: when `write()` returns `false` the
|
|
59
|
+
* client is marked blocked, further writes are skipped, a `drain` listener is
|
|
60
|
+
* armed to resume, and the slow timer starts.
|
|
61
|
+
*/
|
|
62
|
+
private send;
|
|
63
|
+
/** Attaches an SSE response, or refuses it with `503` when at capacity. */
|
|
35
64
|
handleConnection(req: http.IncomingMessage, res: http.ServerResponse): void;
|
|
36
65
|
/** An {@link ApiHandler} for `GET /api/events`; returns false otherwise. */
|
|
37
66
|
apiHandler: (req: http.IncomingMessage, res: http.ServerResponse, ctx: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,0EAA0E;AAC1E,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,iEAAiE;AACjE,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAQxC,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD;;;;GAIG;AACH,qBAAa,SAAS;IAMlB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAN9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+C;IACvE,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAGtB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,YAAA,EACpC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM;IASvC,iFAAiF;IACjF,KAAK,IAAI,IAAI;IASb,+DAA+D;IAC/D,KAAK,IAAI,IAAI;IAab,iEAAiE;IACjE,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,uEAAuE;IACvE,IAAI,kBAAkB,IAAI,MAAM,CAI/B;IAED;;;;;OAKG;IACH,SAAS,IAAI,IAAI;IAOjB;;;;OAIG;IACH,OAAO,CAAC,IAAI;IAYZ,2EAA2E;IAC3E,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,GAAG,IAAI;IAyD3E,4EAA4E;IAC5E,UAAU,GACR,KAAK,IAAI,CAAC,eAAe,EACzB,KAAK,IAAI,CAAC,cAAc,EACxB,KAAK;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KACxB,OAAO,CAMR;CACH"}
|
package/dist/serve/events.js
CHANGED
|
@@ -4,29 +4,40 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Provides `GET /api/events`: a `text/event-stream` that broadcasts a single
|
|
6
6
|
* coalesced `changed` ping whenever the workspace mutates on disk. The event
|
|
7
|
-
* carries no diff payload — clients refetch the affected API data
|
|
8
|
-
* consumer is a later plan).
|
|
7
|
+
* carries no diff payload — clients refetch the affected API data.
|
|
9
8
|
*
|
|
10
9
|
* Exposes an {@link EventsHub} that owns the connected-client set and the
|
|
11
10
|
* workspace watcher, plus an `ApiHandler` the server registers so this module
|
|
12
|
-
* stays decoupled from routing.
|
|
13
|
-
*
|
|
11
|
+
* stays decoupled from routing. Delivery is bounded per session: at most
|
|
12
|
+
* {@link MAX_SSE_CLIENTS} streams are admitted, a client whose socket stops
|
|
13
|
+
* accepting data is written to only once more (one coalesced `changed` on
|
|
14
|
+
* `drain`), and one still blocked after {@link BLOCKED_TIMEOUT_MS} is ended and
|
|
15
|
+
* removed. Disconnect and {@link EventsHub.close} release every per-client
|
|
16
|
+
* timer and listener so nothing leaks. Node built-ins only.
|
|
14
17
|
*/
|
|
15
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.EventsHub = void 0;
|
|
19
|
+
exports.EventsHub = exports.BLOCKED_TIMEOUT_MS = exports.MAX_SSE_CLIENTS = exports.KEEP_ALIVE_MS = void 0;
|
|
17
20
|
const watcher_1 = require("./watcher");
|
|
18
21
|
/** Keep-alive comment interval (ms) to hold idle proxies/streams open. */
|
|
19
|
-
|
|
22
|
+
exports.KEEP_ALIVE_MS = 15000;
|
|
23
|
+
/** Upper bound on concurrently connected SSE clients per hub. */
|
|
24
|
+
exports.MAX_SSE_CLIENTS = 16;
|
|
25
|
+
/** How long (ms) a client may stay blocked on backpressure before it is dropped. */
|
|
26
|
+
exports.BLOCKED_TIMEOUT_MS = 30000;
|
|
27
|
+
/** `Retry-After` (seconds) sent with the `503` for a refused connection. */
|
|
28
|
+
const RETRY_AFTER_SECONDS = 5;
|
|
29
|
+
const CHANGED_EVENT = 'event: changed\ndata: {}\n\n';
|
|
30
|
+
const KEEP_ALIVE_COMMENT = ': keep-alive\n\n';
|
|
20
31
|
/**
|
|
21
32
|
* Owns the SSE client set and the workspace watcher. One hub per server. Start
|
|
22
33
|
* the watcher with {@link start} after the server is listening; release it with
|
|
23
34
|
* {@link close} when the server closes.
|
|
24
35
|
*/
|
|
25
36
|
class EventsHub {
|
|
26
|
-
constructor(workspaceDir, debounceMs) {
|
|
37
|
+
constructor(workspaceDir, debounceMs, limits = {}) {
|
|
27
38
|
this.workspaceDir = workspaceDir;
|
|
28
39
|
this.debounceMs = debounceMs;
|
|
29
|
-
this.clients = new
|
|
40
|
+
this.clients = new Map();
|
|
30
41
|
this.watcher = null;
|
|
31
42
|
/** An {@link ApiHandler} for `GET /api/events`; returns false otherwise. */
|
|
32
43
|
this.apiHandler = (req, res, ctx) => {
|
|
@@ -36,6 +47,11 @@ class EventsHub {
|
|
|
36
47
|
}
|
|
37
48
|
return false;
|
|
38
49
|
};
|
|
50
|
+
this.limits = {
|
|
51
|
+
maxClients: limits.maxClients ?? exports.MAX_SSE_CLIENTS,
|
|
52
|
+
blockedTimeoutMs: limits.blockedTimeoutMs ?? exports.BLOCKED_TIMEOUT_MS,
|
|
53
|
+
keepAliveMs: limits.keepAliveMs ?? exports.KEEP_ALIVE_MS,
|
|
54
|
+
};
|
|
39
55
|
}
|
|
40
56
|
/** Begins watching the workspace; coalesced changes broadcast to all clients. */
|
|
41
57
|
start() {
|
|
@@ -49,42 +65,112 @@ class EventsHub {
|
|
|
49
65
|
this.watcher.close();
|
|
50
66
|
this.watcher = null;
|
|
51
67
|
}
|
|
52
|
-
for (const res of this.clients) {
|
|
53
|
-
|
|
68
|
+
for (const [res, state] of [...this.clients]) {
|
|
69
|
+
state.cleanup();
|
|
70
|
+
// A blocked socket cannot flush an `end()`; drop it instead.
|
|
71
|
+
if (state.blocked)
|
|
72
|
+
res.destroy();
|
|
73
|
+
else
|
|
74
|
+
res.end();
|
|
54
75
|
}
|
|
55
|
-
this.clients.clear();
|
|
56
76
|
}
|
|
57
77
|
/** Number of currently connected SSE clients (used by tests). */
|
|
58
78
|
get clientCount() {
|
|
59
79
|
return this.clients.size;
|
|
60
80
|
}
|
|
61
|
-
/**
|
|
81
|
+
/** Number of connected clients currently held back by backpressure. */
|
|
82
|
+
get blockedClientCount() {
|
|
83
|
+
let count = 0;
|
|
84
|
+
for (const state of this.clients.values())
|
|
85
|
+
if (state.blocked)
|
|
86
|
+
count += 1;
|
|
87
|
+
return count;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Sends a single coalesced `changed` event to every connected client. A
|
|
91
|
+
* blocked client is owed exactly one `changed` on `drain`, however many
|
|
92
|
+
* broadcasts it misses. Called by the watcher; public so tests can drive the
|
|
93
|
+
* stream without touching disk.
|
|
94
|
+
*/
|
|
62
95
|
broadcast() {
|
|
63
|
-
for (const res of this.clients) {
|
|
64
|
-
|
|
96
|
+
for (const [res, state] of this.clients) {
|
|
97
|
+
if (state.blocked)
|
|
98
|
+
state.pending = true;
|
|
99
|
+
else
|
|
100
|
+
this.send(res, state, CHANGED_EVENT);
|
|
65
101
|
}
|
|
66
102
|
}
|
|
67
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Writes one chunk, honoring backpressure: when `write()` returns `false` the
|
|
105
|
+
* client is marked blocked, further writes are skipped, a `drain` listener is
|
|
106
|
+
* armed to resume, and the slow timer starts.
|
|
107
|
+
*/
|
|
108
|
+
send(res, state, chunk) {
|
|
109
|
+
if (state.blocked)
|
|
110
|
+
return;
|
|
111
|
+
if (res.write(chunk))
|
|
112
|
+
return;
|
|
113
|
+
state.blocked = true;
|
|
114
|
+
res.once('drain', state.onDrain);
|
|
115
|
+
state.slowTimer = setTimeout(() => {
|
|
116
|
+
state.cleanup();
|
|
117
|
+
res.destroy();
|
|
118
|
+
}, this.limits.blockedTimeoutMs);
|
|
119
|
+
state.slowTimer.unref?.();
|
|
120
|
+
}
|
|
121
|
+
/** Attaches an SSE response, or refuses it with `503` when at capacity. */
|
|
68
122
|
handleConnection(req, res) {
|
|
123
|
+
if (this.clients.size >= this.limits.maxClients) {
|
|
124
|
+
const body = JSON.stringify({ error: 'Too many event-stream clients.' });
|
|
125
|
+
res.writeHead(503, {
|
|
126
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
127
|
+
'Content-Length': Buffer.byteLength(body),
|
|
128
|
+
'Retry-After': String(RETRY_AFTER_SECONDS),
|
|
129
|
+
});
|
|
130
|
+
res.end(body);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
69
133
|
res.writeHead(200, {
|
|
70
134
|
'Content-Type': 'text/event-stream',
|
|
71
135
|
'Cache-Control': 'no-cache',
|
|
72
136
|
Connection: 'keep-alive',
|
|
73
137
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
138
|
+
const state = {
|
|
139
|
+
blocked: false,
|
|
140
|
+
pending: false,
|
|
141
|
+
keepAlive: setInterval(() => this.send(res, state, KEEP_ALIVE_COMMENT), this.limits.keepAliveMs),
|
|
142
|
+
slowTimer: null,
|
|
143
|
+
onDrain: () => {
|
|
144
|
+
if (!this.clients.has(res))
|
|
145
|
+
return;
|
|
146
|
+
state.blocked = false;
|
|
147
|
+
if (state.slowTimer) {
|
|
148
|
+
clearTimeout(state.slowTimer);
|
|
149
|
+
state.slowTimer = null;
|
|
150
|
+
}
|
|
151
|
+
if (state.pending) {
|
|
152
|
+
state.pending = false;
|
|
153
|
+
this.send(res, state, CHANGED_EVENT);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
cleanup: () => {
|
|
157
|
+
if (!this.clients.delete(res))
|
|
158
|
+
return;
|
|
159
|
+
clearInterval(state.keepAlive);
|
|
160
|
+
if (state.slowTimer)
|
|
161
|
+
clearTimeout(state.slowTimer);
|
|
162
|
+
res.removeListener('drain', state.onDrain);
|
|
163
|
+
req.removeListener('close', state.cleanup);
|
|
164
|
+
res.removeListener('close', state.cleanup);
|
|
165
|
+
},
|
|
85
166
|
};
|
|
86
|
-
|
|
87
|
-
|
|
167
|
+
// Don't let the keep-alive timer hold the event loop / process open.
|
|
168
|
+
state.keepAlive.unref?.();
|
|
169
|
+
this.clients.set(res, state);
|
|
170
|
+
req.on('close', state.cleanup);
|
|
171
|
+
res.on('close', state.cleanup);
|
|
172
|
+
// Initial comment opens the stream and flushes headers to the client.
|
|
173
|
+
this.send(res, state, ': connected\n\n');
|
|
88
174
|
}
|
|
89
175
|
}
|
|
90
176
|
exports.EventsHub = EventsHub;
|
package/dist/serve/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/serve/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,9 +14,17 @@
|
|
|
14
14
|
* Untrusted input (the path string) is never passed to the shell: `spawn` is
|
|
15
15
|
* invoked with an argv array, and the path is rejected before spawning unless it
|
|
16
16
|
* resolves to an existing file under `plans/` or `archive/`. Node built-ins only.
|
|
17
|
+
*
|
|
18
|
+
* Launches are bounded: a {@link LaunchRegistry} tracks the plans whose child is
|
|
19
|
+
* still running, refusing a duplicate for the same plan and anything past
|
|
20
|
+
* {@link MAX_CONCURRENT_SELF_REVIEWS}. The registry is in-memory and per server
|
|
21
|
+
* instance: a restart resets the accounting, and the detached children — which
|
|
22
|
+
* the viewer never waits on — can outlive it. It is not a job manager.
|
|
17
23
|
*/
|
|
18
24
|
/** The binary name looked up on PATH and spawned. */
|
|
19
25
|
export declare const SELF_REVIEW_BINARY = "self-review";
|
|
26
|
+
/** Upper bound on self-review children running at once per server instance. */
|
|
27
|
+
export declare const MAX_CONCURRENT_SELF_REVIEWS = 2;
|
|
20
28
|
/** Where to obtain self-review; surfaced by the SPA when it is not installed. */
|
|
21
29
|
export declare const SELF_REVIEW_URL = "https://github.com/e0ipso/self-review";
|
|
22
30
|
/**
|
|
@@ -40,11 +48,26 @@ export interface LaunchResult {
|
|
|
40
48
|
ok: false;
|
|
41
49
|
error: string;
|
|
42
50
|
};
|
|
51
|
+
/** Extra response headers (e.g. `Retry-After` on a busy refusal). */
|
|
52
|
+
headers?: Record<string, string>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The plans (by canonical absolute path) whose self-review child is running.
|
|
56
|
+
* One per server instance; see the module comment for what it is not.
|
|
57
|
+
*/
|
|
58
|
+
export type LaunchRegistry = Set<string>;
|
|
59
|
+
/** Creates an empty {@link LaunchRegistry}. */
|
|
60
|
+
export declare const createLaunchRegistry: () => LaunchRegistry;
|
|
61
|
+
/** The slice of `ChildProcess` the launcher relies on; fakes implement it. */
|
|
62
|
+
export interface SpawnedChild {
|
|
63
|
+
once(event: string, listener: (...args: never[]) => void): unknown;
|
|
64
|
+
unref(): void;
|
|
43
65
|
}
|
|
44
|
-
/** Seams for testing: availability probe and the
|
|
66
|
+
/** Seams for testing: availability probe, the spawn, and the registry. */
|
|
45
67
|
export interface LaunchDeps {
|
|
46
68
|
available?: () => boolean;
|
|
47
|
-
|
|
69
|
+
spawn?: (command: string, args: string[]) => SpawnedChild;
|
|
70
|
+
registry?: LaunchRegistry;
|
|
48
71
|
}
|
|
49
72
|
/**
|
|
50
73
|
* Resolves a client-supplied plan path to an absolute path, requiring it to be
|
|
@@ -54,7 +77,10 @@ export interface LaunchDeps {
|
|
|
54
77
|
* `root` is the absolute `.ai/strikethroo` directory; client paths are the
|
|
55
78
|
* workspace-relative form the SPA shows (e.g. `.ai/strikethroo/plans/NN--s/…`),
|
|
56
79
|
* so they are resolved against the project root (`root/../..`). Absolute client
|
|
57
|
-
* paths are accepted too — the containment check is what enforces safety
|
|
80
|
+
* paths are accepted too — the containment check is what enforces safety: the
|
|
81
|
+
* lexical check below picks the subtree, and the shared helper walks the real
|
|
82
|
+
* components so a symlinked plan file or directory is refused rather than
|
|
83
|
+
* followed out of the workspace.
|
|
58
84
|
*/
|
|
59
85
|
export declare const resolveReviewPath: (root: string, clientPath: string) => {
|
|
60
86
|
absPath: string;
|
|
@@ -63,9 +89,13 @@ export declare const resolveReviewPath: (root: string, clientPath: string) => {
|
|
|
63
89
|
status: number;
|
|
64
90
|
};
|
|
65
91
|
/**
|
|
66
|
-
* Validates `clientPath` and, if the binary is available,
|
|
67
|
-
* `self-review <absolutePath>` detached.
|
|
68
|
-
*
|
|
92
|
+
* Validates `clientPath` and, if the binary is available and a slot is free,
|
|
93
|
+
* launches `self-review <absolutePath>` detached. Resolves `200` only after the
|
|
94
|
+
* child's `spawn` event; a launch `error` (e.g. `ENOENT`) is a fixed `500`. The
|
|
95
|
+
* plan's slot is taken synchronously before the spawn, so two simultaneous
|
|
96
|
+
* requests for one plan cannot both launch, and is released — idempotently —
|
|
97
|
+
* when the child exits, errors, or fails to launch. Pure of HTTP concerns:
|
|
98
|
+
* returns the status/body the endpoint should send so it stays unit-testable.
|
|
69
99
|
*/
|
|
70
|
-
export declare const launchSelfReview: (root: string, clientPath: string, deps?: LaunchDeps) => LaunchResult
|
|
100
|
+
export declare const launchSelfReview: (root: string, clientPath: string, deps?: LaunchDeps) => Promise<LaunchResult>;
|
|
71
101
|
//# sourceMappingURL=self-review.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self-review.d.ts","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"self-review.d.ts","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAK7C,iFAAiF;AACjF,eAAO,MAAM,eAAe,0CAA0C,CAAC;AAmCvE;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,OAQF,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;AAEzC,+CAA+C;AAC/C,eAAO,MAAM,oBAAoB,QAAO,cAAmC,CAAC;AAK5E,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC;IACnE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,YAAY,CAAC;IAC1D,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAkBD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,YAAY,MAAM,KACjB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAqCvD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,OAAM,UAAe,KACpB,OAAO,CAAC,YAAY,CAmDtB,CAAC"}
|