hitloop 0.0.0-stage → 0.1.1

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.
Files changed (469) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +218 -2
  3. package/dist/agent.js +318 -0
  4. package/dist/cli.js +897 -0
  5. package/dist/client/assets/app.css +1 -0
  6. package/dist/client/assets/chunks/abap-EINPUMCJ.js +1 -0
  7. package/dist/client/assets/chunks/abnfDiagram-S7VZAUFO-W2CM2W6D.js +1 -0
  8. package/dist/client/assets/chunks/actionscript-3-O776AQUO.js +1 -0
  9. package/dist/client/assets/chunks/ada-WLOTXRTV.js +1 -0
  10. package/dist/client/assets/chunks/ahk-EF37A2DY.js +1 -0
  11. package/dist/client/assets/chunks/ahk2-FH4K3CKT.js +1 -0
  12. package/dist/client/assets/chunks/angular-html-ZALQFV2H.js +1 -0
  13. package/dist/client/assets/chunks/angular-ts-4IWMF7QO.js +1 -0
  14. package/dist/client/assets/chunks/apache-44AYOEWM.js +1 -0
  15. package/dist/client/assets/chunks/apex-XRYPID42.js +1 -0
  16. package/dist/client/assets/chunks/apl-5HBALFOI.js +1 -0
  17. package/dist/client/assets/chunks/applescript-2DZEHZEC.js +1 -0
  18. package/dist/client/assets/chunks/ara-ZGZQBLXL.js +1 -0
  19. package/dist/client/assets/chunks/architecture-WOLXFQ4H-EJGENNRL.js +1 -0
  20. package/dist/client/assets/chunks/architectureDiagram-YGSQEFNW-2VHWSKO6.js +36 -0
  21. package/dist/client/assets/chunks/asciidoc-GSQAKCPO.js +1 -0
  22. package/dist/client/assets/chunks/asm-BFURM5BK.js +1 -0
  23. package/dist/client/assets/chunks/astro-VJORWDZJ.js +1 -0
  24. package/dist/client/assets/chunks/awk-BSHTWXXX.js +1 -0
  25. package/dist/client/assets/chunks/ballerina-HAOQJ4B2.js +1 -0
  26. package/dist/client/assets/chunks/bat-OSH45EOF.js +1 -0
  27. package/dist/client/assets/chunks/beancount-RBATIHOV.js +1 -0
  28. package/dist/client/assets/chunks/berry-CZUIOUM4.js +1 -0
  29. package/dist/client/assets/chunks/bibtex-KCL2UWHE.js +1 -0
  30. package/dist/client/assets/chunks/bicep-SZJZB3SG.js +1 -0
  31. package/dist/client/assets/chunks/bird2-XBF5YQQV.js +1 -0
  32. package/dist/client/assets/chunks/blade-Q24LEVFC.js +1 -0
  33. package/dist/client/assets/chunks/blockDiagram-APKKGZFW-53LXSOOT.js +140 -0
  34. package/dist/client/assets/chunks/bpmnIcons-APHXDYXF-FMBRQNTY.js +1 -0
  35. package/dist/client/assets/chunks/bsl-TI44NWFB.js +1 -0
  36. package/dist/client/assets/chunks/c-NLHY4Y4N.js +1 -0
  37. package/dist/client/assets/chunks/c3-BUTEM6PO.js +1 -0
  38. package/dist/client/assets/chunks/c4Diagram-KJ2TOQU5-O53G4GQH.js +38 -0
  39. package/dist/client/assets/chunks/cadence-JIRTEU64.js +1 -0
  40. package/dist/client/assets/chunks/cairo-3W6NVDNW.js +1 -0
  41. package/dist/client/assets/chunks/chapel-BPBJ2E7K.js +1 -0
  42. package/dist/client/assets/chunks/chunk-25KVF5ZE.js +1 -0
  43. package/dist/client/assets/chunks/chunk-2CJKSQOI.js +1 -0
  44. package/dist/client/assets/chunks/chunk-2QIJRTWR.js +1 -0
  45. package/dist/client/assets/chunks/chunk-2ZCRJZGF.js +2 -0
  46. package/dist/client/assets/chunks/chunk-3ILNDZNY.js +213 -0
  47. package/dist/client/assets/chunks/chunk-3M2OOQ7S.js +1 -0
  48. package/dist/client/assets/chunks/chunk-3M57NTNK.js +1 -0
  49. package/dist/client/assets/chunks/chunk-3MR6DCZJ.js +1 -0
  50. package/dist/client/assets/chunks/chunk-3WGHS7F7.js +1 -0
  51. package/dist/client/assets/chunks/chunk-4JK75V33.js +1 -0
  52. package/dist/client/assets/chunks/chunk-4NXNVEWK.js +1 -0
  53. package/dist/client/assets/chunks/chunk-4RNNBDFQ.js +1 -0
  54. package/dist/client/assets/chunks/chunk-4T4NVH7V.js +1 -0
  55. package/dist/client/assets/chunks/chunk-4TFFBC35.js +1 -0
  56. package/dist/client/assets/chunks/chunk-4WYBE67P.js +1 -0
  57. package/dist/client/assets/chunks/chunk-56ITEUFA.js +1 -0
  58. package/dist/client/assets/chunks/chunk-5DXRE7IH.js +1 -0
  59. package/dist/client/assets/chunks/chunk-5IMADCNU.js +1 -0
  60. package/dist/client/assets/chunks/chunk-5XZPGKN4.js +1 -0
  61. package/dist/client/assets/chunks/chunk-6O32UKSP.js +1 -0
  62. package/dist/client/assets/chunks/chunk-7BAEB64Q.js +1 -0
  63. package/dist/client/assets/chunks/chunk-7FMWBHZO.js +1 -0
  64. package/dist/client/assets/chunks/chunk-7GFDITUT.js +1 -0
  65. package/dist/client/assets/chunks/chunk-7H4MLBHI.js +1 -0
  66. package/dist/client/assets/chunks/chunk-7OJ4MEEB.js +1 -0
  67. package/dist/client/assets/chunks/chunk-7RSEISFE.js +1 -0
  68. package/dist/client/assets/chunks/chunk-7YNZZQVT.js +1 -0
  69. package/dist/client/assets/chunks/chunk-AB7TIL2G.js +1 -0
  70. package/dist/client/assets/chunks/chunk-ADDF76FL.js +1 -0
  71. package/dist/client/assets/chunks/chunk-AF6UTCD4.js +321 -0
  72. package/dist/client/assets/chunks/chunk-AJ2K6ASU.js +1 -0
  73. package/dist/client/assets/chunks/chunk-AUBAENQZ.js +1 -0
  74. package/dist/client/assets/chunks/chunk-BJEYVZ65.js +1 -0
  75. package/dist/client/assets/chunks/chunk-BLRM6LXA.js +1 -0
  76. package/dist/client/assets/chunks/chunk-BOCTYCDZ.js +1 -0
  77. package/dist/client/assets/chunks/chunk-BU4VRYN7.js +1 -0
  78. package/dist/client/assets/chunks/chunk-CALYHV7D.js +1 -0
  79. package/dist/client/assets/chunks/chunk-CF4W3RZ4.js +1 -0
  80. package/dist/client/assets/chunks/chunk-DCZ2OBSL.js +1 -0
  81. package/dist/client/assets/chunks/chunk-DUFPBTHD.js +1 -0
  82. package/dist/client/assets/chunks/chunk-DUICIQBC.js +88 -0
  83. package/dist/client/assets/chunks/chunk-EH2N475V.js +1 -0
  84. package/dist/client/assets/chunks/chunk-EHLLNPZT.js +1 -0
  85. package/dist/client/assets/chunks/chunk-EIBFAW37.js +1 -0
  86. package/dist/client/assets/chunks/chunk-EO3ER3GN.js +1 -0
  87. package/dist/client/assets/chunks/chunk-FH24BIIA.js +1 -0
  88. package/dist/client/assets/chunks/chunk-FNOXGAL5.js +2 -0
  89. package/dist/client/assets/chunks/chunk-FTY6WLQF.js +3 -0
  90. package/dist/client/assets/chunks/chunk-FZFME6UK.js +1 -0
  91. package/dist/client/assets/chunks/chunk-FZJZZYYO.js +1 -0
  92. package/dist/client/assets/chunks/chunk-G4Z6L7OO.js +1 -0
  93. package/dist/client/assets/chunks/chunk-GNCEAN2B.js +1 -0
  94. package/dist/client/assets/chunks/chunk-GQJIKV3T.js +1 -0
  95. package/dist/client/assets/chunks/chunk-GUMNOKT2.js +1 -0
  96. package/dist/client/assets/chunks/chunk-GXRORAF3.js +1 -0
  97. package/dist/client/assets/chunks/chunk-H36ABDKY.js +1 -0
  98. package/dist/client/assets/chunks/chunk-HAR5NYVW.js +1 -0
  99. package/dist/client/assets/chunks/chunk-HIGPS4L2.js +1 -0
  100. package/dist/client/assets/chunks/chunk-HMOBGTME.js +1 -0
  101. package/dist/client/assets/chunks/chunk-HNO6SQ7M.js +1 -0
  102. package/dist/client/assets/chunks/chunk-HYVZ3GYN.js +1 -0
  103. package/dist/client/assets/chunks/chunk-I6TGFOQS.js +1 -0
  104. package/dist/client/assets/chunks/chunk-IHIOJK7I.js +1 -0
  105. package/dist/client/assets/chunks/chunk-IHJNUMSC.js +1 -0
  106. package/dist/client/assets/chunks/chunk-IP7PB2OC.js +1 -0
  107. package/dist/client/assets/chunks/chunk-ISDTMH2Y.js +1 -0
  108. package/dist/client/assets/chunks/chunk-J65M2LNT.js +1 -0
  109. package/dist/client/assets/chunks/chunk-JCWYZ7X2.js +62 -0
  110. package/dist/client/assets/chunks/chunk-JENWYTLI.js +1 -0
  111. package/dist/client/assets/chunks/chunk-JJ6YWJQS.js +1 -0
  112. package/dist/client/assets/chunks/chunk-JMUVGGX7.js +32 -0
  113. package/dist/client/assets/chunks/chunk-JNQUFMM4.js +1 -0
  114. package/dist/client/assets/chunks/chunk-JPTECOAL.js +1 -0
  115. package/dist/client/assets/chunks/chunk-JZNK4LKS.js +1 -0
  116. package/dist/client/assets/chunks/chunk-KPNXJBIW.js +1 -0
  117. package/dist/client/assets/chunks/chunk-KZO2GZL7.js +1 -0
  118. package/dist/client/assets/chunks/chunk-L2REESOQ.js +1 -0
  119. package/dist/client/assets/chunks/chunk-LJPJXR7R.js +1 -0
  120. package/dist/client/assets/chunks/chunk-LOEZMLCI.js +1 -0
  121. package/dist/client/assets/chunks/chunk-MLYC6FSE.js +1 -0
  122. package/dist/client/assets/chunks/chunk-MMDGEZYU.js +1 -0
  123. package/dist/client/assets/chunks/chunk-MYXE7CGE.js +1 -0
  124. package/dist/client/assets/chunks/chunk-NBH7YOBD.js +15 -0
  125. package/dist/client/assets/chunks/chunk-NCOVM3YF.js +1 -0
  126. package/dist/client/assets/chunks/chunk-NCWOBVU7.js +1 -0
  127. package/dist/client/assets/chunks/chunk-NLRIHHEH.js +1 -0
  128. package/dist/client/assets/chunks/chunk-NUPEOYK6.js +1 -0
  129. package/dist/client/assets/chunks/chunk-O4MVOA7X.js +1 -0
  130. package/dist/client/assets/chunks/chunk-OBHQQZ4H.js +1 -0
  131. package/dist/client/assets/chunks/chunk-OKPNJIIR.js +1 -0
  132. package/dist/client/assets/chunks/chunk-OLMPB57R.js +1 -0
  133. package/dist/client/assets/chunks/chunk-P2FYOAEV.js +1 -0
  134. package/dist/client/assets/chunks/chunk-PI3SNP4C.js +1 -0
  135. package/dist/client/assets/chunks/chunk-PRDTEROB.js +1 -0
  136. package/dist/client/assets/chunks/chunk-PZELHD2H.js +136 -0
  137. package/dist/client/assets/chunks/chunk-QR2Q34LM.js +1 -0
  138. package/dist/client/assets/chunks/chunk-R4GIXL6S.js +1 -0
  139. package/dist/client/assets/chunks/chunk-RORF4F5V.js +1 -0
  140. package/dist/client/assets/chunks/chunk-S73BYTLL.js +1 -0
  141. package/dist/client/assets/chunks/chunk-SFC5MRYR.js +1 -0
  142. package/dist/client/assets/chunks/chunk-SVM2H22K.js +2 -0
  143. package/dist/client/assets/chunks/chunk-SZ6UCGVD.js +1 -0
  144. package/dist/client/assets/chunks/chunk-SZYM6GIJ.js +127 -0
  145. package/dist/client/assets/chunks/chunk-TT5KJZKM.js +1 -0
  146. package/dist/client/assets/chunks/chunk-UFBKUYNH.js +1 -0
  147. package/dist/client/assets/chunks/chunk-UL57AD4T.js +1 -0
  148. package/dist/client/assets/chunks/chunk-UNEI7LMM.js +1 -0
  149. package/dist/client/assets/chunks/chunk-VNQBBFIY.js +1 -0
  150. package/dist/client/assets/chunks/chunk-WGVITPII.js +1 -0
  151. package/dist/client/assets/chunks/chunk-WRA6KJHX.js +10 -0
  152. package/dist/client/assets/chunks/chunk-WS5EHW43.js +1 -0
  153. package/dist/client/assets/chunks/chunk-XE6SLBBE.js +3 -0
  154. package/dist/client/assets/chunks/chunk-XF5T2P7U.js +72 -0
  155. package/dist/client/assets/chunks/chunk-XFRY5WKO.js +1 -0
  156. package/dist/client/assets/chunks/chunk-XWYV4OPA.js +1 -0
  157. package/dist/client/assets/chunks/chunk-YCE5ECKY.js +1 -0
  158. package/dist/client/assets/chunks/chunk-YIN5CSIF.js +1 -0
  159. package/dist/client/assets/chunks/chunk-YLFUX6XH.js +1 -0
  160. package/dist/client/assets/chunks/chunk-YNXJICZM.js +1 -0
  161. package/dist/client/assets/chunks/chunk-YOHF7NGD.js +1 -0
  162. package/dist/client/assets/chunks/chunk-YORIST7Z.js +1 -0
  163. package/dist/client/assets/chunks/chunk-YUL7CG4R.js +1 -0
  164. package/dist/client/assets/chunks/chunk-YUN7JSFJ.js +2 -0
  165. package/dist/client/assets/chunks/chunk-YZ7D2IT7.js +1 -0
  166. package/dist/client/assets/chunks/chunk-Z7LAPMFJ.js +1 -0
  167. package/dist/client/assets/chunks/chunk-ZE325LPC.js +1 -0
  168. package/dist/client/assets/chunks/chunk-ZN7TN6PO.js +1 -0
  169. package/dist/client/assets/chunks/chunk-ZST3EVPO.js +1 -0
  170. package/dist/client/assets/chunks/chunk-ZZHMDDZN.js +1 -0
  171. package/dist/client/assets/chunks/clarity-RKRYQ7WF.js +1 -0
  172. package/dist/client/assets/chunks/classDiagram-v2-L25IHNXF-Y67HVDZV.js +217 -0
  173. package/dist/client/assets/chunks/clojure-2X2DQECJ.js +1 -0
  174. package/dist/client/assets/chunks/cmake-LH5524XE.js +1 -0
  175. package/dist/client/assets/chunks/cobol-7DALQF3W.js +1 -0
  176. package/dist/client/assets/chunks/codeowners-52SZU5P5.js +1 -0
  177. package/dist/client/assets/chunks/codeql-EISH3KUP.js +1 -0
  178. package/dist/client/assets/chunks/coffee-VAWSGA7Y.js +1 -0
  179. package/dist/client/assets/chunks/common-lisp-4MVK2AN6.js +1 -0
  180. package/dist/client/assets/chunks/coq-4VRYZRZV.js +1 -0
  181. package/dist/client/assets/chunks/core-BRBMZSD2.js +12 -0
  182. package/dist/client/assets/chunks/cose-bilkent-JH36ORCC-BIOOHSAA.js +1 -0
  183. package/dist/client/assets/chunks/cpp-RFECMSKD.js +1 -0
  184. package/dist/client/assets/chunks/crystal-ZBGGFAOI.js +1 -0
  185. package/dist/client/assets/chunks/csharp-BZDPMKKW.js +1 -0
  186. package/dist/client/assets/chunks/css-3WWGM6UD.js +1 -0
  187. package/dist/client/assets/chunks/csv-AB4GNWSB.js +1 -0
  188. package/dist/client/assets/chunks/cue-2E46MZP2.js +1 -0
  189. package/dist/client/assets/chunks/cynefin-EF2NZ3EQ-TLFQLWUN.js +1 -0
  190. package/dist/client/assets/chunks/cynefinDiagram-L36ESFBY-FLPXCSSG.js +62 -0
  191. package/dist/client/assets/chunks/cypher-HR3ILFOL.js +1 -0
  192. package/dist/client/assets/chunks/d-TARSZPOL.js +1 -0
  193. package/dist/client/assets/chunks/dagre-SPEB5RXH-7EGEINJ2.js +4 -0
  194. package/dist/client/assets/chunks/dart-SALLJHVI.js +1 -0
  195. package/dist/client/assets/chunks/dax-WYMRGMXC.js +1 -0
  196. package/dist/client/assets/chunks/desktop-ND5CGLLJ.js +1 -0
  197. package/dist/client/assets/chunks/diagram-3B7GL73J-6USY4HZX.js +200 -0
  198. package/dist/client/assets/chunks/diagram-DNEMPZML-BNSOC4VW.js +24 -0
  199. package/dist/client/assets/chunks/diagram-L3MUGCDN-5V5FZYIG.js +41 -0
  200. package/dist/client/assets/chunks/diagram-LA4NIPWU-25VLY2CO.js +24 -0
  201. package/dist/client/assets/chunks/diagram-MHCOC4E2-G2LFP3JU.js +3 -0
  202. package/dist/client/assets/chunks/diagram-XPFHEONP-E6HBBIBV.js +30 -0
  203. package/dist/client/assets/chunks/diff-PWYGPM7B.js +1 -0
  204. package/dist/client/assets/chunks/docker-A4D7DT7W.js +1 -0
  205. package/dist/client/assets/chunks/dotenv-VWQWV2DY.js +1 -0
  206. package/dist/client/assets/chunks/dream-maker-M5YDQS35.js +1 -0
  207. package/dist/client/assets/chunks/ebnfDiagram-UZSYDL2S-BMXXZZPI.js +1 -0
  208. package/dist/client/assets/chunks/edge-3QXIDJHI.js +1 -0
  209. package/dist/client/assets/chunks/elixir-3OX2UHIZ.js +1 -0
  210. package/dist/client/assets/chunks/elk-XV6XMXQE-IPR65FON.js +27 -0
  211. package/dist/client/assets/chunks/elm-CTS65NCT.js +1 -0
  212. package/dist/client/assets/chunks/emacs-lisp-HHS2IDO7.js +1 -0
  213. package/dist/client/assets/chunks/engine-javascript-DNHSF67B.js +141 -0
  214. package/dist/client/assets/chunks/erDiagram-EYBAPDEH-3GEHFWHG.js +99 -0
  215. package/dist/client/assets/chunks/erb-ICYWK6HS.js +1 -0
  216. package/dist/client/assets/chunks/erlang-BDQPNCKX.js +1 -0
  217. package/dist/client/assets/chunks/eventmodeling-K75KTNOO-B27BJTZL.js +1 -0
  218. package/dist/client/assets/chunks/fennel-4ONBA2PH.js +1 -0
  219. package/dist/client/assets/chunks/fish-ATLPBZSD.js +1 -0
  220. package/dist/client/assets/chunks/flowDiagram-MALGAFMO-5PCLR4AE.js +1 -0
  221. package/dist/client/assets/chunks/fluent-GGMONBVW.js +1 -0
  222. package/dist/client/assets/chunks/fortran-fixed-form-5MSBDRWQ.js +1 -0
  223. package/dist/client/assets/chunks/fortran-free-form-TT3RBL75.js +1 -0
  224. package/dist/client/assets/chunks/fsharp-PAGHNW4O.js +1 -0
  225. package/dist/client/assets/chunks/ganttDiagram-23REXITY-VE5MVBTO.js +292 -0
  226. package/dist/client/assets/chunks/gdresource-5OTP326D.js +1 -0
  227. package/dist/client/assets/chunks/gdscript-VPWHSCLF.js +1 -0
  228. package/dist/client/assets/chunks/gdshader-FYLPXFE5.js +1 -0
  229. package/dist/client/assets/chunks/genie-UYMEEMA2.js +1 -0
  230. package/dist/client/assets/chunks/gherkin-SU7D5DMY.js +1 -0
  231. package/dist/client/assets/chunks/git-commit-5CF5QAG7.js +1 -0
  232. package/dist/client/assets/chunks/git-rebase-X72BAUZI.js +1 -0
  233. package/dist/client/assets/chunks/gitGraph-VSP46ZUC-J6CJ5YZF.js +1 -0
  234. package/dist/client/assets/chunks/gitGraphDiagram-STJD7YCW-7YJGT6ZP.js +106 -0
  235. package/dist/client/assets/chunks/gleam-LR42YRKO.js +1 -0
  236. package/dist/client/assets/chunks/glimmer-js-JPF67FJU.js +1 -0
  237. package/dist/client/assets/chunks/glimmer-ts-BYPAVIZT.js +1 -0
  238. package/dist/client/assets/chunks/glsl-GTGUULBN.js +1 -0
  239. package/dist/client/assets/chunks/gn-NMDQA4K3.js +1 -0
  240. package/dist/client/assets/chunks/gnuplot-UUAMYBCZ.js +1 -0
  241. package/dist/client/assets/chunks/go-4RERSTNP.js +1 -0
  242. package/dist/client/assets/chunks/graphql-5A6RK6YF.js +1 -0
  243. package/dist/client/assets/chunks/groovy-O7BJONCU.js +1 -0
  244. package/dist/client/assets/chunks/hack-7QGTNPDP.js +1 -0
  245. package/dist/client/assets/chunks/haml-ON5GAWN4.js +1 -0
  246. package/dist/client/assets/chunks/handlebars-6UOQSUBP.js +1 -0
  247. package/dist/client/assets/chunks/haskell-OIZXZ26Y.js +1 -0
  248. package/dist/client/assets/chunks/haxe-7FFVS4FO.js +1 -0
  249. package/dist/client/assets/chunks/hcl-XFUFQJHV.js +1 -0
  250. package/dist/client/assets/chunks/hjson-QDBHMTD5.js +1 -0
  251. package/dist/client/assets/chunks/hlsl-4LP25FFN.js +1 -0
  252. package/dist/client/assets/chunks/html-7RNQXAAV.js +1 -0
  253. package/dist/client/assets/chunks/html-derivative-ESOY72Q2.js +1 -0
  254. package/dist/client/assets/chunks/http-SAD4PMBD.js +1 -0
  255. package/dist/client/assets/chunks/hurl-ZSJJXPQH.js +1 -0
  256. package/dist/client/assets/chunks/hxml-HJCC37RK.js +1 -0
  257. package/dist/client/assets/chunks/hy-CLDE3P4K.js +1 -0
  258. package/dist/client/assets/chunks/imba-REB34U5V.js +1 -0
  259. package/dist/client/assets/chunks/info-OHQRW6UA-EQQKXR77.js +1 -0
  260. package/dist/client/assets/chunks/infoDiagram-KBXO4MBG-F6KGZCGS.js +2 -0
  261. package/dist/client/assets/chunks/ini-PDFEMGRA.js +1 -0
  262. package/dist/client/assets/chunks/ishikawaDiagram-M35NCXHK-5D6ZOZ34.js +70 -0
  263. package/dist/client/assets/chunks/java-KB6XENAD.js +1 -0
  264. package/dist/client/assets/chunks/javascript-3JX5T423.js +1 -0
  265. package/dist/client/assets/chunks/jinja-V4UNU6K4.js +1 -0
  266. package/dist/client/assets/chunks/jison-KH5XNLJP.js +1 -0
  267. package/dist/client/assets/chunks/journeyDiagram-OPLOXDXO-ANDOJZKW.js +139 -0
  268. package/dist/client/assets/chunks/json-HPXFRRPY.js +1 -0
  269. package/dist/client/assets/chunks/json5-LJM6TXWM.js +1 -0
  270. package/dist/client/assets/chunks/jsonc-UZWRU3JV.js +1 -0
  271. package/dist/client/assets/chunks/jsonl-RFZD5UN4.js +1 -0
  272. package/dist/client/assets/chunks/jsonnet-GFZABBL6.js +1 -0
  273. package/dist/client/assets/chunks/jssm-2YIGBISJ.js +1 -0
  274. package/dist/client/assets/chunks/jsx-KLV2ZWUT.js +1 -0
  275. package/dist/client/assets/chunks/julia-3TZDIPPO.js +1 -0
  276. package/dist/client/assets/chunks/just-UHCONBQS.js +1 -0
  277. package/dist/client/assets/chunks/kanban-definition-BZKZHSQY-GF5I5NVD.js +89 -0
  278. package/dist/client/assets/chunks/katex-PIN72PQZ.js +257 -0
  279. package/dist/client/assets/chunks/kdl-DARTFOCL.js +1 -0
  280. package/dist/client/assets/chunks/kotlin-7KT5DW6Y.js +1 -0
  281. package/dist/client/assets/chunks/kusto-EKYXZTC5.js +1 -0
  282. package/dist/client/assets/chunks/langs-GO3UQR4H.js +1 -0
  283. package/dist/client/assets/chunks/latex-T57MIHR5.js +1 -0
  284. package/dist/client/assets/chunks/lean-5QVPRMV6.js +1 -0
  285. package/dist/client/assets/chunks/less-K6QEH5TN.js +1 -0
  286. package/dist/client/assets/chunks/liquid-3LCNNEIV.js +1 -0
  287. package/dist/client/assets/chunks/llvm-O32ZIVRF.js +1 -0
  288. package/dist/client/assets/chunks/log-C4YPJ5BB.js +1 -0
  289. package/dist/client/assets/chunks/logo-JPMO43A6.js +1 -0
  290. package/dist/client/assets/chunks/lua-YKVSOG7K.js +1 -0
  291. package/dist/client/assets/chunks/luau-K4EECYSO.js +1 -0
  292. package/dist/client/assets/chunks/make-VHSYMHHW.js +1 -0
  293. package/dist/client/assets/chunks/markdown-GC5J46H4.js +1 -0
  294. package/dist/client/assets/chunks/marko-U45YFADC.js +1 -0
  295. package/dist/client/assets/chunks/matlab-AMOKC4LU.js +1 -0
  296. package/dist/client/assets/chunks/mdc-DIGA2UXP.js +1 -0
  297. package/dist/client/assets/chunks/mdx-BZUGCKQA.js +1 -0
  298. package/dist/client/assets/chunks/mermaid-WHDP6ZPA.js +1 -0
  299. package/dist/client/assets/chunks/mermaid.core-SQMPMUDN.js +10 -0
  300. package/dist/client/assets/chunks/mindmap-definition-I2QAS2VK-4NH5S56C.js +98 -0
  301. package/dist/client/assets/chunks/mipsasm-2S4CUGQV.js +1 -0
  302. package/dist/client/assets/chunks/mojo-ZOL2PNKT.js +1 -0
  303. package/dist/client/assets/chunks/moonbit-U3BDAIFE.js +1 -0
  304. package/dist/client/assets/chunks/move-YSXALBWA.js +1 -0
  305. package/dist/client/assets/chunks/narrat-DHFIAUJH.js +1 -0
  306. package/dist/client/assets/chunks/nextflow-ESAKNTI3.js +1 -0
  307. package/dist/client/assets/chunks/nextflow-groovy-FKDSPJUI.js +1 -0
  308. package/dist/client/assets/chunks/nginx-XYAYERLO.js +1 -0
  309. package/dist/client/assets/chunks/nim-XOWBVFDH.js +1 -0
  310. package/dist/client/assets/chunks/nix-RVSTQSHC.js +1 -0
  311. package/dist/client/assets/chunks/nsis-KMDUKQRL.js +1 -0
  312. package/dist/client/assets/chunks/nushell-SKJHHZ7U.js +1 -0
  313. package/dist/client/assets/chunks/objective-c-3B3KXQ7Q.js +1 -0
  314. package/dist/client/assets/chunks/objective-cpp-6JDULPJS.js +1 -0
  315. package/dist/client/assets/chunks/ocaml-TMRFXBVO.js +1 -0
  316. package/dist/client/assets/chunks/odin-IN3PLCK7.js +1 -0
  317. package/dist/client/assets/chunks/openscad-P52IKPNH.js +1 -0
  318. package/dist/client/assets/chunks/org-N3SJ2PIA.js +1 -0
  319. package/dist/client/assets/chunks/packet-JDAUHWVQ-4SWIKSKP.js +1 -0
  320. package/dist/client/assets/chunks/pascal-T7CUWCQ4.js +1 -0
  321. package/dist/client/assets/chunks/pegDiagram-FD4XPPHP-WDKZSEGN.js +1 -0
  322. package/dist/client/assets/chunks/perl-LCZ4KODH.js +1 -0
  323. package/dist/client/assets/chunks/php-4XHMBVR5.js +1 -0
  324. package/dist/client/assets/chunks/pie-XZMESJXO-PSSWOWGV.js +1 -0
  325. package/dist/client/assets/chunks/pieDiagram-J4AKIIQI-BDW5I5ON.js +39 -0
  326. package/dist/client/assets/chunks/pkl-OACG5B67.js +1 -0
  327. package/dist/client/assets/chunks/plsql-7E5C7CJX.js +1 -0
  328. package/dist/client/assets/chunks/po-ZSREFRRP.js +1 -0
  329. package/dist/client/assets/chunks/polar-4GBINVA7.js +1 -0
  330. package/dist/client/assets/chunks/postcss-B7RPVGFW.js +1 -0
  331. package/dist/client/assets/chunks/powerquery-6UFMTY4G.js +1 -0
  332. package/dist/client/assets/chunks/powershell-3STRPCNT.js +1 -0
  333. package/dist/client/assets/chunks/prisma-4TPSPIZ5.js +1 -0
  334. package/dist/client/assets/chunks/prolog-HEAYPKQW.js +1 -0
  335. package/dist/client/assets/chunks/proto-Y3Y3VKXM.js +1 -0
  336. package/dist/client/assets/chunks/pug-7PBPMG3M.js +1 -0
  337. package/dist/client/assets/chunks/puppet-FR35R4OI.js +1 -0
  338. package/dist/client/assets/chunks/purescript-OUHXQAOW.js +1 -0
  339. package/dist/client/assets/chunks/python-SNDG7FNU.js +1 -0
  340. package/dist/client/assets/chunks/qml-UVIOSWP4.js +1 -0
  341. package/dist/client/assets/chunks/qmldir-6JGUNYL5.js +1 -0
  342. package/dist/client/assets/chunks/qss-ZCC466IZ.js +1 -0
  343. package/dist/client/assets/chunks/quadrantDiagram-XTYBLID2-5VKXWVJ6.js +7 -0
  344. package/dist/client/assets/chunks/r-4XW4O3ZF.js +1 -0
  345. package/dist/client/assets/chunks/racket-YJAYXOOG.js +1 -0
  346. package/dist/client/assets/chunks/radar-ABXABTNO-3AXZCEY2.js +1 -0
  347. package/dist/client/assets/chunks/railroad-I3PHUGI6-2PLXYPOT.js +1 -0
  348. package/dist/client/assets/chunks/railroad-abnf-LNEFI6M7-M4DGICQX.js +1 -0
  349. package/dist/client/assets/chunks/railroad-ebnf-DWYD2UWJ-UEIHQMSZ.js +1 -0
  350. package/dist/client/assets/chunks/railroad-peg-JR7BVNR7-I7VLIBXM.js +1 -0
  351. package/dist/client/assets/chunks/railroadDiagram-MRQ6NCDL-Y6IYWEFL.js +1 -0
  352. package/dist/client/assets/chunks/raku-63NEL5JK.js +1 -0
  353. package/dist/client/assets/chunks/razor-J3CJP523.js +1 -0
  354. package/dist/client/assets/chunks/rbs-6GQLT7NW.js +1 -0
  355. package/dist/client/assets/chunks/reg-6Q3OEC2C.js +1 -0
  356. package/dist/client/assets/chunks/regexp-LPIMILT3.js +1 -0
  357. package/dist/client/assets/chunks/rel-TOQGUTHB.js +1 -0
  358. package/dist/client/assets/chunks/requirementDiagram-Y7LWUY3S-CIWXVVWJ.js +84 -0
  359. package/dist/client/assets/chunks/riscv-UELGBOXE.js +1 -0
  360. package/dist/client/assets/chunks/ron-FW7LCJJH.js +1 -0
  361. package/dist/client/assets/chunks/rosmsg-O63VHE3L.js +1 -0
  362. package/dist/client/assets/chunks/rst-3WJXGLA7.js +1 -0
  363. package/dist/client/assets/chunks/ruby-7S7L6JTH.js +1 -0
  364. package/dist/client/assets/chunks/rust-LIK4HRRI.js +1 -0
  365. package/dist/client/assets/chunks/sankeyDiagram-WGJFYUXA-OGNQPX5V.js +40 -0
  366. package/dist/client/assets/chunks/sas-FHDPZ2JH.js +1 -0
  367. package/dist/client/assets/chunks/sass-UI4HW2FN.js +1 -0
  368. package/dist/client/assets/chunks/scala-KN7RQSUJ.js +1 -0
  369. package/dist/client/assets/chunks/scheme-5R527YZ5.js +1 -0
  370. package/dist/client/assets/chunks/scss-KZ6DRE4A.js +1 -0
  371. package/dist/client/assets/chunks/sdbl-FHOCL5SL.js +1 -0
  372. package/dist/client/assets/chunks/sequenceDiagram-5NDRBG5M-QX2V24ZU.js +169 -0
  373. package/dist/client/assets/chunks/shaderlab-2TLHUS2H.js +1 -0
  374. package/dist/client/assets/chunks/shellscript-PIB6ZBDM.js +1 -0
  375. package/dist/client/assets/chunks/shellsession-5KL7NFNN.js +1 -0
  376. package/dist/client/assets/chunks/sizeCapture-INFHLROL-LCS2PIHM.js +1 -0
  377. package/dist/client/assets/chunks/smalltalk-JFLFU247.js +1 -0
  378. package/dist/client/assets/chunks/smithy-HONEXZAM.js +1 -0
  379. package/dist/client/assets/chunks/solidity-SJ3INJFZ.js +1 -0
  380. package/dist/client/assets/chunks/soy-ND4SWTM2.js +1 -0
  381. package/dist/client/assets/chunks/sparql-YB2JQBZD.js +1 -0
  382. package/dist/client/assets/chunks/splunk-UXIDDAWL.js +1 -0
  383. package/dist/client/assets/chunks/sql-K6OMG7SQ.js +1 -0
  384. package/dist/client/assets/chunks/ssh-config-I7KJY3KQ.js +1 -0
  385. package/dist/client/assets/chunks/stata-DNZ3DTFJ.js +1 -0
  386. package/dist/client/assets/chunks/stateDiagram-v2-FJ4FJNEA-LVAUWF3A.js +291 -0
  387. package/dist/client/assets/chunks/stylus-GWPR6IQY.js +1 -0
  388. package/dist/client/assets/chunks/surrealql-KQNHBWLC.js +1 -0
  389. package/dist/client/assets/chunks/svelte-YQKF25S4.js +1 -0
  390. package/dist/client/assets/chunks/swift-ZCIZUJXA.js +1 -0
  391. package/dist/client/assets/chunks/swimlanes-UMQ2AFYF-B3RQOARQ.js +1 -0
  392. package/dist/client/assets/chunks/swimlanesDiagram-OMPLPG4O-JOE33EOV.js +8 -0
  393. package/dist/client/assets/chunks/system-verilog-Y7E6FIO3.js +1 -0
  394. package/dist/client/assets/chunks/systemd-WHC7NBZP.js +1 -0
  395. package/dist/client/assets/chunks/talonscript-WC7SODAH.js +1 -0
  396. package/dist/client/assets/chunks/tasl-QHY2GTCB.js +1 -0
  397. package/dist/client/assets/chunks/tcl-VAMIL5PJ.js +1 -0
  398. package/dist/client/assets/chunks/temml-ISNSX3VV.js +96 -0
  399. package/dist/client/assets/chunks/templ-B3BHKWV4.js +1 -0
  400. package/dist/client/assets/chunks/terraform-Q4UEK6FK.js +1 -0
  401. package/dist/client/assets/chunks/tex-63OWCYAB.js +1 -0
  402. package/dist/client/assets/chunks/timeline-definition-SEUHKTQE-FDFTVAJG.js +120 -0
  403. package/dist/client/assets/chunks/toml-7Z4IPGES.js +1 -0
  404. package/dist/client/assets/chunks/treeView-D4JQ5SDB-ABSGRAGI.js +1 -0
  405. package/dist/client/assets/chunks/treemap-SAJKECNS-MYX2CBJN.js +1 -0
  406. package/dist/client/assets/chunks/ts-tags-DT62HE52.js +1 -0
  407. package/dist/client/assets/chunks/tsv-RTXHWADP.js +1 -0
  408. package/dist/client/assets/chunks/tsx-UANUBOC7.js +1 -0
  409. package/dist/client/assets/chunks/turtle-QVOUNUUL.js +1 -0
  410. package/dist/client/assets/chunks/twig-ZPC4BPDA.js +1 -0
  411. package/dist/client/assets/chunks/typescript-WGWKIMMW.js +1 -0
  412. package/dist/client/assets/chunks/typespec-TYCVR32J.js +1 -0
  413. package/dist/client/assets/chunks/typst-PIBFYUO6.js +1 -0
  414. package/dist/client/assets/chunks/usecaseDiagram-AFA6YXN4-KW7ADINR.js +370 -0
  415. package/dist/client/assets/chunks/v-3ERNWBSP.js +1 -0
  416. package/dist/client/assets/chunks/vala-UCBCT2GS.js +1 -0
  417. package/dist/client/assets/chunks/vb-DGI3VTPA.js +1 -0
  418. package/dist/client/assets/chunks/vennDiagram-NNMJR3RB-RDGLGOGM.js +34 -0
  419. package/dist/client/assets/chunks/verilog-G72NZROS.js +1 -0
  420. package/dist/client/assets/chunks/vhdl-PYGA77XE.js +1 -0
  421. package/dist/client/assets/chunks/viml-OOC5B5UU.js +1 -0
  422. package/dist/client/assets/chunks/vue-GTNHIOPG.js +1 -0
  423. package/dist/client/assets/chunks/vue-html-DKAMJV55.js +1 -0
  424. package/dist/client/assets/chunks/vue-vine-WTM5HREV.js +1 -0
  425. package/dist/client/assets/chunks/vyper-RHYEHOJM.js +1 -0
  426. package/dist/client/assets/chunks/wardley-7MLQ67FV-QJL2HSBT.js +1 -0
  427. package/dist/client/assets/chunks/wardleyDiagram-S7YFUSEH-A4XX3UJR.js +78 -0
  428. package/dist/client/assets/chunks/wasm-ZMM2Z5XV.js +1 -0
  429. package/dist/client/assets/chunks/wenyan-HF5UTKSJ.js +1 -0
  430. package/dist/client/assets/chunks/wgsl-O7D7OPO7.js +1 -0
  431. package/dist/client/assets/chunks/wikitext-T7BSWSKQ.js +1 -0
  432. package/dist/client/assets/chunks/wit-TKCHPPT6.js +1 -0
  433. package/dist/client/assets/chunks/wolfram-7MN66A7N.js +1 -0
  434. package/dist/client/assets/chunks/xml-NLTLAWOD.js +1 -0
  435. package/dist/client/assets/chunks/xsl-NZ4ECK3P.js +1 -0
  436. package/dist/client/assets/chunks/xychartDiagram-GGNKY7IX-OXJILWHR.js +7 -0
  437. package/dist/client/assets/chunks/yaml-HRJLEV3V.js +1 -0
  438. package/dist/client/assets/chunks/zenscript-4LLRSLPI.js +1 -0
  439. package/dist/client/assets/chunks/zig-Y7MUQFUO.js +1 -0
  440. package/dist/client/assets/icon.svg +1 -0
  441. package/dist/client/assets/main.js +254 -0
  442. package/dist/client/index.html +59 -0
  443. package/dist/diff.js +119 -0
  444. package/dist/fs/files.js +233 -0
  445. package/dist/fs/git.js +369 -0
  446. package/dist/fs/glob.js +89 -0
  447. package/dist/fs/notes.js +368 -0
  448. package/dist/fs/search.js +136 -0
  449. package/dist/fs/watch.js +69 -0
  450. package/dist/fs/zip.js +100 -0
  451. package/dist/hooks.js +65 -0
  452. package/dist/http.js +81 -0
  453. package/dist/hub/atomic.js +77 -0
  454. package/dist/hub/notify.js +239 -0
  455. package/dist/hub/registry.js +219 -0
  456. package/dist/mcp.js +500 -0
  457. package/dist/q/agent.js +215 -0
  458. package/dist/q/model.js +633 -0
  459. package/dist/q/schema.js +133 -0
  460. package/dist/q/store.js +413 -0
  461. package/dist/r/model.js +323 -0
  462. package/dist/r/schema.js +53 -0
  463. package/dist/r/store.js +489 -0
  464. package/dist/server.js +246 -0
  465. package/dist/settings.js +30 -0
  466. package/dist/workspace.js +639 -0
  467. package/package.json +73 -4
  468. package/schema/questions.schema.json +1670 -0
  469. package/schema/reviews.schema.json +151 -0
