onbuzz 3.3.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.
Files changed (506) hide show
  1. package/LICENSE +267 -0
  2. package/README.md +425 -0
  3. package/bin/cli.js +556 -0
  4. package/bin/loxia-terminal-v2.js +162 -0
  5. package/bin/loxia-terminal.js +90 -0
  6. package/bin/start-with-terminal.js +200 -0
  7. package/node_modules/@isaacs/balanced-match/LICENSE.md +23 -0
  8. package/node_modules/@isaacs/balanced-match/README.md +60 -0
  9. package/node_modules/@isaacs/balanced-match/dist/commonjs/index.d.ts +9 -0
  10. package/node_modules/@isaacs/balanced-match/dist/commonjs/index.d.ts.map +1 -0
  11. package/node_modules/@isaacs/balanced-match/dist/commonjs/index.js +59 -0
  12. package/node_modules/@isaacs/balanced-match/dist/commonjs/index.js.map +1 -0
  13. package/node_modules/@isaacs/balanced-match/dist/commonjs/package.json +3 -0
  14. package/node_modules/@isaacs/balanced-match/dist/esm/index.d.ts +9 -0
  15. package/node_modules/@isaacs/balanced-match/dist/esm/index.d.ts.map +1 -0
  16. package/node_modules/@isaacs/balanced-match/dist/esm/index.js +54 -0
  17. package/node_modules/@isaacs/balanced-match/dist/esm/index.js.map +1 -0
  18. package/node_modules/@isaacs/balanced-match/dist/esm/package.json +3 -0
  19. package/node_modules/@isaacs/balanced-match/package.json +79 -0
  20. package/node_modules/@isaacs/brace-expansion/LICENSE +23 -0
  21. package/node_modules/@isaacs/brace-expansion/README.md +97 -0
  22. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.d.ts +6 -0
  23. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.d.ts.map +1 -0
  24. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js +199 -0
  25. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js.map +1 -0
  26. package/node_modules/@isaacs/brace-expansion/dist/commonjs/package.json +3 -0
  27. package/node_modules/@isaacs/brace-expansion/dist/esm/index.d.ts +6 -0
  28. package/node_modules/@isaacs/brace-expansion/dist/esm/index.d.ts.map +1 -0
  29. package/node_modules/@isaacs/brace-expansion/dist/esm/index.js +195 -0
  30. package/node_modules/@isaacs/brace-expansion/dist/esm/index.js.map +1 -0
  31. package/node_modules/@isaacs/brace-expansion/dist/esm/package.json +3 -0
  32. package/node_modules/@isaacs/brace-expansion/package.json +60 -0
  33. package/node_modules/glob/LICENSE.md +63 -0
  34. package/node_modules/glob/README.md +1177 -0
  35. package/node_modules/glob/dist/commonjs/glob.d.ts +388 -0
  36. package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -0
  37. package/node_modules/glob/dist/commonjs/glob.js +247 -0
  38. package/node_modules/glob/dist/commonjs/glob.js.map +1 -0
  39. package/node_modules/glob/dist/commonjs/has-magic.d.ts +14 -0
  40. package/node_modules/glob/dist/commonjs/has-magic.d.ts.map +1 -0
  41. package/node_modules/glob/dist/commonjs/has-magic.js +27 -0
  42. package/node_modules/glob/dist/commonjs/has-magic.js.map +1 -0
  43. package/node_modules/glob/dist/commonjs/ignore.d.ts +24 -0
  44. package/node_modules/glob/dist/commonjs/ignore.d.ts.map +1 -0
  45. package/node_modules/glob/dist/commonjs/ignore.js +119 -0
  46. package/node_modules/glob/dist/commonjs/ignore.js.map +1 -0
  47. package/node_modules/glob/dist/commonjs/index.d.ts +97 -0
  48. package/node_modules/glob/dist/commonjs/index.d.ts.map +1 -0
  49. package/node_modules/glob/dist/commonjs/index.js +68 -0
  50. package/node_modules/glob/dist/commonjs/index.js.map +1 -0
  51. package/node_modules/glob/dist/commonjs/index.min.js +4 -0
  52. package/node_modules/glob/dist/commonjs/index.min.js.map +7 -0
  53. package/node_modules/glob/dist/commonjs/package.json +3 -0
  54. package/node_modules/glob/dist/commonjs/pattern.d.ts +76 -0
  55. package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -0
  56. package/node_modules/glob/dist/commonjs/pattern.js +219 -0
  57. package/node_modules/glob/dist/commonjs/pattern.js.map +1 -0
  58. package/node_modules/glob/dist/commonjs/processor.d.ts +59 -0
  59. package/node_modules/glob/dist/commonjs/processor.d.ts.map +1 -0
  60. package/node_modules/glob/dist/commonjs/processor.js +301 -0
  61. package/node_modules/glob/dist/commonjs/processor.js.map +1 -0
  62. package/node_modules/glob/dist/commonjs/walker.d.ts +97 -0
  63. package/node_modules/glob/dist/commonjs/walker.d.ts.map +1 -0
  64. package/node_modules/glob/dist/commonjs/walker.js +387 -0
  65. package/node_modules/glob/dist/commonjs/walker.js.map +1 -0
  66. package/node_modules/glob/dist/esm/glob.d.ts +388 -0
  67. package/node_modules/glob/dist/esm/glob.d.ts.map +1 -0
  68. package/node_modules/glob/dist/esm/glob.js +243 -0
  69. package/node_modules/glob/dist/esm/glob.js.map +1 -0
  70. package/node_modules/glob/dist/esm/has-magic.d.ts +14 -0
  71. package/node_modules/glob/dist/esm/has-magic.d.ts.map +1 -0
  72. package/node_modules/glob/dist/esm/has-magic.js +23 -0
  73. package/node_modules/glob/dist/esm/has-magic.js.map +1 -0
  74. package/node_modules/glob/dist/esm/ignore.d.ts +24 -0
  75. package/node_modules/glob/dist/esm/ignore.d.ts.map +1 -0
  76. package/node_modules/glob/dist/esm/ignore.js +115 -0
  77. package/node_modules/glob/dist/esm/ignore.js.map +1 -0
  78. package/node_modules/glob/dist/esm/index.d.ts +97 -0
  79. package/node_modules/glob/dist/esm/index.d.ts.map +1 -0
  80. package/node_modules/glob/dist/esm/index.js +55 -0
  81. package/node_modules/glob/dist/esm/index.js.map +1 -0
  82. package/node_modules/glob/dist/esm/index.min.js +4 -0
  83. package/node_modules/glob/dist/esm/index.min.js.map +7 -0
  84. package/node_modules/glob/dist/esm/package.json +3 -0
  85. package/node_modules/glob/dist/esm/pattern.d.ts +76 -0
  86. package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -0
  87. package/node_modules/glob/dist/esm/pattern.js +215 -0
  88. package/node_modules/glob/dist/esm/pattern.js.map +1 -0
  89. package/node_modules/glob/dist/esm/processor.d.ts +59 -0
  90. package/node_modules/glob/dist/esm/processor.d.ts.map +1 -0
  91. package/node_modules/glob/dist/esm/processor.js +294 -0
  92. package/node_modules/glob/dist/esm/processor.js.map +1 -0
  93. package/node_modules/glob/dist/esm/walker.d.ts +97 -0
  94. package/node_modules/glob/dist/esm/walker.d.ts.map +1 -0
  95. package/node_modules/glob/dist/esm/walker.js +381 -0
  96. package/node_modules/glob/dist/esm/walker.js.map +1 -0
  97. package/node_modules/glob/node_modules/minimatch/LICENSE.md +55 -0
  98. package/node_modules/glob/node_modules/minimatch/README.md +453 -0
  99. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
  100. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -0
  101. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
  102. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -0
  103. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
  104. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -0
  105. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js +591 -0
  106. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js.map +1 -0
  107. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
  108. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -0
  109. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js +152 -0
  110. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -0
  111. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts +15 -0
  112. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -0
  113. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js +30 -0
  114. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js.map +1 -0
  115. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts +94 -0
  116. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -0
  117. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js +1029 -0
  118. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js.map +1 -0
  119. package/node_modules/glob/node_modules/minimatch/dist/commonjs/package.json +3 -0
  120. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts +22 -0
  121. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -0
  122. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js +38 -0
  123. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -0
  124. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
  125. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -0
  126. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
  127. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -0
  128. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
  129. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -0
  130. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js +587 -0
  131. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js.map +1 -0
  132. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
  133. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -0
  134. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js +148 -0
  135. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -0
  136. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts +15 -0
  137. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -0
  138. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js +26 -0
  139. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js.map +1 -0
  140. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts +94 -0
  141. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts.map +1 -0
  142. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js +1016 -0
  143. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js.map +1 -0
  144. package/node_modules/glob/node_modules/minimatch/dist/esm/package.json +3 -0
  145. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts +22 -0
  146. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -0
  147. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js +34 -0
  148. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js.map +1 -0
  149. package/node_modules/glob/node_modules/minimatch/package.json +67 -0
  150. package/node_modules/glob/package.json +101 -0
  151. package/node_modules/minipass/LICENSE +15 -0
  152. package/node_modules/minipass/README.md +825 -0
  153. package/node_modules/minipass/dist/commonjs/index.d.ts +549 -0
  154. package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -0
  155. package/node_modules/minipass/dist/commonjs/index.js +1028 -0
  156. package/node_modules/minipass/dist/commonjs/index.js.map +1 -0
  157. package/node_modules/minipass/dist/commonjs/package.json +3 -0
  158. package/node_modules/minipass/dist/esm/index.d.ts +549 -0
  159. package/node_modules/minipass/dist/esm/index.d.ts.map +1 -0
  160. package/node_modules/minipass/dist/esm/index.js +1018 -0
  161. package/node_modules/minipass/dist/esm/index.js.map +1 -0
  162. package/node_modules/minipass/dist/esm/package.json +3 -0
  163. package/node_modules/minipass/package.json +82 -0
  164. package/node_modules/package-json-from-dist/LICENSE.md +63 -0
  165. package/node_modules/package-json-from-dist/README.md +110 -0
  166. package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts +89 -0
  167. package/node_modules/package-json-from-dist/dist/commonjs/index.d.ts.map +1 -0
  168. package/node_modules/package-json-from-dist/dist/commonjs/index.js +134 -0
  169. package/node_modules/package-json-from-dist/dist/commonjs/index.js.map +1 -0
  170. package/node_modules/package-json-from-dist/dist/commonjs/package.json +3 -0
  171. package/node_modules/package-json-from-dist/dist/esm/index.d.ts +89 -0
  172. package/node_modules/package-json-from-dist/dist/esm/index.d.ts.map +1 -0
  173. package/node_modules/package-json-from-dist/dist/esm/index.js +129 -0
  174. package/node_modules/package-json-from-dist/dist/esm/index.js.map +1 -0
  175. package/node_modules/package-json-from-dist/dist/esm/package.json +3 -0
  176. package/node_modules/package-json-from-dist/package.json +68 -0
  177. package/node_modules/path-scurry/LICENSE.md +55 -0
  178. package/node_modules/path-scurry/README.md +636 -0
  179. package/node_modules/path-scurry/dist/commonjs/index.d.ts +1115 -0
  180. package/node_modules/path-scurry/dist/commonjs/index.d.ts.map +1 -0
  181. package/node_modules/path-scurry/dist/commonjs/index.js +2018 -0
  182. package/node_modules/path-scurry/dist/commonjs/index.js.map +1 -0
  183. package/node_modules/path-scurry/dist/commonjs/package.json +3 -0
  184. package/node_modules/path-scurry/dist/esm/index.d.ts +1115 -0
  185. package/node_modules/path-scurry/dist/esm/index.d.ts.map +1 -0
  186. package/node_modules/path-scurry/dist/esm/index.js +1983 -0
  187. package/node_modules/path-scurry/dist/esm/index.js.map +1 -0
  188. package/node_modules/path-scurry/dist/esm/package.json +3 -0
  189. package/node_modules/path-scurry/node_modules/lru-cache/LICENSE.md +55 -0
  190. package/node_modules/path-scurry/node_modules/lru-cache/README.md +383 -0
  191. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts +1323 -0
  192. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -0
  193. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +1589 -0
  194. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js.map +1 -0
  195. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
  196. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js.map +7 -0
  197. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/package.json +3 -0
  198. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts +1323 -0
  199. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -0
  200. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +1585 -0
  201. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js.map +1 -0
  202. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +2 -0
  203. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js.map +7 -0
  204. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/package.json +3 -0
  205. package/node_modules/path-scurry/node_modules/lru-cache/package.json +101 -0
  206. package/node_modules/path-scurry/package.json +88 -0
  207. package/node_modules/rimraf/LICENSE.md +55 -0
  208. package/node_modules/rimraf/README.md +226 -0
  209. package/node_modules/rimraf/dist/commonjs/default-tmp.d.ts +3 -0
  210. package/node_modules/rimraf/dist/commonjs/default-tmp.d.ts.map +1 -0
  211. package/node_modules/rimraf/dist/commonjs/default-tmp.js +58 -0
  212. package/node_modules/rimraf/dist/commonjs/default-tmp.js.map +1 -0
  213. package/node_modules/rimraf/dist/commonjs/error.d.ts +6 -0
  214. package/node_modules/rimraf/dist/commonjs/error.d.ts.map +1 -0
  215. package/node_modules/rimraf/dist/commonjs/error.js +10 -0
  216. package/node_modules/rimraf/dist/commonjs/error.js.map +1 -0
  217. package/node_modules/rimraf/dist/commonjs/fix-eperm.d.ts +3 -0
  218. package/node_modules/rimraf/dist/commonjs/fix-eperm.d.ts.map +1 -0
  219. package/node_modules/rimraf/dist/commonjs/fix-eperm.js +38 -0
  220. package/node_modules/rimraf/dist/commonjs/fix-eperm.js.map +1 -0
  221. package/node_modules/rimraf/dist/commonjs/fs.d.ts +15 -0
  222. package/node_modules/rimraf/dist/commonjs/fs.d.ts.map +1 -0
  223. package/node_modules/rimraf/dist/commonjs/fs.js +33 -0
  224. package/node_modules/rimraf/dist/commonjs/fs.js.map +1 -0
  225. package/node_modules/rimraf/dist/commonjs/ignore-enoent.d.ts +3 -0
  226. package/node_modules/rimraf/dist/commonjs/ignore-enoent.d.ts.map +1 -0
  227. package/node_modules/rimraf/dist/commonjs/ignore-enoent.js +24 -0
  228. package/node_modules/rimraf/dist/commonjs/ignore-enoent.js.map +1 -0
  229. package/node_modules/rimraf/dist/commonjs/index.d.ts +50 -0
  230. package/node_modules/rimraf/dist/commonjs/index.d.ts.map +1 -0
  231. package/node_modules/rimraf/dist/commonjs/index.js +78 -0
  232. package/node_modules/rimraf/dist/commonjs/index.js.map +1 -0
  233. package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts +34 -0
  234. package/node_modules/rimraf/dist/commonjs/opt-arg.d.ts.map +1 -0
  235. package/node_modules/rimraf/dist/commonjs/opt-arg.js +53 -0
  236. package/node_modules/rimraf/dist/commonjs/opt-arg.js.map +1 -0
  237. package/node_modules/rimraf/dist/commonjs/package.json +3 -0
  238. package/node_modules/rimraf/dist/commonjs/path-arg.d.ts +4 -0
  239. package/node_modules/rimraf/dist/commonjs/path-arg.d.ts.map +1 -0
  240. package/node_modules/rimraf/dist/commonjs/path-arg.js +48 -0
  241. package/node_modules/rimraf/dist/commonjs/path-arg.js.map +1 -0
  242. package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts +3 -0
  243. package/node_modules/rimraf/dist/commonjs/readdir-or-error.d.ts.map +1 -0
  244. package/node_modules/rimraf/dist/commonjs/readdir-or-error.js +19 -0
  245. package/node_modules/rimraf/dist/commonjs/readdir-or-error.js.map +1 -0
  246. package/node_modules/rimraf/dist/commonjs/retry-busy.d.ts +8 -0
  247. package/node_modules/rimraf/dist/commonjs/retry-busy.d.ts.map +1 -0
  248. package/node_modules/rimraf/dist/commonjs/retry-busy.js +65 -0
  249. package/node_modules/rimraf/dist/commonjs/retry-busy.js.map +1 -0
  250. package/node_modules/rimraf/dist/commonjs/rimraf-manual.d.ts +3 -0
  251. package/node_modules/rimraf/dist/commonjs/rimraf-manual.d.ts.map +1 -0
  252. package/node_modules/rimraf/dist/commonjs/rimraf-manual.js +8 -0
  253. package/node_modules/rimraf/dist/commonjs/rimraf-manual.js.map +1 -0
  254. package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts +4 -0
  255. package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.d.ts.map +1 -0
  256. package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js +138 -0
  257. package/node_modules/rimraf/dist/commonjs/rimraf-move-remove.js.map +1 -0
  258. package/node_modules/rimraf/dist/commonjs/rimraf-native.d.ts +4 -0
  259. package/node_modules/rimraf/dist/commonjs/rimraf-native.d.ts.map +1 -0
  260. package/node_modules/rimraf/dist/commonjs/rimraf-native.js +24 -0
  261. package/node_modules/rimraf/dist/commonjs/rimraf-native.js.map +1 -0
  262. package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts +4 -0
  263. package/node_modules/rimraf/dist/commonjs/rimraf-posix.d.ts.map +1 -0
  264. package/node_modules/rimraf/dist/commonjs/rimraf-posix.js +103 -0
  265. package/node_modules/rimraf/dist/commonjs/rimraf-posix.js.map +1 -0
  266. package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts +4 -0
  267. package/node_modules/rimraf/dist/commonjs/rimraf-windows.d.ts.map +1 -0
  268. package/node_modules/rimraf/dist/commonjs/rimraf-windows.js +159 -0
  269. package/node_modules/rimraf/dist/commonjs/rimraf-windows.js.map +1 -0
  270. package/node_modules/rimraf/dist/commonjs/use-native.d.ts +4 -0
  271. package/node_modules/rimraf/dist/commonjs/use-native.d.ts.map +1 -0
  272. package/node_modules/rimraf/dist/commonjs/use-native.js +18 -0
  273. package/node_modules/rimraf/dist/commonjs/use-native.js.map +1 -0
  274. package/node_modules/rimraf/dist/esm/bin.d.mts +3 -0
  275. package/node_modules/rimraf/dist/esm/bin.d.mts.map +1 -0
  276. package/node_modules/rimraf/dist/esm/bin.mjs +250 -0
  277. package/node_modules/rimraf/dist/esm/bin.mjs.map +1 -0
  278. package/node_modules/rimraf/dist/esm/default-tmp.d.ts +3 -0
  279. package/node_modules/rimraf/dist/esm/default-tmp.d.ts.map +1 -0
  280. package/node_modules/rimraf/dist/esm/default-tmp.js +55 -0
  281. package/node_modules/rimraf/dist/esm/default-tmp.js.map +1 -0
  282. package/node_modules/rimraf/dist/esm/error.d.ts +6 -0
  283. package/node_modules/rimraf/dist/esm/error.d.ts.map +1 -0
  284. package/node_modules/rimraf/dist/esm/error.js +5 -0
  285. package/node_modules/rimraf/dist/esm/error.js.map +1 -0
  286. package/node_modules/rimraf/dist/esm/fix-eperm.d.ts +3 -0
  287. package/node_modules/rimraf/dist/esm/fix-eperm.d.ts.map +1 -0
  288. package/node_modules/rimraf/dist/esm/fix-eperm.js +33 -0
  289. package/node_modules/rimraf/dist/esm/fix-eperm.js.map +1 -0
  290. package/node_modules/rimraf/dist/esm/fs.d.ts +15 -0
  291. package/node_modules/rimraf/dist/esm/fs.d.ts.map +1 -0
  292. package/node_modules/rimraf/dist/esm/fs.js +18 -0
  293. package/node_modules/rimraf/dist/esm/fs.js.map +1 -0
  294. package/node_modules/rimraf/dist/esm/ignore-enoent.d.ts +3 -0
  295. package/node_modules/rimraf/dist/esm/ignore-enoent.d.ts.map +1 -0
  296. package/node_modules/rimraf/dist/esm/ignore-enoent.js +19 -0
  297. package/node_modules/rimraf/dist/esm/ignore-enoent.js.map +1 -0
  298. package/node_modules/rimraf/dist/esm/index.d.ts +50 -0
  299. package/node_modules/rimraf/dist/esm/index.d.ts.map +1 -0
  300. package/node_modules/rimraf/dist/esm/index.js +70 -0
  301. package/node_modules/rimraf/dist/esm/index.js.map +1 -0
  302. package/node_modules/rimraf/dist/esm/opt-arg.d.ts +34 -0
  303. package/node_modules/rimraf/dist/esm/opt-arg.d.ts.map +1 -0
  304. package/node_modules/rimraf/dist/esm/opt-arg.js +46 -0
  305. package/node_modules/rimraf/dist/esm/opt-arg.js.map +1 -0
  306. package/node_modules/rimraf/dist/esm/package.json +3 -0
  307. package/node_modules/rimraf/dist/esm/path-arg.d.ts +4 -0
  308. package/node_modules/rimraf/dist/esm/path-arg.d.ts.map +1 -0
  309. package/node_modules/rimraf/dist/esm/path-arg.js +46 -0
  310. package/node_modules/rimraf/dist/esm/path-arg.js.map +1 -0
  311. package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts +3 -0
  312. package/node_modules/rimraf/dist/esm/readdir-or-error.d.ts.map +1 -0
  313. package/node_modules/rimraf/dist/esm/readdir-or-error.js +14 -0
  314. package/node_modules/rimraf/dist/esm/readdir-or-error.js.map +1 -0
  315. package/node_modules/rimraf/dist/esm/retry-busy.d.ts +8 -0
  316. package/node_modules/rimraf/dist/esm/retry-busy.d.ts.map +1 -0
  317. package/node_modules/rimraf/dist/esm/retry-busy.js +60 -0
  318. package/node_modules/rimraf/dist/esm/retry-busy.js.map +1 -0
  319. package/node_modules/rimraf/dist/esm/rimraf-manual.d.ts +3 -0
  320. package/node_modules/rimraf/dist/esm/rimraf-manual.d.ts.map +1 -0
  321. package/node_modules/rimraf/dist/esm/rimraf-manual.js +5 -0
  322. package/node_modules/rimraf/dist/esm/rimraf-manual.js.map +1 -0
  323. package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts +4 -0
  324. package/node_modules/rimraf/dist/esm/rimraf-move-remove.d.ts.map +1 -0
  325. package/node_modules/rimraf/dist/esm/rimraf-move-remove.js +133 -0
  326. package/node_modules/rimraf/dist/esm/rimraf-move-remove.js.map +1 -0
  327. package/node_modules/rimraf/dist/esm/rimraf-native.d.ts +4 -0
  328. package/node_modules/rimraf/dist/esm/rimraf-native.d.ts.map +1 -0
  329. package/node_modules/rimraf/dist/esm/rimraf-native.js +19 -0
  330. package/node_modules/rimraf/dist/esm/rimraf-native.js.map +1 -0
  331. package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts +4 -0
  332. package/node_modules/rimraf/dist/esm/rimraf-posix.d.ts.map +1 -0
  333. package/node_modules/rimraf/dist/esm/rimraf-posix.js +98 -0
  334. package/node_modules/rimraf/dist/esm/rimraf-posix.js.map +1 -0
  335. package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts +4 -0
  336. package/node_modules/rimraf/dist/esm/rimraf-windows.d.ts.map +1 -0
  337. package/node_modules/rimraf/dist/esm/rimraf-windows.js +154 -0
  338. package/node_modules/rimraf/dist/esm/rimraf-windows.js.map +1 -0
  339. package/node_modules/rimraf/dist/esm/use-native.d.ts +4 -0
  340. package/node_modules/rimraf/dist/esm/use-native.d.ts.map +1 -0
  341. package/node_modules/rimraf/dist/esm/use-native.js +15 -0
  342. package/node_modules/rimraf/dist/esm/use-native.js.map +1 -0
  343. package/node_modules/rimraf/package.json +92 -0
  344. package/package.json +152 -0
  345. package/scripts/install-scanners.js +258 -0
  346. package/scripts/watchdog.js +147 -0
  347. package/src/analyzers/CSSAnalyzer.js +297 -0
  348. package/src/analyzers/ConfigValidator.js +690 -0
  349. package/src/analyzers/ESLintAnalyzer.js +320 -0
  350. package/src/analyzers/JavaScriptAnalyzer.js +261 -0
  351. package/src/analyzers/PrettierFormatter.js +247 -0
  352. package/src/analyzers/PythonAnalyzer.js +283 -0
  353. package/src/analyzers/SecurityAnalyzer.js +729 -0
  354. package/src/analyzers/SparrowAnalyzer.js +341 -0
  355. package/src/analyzers/TypeScriptAnalyzer.js +247 -0
  356. package/src/analyzers/codeCloneDetector/analyzer.js +344 -0
  357. package/src/analyzers/codeCloneDetector/detector.js +250 -0
  358. package/src/analyzers/codeCloneDetector/index.js +192 -0
  359. package/src/analyzers/codeCloneDetector/parser.js +199 -0
  360. package/src/analyzers/codeCloneDetector/reporter.js +148 -0
  361. package/src/analyzers/codeCloneDetector/scanner.js +88 -0
  362. package/src/core/agentPool.js +1957 -0
  363. package/src/core/agentScheduler.js +3212 -0
  364. package/src/core/contextManager.js +709 -0
  365. package/src/core/flowExecutor.js +928 -0
  366. package/src/core/messageProcessor.js +808 -0
  367. package/src/core/orchestrator.js +584 -0
  368. package/src/core/stateManager.js +1500 -0
  369. package/src/index.js +972 -0
  370. package/src/interfaces/cli.js +553 -0
  371. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +208 -0
  372. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +236 -0
  373. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +138 -0
  374. package/src/interfaces/terminal/__tests__/smoke/components.test.js +137 -0
  375. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +350 -0
  376. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +156 -0
  377. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +332 -0
  378. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +256 -0
  379. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +388 -0
  380. package/src/interfaces/terminal/api/apiClient.js +299 -0
  381. package/src/interfaces/terminal/api/messageRouter.js +262 -0
  382. package/src/interfaces/terminal/api/session.js +266 -0
  383. package/src/interfaces/terminal/api/websocket.js +497 -0
  384. package/src/interfaces/terminal/components/AgentCreator.js +705 -0
  385. package/src/interfaces/terminal/components/AgentEditor.js +678 -0
  386. package/src/interfaces/terminal/components/AgentSwitcher.js +330 -0
  387. package/src/interfaces/terminal/components/ErrorBoundary.js +92 -0
  388. package/src/interfaces/terminal/components/ErrorPanel.js +264 -0
  389. package/src/interfaces/terminal/components/Header.js +28 -0
  390. package/src/interfaces/terminal/components/HelpPanel.js +231 -0
  391. package/src/interfaces/terminal/components/InputBox.js +118 -0
  392. package/src/interfaces/terminal/components/Layout.js +603 -0
  393. package/src/interfaces/terminal/components/LoadingSpinner.js +71 -0
  394. package/src/interfaces/terminal/components/MessageList.js +281 -0
  395. package/src/interfaces/terminal/components/MultilineTextInput.js +251 -0
  396. package/src/interfaces/terminal/components/SearchPanel.js +265 -0
  397. package/src/interfaces/terminal/components/SettingsPanel.js +415 -0
  398. package/src/interfaces/terminal/components/StatusBar.js +65 -0
  399. package/src/interfaces/terminal/components/TextInput.js +127 -0
  400. package/src/interfaces/terminal/config/agentEditorConstants.js +227 -0
  401. package/src/interfaces/terminal/config/constants.js +393 -0
  402. package/src/interfaces/terminal/index.js +168 -0
  403. package/src/interfaces/terminal/state/useAgentControl.js +496 -0
  404. package/src/interfaces/terminal/state/useAgents.js +537 -0
  405. package/src/interfaces/terminal/state/useConnection.js +444 -0
  406. package/src/interfaces/terminal/state/useMessages.js +630 -0
  407. package/src/interfaces/terminal/state/useTools.js +554 -0
  408. package/src/interfaces/terminal/utils/debugLogger.js +44 -0
  409. package/src/interfaces/terminal/utils/settingsStorage.js +232 -0
  410. package/src/interfaces/terminal/utils/theme.js +85 -0
  411. package/src/interfaces/webServer.js +5457 -0
  412. package/src/modules/fileExplorer/controller.js +413 -0
  413. package/src/modules/fileExplorer/index.js +37 -0
  414. package/src/modules/fileExplorer/middleware.js +92 -0
  415. package/src/modules/fileExplorer/routes.js +158 -0
  416. package/src/modules/fileExplorer/types.js +44 -0
  417. package/src/services/agentActivityService.js +399 -0
  418. package/src/services/aiService.js +2618 -0
  419. package/src/services/apiKeyManager.js +334 -0
  420. package/src/services/benchmarkService.js +196 -0
  421. package/src/services/budgetService.js +565 -0
  422. package/src/services/contextInjectionService.js +268 -0
  423. package/src/services/conversationCompactionService.js +1103 -0
  424. package/src/services/credentialVault.js +685 -0
  425. package/src/services/errorHandler.js +810 -0
  426. package/src/services/fileAttachmentService.js +547 -0
  427. package/src/services/flowContextService.js +189 -0
  428. package/src/services/memoryService.js +521 -0
  429. package/src/services/modelRouterService.js +365 -0
  430. package/src/services/modelsService.js +323 -0
  431. package/src/services/ollamaService.js +452 -0
  432. package/src/services/portRegistry.js +336 -0
  433. package/src/services/portTracker.js +223 -0
  434. package/src/services/projectDetector.js +404 -0
  435. package/src/services/promptService.js +372 -0
  436. package/src/services/qualityInspector.js +796 -0
  437. package/src/services/scheduleService.js +725 -0
  438. package/src/services/serviceRegistry.js +386 -0
  439. package/src/services/skillsService.js +486 -0
  440. package/src/services/telegramService.js +920 -0
  441. package/src/services/tokenCountingService.js +316 -0
  442. package/src/services/visualEditorBridge.js +1033 -0
  443. package/src/services/visualEditorServer.js +1727 -0
  444. package/src/services/whatsappService.js +663 -0
  445. package/src/tools/__tests__/webTool.e2e.test.js +569 -0
  446. package/src/tools/__tests__/webTool.unit.test.js +195 -0
  447. package/src/tools/agentCommunicationTool.js +1343 -0
  448. package/src/tools/agentDelayTool.js +498 -0
  449. package/src/tools/asyncToolManager.js +604 -0
  450. package/src/tools/baseTool.js +887 -0
  451. package/src/tools/browserTool.js +897 -0
  452. package/src/tools/cloneDetectionTool.js +581 -0
  453. package/src/tools/codeMapTool.js +857 -0
  454. package/src/tools/dependencyResolverTool.js +1212 -0
  455. package/src/tools/docxTool.js +623 -0
  456. package/src/tools/excelTool.js +636 -0
  457. package/src/tools/fileContentReplaceTool.js +840 -0
  458. package/src/tools/fileTreeTool.js +833 -0
  459. package/src/tools/filesystemTool.js +1217 -0
  460. package/src/tools/helpTool.js +198 -0
  461. package/src/tools/imageTool.js +1034 -0
  462. package/src/tools/importAnalyzerTool.js +1056 -0
  463. package/src/tools/jobDoneTool.js +388 -0
  464. package/src/tools/memoryTool.js +554 -0
  465. package/src/tools/pdfTool.js +627 -0
  466. package/src/tools/seekTool.js +883 -0
  467. package/src/tools/skillsTool.js +276 -0
  468. package/src/tools/staticAnalysisTool.js +2146 -0
  469. package/src/tools/taskManagerTool.js +2836 -0
  470. package/src/tools/terminalTool.js +2486 -0
  471. package/src/tools/userPromptTool.js +474 -0
  472. package/src/tools/videoTool.js +1139 -0
  473. package/src/tools/visionTool.js +507 -0
  474. package/src/tools/visualEditorTool.js +1175 -0
  475. package/src/tools/webTool.js +3114 -0
  476. package/src/tools/whatsappTool.js +457 -0
  477. package/src/types/agent.js +519 -0
  478. package/src/types/contextReference.js +972 -0
  479. package/src/types/conversation.js +730 -0
  480. package/src/types/toolCommand.js +747 -0
  481. package/src/utilities/attachmentValidator.js +288 -0
  482. package/src/utilities/browserStealth.js +630 -0
  483. package/src/utilities/configManager.js +618 -0
  484. package/src/utilities/constants.js +870 -0
  485. package/src/utilities/directoryAccessManager.js +566 -0
  486. package/src/utilities/fileProcessor.js +307 -0
  487. package/src/utilities/humanBehavior.js +453 -0
  488. package/src/utilities/jsonRepair.js +242 -0
  489. package/src/utilities/logger.js +436 -0
  490. package/src/utilities/platformUtils.js +255 -0
  491. package/src/utilities/platformUtils.test.js +98 -0
  492. package/src/utilities/stealthConstants.js +377 -0
  493. package/src/utilities/structuredFileValidator.js +699 -0
  494. package/src/utilities/tagParser.js +878 -0
  495. package/src/utilities/toolConstants.js +415 -0
  496. package/src/utilities/userDataDir.js +300 -0
  497. package/web-ui/build/brands/autopilot/favicon.svg +1 -0
  498. package/web-ui/build/brands/autopilot/logo.webp +0 -0
  499. package/web-ui/build/brands/onbuzz/favicon.svg +1 -0
  500. package/web-ui/build/brands/onbuzz/logo-text.webp +0 -0
  501. package/web-ui/build/brands/onbuzz/logo.webp +0 -0
  502. package/web-ui/build/index.html +15 -0
  503. package/web-ui/build/logo.png +0 -0
  504. package/web-ui/build/logo2.png +0 -0
  505. package/web-ui/build/static/index-SmQFfvBs.js +746 -0
  506. package/web-ui/build/static/index-V2ySwjHp.css +1 -0
@@ -0,0 +1,1217 @@
1
+ /**
2
+ * FileSystemTool - Handle file system operations safely
3
+ *
4
+ * Purpose:
5
+ * - Read, write, and manipulate files
6
+ * - Directory operations
7
+ * - File metadata and permissions
8
+ * - Safe file operations with validation
9
+ */
10
+
11
+ import { BaseTool } from './baseTool.js';
12
+ import TagParser from '../utilities/tagParser.js';
13
+ import DirectoryAccessManager from '../utilities/directoryAccessManager.js';
14
+ import fs from 'fs/promises';
15
+ import path from 'path';
16
+ import crypto from 'crypto';
17
+
18
+ import {
19
+ TOOL_STATUS,
20
+ FILE_EXTENSIONS,
21
+ SYSTEM_DEFAULTS
22
+ } from '../utilities/constants.js';
23
+ import { validateForToolResponse } from '../utilities/structuredFileValidator.js';
24
+ import { createTruncationNotice, getFileExtension } from '../utilities/jsonRepair.js';
25
+
26
+ class FileSystemTool extends BaseTool {
27
+ constructor(config = {}, logger = null) {
28
+ super(config, logger);
29
+
30
+ // Tool metadata
31
+ this.requiresProject = true;
32
+ this.isAsync = false; // Most file operations are quick
33
+ this.timeout = config.timeout || 30000; // 30 seconds
34
+ this.maxConcurrentOperations = config.maxConcurrentOperations || 5;
35
+
36
+ // Security settings
37
+ this.maxFileSize = config.maxFileSize || SYSTEM_DEFAULTS.MAX_FILE_SIZE;
38
+ this.allowedExtensions = config.allowedExtensions || null; // null = all allowed
39
+ this.blockedExtensions = config.blockedExtensions || ['.exe', '.bat', '.cmd', '.scr', '.com'];
40
+ this.allowedDirectories = config.allowedDirectories || null; // null = project dir only
41
+
42
+ // Post-write validation for structured files (JSON, YAML, XML, etc.)
43
+ // When enabled, validates structured files after writing and includes result in response
44
+ this.validateStructuredFiles = config.validateStructuredFiles !== false; // enabled by default
45
+
46
+ // File operation history
47
+ this.operationHistory = [];
48
+
49
+ // Directory access manager
50
+ this.directoryAccessManager = new DirectoryAccessManager(config, logger);
51
+ }
52
+
53
+ /**
54
+ * Get tool description for LLM consumption
55
+ * @returns {string} Tool description
56
+ */
57
+ getDescription() {
58
+ return `
59
+ File System Tool: Perform file and directory operations safely within the project scope.
60
+
61
+ USAGE:
62
+ \`\`\`json
63
+ {
64
+ "toolId": "filesystem",
65
+ "actions": [
66
+ {"type": "read", "filePath": "src/index.js"},
67
+ {"type": "write", "outputPath": "src/file.js", "content": "..."}
68
+ ]
69
+ }
70
+ \`\`\`
71
+
72
+ TIP: For exploring large or unfamiliar files, prefer the code-map tool (skeleton + read-range) to understand structure without reading entire files. Use filesystem read when you need the complete file content.
73
+
74
+ SUPPORTED ACTIONS:
75
+ - read: Read file contents (filePath)
76
+ - write: Write content to file (outputPath, content)
77
+ - append: Append content to existing file (filePath, content)
78
+ - delete: Delete a file (filePath)
79
+ - copy: Copy file (sourcePath, destPath)
80
+ - move: Move/rename file (sourcePath, destPath)
81
+ - create-dir: Create directory (directory)
82
+ - list: List directory contents (directory)
83
+ - exists: Check if file/directory exists (filePath)
84
+ - stats: Get file/directory metadata (filePath)
85
+
86
+ PARAMETERS:
87
+ - filePath: Path to file (for read, delete, append, exists, stats)
88
+ - outputPath: Path where to write/create file
89
+ - sourcePath: Source path for copy/move operations
90
+ - destPath: Destination path for copy/move operations
91
+ - directory: Directory path for create-dir and list operations
92
+ - content: Content to write/append
93
+ - encoding: File encoding (default: utf8)
94
+ - createDirs: Create parent directories if they don't exist (true/false)
95
+
96
+ EXAMPLES:
97
+
98
+ Write a file:
99
+ \`\`\`json
100
+ {
101
+ "toolId": "filesystem",
102
+ "actions": [{"type": "write", "outputPath": "hello.js", "content": "console.log('Hello');"}]
103
+ }
104
+ \`\`\`
105
+
106
+ Read a file:
107
+ \`\`\`json
108
+ {
109
+ "toolId": "filesystem",
110
+ "actions": [{"type": "read", "filePath": "package.json"}]
111
+ }
112
+ \`\`\`
113
+
114
+ Multiple operations:
115
+ \`\`\`json
116
+ {
117
+ "toolId": "filesystem",
118
+ "actions": [
119
+ {"type": "read", "filePath": "src/index.js"},
120
+ {"type": "copy", "sourcePath": "template.js", "destPath": "src/component.js"},
121
+ {"type": "create-dir", "directory": "src/components/ui"}
122
+ ]
123
+ }
124
+ \`\`\`
125
+
126
+ SECURITY:
127
+ - Operations restricted to project directory
128
+ - File size limits enforced (max ${Math.round(this.maxFileSize / 1024 / 1024)}MB)
129
+ - Dangerous file types blocked
130
+ - Path traversal protection
131
+ `;
132
+ }
133
+
134
+ /**
135
+ * Parse parameters from tool command content
136
+ * @param {string} content - Raw tool command content
137
+ * @returns {Object} Parsed parameters
138
+ */
139
+ parseParameters(content) {
140
+ try {
141
+ const params = {};
142
+ const actions = [];
143
+
144
+ this.logger?.debug('FileSystem tool parsing parameters', {
145
+ contentLength: content.length,
146
+ contentPreview: content.substring(0, 200)
147
+ });
148
+
149
+ // Extract self-closing tags (read, delete, copy, etc.)
150
+ const selfClosingTags = [
151
+ 'read', 'delete', 'copy', 'move', 'create-dir',
152
+ 'list', 'exists', 'stats', 'append'
153
+ ];
154
+
155
+ for (const tagName of selfClosingTags) {
156
+ const tags = TagParser.extractTagsWithAttributes(content, tagName);
157
+ for (const tag of tags) {
158
+ const action = {
159
+ type: tagName,
160
+ ...tag.attributes
161
+ };
162
+
163
+ // Normalize common attribute names
164
+ if (action['file-path']) {
165
+ action.filePath = action['file-path'];
166
+ delete action['file-path'];
167
+ }
168
+ if (action['output-path']) {
169
+ action.outputPath = action['output-path'];
170
+ delete action['output-path'];
171
+ }
172
+ if (action['source-path']) {
173
+ action.sourcePath = action['source-path'];
174
+ delete action['source-path'];
175
+ }
176
+ if (action['dest-path']) {
177
+ action.destPath = action['dest-path'];
178
+ delete action['dest-path'];
179
+ }
180
+ if (action['create-dirs']) {
181
+ action.createDirs = action['create-dirs'] === 'true';
182
+ delete action['create-dirs'];
183
+ }
184
+
185
+ actions.push(action);
186
+ }
187
+ }
188
+
189
+ // Extract write and append tags with content
190
+ const writeMatches = content.matchAll(/<write\s+([^>]*)>(.*?)<\/write>/gs);
191
+ for (const match of writeMatches) {
192
+ const parser = new TagParser();
193
+ const attributes = parser.parseAttributes(match[1]);
194
+ const writeContent = match[2].trim();
195
+
196
+ const action = {
197
+ type: 'write',
198
+ content: writeContent,
199
+ ...attributes
200
+ };
201
+
202
+ // Normalize attribute names
203
+ if (action['output-path']) {
204
+ action.outputPath = action['output-path'];
205
+ delete action['output-path'];
206
+ }
207
+ if (action['create-dirs']) {
208
+ action.createDirs = action['create-dirs'] === 'true';
209
+ delete action['create-dirs'];
210
+ }
211
+
212
+ actions.push(action);
213
+ }
214
+
215
+ const appendMatches = content.matchAll(/<append\s+([^>]*)>(.*?)<\/append>/gs);
216
+ for (const match of appendMatches) {
217
+ const parser = new TagParser();
218
+ const attributes = parser.parseAttributes(match[1]);
219
+ const appendContent = match[2].trim();
220
+
221
+ const action = {
222
+ type: 'append',
223
+ content: appendContent,
224
+ ...attributes
225
+ };
226
+
227
+ // Normalize attribute names
228
+ if (action['file-path']) {
229
+ action.filePath = action['file-path'];
230
+ delete action['file-path'];
231
+ }
232
+
233
+ actions.push(action);
234
+ }
235
+
236
+ params.actions = actions;
237
+ params.rawContent = content.trim();
238
+
239
+ this.logger?.debug('Parsed FileSystem tool parameters', {
240
+ totalActions: actions.length,
241
+ actionTypes: actions.map(a => a.type),
242
+ actions: actions.map(a => ({
243
+ type: a.type,
244
+ filePath: a.filePath,
245
+ outputPath: a.outputPath,
246
+ hasContent: !!a.content
247
+ }))
248
+ });
249
+
250
+ return params;
251
+
252
+ } catch (error) {
253
+ throw new Error(`Failed to parse filesystem parameters: ${error.message}`);
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Get required parameters
259
+ * @returns {Array<string>} Array of required parameter names
260
+ */
261
+ getRequiredParameters() {
262
+ return ['actions'];
263
+ }
264
+
265
+ /**
266
+ * Custom parameter validation
267
+ * @param {Object} params - Parameters to validate
268
+ * @returns {Object} Validation result
269
+ */
270
+ customValidateParameters(params) {
271
+ const errors = [];
272
+
273
+ if (!params.actions || !Array.isArray(params.actions) || params.actions.length === 0) {
274
+ errors.push('At least one action is required');
275
+ } else {
276
+ // Validate each action
277
+ for (const [index, action] of params.actions.entries()) {
278
+ if (!action.type) {
279
+ errors.push(`Action ${index + 1}: type is required`);
280
+ continue;
281
+ }
282
+
283
+ switch (action.type) {
284
+ case 'read':
285
+ case 'delete':
286
+ case 'exists':
287
+ case 'stats':
288
+ if (!action.filePath) {
289
+ errors.push(`Action ${index + 1}: file-path is required for ${action.type}`);
290
+ }
291
+ break;
292
+
293
+ case 'write':
294
+ if (!action.outputPath) {
295
+ errors.push(`Action ${index + 1}: output-path is required for write`);
296
+ }
297
+ // Content validation with detailed diagnostics
298
+ if (action.content === undefined) {
299
+ errors.push(`Action ${index + 1}: content is undefined for write (outputPath: ${action.outputPath || 'not set'})`);
300
+ console.error('[FileSystemTool] Write validation failed: content is undefined', {
301
+ outputPath: action.outputPath,
302
+ actionKeys: Object.keys(action)
303
+ });
304
+ } else if (action.content === null) {
305
+ errors.push(`Action ${index + 1}: content is null for write (outputPath: ${action.outputPath || 'not set'})`);
306
+ console.error('[FileSystemTool] Write validation failed: content is null', {
307
+ outputPath: action.outputPath
308
+ });
309
+ } else if (typeof action.content !== 'string') {
310
+ errors.push(`Action ${index + 1}: content must be a string, got ${typeof action.content}`);
311
+ console.error('[FileSystemTool] Write validation failed: content is not a string', {
312
+ outputPath: action.outputPath,
313
+ contentType: typeof action.content
314
+ });
315
+ }
316
+ // Note: empty string content is allowed (creates empty file)
317
+ break;
318
+
319
+ case 'append':
320
+ if (!action.filePath) {
321
+ errors.push(`Action ${index + 1}: file-path is required for append`);
322
+ }
323
+ // Content validation with detailed diagnostics
324
+ if (action.content === undefined) {
325
+ errors.push(`Action ${index + 1}: content is undefined for append (filePath: ${action.filePath || 'not set'})`);
326
+ console.error('[FileSystemTool] Append validation failed: content is undefined', {
327
+ filePath: action.filePath,
328
+ actionKeys: Object.keys(action)
329
+ });
330
+ } else if (action.content === null) {
331
+ errors.push(`Action ${index + 1}: content is null for append (filePath: ${action.filePath || 'not set'})`);
332
+ console.error('[FileSystemTool] Append validation failed: content is null', {
333
+ filePath: action.filePath
334
+ });
335
+ } else if (typeof action.content !== 'string') {
336
+ errors.push(`Action ${index + 1}: content must be a string, got ${typeof action.content}`);
337
+ console.error('[FileSystemTool] Append validation failed: content is not a string', {
338
+ filePath: action.filePath,
339
+ contentType: typeof action.content
340
+ });
341
+ } else if (action.content.length === 0) {
342
+ // Empty append is suspicious - log a warning but allow it
343
+ console.warn('[FileSystemTool] Append with empty content', {
344
+ filePath: action.filePath
345
+ });
346
+ }
347
+ break;
348
+
349
+ case 'copy':
350
+ case 'move':
351
+ if (!action.sourcePath) {
352
+ errors.push(`Action ${index + 1}: source-path is required for ${action.type}`);
353
+ }
354
+ if (!action.destPath) {
355
+ errors.push(`Action ${index + 1}: dest-path is required for ${action.type}`);
356
+ }
357
+ break;
358
+
359
+ case 'create-dir':
360
+ case 'list':
361
+ if (!action.directory) {
362
+ errors.push(`Action ${index + 1}: directory is required for ${action.type}`);
363
+ }
364
+ break;
365
+
366
+ default:
367
+ errors.push(`Action ${index + 1}: unknown action type: ${action.type}`);
368
+ }
369
+
370
+ // Validate file extensions if specified
371
+ if (action.filePath && !this.isAllowedFileExtension(action.filePath)) {
372
+ errors.push(`Action ${index + 1}: file type not allowed: ${path.extname(action.filePath)}`);
373
+ }
374
+ if (action.outputPath && !this.isAllowedFileExtension(action.outputPath)) {
375
+ errors.push(`Action ${index + 1}: file type not allowed: ${path.extname(action.outputPath)}`);
376
+ }
377
+ }
378
+ }
379
+
380
+ return {
381
+ valid: errors.length === 0,
382
+ errors
383
+ };
384
+ }
385
+
386
+ /**
387
+ * Execute tool with parsed parameters
388
+ * @param {Object} params - Parsed parameters
389
+ * @param {Object} context - Execution context
390
+ * @returns {Promise<Object>} Execution result
391
+ */
392
+ async execute(params, context) {
393
+ // Validate params structure
394
+ if (!params || typeof params !== 'object') {
395
+ throw new Error('Invalid parameters: params must be an object');
396
+ }
397
+
398
+ const { actions } = params;
399
+
400
+ // Validate actions array
401
+ if (!actions) {
402
+ throw new Error('Invalid parameters: actions is required. Received params: ' + JSON.stringify(Object.keys(params)));
403
+ }
404
+
405
+ if (!Array.isArray(actions)) {
406
+ throw new Error('Invalid parameters: actions must be an array. Received type: ' + typeof actions);
407
+ }
408
+
409
+ if (actions.length === 0) {
410
+ throw new Error('Invalid parameters: actions array is empty');
411
+ }
412
+
413
+ // CRITICAL: Run custom validation (not called by messageProcessor)
414
+ // This ensures write/append actions have required content
415
+ const validation = this.customValidateParameters(params);
416
+ if (!validation.valid) {
417
+ const errorMsg = validation.errors?.join('; ') || validation.error || 'Validation failed';
418
+ console.error('[FileSystemTool] Parameter validation failed:', errorMsg);
419
+ throw new Error(`Parameter validation failed: ${errorMsg}`);
420
+ }
421
+
422
+ const { projectDir, agentId, directoryAccess } = context;
423
+
424
+ // Get directory access configuration from agent or create default
425
+ const accessConfig = directoryAccess ||
426
+ this.directoryAccessManager.createDirectoryAccess({
427
+ workingDirectory: projectDir || process.cwd(),
428
+ writeEnabledDirectories: [projectDir || process.cwd()],
429
+ restrictToProject: true
430
+ });
431
+
432
+ // IMPORTANT: If the agent has directoryAccess configured, use its workingDirectory
433
+ // This ensures UI-configured project directories are respected
434
+ if (directoryAccess && directoryAccess.workingDirectory) {
435
+ // Agent has explicitly configured working directory from UI - use it
436
+ console.log('FileSystem DEBUG: Using agent configured working directory:', directoryAccess.workingDirectory);
437
+ console.log('FileSystem DEBUG: Full directoryAccess object:', JSON.stringify(directoryAccess, null, 2));
438
+ } else {
439
+ // Using fallback to projectDir or process.cwd()
440
+ console.log('FileSystem DEBUG: Using fallback working directory:', projectDir || process.cwd());
441
+ console.log('FileSystem DEBUG: directoryAccess is:', directoryAccess);
442
+ console.log('FileSystem DEBUG: projectDir is:', projectDir);
443
+ }
444
+
445
+ const results = [];
446
+
447
+ for (const action of actions) {
448
+ try {
449
+ let result;
450
+
451
+ switch (action.type) {
452
+ case 'read':
453
+ result = await this.readFile(action.filePath, accessConfig, action.encoding);
454
+ break;
455
+
456
+ case 'write':
457
+ result = await this.writeFile(action.outputPath, action.content, accessConfig, {
458
+ encoding: action.encoding,
459
+ createDirs: action.createDirs,
460
+ wasTruncated: context.wasTruncated || false
461
+ });
462
+ break;
463
+
464
+ case 'append':
465
+ result = await this.appendToFile(action.filePath, action.content, accessConfig, action.encoding);
466
+ break;
467
+
468
+ case 'delete':
469
+ result = await this.deleteFile(action.filePath, accessConfig);
470
+ break;
471
+
472
+ case 'copy':
473
+ result = await this.copyFile(action.sourcePath, action.destPath, accessConfig);
474
+ break;
475
+
476
+ case 'move':
477
+ result = await this.moveFile(action.sourcePath, action.destPath, accessConfig);
478
+ break;
479
+
480
+ case 'create-dir':
481
+ result = await this.createDirectory(action.directory, accessConfig);
482
+ break;
483
+
484
+ case 'list':
485
+ result = await this.listDirectory(action.directory, accessConfig);
486
+ break;
487
+
488
+ case 'exists':
489
+ result = await this.checkExists(action.filePath, accessConfig);
490
+ break;
491
+
492
+ case 'stats':
493
+ result = await this.getFileStats(action.filePath, accessConfig);
494
+ break;
495
+
496
+ default:
497
+ throw new Error(`Unknown action type: ${action.type}`);
498
+ }
499
+
500
+ results.push(result);
501
+ this.addToHistory(action, result, context.agentId);
502
+
503
+ } catch (error) {
504
+ // Log detailed error for debugging
505
+ console.error(`[FileSystemTool] Action '${action.type}' failed:`, {
506
+ action: action.type,
507
+ filePath: action.filePath || action.outputPath || action.directory,
508
+ error: error.message,
509
+ stack: error.stack?.split('\n').slice(0, 3).join('\n'),
510
+ contentLength: action.content?.length,
511
+ hasContent: action.content !== undefined && action.content !== null
512
+ });
513
+
514
+ const errorResult = {
515
+ success: false,
516
+ action: action.type,
517
+ error: error.message,
518
+ filePath: action.filePath || action.outputPath || action.directory,
519
+ // Include debug info for troubleshooting
520
+ debug: {
521
+ contentProvided: action.content !== undefined && action.content !== null,
522
+ contentLength: action.content?.length || 0,
523
+ contentPreview: action.content ? action.content.substring(0, 100) + (action.content.length > 100 ? '...' : '') : null
524
+ }
525
+ };
526
+
527
+ results.push(errorResult);
528
+ this.addToHistory(action, errorResult, context.agentId);
529
+ }
530
+ }
531
+
532
+ // Determine overall success - only true if ALL actions succeeded
533
+ const allSucceeded = results.every(r => r.success === true);
534
+ const failedCount = results.filter(r => r.success === false).length;
535
+
536
+ return {
537
+ success: allSucceeded,
538
+ actions: results,
539
+ executedActions: actions.length,
540
+ successfulActions: actions.length - failedCount,
541
+ failedActions: failedCount,
542
+ toolUsed: 'filesys',
543
+ ...(failedCount > 0 && {
544
+ warning: `${failedCount} of ${actions.length} action(s) failed. Check individual action results for details.`
545
+ })
546
+ };
547
+ }
548
+
549
+ /**
550
+ * Read file contents
551
+ * @private
552
+ */
553
+ async readFile(filePath, accessConfig, encoding = 'utf8') {
554
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
555
+ const fullPath = this.resolvePath(filePath, workingDir);
556
+
557
+ // Validate read access using DirectoryAccessManager
558
+ const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
559
+ if (!accessResult.allowed) {
560
+ throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
561
+ }
562
+
563
+ try {
564
+ const stats = await fs.stat(fullPath);
565
+
566
+ if (stats.size > this.maxFileSize) {
567
+ throw new Error(`File too large: ${stats.size} bytes (max ${this.maxFileSize})`);
568
+ }
569
+
570
+ const content = await fs.readFile(fullPath, encoding);
571
+
572
+ return {
573
+ success: true,
574
+ action: 'read',
575
+ filePath: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
576
+ content,
577
+ size: stats.size,
578
+ encoding,
579
+ lastModified: stats.mtime.toISOString(),
580
+ message: `Read ${stats.size} bytes from ${filePath}`
581
+ };
582
+
583
+ } catch (error) {
584
+ throw new Error(`Failed to read file ${filePath}: ${error.message}`);
585
+ }
586
+ }
587
+
588
+ /**
589
+ * Write content to file
590
+ * @private
591
+ */
592
+ async writeFile(outputPath, content, accessConfig, options = {}) {
593
+ const { encoding = 'utf8', createDirs = true, wasTruncated = false } = options;
594
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
595
+ const fullPath = this.resolvePath(outputPath, workingDir);
596
+
597
+ // Validate write access using DirectoryAccessManager
598
+ const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
599
+ if (!accessResult.allowed) {
600
+ throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
601
+ }
602
+
603
+ // Handle truncated content - append notice if AI response was cut off
604
+ let finalContent = content;
605
+ let truncationApplied = false;
606
+
607
+ if (wasTruncated && content) {
608
+ const fileExt = getFileExtension(outputPath);
609
+ const truncationNotice = createTruncationNotice(fileExt);
610
+ if (truncationNotice) {
611
+ finalContent = content + truncationNotice;
612
+ truncationApplied = true;
613
+ console.log(`[FileSystemTool] Appending truncation notice to ${outputPath} (AI response was truncated)`);
614
+ }
615
+ }
616
+
617
+ try {
618
+ // Check content size
619
+ const contentSize = Buffer.byteLength(finalContent, encoding);
620
+ if (contentSize > this.maxFileSize) {
621
+ throw new Error(`Content too large: ${contentSize} bytes (max ${this.maxFileSize})`);
622
+ }
623
+
624
+ // Create parent directories if requested
625
+ if (createDirs) {
626
+ const dirPath = path.dirname(fullPath);
627
+ await fs.mkdir(dirPath, { recursive: true });
628
+ }
629
+
630
+ // Create backup if file exists
631
+ let backupPath = null;
632
+ try {
633
+ await fs.access(fullPath);
634
+ backupPath = `${fullPath}.backup-${Date.now()}`;
635
+ await fs.copyFile(fullPath, backupPath);
636
+ } catch {
637
+ // File doesn't exist, no backup needed
638
+ }
639
+
640
+ await fs.writeFile(fullPath, finalContent, encoding);
641
+
642
+ // VERIFICATION: Confirm file was written correctly
643
+ const stats = await fs.stat(fullPath);
644
+
645
+ // Verify file size matches expected content size
646
+ const expectedSize = Buffer.byteLength(finalContent, encoding);
647
+ if (stats.size !== expectedSize) {
648
+ throw new Error(`Write verification failed: expected ${expectedSize} bytes but file is ${stats.size} bytes`);
649
+ }
650
+
651
+ // For text files, verify content was written (read back and compare hash)
652
+ if (encoding === 'utf8' || encoding === 'utf-8') {
653
+ const writtenContent = await fs.readFile(fullPath, encoding);
654
+ if (writtenContent !== finalContent) {
655
+ throw new Error(`Write verification failed: content mismatch after write`);
656
+ }
657
+ }
658
+
659
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
660
+
661
+ // Build base result
662
+ const result = {
663
+ success: true,
664
+ action: 'write',
665
+ outputPath: relativePath,
666
+ fullPath: fullPath,
667
+ size: stats.size,
668
+ encoding,
669
+ verified: true, // Content was verified after write
670
+ backupPath: backupPath ? this.directoryAccessManager.createRelativePath(backupPath, accessConfig) : null,
671
+ backupFullPath: backupPath || null,
672
+ message: `Wrote ${stats.size} bytes to ${fullPath} (verified)`,
673
+ // Include truncation info if applicable
674
+ ...(truncationApplied && {
675
+ wasTruncated: true,
676
+ truncationWarning: 'Content was truncated due to AI response token limit. A notice was appended to the file.'
677
+ }),
678
+ // Warn if content is empty
679
+ ...(stats.size === 0 && {
680
+ emptyContent: true,
681
+ emptyWarning: 'File was written with empty content'
682
+ })
683
+ };
684
+
685
+ // Add truncation warning to message
686
+ if (truncationApplied) {
687
+ result.message += ' [PARTIAL: AI response was truncated - content may be incomplete]';
688
+ }
689
+
690
+ // Post-write validation for structured files (plug-and-play via structuredFileValidator)
691
+ if (this.validateStructuredFiles) {
692
+ const validation = validateForToolResponse(content, fullPath);
693
+ if (validation) {
694
+ result.validation = validation;
695
+ // Add warning to message if validation failed
696
+ if (!validation.valid) {
697
+ result.message += ` [WARNING: ${validation.format.toUpperCase()} validation failed with ${validation.errorCount} error(s)]`;
698
+ }
699
+ }
700
+ }
701
+
702
+ return result;
703
+
704
+ } catch (error) {
705
+ throw new Error(`Failed to write file ${fullPath}: ${error.message}`);
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Append content to file
711
+ * @private
712
+ */
713
+ async appendToFile(filePath, content, accessConfig, encoding = 'utf8') {
714
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
715
+ const fullPath = this.resolvePath(filePath, workingDir);
716
+
717
+ // Validate write access using DirectoryAccessManager
718
+ const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
719
+ if (!accessResult.allowed) {
720
+ throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
721
+ }
722
+
723
+ try {
724
+ // Check if file exists and get current size
725
+ let currentSize = 0;
726
+ try {
727
+ const stats = await fs.stat(fullPath);
728
+ currentSize = stats.size;
729
+ } catch {
730
+ // File doesn't exist, will be created
731
+ }
732
+
733
+ const contentSize = Buffer.byteLength(content, encoding);
734
+ if (currentSize + contentSize > this.maxFileSize) {
735
+ throw new Error(`File would become too large: ${currentSize + contentSize} bytes (max ${this.maxFileSize})`);
736
+ }
737
+
738
+ // Store size before append for verification
739
+ const sizeBefore = currentSize;
740
+
741
+ await fs.appendFile(fullPath, content, encoding);
742
+
743
+ const stats = await fs.stat(fullPath);
744
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
745
+
746
+ // VERIFICATION: Confirm append actually happened
747
+ const expectedSize = sizeBefore + contentSize;
748
+ if (stats.size < expectedSize) {
749
+ throw new Error(`Append verification failed: expected at least ${expectedSize} bytes but file is ${stats.size} bytes`);
750
+ }
751
+
752
+ // For text files, verify the appended content is at the end
753
+ if (encoding === 'utf8' || encoding === 'utf-8') {
754
+ const fileContent = await fs.readFile(fullPath, encoding);
755
+ if (!fileContent.endsWith(content)) {
756
+ throw new Error(`Append verification failed: appended content not found at end of file`);
757
+ }
758
+ }
759
+
760
+ return {
761
+ success: true,
762
+ action: 'append',
763
+ filePath: relativePath,
764
+ fullPath: fullPath,
765
+ appendedBytes: contentSize,
766
+ totalSize: stats.size,
767
+ sizeBefore: sizeBefore,
768
+ encoding,
769
+ verified: true,
770
+ message: `Appended ${contentSize} bytes to ${fullPath} (verified)`
771
+ };
772
+
773
+ } catch (error) {
774
+ throw new Error(`Failed to append to file ${fullPath}: ${error.message}`);
775
+ }
776
+ }
777
+
778
+ /**
779
+ * Delete file
780
+ * @private
781
+ */
782
+ async deleteFile(filePath, accessConfig) {
783
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
784
+ const fullPath = this.resolvePath(filePath, workingDir);
785
+
786
+ // Validate write access for deletion
787
+ const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
788
+ if (!accessResult.allowed) {
789
+ throw new Error(`Delete access denied: ${accessResult.reason} (${accessResult.path})`);
790
+ }
791
+
792
+ try {
793
+ const stats = await fs.stat(fullPath);
794
+
795
+ // Create backup before deletion
796
+ const backupPath = `${fullPath}.deleted-backup-${Date.now()}`;
797
+ await fs.copyFile(fullPath, backupPath);
798
+
799
+ await fs.unlink(fullPath);
800
+
801
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
802
+ const backupRelativePath = this.directoryAccessManager.createRelativePath(backupPath, accessConfig);
803
+
804
+ return {
805
+ success: true,
806
+ action: 'delete',
807
+ filePath: relativePath,
808
+ fullPath: fullPath,
809
+ size: stats.size,
810
+ backupPath: backupRelativePath,
811
+ backupFullPath: backupPath,
812
+ message: `Deleted ${fullPath} (backup created)`
813
+ };
814
+
815
+ } catch (error) {
816
+ throw new Error(`Failed to delete file ${fullPath}: ${error.message}`);
817
+ }
818
+ }
819
+
820
+ /**
821
+ * Copy file
822
+ * @private
823
+ */
824
+ async copyFile(sourcePath, destPath, accessConfig) {
825
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
826
+ const fullSourcePath = this.resolvePath(sourcePath, workingDir);
827
+ const fullDestPath = this.resolvePath(destPath, workingDir);
828
+
829
+ // Validate read access for source
830
+ const sourceAccessResult = this.directoryAccessManager.validateReadAccess(fullSourcePath, accessConfig);
831
+ if (!sourceAccessResult.allowed) {
832
+ throw new Error(`Source read access denied: ${sourceAccessResult.reason} (${sourceAccessResult.path})`);
833
+ }
834
+
835
+ // Validate write access for destination
836
+ const destAccessResult = this.directoryAccessManager.validateWriteAccess(fullDestPath, accessConfig);
837
+ if (!destAccessResult.allowed) {
838
+ throw new Error(`Destination write access denied: ${destAccessResult.reason} (${destAccessResult.path})`);
839
+ }
840
+
841
+ try {
842
+ const sourceStats = await fs.stat(fullSourcePath);
843
+
844
+ if (sourceStats.size > this.maxFileSize) {
845
+ throw new Error(`Source file too large: ${sourceStats.size} bytes`);
846
+ }
847
+
848
+ // Create destination directory if needed
849
+ const destDir = path.dirname(fullDestPath);
850
+ await fs.mkdir(destDir, { recursive: true });
851
+
852
+ await fs.copyFile(fullSourcePath, fullDestPath);
853
+
854
+ const sourceRelativePath = this.directoryAccessManager.createRelativePath(fullSourcePath, accessConfig);
855
+ const destRelativePath = this.directoryAccessManager.createRelativePath(fullDestPath, accessConfig);
856
+
857
+ return {
858
+ success: true,
859
+ action: 'copy',
860
+ sourcePath: sourceRelativePath,
861
+ destPath: destRelativePath,
862
+ sourceFullPath: fullSourcePath,
863
+ destFullPath: fullDestPath,
864
+ size: sourceStats.size,
865
+ message: `Copied ${fullSourcePath} to ${fullDestPath}`
866
+ };
867
+
868
+ } catch (error) {
869
+ throw new Error(`Failed to copy ${fullSourcePath} to ${fullDestPath}: ${error.message}`);
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Move/rename file
875
+ * @private
876
+ */
877
+ async moveFile(sourcePath, destPath, accessConfig) {
878
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
879
+ const fullSourcePath = this.resolvePath(sourcePath, workingDir);
880
+ const fullDestPath = this.resolvePath(destPath, workingDir);
881
+
882
+ // Validate read access for source
883
+ const readResult = this.directoryAccessManager.validateReadAccess(fullSourcePath, accessConfig);
884
+ if (!readResult.allowed) {
885
+ throw new Error(`Read access denied for source: ${readResult.reason} (${readResult.path})`);
886
+ }
887
+
888
+ // Validate write access for destination
889
+ const writeResult = this.directoryAccessManager.validateWriteAccess(fullDestPath, accessConfig);
890
+ if (!writeResult.allowed) {
891
+ throw new Error(`Write access denied for destination: ${writeResult.reason} (${writeResult.path})`);
892
+ }
893
+
894
+ try {
895
+ const sourceStats = await fs.stat(fullSourcePath);
896
+
897
+ // Create destination directory if needed
898
+ const destDir = path.dirname(fullDestPath);
899
+ await fs.mkdir(destDir, { recursive: true });
900
+
901
+ await fs.rename(fullSourcePath, fullDestPath);
902
+
903
+ const relativeSource = this.directoryAccessManager.createRelativePath(fullSourcePath, accessConfig);
904
+ const relativeDest = this.directoryAccessManager.createRelativePath(fullDestPath, accessConfig);
905
+
906
+ return {
907
+ success: true,
908
+ action: 'move',
909
+ sourcePath: relativeSource,
910
+ destPath: relativeDest,
911
+ fullSourcePath: fullSourcePath,
912
+ fullDestPath: fullDestPath,
913
+ size: sourceStats.size,
914
+ message: `Moved ${sourcePath} to ${destPath}`
915
+ };
916
+
917
+ } catch (error) {
918
+ throw new Error(`Failed to move ${sourcePath} to ${destPath}: ${error.message}`);
919
+ }
920
+ }
921
+
922
+ /**
923
+ * Create directory
924
+ * @private
925
+ */
926
+ async createDirectory(directory, accessConfig) {
927
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
928
+ const fullPath = this.resolvePath(directory, workingDir);
929
+
930
+ // Validate write access using DirectoryAccessManager
931
+ const accessResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
932
+ if (!accessResult.allowed) {
933
+ throw new Error(`Write access denied: ${accessResult.reason} (${accessResult.path})`);
934
+ }
935
+
936
+ try {
937
+ await fs.mkdir(fullPath, { recursive: true });
938
+
939
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
940
+
941
+ return {
942
+ success: true,
943
+ action: 'create-dir',
944
+ directory: relativePath,
945
+ fullPath: fullPath,
946
+ message: `Created directory ${directory}`
947
+ };
948
+
949
+ } catch (error) {
950
+ throw new Error(`Failed to create directory ${directory}: ${error.message}`);
951
+ }
952
+ }
953
+
954
+ /**
955
+ * List directory contents
956
+ * @private
957
+ */
958
+ async listDirectory(directory, accessConfig) {
959
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
960
+ const fullPath = this.resolvePath(directory, workingDir);
961
+
962
+ // Validate read access using DirectoryAccessManager
963
+ const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
964
+ if (!accessResult.allowed) {
965
+ throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
966
+ }
967
+
968
+ try {
969
+ const entries = await fs.readdir(fullPath, { withFileTypes: true });
970
+
971
+ const contents = [];
972
+ for (const entry of entries) {
973
+ const entryPath = path.join(fullPath, entry.name);
974
+ const stats = await fs.stat(entryPath);
975
+
976
+ contents.push({
977
+ name: entry.name,
978
+ type: entry.isDirectory() ? 'directory' : 'file',
979
+ size: entry.isFile() ? stats.size : undefined,
980
+ lastModified: stats.mtime.toISOString(),
981
+ permissions: stats.mode,
982
+ isSymlink: entry.isSymbolicLink()
983
+ });
984
+ }
985
+
986
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
987
+
988
+ return {
989
+ success: true,
990
+ action: 'list',
991
+ directory: relativePath,
992
+ fullPath: fullPath,
993
+ contents,
994
+ totalItems: contents.length,
995
+ directories: contents.filter(item => item.type === 'directory').length,
996
+ files: contents.filter(item => item.type === 'file').length,
997
+ message: `Listed ${contents.length} items in ${directory}`
998
+ };
999
+
1000
+ } catch (error) {
1001
+ throw new Error(`Failed to list directory ${directory}: ${error.message}`);
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * Check if file/directory exists
1007
+ * @private
1008
+ */
1009
+ async checkExists(filePath, accessConfig) {
1010
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
1011
+ const fullPath = this.resolvePath(filePath, workingDir);
1012
+
1013
+ // Validate read access
1014
+ const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
1015
+ if (!accessResult.allowed) {
1016
+ throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
1017
+ }
1018
+
1019
+ try {
1020
+ const stats = await fs.stat(fullPath);
1021
+
1022
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
1023
+
1024
+ return {
1025
+ success: true,
1026
+ action: 'exists',
1027
+ filePath: relativePath,
1028
+ fullPath: fullPath,
1029
+ exists: true,
1030
+ type: stats.isDirectory() ? 'directory' : 'file',
1031
+ message: `${filePath} exists as ${stats.isDirectory() ? 'directory' : 'file'}`
1032
+ };
1033
+
1034
+ } catch (error) {
1035
+ if (error.code === 'ENOENT') {
1036
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
1037
+ return {
1038
+ success: true,
1039
+ action: 'exists',
1040
+ filePath: relativePath,
1041
+ fullPath: fullPath,
1042
+ exists: false,
1043
+ message: `${filePath} does not exist`
1044
+ };
1045
+ }
1046
+
1047
+ throw new Error(`Failed to check existence of ${filePath}: ${error.message}`);
1048
+ }
1049
+ }
1050
+
1051
+ /**
1052
+ * Get file statistics
1053
+ * @private
1054
+ */
1055
+ async getFileStats(filePath, accessConfig) {
1056
+ const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
1057
+ const fullPath = this.resolvePath(filePath, workingDir);
1058
+
1059
+ // Validate read access
1060
+ const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
1061
+ if (!accessResult.allowed) {
1062
+ throw new Error(`Read access denied: ${accessResult.reason} (${accessResult.path})`);
1063
+ }
1064
+
1065
+ try {
1066
+ const stats = await fs.stat(fullPath);
1067
+
1068
+ const relativePath = this.directoryAccessManager.createRelativePath(fullPath, accessConfig);
1069
+
1070
+ return {
1071
+ success: true,
1072
+ action: 'stats',
1073
+ filePath: relativePath,
1074
+ fullPath: fullPath,
1075
+ stats: {
1076
+ size: stats.size,
1077
+ type: stats.isDirectory() ? 'directory' : 'file',
1078
+ lastModified: stats.mtime.toISOString(),
1079
+ lastAccessed: stats.atime.toISOString(),
1080
+ created: stats.birthtime.toISOString(),
1081
+ permissions: stats.mode,
1082
+ isSymlink: stats.isSymbolicLink()
1083
+ },
1084
+ message: `Retrieved stats for ${filePath}`
1085
+ };
1086
+
1087
+ } catch (error) {
1088
+ throw new Error(`Failed to get stats for ${filePath}: ${error.message}`);
1089
+ }
1090
+ }
1091
+
1092
+ /**
1093
+ * Resolve file path safely (legacy method for compatibility)
1094
+ * @private
1095
+ */
1096
+ resolvePath(filePath, workingDir) {
1097
+ if (path.isAbsolute(filePath)) {
1098
+ return path.normalize(filePath);
1099
+ }
1100
+ return path.resolve(workingDir, filePath);
1101
+ }
1102
+
1103
+ /**
1104
+ * Validate path access using DirectoryAccessManager
1105
+ * @private
1106
+ */
1107
+ validatePathAccess(fullPath, accessConfig, operation = 'read') {
1108
+ const accessResult = operation === 'write'
1109
+ ? this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig)
1110
+ : this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
1111
+
1112
+ if (!accessResult.allowed) {
1113
+ throw new Error(`${operation} access denied: ${accessResult.reason} (${accessResult.path})`);
1114
+ }
1115
+
1116
+ return accessResult;
1117
+ }
1118
+
1119
+ /**
1120
+ * Check if file extension is allowed
1121
+ * @private
1122
+ */
1123
+ isAllowedFileExtension(filePath) {
1124
+ const ext = path.extname(filePath).toLowerCase();
1125
+
1126
+ if (this.blockedExtensions.includes(ext)) {
1127
+ return false;
1128
+ }
1129
+
1130
+ if (this.allowedExtensions && !this.allowedExtensions.includes(ext)) {
1131
+ return false;
1132
+ }
1133
+
1134
+ return true;
1135
+ }
1136
+
1137
+ /**
1138
+ * Add operation to history
1139
+ * @private
1140
+ */
1141
+ addToHistory(action, result, agentId) {
1142
+ const historyEntry = {
1143
+ timestamp: new Date().toISOString(),
1144
+ agentId,
1145
+ action: action.type,
1146
+ filePath: action.filePath || action.outputPath || action.directory,
1147
+ success: result.success,
1148
+ size: result.size
1149
+ };
1150
+
1151
+ this.operationHistory.push(historyEntry);
1152
+
1153
+ // Keep only last 200 entries
1154
+ if (this.operationHistory.length > 200) {
1155
+ this.operationHistory = this.operationHistory.slice(-200);
1156
+ }
1157
+ }
1158
+
1159
+ /**
1160
+ * Get supported actions for this tool
1161
+ * @returns {Array<string>} Array of supported action names
1162
+ */
1163
+ getSupportedActions() {
1164
+ return [
1165
+ 'read', 'write', 'append', 'delete', 'copy', 'move',
1166
+ 'create-dir', 'list', 'exists', 'stats'
1167
+ ];
1168
+ }
1169
+
1170
+ /**
1171
+ * Get parameter schema for validation
1172
+ * @returns {Object} Parameter schema
1173
+ */
1174
+ getParameterSchema() {
1175
+ return {
1176
+ type: 'object',
1177
+ properties: {
1178
+ actions: {
1179
+ type: 'array',
1180
+ minItems: 1,
1181
+ items: {
1182
+ type: 'object',
1183
+ properties: {
1184
+ type: {
1185
+ type: 'string',
1186
+ enum: this.getSupportedActions()
1187
+ },
1188
+ filePath: { type: 'string' },
1189
+ outputPath: { type: 'string' },
1190
+ sourcePath: { type: 'string' },
1191
+ destPath: { type: 'string' },
1192
+ directory: { type: 'string' },
1193
+ content: { type: 'string' },
1194
+ encoding: { type: 'string' },
1195
+ createDirs: { type: 'boolean' }
1196
+ },
1197
+ required: ['type']
1198
+ }
1199
+ }
1200
+ },
1201
+ required: ['actions']
1202
+ };
1203
+ }
1204
+
1205
+ /**
1206
+ * Get operation history for debugging
1207
+ * @returns {Array} Operation history
1208
+ */
1209
+ getOperationHistory(agentId = null) {
1210
+ if (agentId) {
1211
+ return this.operationHistory.filter(entry => entry.agentId === agentId);
1212
+ }
1213
+ return [...this.operationHistory];
1214
+ }
1215
+ }
1216
+
1217
+ export default FileSystemTool;