@@ -0,0 +1,489 @@
1
+ // A project's reviews on disk:
2
+ // <folder>/.hitl/reviews/<id>.json what to look at (the agent writes these: the MCP tools, the CLI, or by hand)
3
+ // <folder>/.hitl/answers/<id>.json the human's verdicts and comments (hitl writes these)
4
+ // <folder>/.hitl/answers/<id>.md the same, readable
5
+ // <folder>/.hitl/media/ pictures passed as data, snapshots of shown files, marked-up pictures, photos
6
+ // Each review is its own file and a new one always gets a fresh id, so one agent's review never replaces another's.
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import crypto from 'node:crypto';
10
+ import { StoreError, ensureReadme, stripBom, withLock, writeAtomic } from '../hub/atomic.js';
11
+ import { REVIEW_ID, VERDICTS, emptyFeedback, feedbackMarkdown, itemIdFor, kindOf, normalise, slug, summarise, } from './model.js';
12
+ export const DIR = '.hitl';
13
+ export const SCHEMA_URL = 'https://unpkg.com/hitloop/schema/reviews.schema.json';
14
+ const SNAP_MAX = 5 * 1048576;
15
+ const PHOTO_MAX = 12 * 1048576;
16
+ const IMG_EXT = { 'image/png': 'png', 'image/jpeg': 'jpg', 'image/gif': 'gif', 'image/webp': 'webp', 'image/avif': 'avif', 'image/svg+xml': 'svg', 'image/heic': 'heic' };
17
+ export class Reviews {
18
+ root;
19
+ dir;
20
+ reviewsDir;
21
+ answersDir;
22
+ mediaDir;
23
+ cache = new Map();
24
+ constructor(root) {
25
+ this.root = root;
26
+ this.root = path.resolve(root);
27
+ this.dir = path.join(this.root, DIR);
28
+ this.reviewsDir = path.join(this.dir, 'reviews');
29
+ this.answersDir = path.join(this.dir, 'answers');
30
+ this.mediaDir = path.join(this.dir, 'media');
31
+ }
32
+ get exists() {
33
+ return fs.existsSync(this.reviewsDir);
34
+ }
35
+ ensure() {
36
+ fs.mkdirSync(this.reviewsDir, { recursive: true });
37
+ fs.mkdirSync(this.answersDir, { recursive: true });
38
+ ensureReadme(this.dir);
39
+ }
40
+ reviewPath(id) {
41
+ checkId(id);
42
+ return path.join(this.reviewsDir, id + '.json');
43
+ }
44
+ answersPath(id) {
45
+ checkId(id);
46
+ return path.join(this.answersDir, id + '.json');
47
+ }
48
+ markdownPath(id) {
49
+ checkId(id);
50
+ return path.join(this.answersDir, id + '.md');
51
+ }
52
+ /** project-relative, forward slashes */
53
+ rel(abs) {
54
+ return path.relative(this.root, abs).split(path.sep).join('/');
55
+ }
56
+ ids() {
57
+ try {
58
+ return fs
59
+ .readdirSync(this.reviewsDir)
60
+ .filter((f) => f.endsWith('.json') && REVIEW_ID.test(f.slice(0, -5)))
61
+ .map((f) => f.slice(0, -5))
62
+ .sort();
63
+ }
64
+ catch {
65
+ return [];
66
+ }
67
+ }
68
+ has(id) {
69
+ return REVIEW_ID.test(id) && fs.existsSync(this.reviewPath(id));
70
+ }
71
+ load(id) {
72
+ if (!REVIEW_ID.test(id))
73
+ return undefined;
74
+ const file = this.reviewPath(id);
75
+ let st;
76
+ try {
77
+ st = fs.statSync(file);
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ const hit = this.cache.get(id);
83
+ if (hit && hit.mtime === st.mtimeMs && hit.size === st.size)
84
+ return hit.loaded;
85
+ let raw;
86
+ let parseError = '';
87
+ try {
88
+ raw = JSON.parse(stripBom(fs.readFileSync(file, 'utf8')));
89
+ }
90
+ catch (e) {
91
+ parseError = `${path.basename(file)} isn't valid JSON: ${e instanceof Error ? e.message : String(e)}`;
92
+ raw = {};
93
+ }
94
+ const n = normalise(id, raw);
95
+ if (parseError)
96
+ n.errors.unshift(parseError);
97
+ const loaded = { ...n, raw: raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {}, mtime: st.mtimeMs };
98
+ this.cache.set(id, { mtime: st.mtimeMs, size: st.size, loaded });
99
+ return loaded;
100
+ }
101
+ feedback(id) {
102
+ try {
103
+ const d = JSON.parse(stripBom(fs.readFileSync(this.answersPath(id), 'utf8')));
104
+ if (!d || typeof d !== 'object')
105
+ return emptyFeedback();
106
+ return {
107
+ version: 1,
108
+ kind: 'review',
109
+ seq: typeof d.seq === 'number' ? d.seq : 0,
110
+ readSeq: typeof d.readSeq === 'number' ? d.readSeq : 0,
111
+ ...(d.overall && typeof d.overall === 'object' ? { overall: d.overall } : {}),
112
+ items: d.items && typeof d.items === 'object' ? d.items : {},
113
+ comments: Array.isArray(d.comments) ? d.comments.map((c) => ({ ...c, replies: Array.isArray(c.replies) ? c.replies : [] })) : [],
114
+ };
115
+ }
116
+ catch {
117
+ return emptyFeedback();
118
+ }
119
+ }
120
+ summary(id) {
121
+ const l = this.load(id);
122
+ return l ? summarise(l.review, this.feedback(id), l.errors.length) : undefined;
123
+ }
124
+ summaries() {
125
+ return this.ids()
126
+ .map((id) => this.summary(id))
127
+ .filter((s) => !!s);
128
+ }
129
+ // ── writing reviews ──
130
+ /** A fresh id from the title: never one already used by a review, a question set or an answers file. */
131
+ freshId(title) {
132
+ const base = slug(title || 'review', 48);
133
+ const used = (id) => ['reviews', 'questions', 'answers'].some((d) => fs.existsSync(path.join(this.dir, d, id + '.json')));
134
+ let id = base, n = 2;
135
+ while (used(id))
136
+ id = `${base}-${n++}`;
137
+ return id;
138
+ }
139
+ mutate(id, fn, opts = {}) {
140
+ checkId(id);
141
+ this.ensure();
142
+ const file = this.reviewPath(id);
143
+ return withLock(file, () => {
144
+ let raw;
145
+ // a new review: another process may have taken this id since it was picked
146
+ if (opts.fresh && fs.existsSync(file))
147
+ throw TAKEN;
148
+ if (fs.existsSync(file)) {
149
+ try {
150
+ raw = JSON.parse(stripBom(fs.readFileSync(file, 'utf8')));
151
+ }
152
+ catch (e) {
153
+ throw new StoreError(`${path.basename(file)} isn't valid JSON (${e instanceof Error ? e.message : String(e)}); fix it by hand first`);
154
+ }
155
+ }
156
+ else if (opts.create)
157
+ raw = { $schema: SCHEMA_URL, ...opts.create, created: new Date().toISOString(), items: [] };
158
+ else
159
+ throw new StoreError(`No review "${id}"`);
160
+ const before = normalise(id, raw).errors.length;
161
+ const result = fn(raw);
162
+ raw.updated = new Date().toISOString();
163
+ const n = normalise(id, raw);
164
+ if (n.errors.length > before && !opts.force)
165
+ throw new StoreError('That would make the review invalid:\n' + n.errors.map((e) => ' ' + e).join('\n'));
166
+ writeAtomic(file, JSON.stringify(raw, null, 2) + '\n');
167
+ this.cache.delete(id);
168
+ return { result, normalised: n };
169
+ });
170
+ }
171
+ /**
172
+ * Make a review (always a new file, with a fresh id unless `id` is given and new), or, with `to`, add items to an
173
+ * existing one. Returns its id, the new items' ids, and any problems.
174
+ */
175
+ create(head, items) {
176
+ const { id: wanted, ...rest } = head;
177
+ if (wanted && this.has(wanted))
178
+ throw new StoreError(`There's already a review "${wanted}": add to it (to: "${wanted}") or leave out the id for a new one`);
179
+ for (let tries = 0;; tries++) {
180
+ const id = wanted ? (checkId(wanted), wanted) : this.freshId(head.title ?? '');
181
+ try {
182
+ const { result, normalised } = this.mutate(id, (raw) => this.append(id, raw, items), { create: { title: head.title || id, ...rest }, fresh: true });
183
+ return { id, ids: result, normalised };
184
+ }
185
+ catch (e) {
186
+ if (e !== TAKEN)
187
+ throw e;
188
+ if (wanted || tries >= 100)
189
+ throw new StoreError(`There's already a review "${id}"`);
190
+ }
191
+ }
192
+ }
193
+ addItems(id, items, patch = {}) {
194
+ const { result, normalised } = this.mutate(id, (raw) => {
195
+ for (const [k, v] of Object.entries(patch))
196
+ if (v)
197
+ raw[k] = v;
198
+ if (raw.status === 'closed')
199
+ raw.status = 'open';
200
+ return this.append(id, raw, items);
201
+ });
202
+ return { ids: result, normalised };
203
+ }
204
+ append(id, raw, items) {
205
+ raw.items ??= [];
206
+ const taken = new Set(raw.items.map((i) => i.id).filter((x) => !!x));
207
+ const ids = [];
208
+ const expanded = items.flatMap((i) => (Array.isArray(i.files) ? i.files.map((f) => ({ ...i, files: undefined, file: f, title: i.files && i.files.length > 1 ? undefined : i.title })) : [i]));
209
+ for (const it of expanded) {
210
+ const copy = { ...it };
211
+ delete copy.files;
212
+ if (!kindOf(copy))
213
+ throw new StoreError(`An item needs content: file, code, text, md, json, diff, image, mermaid, html or link (got ${Object.keys(it).join(', ') || 'nothing'})`);
214
+ if (!copy.id)
215
+ copy.id = itemIdFor(copy, taken);
216
+ if (taken.has(copy.id))
217
+ throw new StoreError(`The item id "${copy.id}" is already in "${id}" (update_item changes it)`);
218
+ taken.add(copy.id);
219
+ for (const k of ['image', 'before']) {
220
+ const v = copy[k];
221
+ if (typeof v === 'string' && v.startsWith('data:'))
222
+ copy[k] = this.saveData(v, `items/${id}-${copy.id}${k === 'before' ? '-before' : ''}`);
223
+ }
224
+ if (copy.file && copy.snapshot !== false && !copy.against) {
225
+ const snap = this.snapshot(id, copy.id, copy.file);
226
+ if (snap)
227
+ copy.snap = snap;
228
+ }
229
+ delete copy.snapshot;
230
+ raw.items.push(copy);
231
+ ids.push(copy.id);
232
+ }
233
+ return ids;
234
+ }
235
+ /** a data: URL saved as a file in media/; returns its project-relative path */
236
+ saveData(url, name) {
237
+ const m = /^data:([a-z]+\/[a-z0-9.+-]+)(;base64)?,(.*)$/is.exec(url);
238
+ if (!m)
239
+ throw new StoreError('A data URL looks like data:image/png;base64,…');
240
+ const type = (m[1] ?? '').toLowerCase();
241
+ const ext = IMG_EXT[type];
242
+ if (!ext)
243
+ throw new StoreError(`Pictures only (png, jpeg, gif, webp, avif, svg), not ${type}`);
244
+ const buf = m[2] ? Buffer.from(m[3] ?? '', 'base64') : Buffer.from(decodeURIComponent(m[3] ?? ''), 'utf8');
245
+ if (buf.length > PHOTO_MAX)
246
+ throw new StoreError('That picture is too big (12 MB at most)');
247
+ const abs = path.join(this.mediaDir, name + '.' + ext);
248
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
249
+ fs.writeFileSync(abs, buf);
250
+ return this.rel(abs);
251
+ }
252
+ /** a copy of a project file as it is now, so later edits show as "changed since shown" */
253
+ snapshot(id, iid, rel) {
254
+ const abs = path.resolve(this.root, rel);
255
+ if (!abs.startsWith(this.root + path.sep) || abs.startsWith(this.dir + path.sep))
256
+ return undefined;
257
+ let buf;
258
+ try {
259
+ const st = fs.statSync(abs);
260
+ if (!st.isFile() || st.size > SNAP_MAX)
261
+ return undefined;
262
+ buf = fs.readFileSync(abs);
263
+ }
264
+ catch {
265
+ return undefined;
266
+ }
267
+ const sha = crypto.createHash('sha1').update(buf).digest('hex');
268
+ const ext = path.extname(rel).slice(0, 12);
269
+ const out = path.join(this.mediaDir, 'snaps', id, `${iid}-${sha.slice(0, 8)}${ext}`);
270
+ fs.mkdirSync(path.dirname(out), { recursive: true });
271
+ if (!fs.existsSync(out))
272
+ fs.writeFileSync(out, buf);
273
+ return { path: this.rel(out), sha, size: buf.length, at: new Date().toISOString() };
274
+ }
275
+ /** Change one item: the patch's fields replace the item's (null removes one). A changed file is snapshotted again. */
276
+ updateItem(id, iid, patch) {
277
+ return this.mutate(id, (raw) => {
278
+ const it = (raw.items ?? []).find((i) => i.id === iid);
279
+ if (!it)
280
+ throw new StoreError(`No item "${iid}" in "${id}"`);
281
+ for (const [k, v] of Object.entries(patch)) {
282
+ if (k === 'id')
283
+ continue;
284
+ if (v === null)
285
+ delete it[k];
286
+ else
287
+ it[k] = typeof v === 'string' && v.startsWith('data:') && (k === 'image' || k === 'before') ? this.saveData(v, `items/${id}-${iid}${k === 'before' ? '-before' : ''}-${Date.now().toString(36)}`) : v;
288
+ }
289
+ if (it.file && it.snapshot !== false && !it.against) {
290
+ const snap = this.snapshot(id, iid, it.file);
291
+ if (snap)
292
+ it.snap = snap;
293
+ }
294
+ delete it.snapshot;
295
+ }).normalised;
296
+ }
297
+ removeItems(id, iids) {
298
+ return this.mutate(id, (raw) => {
299
+ const removed = (raw.items ?? []).filter((i) => i.id && iids.includes(i.id)).map((i) => i.id ?? '');
300
+ raw.items = (raw.items ?? []).filter((i) => !i.id || !iids.includes(i.id));
301
+ return removed;
302
+ }, { force: true }).result;
303
+ }
304
+ update(id, patch) {
305
+ return this.mutate(id, (raw) => {
306
+ for (const [k, v] of Object.entries(patch))
307
+ if (v !== undefined)
308
+ raw[k] = v;
309
+ }).normalised;
310
+ }
311
+ /** Delete a review and its feedback (not its media). */
312
+ remove(id) {
313
+ if (!this.has(id))
314
+ return false;
315
+ fs.rmSync(this.reviewPath(id), { force: true });
316
+ fs.rmSync(this.answersPath(id), { force: true });
317
+ fs.rmSync(this.markdownPath(id), { force: true });
318
+ this.cache.delete(id);
319
+ return true;
320
+ }
321
+ // ── writing feedback ──
322
+ mutateFeedback(id, fn) {
323
+ if (!this.has(id))
324
+ throw new StoreError(`No review "${id}"`);
325
+ fs.mkdirSync(this.answersDir, { recursive: true });
326
+ return withLock(this.answersPath(id), () => {
327
+ const fb = this.feedback(id);
328
+ const result = fn(fb);
329
+ writeAtomic(this.answersPath(id), JSON.stringify(fb, null, 2) + '\n');
330
+ const l = this.load(id);
331
+ if (l)
332
+ writeAtomic(this.markdownPath(id), feedbackMarkdown(l.review, fb));
333
+ return result;
334
+ });
335
+ }
336
+ mustLoad(id) {
337
+ const l = this.load(id);
338
+ if (!l)
339
+ throw new StoreError(`No review "${id}"`);
340
+ return l;
341
+ }
342
+ /** The human's verdict on an item (null clears it). */
343
+ verdict(id, iid, verdict, note = '') {
344
+ const l = this.mustLoad(id);
345
+ const it = l.review.items.find((i) => i.id === iid);
346
+ if (!it)
347
+ throw new StoreError(`No item "${iid}" in "${id}"`);
348
+ if (verdict !== null && !VERDICTS.includes(verdict))
349
+ throw new StoreError(`A verdict is ${VERDICTS.join(', ')}`);
350
+ return this.mutateFeedback(id, (fb) => {
351
+ if (verdict === null) {
352
+ if (fb.items[iid]) {
353
+ delete fb.items[iid];
354
+ fb.seq++;
355
+ }
356
+ return null;
357
+ }
358
+ const prev = fb.items[iid];
359
+ const v = { verdict, ...(note.trim() ? { note: note.trim().slice(0, 20000) } : {}), rev: it.rev, at: new Date().toISOString(), seq: ++fb.seq };
360
+ fb.items[iid] = prev?.ack && prev.verdict === verdict && prev.rev === it.rev ? { ...v, ack: prev.ack } : v;
361
+ return fb.items[iid] ?? null;
362
+ });
363
+ }
364
+ /** The human's verdict on the whole review (for an approval: the answer). null takes it back. */
365
+ overall(id, verdict, note = '') {
366
+ this.mustLoad(id);
367
+ if (verdict !== null && !VERDICTS.includes(verdict))
368
+ throw new StoreError(`A verdict is ${VERDICTS.join(', ')}`);
369
+ return this.mutateFeedback(id, (fb) => {
370
+ if (verdict === null) {
371
+ delete fb.overall;
372
+ fb.seq++;
373
+ return null;
374
+ }
375
+ fb.overall = { verdict, ...(note.trim() ? { note: note.trim().slice(0, 20000) } : {}), at: new Date().toISOString(), seq: ++fb.seq };
376
+ return fb.overall;
377
+ });
378
+ }
379
+ comment(id, input, from = 'owner') {
380
+ const l = this.mustLoad(id);
381
+ const iid = input.item ?? '';
382
+ const it = iid ? l.review.items.find((i) => i.id === iid) : undefined;
383
+ if (iid && !it)
384
+ throw new StoreError(`No item "${iid}" in "${id}"`);
385
+ if (!input.body.trim() && !input.photos?.length)
386
+ throw new StoreError('The comment is empty');
387
+ return this.mutateFeedback(id, (fb) => {
388
+ const seq = ++fb.seq;
389
+ const cid = `c${seq}`;
390
+ const c = { id: cid, item: iid, body: input.body.trim().slice(0, 20000), from, at: new Date().toISOString(), seq, status: 'open', replies: [], rev: it?.rev ?? '' };
391
+ if (input.line && input.line > 0) {
392
+ c.line = Math.round(input.line);
393
+ if (input.endLine && input.endLine > c.line)
394
+ c.endLine = Math.round(input.endLine);
395
+ if (input.side === 'old')
396
+ c.side = 'old';
397
+ }
398
+ if (input.quote)
399
+ c.quote = input.quote.slice(0, 4000);
400
+ if (input.strokes?.length) {
401
+ c.strokes = input.strokes;
402
+ if (input.area)
403
+ c.area = input.area;
404
+ if (input.snapshot)
405
+ c.marked = this.saveData(input.snapshot, `marks/${id}-${cid}`);
406
+ }
407
+ const photos = (input.photos ?? []).slice(0, 8).map((p, n) => this.saveData(p, `photos/${id}-${cid}-${n + 1}`));
408
+ if (photos.length)
409
+ c.photos = photos;
410
+ fb.comments.push(c);
411
+ return c;
412
+ });
413
+ }
414
+ reply(id, cid, from, body) {
415
+ if (!body.trim())
416
+ throw new StoreError('The reply is empty');
417
+ return this.mutateFeedback(id, (fb) => {
418
+ const c = fb.comments.find((x) => x.id === cid);
419
+ if (!c)
420
+ throw new StoreError(`No comment "${cid}" in "${id}"`);
421
+ c.replies.push({ from, body: body.trim().slice(0, 20000), at: new Date().toISOString(), seq: ++fb.seq });
422
+ return c;
423
+ });
424
+ }
425
+ /** Resolve or reopen comments; with a note, it's added as a reply from whoever did it. */
426
+ setStatus(id, cids, status, from, note = '') {
427
+ return this.mutateFeedback(id, (fb) => {
428
+ const done = [];
429
+ for (const cid of cids) {
430
+ const c = fb.comments.find((x) => x.id === cid);
431
+ if (!c)
432
+ continue;
433
+ c.status = status;
434
+ if (note.trim())
435
+ c.replies.push({ from, body: note.trim().slice(0, 20000), at: new Date().toISOString(), seq: ++fb.seq });
436
+ else
437
+ fb.seq++;
438
+ done.push(cid);
439
+ }
440
+ return done;
441
+ });
442
+ }
443
+ editComment(id, cid, body) {
444
+ return this.mutateFeedback(id, (fb) => {
445
+ const c = fb.comments.find((x) => x.id === cid);
446
+ if (!c)
447
+ throw new StoreError(`No comment "${cid}"`);
448
+ c.body = body.trim().slice(0, 20000);
449
+ c.seq = ++fb.seq;
450
+ return c;
451
+ });
452
+ }
453
+ deleteComment(id, cid) {
454
+ return this.mutateFeedback(id, (fb) => {
455
+ const n = fb.comments.length;
456
+ fb.comments = fb.comments.filter((c) => c.id !== cid);
457
+ if (fb.comments.length !== n)
458
+ fb.seq++;
459
+ return fb.comments.length !== n;
460
+ });
461
+ }
462
+ /** The agent dealt with these items' verdicts: a note the human sees. */
463
+ ack(id, iids, note) {
464
+ return this.mutateFeedback(id, (fb) => {
465
+ const done = [];
466
+ for (const iid of iids) {
467
+ const v = fb.items[iid];
468
+ if (!v)
469
+ continue;
470
+ v.ack = { at: new Date().toISOString(), note: note.slice(0, 2000) };
471
+ done.push(iid);
472
+ }
473
+ if (done.length)
474
+ fb.seq++;
475
+ return done;
476
+ });
477
+ }
478
+ markRead(id, upTo) {
479
+ this.mutateFeedback(id, (fb) => {
480
+ fb.readSeq = Math.max(fb.readSeq, Math.min(upTo ?? fb.seq, fb.seq));
481
+ });
482
+ }
483
+ }
484
+ /** thrown inside the lock when a new review's id was taken meanwhile: create picks the next one */
485
+ const TAKEN = new Error('taken');
486
+ function checkId(id) {
487
+ if (!REVIEW_ID.test(id))
488
+ throw new StoreError(`Bad review id "${id}": letters, digits, . _ - (up to 80)`);
489
+ }