onbuzz 4.9.13 → 4.10.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 (451) hide show
  1. package/node_modules/glob/README.md +31 -5
  2. package/node_modules/glob/dist/commonjs/glob.d.ts +8 -0
  3. package/node_modules/glob/dist/commonjs/glob.d.ts.map +1 -1
  4. package/node_modules/glob/dist/commonjs/glob.js +2 -1
  5. package/node_modules/glob/dist/commonjs/glob.js.map +1 -1
  6. package/node_modules/glob/dist/commonjs/index.min.js +3 -3
  7. package/node_modules/glob/dist/commonjs/index.min.js.map +4 -4
  8. package/node_modules/glob/dist/commonjs/pattern.d.ts +3 -0
  9. package/node_modules/glob/dist/commonjs/pattern.d.ts.map +1 -1
  10. package/node_modules/glob/dist/commonjs/pattern.js +4 -0
  11. package/node_modules/glob/dist/commonjs/pattern.js.map +1 -1
  12. package/node_modules/glob/dist/esm/glob.d.ts +8 -0
  13. package/node_modules/glob/dist/esm/glob.d.ts.map +1 -1
  14. package/node_modules/glob/dist/esm/glob.js +2 -1
  15. package/node_modules/glob/dist/esm/glob.js.map +1 -1
  16. package/node_modules/glob/dist/esm/index.min.js +3 -3
  17. package/node_modules/glob/dist/esm/index.min.js.map +4 -4
  18. package/node_modules/glob/dist/esm/pattern.d.ts +3 -0
  19. package/node_modules/glob/dist/esm/pattern.d.ts.map +1 -1
  20. package/node_modules/glob/dist/esm/pattern.js +4 -0
  21. package/node_modules/glob/dist/esm/pattern.js.map +1 -1
  22. package/node_modules/{@isaacs → glob/node_modules}/balanced-match/README.md +7 -10
  23. package/node_modules/{@isaacs → glob/node_modules}/balanced-match/package.json +7 -18
  24. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/README.md +3 -6
  25. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.js +6 -4
  26. package/node_modules/glob/node_modules/brace-expansion/dist/commonjs/index.js.map +1 -0
  27. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.js +6 -4
  28. package/node_modules/glob/node_modules/brace-expansion/dist/esm/index.js.map +1 -0
  29. package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/package.json +11 -7
  30. package/node_modules/glob/node_modules/minimatch/README.md +76 -1
  31. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +1 -1
  32. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts.map +1 -1
  33. package/node_modules/glob/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js.map +1 -1
  34. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts +4 -2
  35. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.d.ts.map +1 -1
  36. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js +309 -55
  37. package/node_modules/glob/node_modules/minimatch/dist/commonjs/ast.js.map +1 -1
  38. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts.map +1 -1
  39. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js +2 -4
  40. package/node_modules/glob/node_modules/minimatch/dist/commonjs/brace-expressions.js.map +1 -1
  41. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts +1 -1
  42. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.d.ts.map +1 -1
  43. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js +4 -4
  44. package/node_modules/glob/node_modules/minimatch/dist/commonjs/escape.js.map +1 -1
  45. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts +81 -1
  46. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.d.ts.map +1 -1
  47. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js +232 -134
  48. package/node_modules/glob/node_modules/minimatch/dist/commonjs/index.js.map +1 -1
  49. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts +1 -1
  50. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.d.ts.map +1 -1
  51. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js +8 -8
  52. package/node_modules/glob/node_modules/minimatch/dist/commonjs/unescape.js.map +1 -1
  53. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +1 -1
  54. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts.map +1 -1
  55. package/node_modules/glob/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -1
  56. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts +4 -2
  57. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.d.ts.map +1 -1
  58. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js +309 -55
  59. package/node_modules/glob/node_modules/minimatch/dist/esm/ast.js.map +1 -1
  60. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.d.ts.map +1 -1
  61. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js +2 -4
  62. package/node_modules/glob/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
  63. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts +1 -1
  64. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.d.ts.map +1 -1
  65. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js +4 -4
  66. package/node_modules/glob/node_modules/minimatch/dist/esm/escape.js.map +1 -1
  67. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts +81 -1
  68. package/node_modules/glob/node_modules/minimatch/dist/esm/index.d.ts.map +1 -1
  69. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js +232 -134
  70. package/node_modules/glob/node_modules/minimatch/dist/esm/index.js.map +1 -1
  71. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts +1 -1
  72. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.d.ts.map +1 -1
  73. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js +8 -8
  74. package/node_modules/glob/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
  75. package/node_modules/glob/node_modules/minimatch/package.json +17 -11
  76. package/node_modules/glob/package.json +10 -13
  77. package/node_modules/minipass/LICENSE.md +55 -0
  78. package/node_modules/minipass/dist/commonjs/index.d.ts +12 -16
  79. package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -1
  80. package/node_modules/minipass/dist/commonjs/index.js +13 -3
  81. package/node_modules/minipass/dist/commonjs/index.js.map +1 -1
  82. package/node_modules/minipass/dist/esm/index.d.ts +12 -16
  83. package/node_modules/minipass/dist/esm/index.d.ts.map +1 -1
  84. package/node_modules/minipass/dist/esm/index.js +3 -1
  85. package/node_modules/minipass/dist/esm/index.js.map +1 -1
  86. package/node_modules/minipass/package.json +9 -14
  87. package/node_modules/path-scurry/node_modules/lru-cache/README.md +96 -10
  88. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.d.ts.map +1 -0
  89. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel-browser.js.map +1 -0
  90. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.d.ts +5 -0
  91. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
  92. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +1400 -0
  93. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -0
  94. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
  95. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -0
  96. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
  97. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +7 -0
  98. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts +12 -0
  99. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.d.ts.map +1 -0
  100. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
  101. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js.map +1 -0
  102. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.cjs.map +1 -0
  103. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
  104. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.d.ts +5 -0
  105. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
  106. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts +109 -32
  107. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
  108. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +334 -197
  109. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
  110. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +1 -1
  111. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js.map +4 -4
  112. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.d.ts.map +1 -0
  113. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel-node.js.map +1 -0
  114. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.d.ts +5 -0
  115. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
  116. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts +1400 -0
  117. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -0
  118. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
  119. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -0
  120. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
  121. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +7 -0
  122. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts +12 -0
  123. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.d.ts.map +1 -0
  124. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
  125. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js.map +1 -0
  126. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts +12 -0
  127. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.d.ts.map +1 -0
  128. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
  129. package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js.map +1 -0
  130. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.d.ts.map +1 -0
  131. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel-browser.js.map +1 -0
  132. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.d.ts +5 -0
  133. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
  134. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts +1400 -0
  135. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -0
  136. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
  137. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -0
  138. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
  139. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js.map +7 -0
  140. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts +12 -0
  141. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.d.ts.map +1 -0
  142. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
  143. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js.map +1 -0
  144. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
  145. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.mjs.map +1 -0
  146. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.d.ts +5 -0
  147. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
  148. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts +109 -32
  149. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
  150. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +333 -196
  151. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js.map +1 -1
  152. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +1 -1
  153. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js.map +4 -4
  154. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.d.ts.map +1 -0
  155. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel-node.js.map +1 -0
  156. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.d.ts +5 -0
  157. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
  158. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts +1400 -0
  159. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -0
  160. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
  161. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js.map +1 -0
  162. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
  163. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js.map +7 -0
  164. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts +12 -0
  165. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.d.ts.map +1 -0
  166. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
  167. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js.map +1 -0
  168. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts +12 -0
  169. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.d.ts.map +1 -0
  170. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
  171. package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js.map +1 -0
  172. package/node_modules/path-scurry/node_modules/lru-cache/package.json +71 -18
  173. package/node_modules/path-scurry/package.json +8 -24
  174. package/package.json +1 -1
  175. package/scripts/debug-balance-probe.mjs +35 -35
  176. package/scripts/push-image.sh +43 -43
  177. package/scripts/setup-acr.sh +65 -65
  178. package/scripts/verify-optional-deps.js +96 -1
  179. package/src/__tests__/composioCliFlags.test.js +239 -239
  180. package/src/analyzers/CSSAnalyzer.js +298 -297
  181. package/src/analyzers/ConfigValidator.js +691 -690
  182. package/src/analyzers/ESLintAnalyzer.js +320 -320
  183. package/src/analyzers/JavaScriptAnalyzer.js +260 -261
  184. package/src/analyzers/PrettierFormatter.js +246 -247
  185. package/src/analyzers/PythonAnalyzer.js +283 -283
  186. package/src/analyzers/SecurityAnalyzer.js +729 -729
  187. package/src/analyzers/SparrowAnalyzer.js +341 -341
  188. package/src/analyzers/TypeScriptAnalyzer.js +247 -247
  189. package/src/analyzers/__tests__/CSSAnalyzer.test.js +41 -41
  190. package/src/analyzers/__tests__/ConfigValidator.test.js +362 -362
  191. package/src/analyzers/__tests__/JavaScriptAnalyzer.test.js +40 -40
  192. package/src/analyzers/__tests__/PythonAnalyzer.test.js +205 -208
  193. package/src/analyzers/__tests__/SecurityAnalyzer.test.js +303 -303
  194. package/src/analyzers/__tests__/TypeScriptAnalyzer.test.js +187 -187
  195. package/src/analyzers/codeCloneDetector/analyzer.js +344 -344
  196. package/src/analyzers/codeCloneDetector/detector.js +250 -250
  197. package/src/analyzers/codeCloneDetector/index.js +194 -192
  198. package/src/analyzers/codeCloneDetector/parser.js +199 -199
  199. package/src/core/__tests__/agentPool.test.js +866 -866
  200. package/src/core/__tests__/agentPoolAutoResume.test.js +209 -209
  201. package/src/core/__tests__/agentPoolWakeOnMessage.test.js +315 -315
  202. package/src/core/__tests__/agentScheduler.emptyResponseChatStall.test.js +213 -213
  203. package/src/core/__tests__/agentScheduler.errorCategorisation.test.js +246 -246
  204. package/src/core/__tests__/agentScheduler.firstChunkTimeout.test.js +138 -138
  205. package/src/core/__tests__/agentScheduler.modeTransitions.test.js +233 -233
  206. package/src/core/__tests__/agentScheduler.nativePromptPick.test.js +319 -319
  207. package/src/core/__tests__/agentScheduler.taskLifecycleInstruction.test.js +78 -78
  208. package/src/core/__tests__/agentScheduler.visualizer.test.js +258 -258
  209. package/src/core/__tests__/flowCheckpointStore.test.js +140 -140
  210. package/src/core/__tests__/flowEndToEnd.test.js +565 -565
  211. package/src/core/__tests__/flowFieldMapping.test.js +188 -189
  212. package/src/core/__tests__/flowLintClientMirror.test.js +96 -98
  213. package/src/core/__tests__/flowSavePayload.test.js +170 -169
  214. package/src/core/__tests__/flowTemplates.test.js +311 -311
  215. package/src/core/__tests__/flowVersionStore.test.js +123 -123
  216. package/src/core/__tests__/messageProcessor.test.js +669 -669
  217. package/src/core/__tests__/stateManager.test.js +0 -1
  218. package/src/core/agentPool.js +2474 -2475
  219. package/src/core/agentScheduler.js +1 -4
  220. package/src/core/contextManager.js +708 -708
  221. package/src/core/flowExecutor.js +1510 -1510
  222. package/src/core/flowFieldMapping.js +136 -138
  223. package/src/core/messageProcessor.js +953 -954
  224. package/src/core/orchestrator.js +593 -595
  225. package/src/core/stateManager.js +1765 -1752
  226. package/src/index.js +1221 -1221
  227. package/src/interfaces/__tests__/archivedAgentDelete.test.js +207 -207
  228. package/src/interfaces/__tests__/bulkAgentRoute.test.js +361 -361
  229. package/src/interfaces/__tests__/imageServing.test.js +228 -228
  230. package/src/interfaces/__tests__/remoteSessionAuth.test.js +308 -308
  231. package/src/interfaces/__tests__/videoJobsRoutes.test.js +178 -179
  232. package/src/interfaces/__tests__/webServer.marketplace.test.js +629 -629
  233. package/src/interfaces/schedulerRoutes.js +50 -50
  234. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +341 -350
  235. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +156 -156
  236. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +325 -330
  237. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +385 -388
  238. package/src/interfaces/terminal/api/session.js +265 -266
  239. package/src/interfaces/terminal/api/websocket.js +496 -497
  240. package/src/interfaces/terminal/components/AgentCreator.js +691 -705
  241. package/src/interfaces/terminal/components/AgentEditor.js +676 -678
  242. package/src/interfaces/terminal/components/AgentSwitcher.js +331 -330
  243. package/src/interfaces/terminal/components/ErrorPanel.js +263 -264
  244. package/src/interfaces/terminal/components/Header.js +28 -28
  245. package/src/interfaces/terminal/components/Layout.js +598 -603
  246. package/src/interfaces/terminal/components/MessageList.js +280 -281
  247. package/src/interfaces/terminal/components/SettingsPanel.js +410 -415
  248. package/src/interfaces/terminal/components/StatusBar.js +2 -0
  249. package/src/interfaces/terminal/index.js +168 -168
  250. package/src/interfaces/terminal/state/useAgentControl.js +496 -496
  251. package/src/interfaces/terminal/state/useAgents.js +537 -537
  252. package/src/interfaces/terminal/state/useMessages.js +629 -630
  253. package/src/interfaces/terminal/state/useTools.js +554 -554
  254. package/src/interfaces/terminal/utils/debugLogger.js +44 -44
  255. package/src/interfaces/terminal/utils/settingsStorage.js +232 -232
  256. package/src/interfaces/webServer.js +7578 -7579
  257. package/src/interfaces/webServer.js.bak +7046 -7046
  258. package/src/modules/fileExplorer/__tests__/zipDownload.test.js +237 -237
  259. package/src/modules/fileExplorer/controller.js +470 -469
  260. package/src/modules/fileExplorer/routes.js +285 -286
  261. package/src/modules/widget/__tests__/isDisabled.test.js +41 -41
  262. package/src/modules/widget/__tests__/routes.test.js +677 -678
  263. package/src/modules/widget/__tests__/runtime.test.js +401 -401
  264. package/src/modules/widget/__tests__/versioning.test.js +309 -309
  265. package/src/modules/widget/__tests__/webComponentRuntime.test.js +565 -565
  266. package/src/modules/widget/__tests__/widgetTool.test.js +316 -316
  267. package/src/modules/widget/routes.js +435 -435
  268. package/src/modules/widget/runtime/bundle.js +640 -640
  269. package/src/modules/widget/runtime/webComponentBundle.js +470 -470
  270. package/src/modules/widget/schema.js +182 -181
  271. package/src/modules/widget/widgetTool.js +1389 -1389
  272. package/src/services/__tests__/agentActivityService.test.js +401 -402
  273. package/src/services/__tests__/benchmarkService.test.js +184 -184
  274. package/src/services/__tests__/contextInjectionService.test.js +246 -246
  275. package/src/services/__tests__/conversationQuery.test.js +721 -723
  276. package/src/services/__tests__/credentialVault.test.js +469 -469
  277. package/src/services/__tests__/discordService.integration.test.js +638 -639
  278. package/src/services/__tests__/flowContextService.test.js +590 -590
  279. package/src/services/__tests__/memoryService.test.js +1 -1
  280. package/src/services/__tests__/messageSource.test.js +380 -380
  281. package/src/services/__tests__/modelRouterNaming.test.js +111 -111
  282. package/src/services/__tests__/projectDetector.test.js +34 -34
  283. package/src/services/__tests__/promptService.test.js +242 -242
  284. package/src/services/__tests__/telegramService.test.js +941 -941
  285. package/src/services/__tests__/tokenCountingService.test.js +48 -48
  286. package/src/services/agentActivityService.js +419 -420
  287. package/src/services/aiService.js +2997 -3001
  288. package/src/services/apiKeyManager.js +359 -359
  289. package/src/services/benchmarkService.js +196 -196
  290. package/src/services/codebaseKnowledgeService.js +2 -2
  291. package/src/services/composioService.js +738 -738
  292. package/src/services/conversationCompactionService.js +1258 -1257
  293. package/src/services/credentialVault.js +685 -685
  294. package/src/services/discordService.js +792 -793
  295. package/src/services/embeddings/__tests__/azureCustomProvider.test.js +232 -232
  296. package/src/services/embeddings/__tests__/embeddingService.test.js +417 -417
  297. package/src/services/embeddings/__tests__/localProvider.test.js +263 -263
  298. package/src/services/embeddings/autoRecall.js +218 -219
  299. package/src/services/embeddings/indexers/__tests__/agentIndexer.test.js +232 -232
  300. package/src/services/embeddings/indexers/__tests__/memoryIndexer.test.js +418 -418
  301. package/src/services/embeddings/indexers/__tests__/reminisceIndexer.test.js +356 -357
  302. package/src/services/embeddings/indexers/__tests__/skillsIndexer.test.js +145 -145
  303. package/src/services/embeddings/indexers/__tests__/taskIndexer.test.js +146 -146
  304. package/src/services/embeddings/indexers/composioIndexer.js +279 -279
  305. package/src/services/embeddings/providerInterface.js +206 -206
  306. package/src/services/embeddings/providers/localProvider.js +11 -7
  307. package/src/services/embeddings/providers/openaiProvider.js +101 -101
  308. package/src/services/embeddings/vectorStore/inMemoryJsonStore.js +356 -356
  309. package/src/services/errorHandler.js +809 -809
  310. package/src/services/flowContextService.js +586 -586
  311. package/src/services/grounding/MockAdapter.js +125 -125
  312. package/src/services/modelRouterService.js +26 -31
  313. package/src/services/modelsService.js +322 -322
  314. package/src/services/ollamaService.js +452 -452
  315. package/src/services/projectDetector.js +403 -404
  316. package/src/services/promptService.js +418 -418
  317. package/src/services/qualityInspector.js +795 -795
  318. package/src/services/scheduleService.js +726 -726
  319. package/src/services/serviceRegistry.js +386 -386
  320. package/src/services/telegrafBot.js +174 -174
  321. package/src/services/telegramService.js +1972 -1972
  322. package/src/services/visualEditorBridge.js +1033 -1033
  323. package/src/services/visualEditorServer.js +1769 -1774
  324. package/src/services/whatsappService.js +667 -668
  325. package/src/tools/__tests__/agentCommunicationTool.findAgent.test.js +226 -226
  326. package/src/tools/__tests__/agentCommunicationTool.test.js +3 -3
  327. package/src/tools/__tests__/agentDelayTool.test.js +342 -342
  328. package/src/tools/__tests__/baseTool.test.js +3 -3
  329. package/src/tools/__tests__/codeMapTool.test.js +915 -915
  330. package/src/tools/__tests__/fileContentReplaceTool.test.js +309 -309
  331. package/src/tools/__tests__/fileTreeTool.test.js +274 -274
  332. package/src/tools/__tests__/filesystemTool.test.js +815 -815
  333. package/src/tools/__tests__/foundryWebSearchTool.test.js +252 -252
  334. package/src/tools/__tests__/imageTool.validator.test.js +194 -194
  335. package/src/tools/__tests__/jobDoneTool.test.js +580 -581
  336. package/src/tools/__tests__/memoryTool.forgetStale.test.js +272 -272
  337. package/src/tools/__tests__/memoryTool.reminisce.test.js +2 -2
  338. package/src/tools/__tests__/memoryTool.reminisceSemanticSearch.test.js +301 -301
  339. package/src/tools/__tests__/memoryTool.semanticSearch.test.js +405 -405
  340. package/src/tools/__tests__/memoryTool.teamPool.test.js +293 -293
  341. package/src/tools/__tests__/memoryTool.test.js +1 -1
  342. package/src/tools/__tests__/seekTool.test.js +282 -282
  343. package/src/tools/__tests__/skillsTool.search.test.js +164 -164
  344. package/src/tools/__tests__/skillsTool.test.js +226 -226
  345. package/src/tools/__tests__/staticAnalysisTool.test.js +509 -509
  346. package/src/tools/__tests__/taskManagerTool.discipline.test.js +137 -137
  347. package/src/tools/__tests__/taskManagerTool.search.test.js +143 -143
  348. package/src/tools/__tests__/taskManagerTool.test.js +866 -866
  349. package/src/tools/__tests__/terminalTool.test.js +448 -448
  350. package/src/tools/__tests__/toolShapeForgiveness.test.js +259 -260
  351. package/src/tools/__tests__/userPromptTool.test.js +297 -297
  352. package/src/tools/__tests__/videoTool.jobs.test.js +147 -147
  353. package/src/tools/__tests__/webTool.e2e.test.js +609 -603
  354. package/src/tools/__tests__/webTool.unit.test.js +195 -195
  355. package/src/tools/__tests__/webTool.visionModel.test.js +75 -75
  356. package/src/tools/agentCommunicationTool.js +8 -10
  357. package/src/tools/agentDelayTool.js +496 -497
  358. package/src/tools/asyncToolManager.js +602 -603
  359. package/src/tools/baseTool.js +12 -11
  360. package/src/tools/cloneDetectionTool.js +576 -581
  361. package/src/tools/codeMapTool.js +0 -6
  362. package/src/tools/composioTool.js +617 -617
  363. package/src/tools/dependencyResolverTool.js +1211 -1212
  364. package/src/tools/desktop/DesktopTool.js +629 -638
  365. package/src/tools/desktop/__tests__/DesktopTool.e2e.test.js +306 -306
  366. package/src/tools/desktop/__tests__/DesktopTool.test.js +507 -507
  367. package/src/tools/desktop/__tests__/osController.test.js +364 -364
  368. package/src/tools/desktop/osController.js +491 -491
  369. package/src/tools/docxTool.js +623 -623
  370. package/src/tools/excelTool.js +636 -636
  371. package/src/tools/fileContentReplaceTool.js +5 -7
  372. package/src/tools/fileSystemTool.js +12 -19
  373. package/src/tools/fileTreeTool.js +840 -840
  374. package/src/tools/foundryWebSearchTool.js +273 -273
  375. package/src/tools/helpTool.js +198 -198
  376. package/src/tools/imageTool.js +1397 -1397
  377. package/src/tools/importAnalyzerTool.js +1056 -1056
  378. package/src/tools/jobDoneTool.js +495 -495
  379. package/src/tools/memoryTool.js +1 -1
  380. package/src/tools/office/pres/__tests__/presSystem.test.js +365 -365
  381. package/src/tools/office/pres/archetypes/agenda.js +61 -61
  382. package/src/tools/office/pres/archetypes/bentoGrid.js +218 -219
  383. package/src/tools/office/pres/archetypes/bigStat.js +140 -142
  384. package/src/tools/office/pres/archetypes/closing.js +70 -70
  385. package/src/tools/office/pres/archetypes/hero.js +70 -70
  386. package/src/tools/office/pres/archetypes/productHero.js +93 -94
  387. package/src/tools/office/pres/archetypes/table.js +73 -74
  388. package/src/tools/office/pres/backgrounds/orb.js +66 -66
  389. package/src/tools/office/pres/components.js +422 -423
  390. package/src/tools/officeTool.js +441 -441
  391. package/src/tools/pdfTool.js +625 -627
  392. package/src/tools/platformControlTool.js +1081 -1081
  393. package/src/tools/seekTool.js +917 -918
  394. package/src/tools/skillsTool.js +1 -1
  395. package/src/tools/staticAnalysisTool.js +2143 -2146
  396. package/src/tools/taskManagerTool.js +3324 -3324
  397. package/src/tools/terminalTool.js +2615 -2618
  398. package/src/tools/videoTool.js +1303 -1303
  399. package/src/tools/visionTool.js +508 -508
  400. package/src/tools/visualEditorTool.js +1289 -1290
  401. package/src/tools/webTool.js +3368 -3368
  402. package/src/tools/whatsappTool.js +464 -464
  403. package/src/types/__tests__/agent.test.js +499 -499
  404. package/src/types/__tests__/contextReference.test.js +606 -606
  405. package/src/types/__tests__/conversation.test.js +555 -555
  406. package/src/types/__tests__/toolCommand.test.js +584 -584
  407. package/src/types/contextReference.js +974 -971
  408. package/src/types/conversation.js +729 -729
  409. package/src/types/toolCommand.js +746 -746
  410. package/src/utilities/__tests__/attachmentValidator.test.js +80 -80
  411. package/src/utilities/__tests__/auditReport.test.js +328 -328
  412. package/src/utilities/__tests__/directoryAccessManager.test.js +388 -388
  413. package/src/utilities/__tests__/jsonRepair.test.js +103 -104
  414. package/src/utilities/__tests__/modeTransitionReasons.test.js +105 -105
  415. package/src/utilities/__tests__/platformUtils.test.js +80 -87
  416. package/src/utilities/__tests__/structuredFileValidator.test.js +261 -263
  417. package/src/utilities/__tests__/toolConstants.test.js +92 -94
  418. package/src/utilities/__tests__/useIsTouchDevice.detect.test.js +114 -114
  419. package/src/utilities/__tests__/webUiUtilSync.test.js +117 -117
  420. package/src/utilities/attachmentValidator.js +284 -288
  421. package/src/utilities/authCache.js.backup-1779570472481 +121 -121
  422. package/src/utilities/browserStealth.js +631 -630
  423. package/src/utilities/configManager.js +616 -617
  424. package/src/utilities/directoryAccessManager.js +564 -565
  425. package/src/utilities/fileProcessor.js +308 -307
  426. package/src/utilities/humanBehavior.js +454 -453
  427. package/src/utilities/logger.js +479 -479
  428. package/src/utilities/structuredFileValidator.js +696 -699
  429. package/src/utilities/tagParser.js +5 -10
  430. package/src/utilities/userDataDir.js +308 -308
  431. package/node_modules/@isaacs/brace-expansion/dist/commonjs/index.js.map +0 -1
  432. package/node_modules/@isaacs/brace-expansion/dist/esm/index.js.map +0 -1
  433. package/node_modules/minipass/LICENSE +0 -15
  434. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/LICENSE.md +0 -0
  435. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts +0 -0
  436. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.d.ts.map +0 -0
  437. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js +0 -0
  438. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/index.js.map +0 -0
  439. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/commonjs/package.json +0 -0
  440. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts +0 -0
  441. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.d.ts.map +0 -0
  442. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js +0 -0
  443. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/index.js.map +0 -0
  444. /package/node_modules/{@isaacs → glob/node_modules}/balanced-match/dist/esm/package.json +0 -0
  445. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/LICENSE +0 -0
  446. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts +0 -0
  447. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/index.d.ts.map +0 -0
  448. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/commonjs/package.json +0 -0
  449. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts +0 -0
  450. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/index.d.ts.map +0 -0
  451. /package/node_modules/{@isaacs → glob/node_modules}/brace-expansion/dist/esm/package.json +0 -0
@@ -1,840 +1,840 @@
1
- /**
2
- * FileTreeTool - Generate hierarchical file tree representations
3
- *
4
- * Purpose:
5
- * - Generate ASCII tree of project directory structure
6
- * - Help agents understand project organization
7
- * - Support filtering by file types (whitelist/blacklist)
8
- * - Respect directory access permissions
9
- * - Provide focused views of codebases
10
- */
11
-
12
- import { BaseTool } from './baseTool.js';
13
- import { promises as fs } from 'fs';
14
- import path from 'path';
15
-
16
- // Configuration constants
17
- const TREE_CONFIG = {
18
- // Depth limits
19
- DEFAULT_MAX_DEPTH: 3,
20
- MAX_DEPTH_LIMIT: 10, // Absolute maximum to prevent performance issues
21
-
22
- // Size limits
23
- MAX_FILES_IN_TREE: 10000, // Maximum files to include
24
- MAX_DIRECTORIES: 1000, // Maximum directories to scan
25
-
26
- // Display settings
27
- SHOW_FILES_DEFAULT: true,
28
- SHOW_HIDDEN_DEFAULT: false,
29
- SHOW_SIZES_DEFAULT: false,
30
-
31
- // Tree symbols
32
- SYMBOLS: {
33
- BRANCH: '├── ',
34
- LAST_BRANCH: '└── ',
35
- VERTICAL: '│ ',
36
- INDENT: ' '
37
- }
38
- };
39
-
40
- // Default directories to ignore
41
- const DEFAULT_IGNORE_DIRECTORIES = [
42
- 'node_modules',
43
- '.git',
44
- 'dist',
45
- 'build',
46
- 'coverage',
47
- '.next',
48
- '.nuxt',
49
- '.cache',
50
- 'out',
51
- 'target',
52
- 'vendor',
53
- 'bower_components',
54
- '.vscode',
55
- '.idea',
56
- '.vs',
57
- '__pycache__',
58
- 'venv',
59
- 'env',
60
- '.env',
61
- '.pytest_cache',
62
- '.mypy_cache',
63
- 'eggs',
64
- '.eggs',
65
- 'lib',
66
- 'lib64',
67
- 'parts',
68
- 'sdist',
69
- 'wheels',
70
- '.tox',
71
- '.nox',
72
- 'htmlcov',
73
- '.hypothesis',
74
- 'tmp',
75
- 'temp',
76
- '.tmp',
77
- '.temp'
78
- ];
79
-
80
- // Default file extensions to ignore (blacklist)
81
- const DEFAULT_IGNORE_EXTENSIONS = [
82
- '.map',
83
- '.min.js',
84
- '.min.css',
85
- '.lock',
86
- '.log',
87
- '.tmp',
88
- '.temp',
89
- '.pyc',
90
- '.pyo',
91
- '.pyd',
92
- '.so',
93
- '.dll',
94
- '.dylib',
95
- '.exe',
96
- '.obj',
97
- '.o',
98
- '.a',
99
- '.class',
100
- '.jar',
101
- '.war'
102
- ];
103
-
104
- // Common binary/media file extensions to optionally ignore
105
- const BINARY_EXTENSIONS = [
106
- '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.svg',
107
- '.pdf', '.zip', '.tar', '.gz', '.rar', '.7z',
108
- '.mp3', '.mp4', '.avi', '.mov', '.wmv',
109
- '.woff', '.woff2', '.ttf', '.eot',
110
- '.bin', '.dat', '.db', '.sqlite'
111
- ];
112
-
113
- class FileTreeTool extends BaseTool {
114
- constructor(config = {}, logger = null) {
115
- super(config, logger);
116
-
117
- // Override tool ID to match documentation (with hyphen)
118
- this.id = 'file-tree';
119
-
120
- // Tool metadata
121
- this.requiresProject = true;
122
- this.isAsync = true;
123
- this.timeout = config.timeout || 120000; // 2 minutes default
124
-
125
- // Merge config with defaults
126
- this.treeConfig = {
127
- ...TREE_CONFIG,
128
- ...config.treeConfig
129
- };
130
-
131
- // Track statistics during tree generation
132
- this.stats = {
133
- filesCount: 0,
134
- directoriesCount: 0,
135
- skippedCount: 0
136
- };
137
- }
138
-
139
- /**
140
- * Get tool description for LLM consumption
141
- * @returns {string} Tool description
142
- */
143
- getDescription() {
144
- return `
145
- File Tree Tool: Generate hierarchical tree representation of project directory structure.
146
-
147
- USAGE:
148
- \`\`\`json
149
- {
150
- "toolId": "file-tree",
151
- "directory": "src",
152
- "maxDepth": 4,
153
- "includeExtensions": [".js", ".jsx", ".ts", ".tsx"],
154
- "excludeExtensions": [".test.js", ".spec.js"],
155
- "showFiles": true,
156
- "showHidden": false
157
- }
158
- \`\`\`
159
-
160
- PARAMETERS:
161
-
162
- directory (optional):
163
- - Directory to scan (default: working directory)
164
- - Can be relative or absolute path
165
- - Examples: "src", "src/components", "/home/user/project"
166
-
167
- maxDepth (optional):
168
- - Maximum depth to scan (default: ${TREE_CONFIG.DEFAULT_MAX_DEPTH})
169
- - Range: 1-${TREE_CONFIG.MAX_DEPTH_LIMIT}
170
- - Deeper = more detail, slower performance
171
-
172
- includeExtensions (optional - WHITELIST):
173
- - Include ONLY these file extensions
174
- - Array of extensions
175
- - Examples: [".js", ".jsx", ".ts", ".tsx"]
176
- - Takes precedence over excludeExtensions
177
-
178
- excludeExtensions (optional - BLACKLIST):
179
- - Exclude these file extensions
180
- - Array of extensions
181
- - Examples: [".test.js", ".spec.js", ".min.js"]
182
- - Only applies if includeExtensions is not set
183
-
184
- excludeDirectories (optional):
185
- - Additional directories to ignore
186
- - Already ignores: node_modules, .git, dist, build, etc.
187
- - Examples: ["tests", "fixtures", "mocks"]
188
-
189
- showFiles (optional):
190
- - Whether to show files (default: true)
191
- - Set to false to show only directory structure
192
-
193
- showHidden (optional):
194
- - Whether to show hidden files/folders (default: false)
195
- - Hidden = starts with '.'
196
-
197
- showSizes (optional):
198
- - Whether to show file sizes (default: false)
199
- - Format: KB, MB
200
-
201
- ignoreBinaryFiles (optional):
202
- - Whether to ignore binary/media files (default: false)
203
- - Ignores: images, videos, archives, fonts, etc.
204
-
205
- EXAMPLES:
206
-
207
- Example 1 - Basic tree:
208
- \`\`\`json
209
- {
210
- "toolId": "file-tree",
211
- "directory": "."
212
- }
213
- \`\`\`
214
-
215
- Example 2 - JavaScript/TypeScript only:
216
- \`\`\`json
217
- {
218
- "toolId": "file-tree",
219
- "directory": "src",
220
- "includeExtensions": [".js", ".jsx", ".ts", ".tsx"],
221
- "maxDepth": 5
222
- }
223
- \`\`\`
224
-
225
- Example 3 - Python project structure:
226
- \`\`\`json
227
- {
228
- "toolId": "file-tree",
229
- "directory": ".",
230
- "includeExtensions": [".py"],
231
- "excludeExtensions": [".pyc"],
232
- "showFiles": true
233
- }
234
- \`\`\`
235
-
236
- Example 4 - Directory structure only:
237
- \`\`\`json
238
- {
239
- "toolId": "file-tree",
240
- "directory": "src",
241
- "showFiles": false,
242
- "maxDepth": 3
243
- }
244
- \`\`\`
245
-
246
- Example 5 - Exclude test files:
247
- \`\`\`json
248
- {
249
- "toolId": "file-tree",
250
- "directory": "src",
251
- "excludeExtensions": [".test.js", ".spec.js", ".test.ts", ".spec.ts"],
252
- "excludeDirectories": ["__tests__", "tests", "specs"]
253
- }
254
- \`\`\`
255
-
256
- OUTPUT FORMAT:
257
- src/
258
- ├── components/
259
- │ ├── Header.jsx
260
- │ ├── Footer.jsx
261
- │ └── Layout.jsx
262
- ├── utils/
263
- │ ├── helpers.js
264
- │ └── config.js
265
- └── index.js
266
-
267
- AUTOMATIC IGNORES:
268
- The tool automatically ignores common directories:
269
- - node_modules, .git, dist, build, coverage
270
- - .next, .nuxt, .cache, out, target
271
- - .vscode, .idea, __pycache__, venv
272
-
273
- LIMITATIONS:
274
- - Maximum depth: ${TREE_CONFIG.MAX_DEPTH_LIMIT}
275
- - Maximum files: ${TREE_CONFIG.MAX_FILES_IN_TREE}
276
- - Maximum directories: ${TREE_CONFIG.MAX_DIRECTORIES}
277
- - Binary files can be filtered with ignoreBinaryFiles option
278
- `;
279
- }
280
-
281
- /**
282
- * Parse parameters from tool command content
283
- * @param {string} content - Raw tool command content
284
- * @returns {Object} Parsed parameters
285
- */
286
- parseParameters(content) {
287
- try {
288
- // Try JSON first
289
- if (content.trim().startsWith('{')) {
290
- const parsed = JSON.parse(content);
291
-
292
- return {
293
- directory: parsed.directory || '.',
294
- maxDepth: parsed.maxDepth || TREE_CONFIG.DEFAULT_MAX_DEPTH,
295
- includeExtensions: parsed.includeExtensions || [],
296
- excludeExtensions: parsed.excludeExtensions || [],
297
- excludeDirectories: parsed.excludeDirectories || [],
298
- showFiles: parsed.showFiles !== false,
299
- showHidden: parsed.showHidden === true,
300
- showSizes: parsed.showSizes === true,
301
- ignoreBinaryFiles: parsed.ignoreBinaryFiles === true
302
- };
303
- }
304
-
305
- // XML parsing
306
- const params = {
307
- directory: '.',
308
- maxDepth: TREE_CONFIG.DEFAULT_MAX_DEPTH,
309
- includeExtensions: [],
310
- excludeExtensions: [],
311
- excludeDirectories: [],
312
- showFiles: true,
313
- showHidden: false,
314
- showSizes: false,
315
- ignoreBinaryFiles: false
316
- };
317
-
318
- // Extract directory
319
- const dirPattern = /<directory>(.*?)<\/directory>/i;
320
- const dirMatch = dirPattern.exec(content);
321
- if (dirMatch) {
322
- params.directory = dirMatch[1].trim();
323
- }
324
-
325
- // Extract max-depth
326
- const depthPattern = /<max-depth>(\d+)<\/max-depth>/i;
327
- const depthMatch = depthPattern.exec(content);
328
- if (depthMatch) {
329
- params.maxDepth = parseInt(depthMatch[1], 10);
330
- }
331
-
332
- // Extract include-extensions (whitelist)
333
- const includePattern = /<include-extensions>(.*?)<\/include-extensions>/i;
334
- const includeMatch = includePattern.exec(content);
335
- if (includeMatch) {
336
- params.includeExtensions = includeMatch[1]
337
- .split(',')
338
- .map(ext => ext.trim())
339
- .filter(ext => ext.length > 0);
340
- }
341
-
342
- // Extract exclude-extensions (blacklist)
343
- const excludePattern = /<exclude-extensions>(.*?)<\/exclude-extensions>/i;
344
- const excludeMatch = excludePattern.exec(content);
345
- if (excludeMatch) {
346
- params.excludeExtensions = excludeMatch[1]
347
- .split(',')
348
- .map(ext => ext.trim())
349
- .filter(ext => ext.length > 0);
350
- }
351
-
352
- // Extract exclude-directories
353
- const excludeDirsPattern = /<exclude-directories>(.*?)<\/exclude-directories>/i;
354
- const excludeDirsMatch = excludeDirsPattern.exec(content);
355
- if (excludeDirsMatch) {
356
- params.excludeDirectories = excludeDirsMatch[1]
357
- .split(',')
358
- .map(dir => dir.trim())
359
- .filter(dir => dir.length > 0);
360
- }
361
-
362
- // Extract boolean flags
363
- const showFilesPattern = /<show-files>(.*?)<\/show-files>/i;
364
- const showFilesMatch = showFilesPattern.exec(content);
365
- if (showFilesMatch) {
366
- params.showFiles = showFilesMatch[1].trim().toLowerCase() !== 'false';
367
- }
368
-
369
- const showHiddenPattern = /<show-hidden>(.*?)<\/show-hidden>/i;
370
- const showHiddenMatch = showHiddenPattern.exec(content);
371
- if (showHiddenMatch) {
372
- params.showHidden = showHiddenMatch[1].trim().toLowerCase() === 'true';
373
- }
374
-
375
- const showSizesPattern = /<show-sizes>(.*?)<\/show-sizes>/i;
376
- const showSizesMatch = showSizesPattern.exec(content);
377
- if (showSizesMatch) {
378
- params.showSizes = showSizesMatch[1].trim().toLowerCase() === 'true';
379
- }
380
-
381
- const ignoreBinaryPattern = /<ignore-binary-files>(.*?)<\/ignore-binary-files>/i;
382
- const ignoreBinaryMatch = ignoreBinaryPattern.exec(content);
383
- if (ignoreBinaryMatch) {
384
- params.ignoreBinaryFiles = ignoreBinaryMatch[1].trim().toLowerCase() === 'true';
385
- }
386
-
387
- return params;
388
-
389
- } catch (error) {
390
- this.logger?.error('Failed to parse file-tree parameters', { error: error.message });
391
- return {
392
- directory: '.',
393
- maxDepth: TREE_CONFIG.DEFAULT_MAX_DEPTH,
394
- includeExtensions: [],
395
- excludeExtensions: [],
396
- excludeDirectories: [],
397
- showFiles: true,
398
- showHidden: false,
399
- showSizes: false,
400
- ignoreBinaryFiles: false,
401
- parseError: error.message
402
- };
403
- }
404
- }
405
-
406
- /**
407
- * Get required parameters
408
- * @returns {Array<string>} Array of required parameter names
409
- */
410
- getRequiredParameters() {
411
- return []; // All parameters are optional
412
- }
413
-
414
- /**
415
- * Custom parameter validation
416
- * @param {Object} params - Parameters to validate
417
- * @returns {Object} Validation result
418
- */
419
- customValidateParameters(params) {
420
- const errors = [];
421
-
422
- // Validate maxDepth
423
- if (params.maxDepth !== undefined) {
424
- if (typeof params.maxDepth !== 'number' || params.maxDepth < 1) {
425
- errors.push('max-depth must be a positive number');
426
- } else if (params.maxDepth > this.treeConfig.MAX_DEPTH_LIMIT) {
427
- errors.push(`max-depth cannot exceed ${this.treeConfig.MAX_DEPTH_LIMIT}`);
428
- }
429
- }
430
-
431
- // Validate directory path
432
- if (params.directory && params.directory.includes('..')) {
433
- errors.push('Path traversal (..) not allowed for security');
434
- }
435
-
436
- // Validate includeExtensions format
437
- if (params.includeExtensions !== undefined && params.includeExtensions !== null) {
438
- if (!Array.isArray(params.includeExtensions)) {
439
- errors.push('includeExtensions must be an array');
440
- } else {
441
- for (const ext of params.includeExtensions) {
442
- if (!ext.startsWith('.')) {
443
- errors.push(`Extension "${ext}" must start with a dot (e.g., ".js")`);
444
- }
445
- }
446
- }
447
- }
448
-
449
- // Validate excludeExtensions format
450
- if (params.excludeExtensions !== undefined && params.excludeExtensions !== null) {
451
- if (!Array.isArray(params.excludeExtensions)) {
452
- errors.push('excludeExtensions must be an array');
453
- } else {
454
- for (const ext of params.excludeExtensions) {
455
- if (!ext.startsWith('.')) {
456
- errors.push(`Extension "${ext}" must start with a dot (e.g., ".js")`);
457
- }
458
- }
459
- }
460
- }
461
-
462
- // Validate excludeDirectories format
463
- if (params.excludeDirectories !== undefined && params.excludeDirectories !== null) {
464
- if (!Array.isArray(params.excludeDirectories)) {
465
- errors.push('excludeDirectories must be an array');
466
- }
467
- }
468
-
469
- // Throw error if validation fails
470
- if (errors.length > 0) {
471
- throw new Error(`Parameter validation failed: ${errors.join(', ')}`);
472
- }
473
-
474
- return {
475
- valid: true,
476
- errors: []
477
- };
478
- }
479
-
480
- /**
481
- * Execute tool with parsed parameters
482
- * @param {Object} params - Parsed parameters
483
- * @param {Object} context - Execution context
484
- * @returns {Promise<Object>} Execution result
485
- */
486
- async execute(params, context) {
487
- // Reverse-forgiveness: accept plural {actions:[{...}]} envelope
488
- // (cross-tool envelope unification).
489
- if (Array.isArray(params?.actions) && params.actions.length > 0) {
490
- const a = params.actions[0] || {};
491
- params = { ...params, ...a };
492
- }
493
-
494
- // Extract params with defaults
495
- const {
496
- directory = '.',
497
- maxDepth = TREE_CONFIG.DEFAULT_MAX_DEPTH,
498
- includeExtensions = [],
499
- excludeExtensions = [],
500
- excludeDirectories = [],
501
- showFiles = true,
502
- showHidden = false,
503
- showSizes = false,
504
- ignoreBinaryFiles = false
505
- } = params;
506
- const { projectDir, agentId, directoryAccess } = context;
507
-
508
- // Determine working directory (respect multi-directory access)
509
- let workingDirectory = projectDir || process.cwd();
510
-
511
- if (directoryAccess && directoryAccess.workingDirectory) {
512
- workingDirectory = directoryAccess.workingDirectory;
513
- this.logger?.info('Using agent configured working directory', {
514
- workingDirectory: directoryAccess.workingDirectory,
515
- agentId
516
- });
517
- }
518
-
519
- // Resolve target directory
520
- const targetDir = path.isAbsolute(directory)
521
- ? directory
522
- : path.resolve(workingDirectory, directory);
523
-
524
- // Validate directory exists
525
- try {
526
- const stats = await fs.stat(targetDir);
527
- if (!stats.isDirectory()) {
528
- throw new Error('Path is not a directory');
529
- }
530
- } catch (error) {
531
- throw new Error(`Directory does not exist or is inaccessible: ${directory}`);
532
- }
533
-
534
- this.logger?.info('Generating file tree', {
535
- directory,
536
- targetDir,
537
- maxDepth,
538
- includeExtensions: includeExtensions?.length || 0,
539
- excludeExtensions: excludeExtensions?.length || 0,
540
- agentId
541
- });
542
-
543
- // Reset statistics
544
- this.stats = {
545
- filesCount: 0,
546
- directoriesCount: 0,
547
- skippedCount: 0
548
- };
549
-
550
- // Build ignore lists (ensure arrays exist)
551
- const ignoreDirs = [...DEFAULT_IGNORE_DIRECTORIES, ...(excludeDirectories || [])];
552
- const ignoreExts = [...DEFAULT_IGNORE_EXTENSIONS];
553
-
554
- if (ignoreBinaryFiles) {
555
- ignoreExts.push(...BINARY_EXTENSIONS);
556
- }
557
-
558
- // Generate tree (ensure arrays exist)
559
- const tree = await this.buildTree(
560
- targetDir,
561
- targetDir,
562
- 0,
563
- maxDepth,
564
- ignoreDirs,
565
- includeExtensions || [],
566
- [...(excludeExtensions || []), ...ignoreExts],
567
- showFiles,
568
- showHidden,
569
- showSizes
570
- );
571
-
572
- // Format tree as string
573
- const treeString = this.formatTree(tree);
574
-
575
- // Generate summary
576
- const summary = this.generateSummary(directory, this.stats, maxDepth);
577
-
578
- return {
579
- success: true,
580
- directory: targetDir,
581
- tree: treeString,
582
- summary,
583
- maxDepth,
584
- totalFiles: this.stats.filesCount,
585
- totalDirectories: this.stats.directoriesCount,
586
- skippedCount: this.stats.skippedCount,
587
- statistics: { ...this.stats },
588
- toolUsed: 'file-tree',
589
- guidance: 'To understand the code structure of files shown above, use code-map skeleton. Example: {"toolId":"code-map","parameters":{"action":"skeleton","path":"src/","level":"B.0"}}'
590
- };
591
- }
592
-
593
- /**
594
- * Build tree data structure recursively
595
- * @param {string} basePath - Base path for relative calculations
596
- * @param {string} currentPath - Current directory being processed
597
- * @param {number} currentDepth - Current depth in tree
598
- * @param {number} maxDepth - Maximum depth to scan
599
- * @param {Array<string>} ignoreDirs - Directories to ignore
600
- * @param {Array<string>} includeExts - Extensions to include (whitelist)
601
- * @param {Array<string>} excludeExts - Extensions to exclude (blacklist)
602
- * @param {boolean} showFiles - Whether to show files
603
- * @param {boolean} showHidden - Whether to show hidden files/folders
604
- * @param {boolean} showSizes - Whether to show file sizes
605
- * @returns {Promise<Object>} Tree node
606
- * @private
607
- */
608
- async buildTree(
609
- basePath,
610
- currentPath,
611
- currentDepth,
612
- maxDepth,
613
- ignoreDirs,
614
- includeExts,
615
- excludeExts,
616
- showFiles,
617
- showHidden,
618
- showSizes
619
- ) {
620
- // Check depth limit
621
- if (currentDepth > maxDepth) {
622
- return null;
623
- }
624
-
625
- // Check directory count limit
626
- if (this.stats.directoriesCount >= this.treeConfig.MAX_DIRECTORIES) {
627
- this.logger?.warn('Maximum directory count reached', {
628
- maxDirectories: this.treeConfig.MAX_DIRECTORIES
629
- });
630
- return null;
631
- }
632
-
633
- try {
634
- const entries = await fs.readdir(currentPath, { withFileTypes: true });
635
-
636
- const node = {
637
- name: currentDepth === 0 ? path.basename(currentPath) + '/' : path.basename(currentPath),
638
- path: path.relative(basePath, currentPath),
639
- type: 'directory',
640
- children: []
641
- };
642
-
643
- this.stats.directoriesCount++;
644
-
645
- for (const entry of entries) {
646
- // Check file count limit
647
- if (this.stats.filesCount >= this.treeConfig.MAX_FILES_IN_TREE) {
648
- this.logger?.warn('Maximum file count reached', {
649
- maxFiles: this.treeConfig.MAX_FILES_IN_TREE
650
- });
651
- break;
652
- }
653
-
654
- // Skip hidden files/folders if not showing hidden
655
- if (!showHidden && entry.name.startsWith('.')) {
656
- this.stats.skippedCount++;
657
- continue;
658
- }
659
-
660
- const entryPath = path.join(currentPath, entry.name);
661
-
662
- if (entry.isDirectory()) {
663
- // Skip ignored directories
664
- if (ignoreDirs.includes(entry.name)) {
665
- this.stats.skippedCount++;
666
- continue;
667
- }
668
-
669
- // Recursively build subtree
670
- const subTree = await this.buildTree(
671
- basePath,
672
- entryPath,
673
- currentDepth + 1,
674
- maxDepth,
675
- ignoreDirs,
676
- includeExts,
677
- excludeExts,
678
- showFiles,
679
- showHidden,
680
- showSizes
681
- );
682
-
683
- if (subTree && (subTree.children.length > 0 || currentDepth === 0)) {
684
- node.children.push(subTree);
685
- }
686
- } else if (entry.isFile() && showFiles) {
687
- // Files are children of current directory, so they're at currentDepth + 1
688
- // Don't show files if they would exceed maxDepth
689
- if (currentDepth + 1 > maxDepth) {
690
- continue;
691
- }
692
-
693
- const ext = path.extname(entry.name);
694
-
695
- // WHITELIST: If includeExtensions is specified, ONLY include those
696
- if (includeExts.length > 0) {
697
- if (!includeExts.includes(ext)) {
698
- this.stats.skippedCount++;
699
- continue;
700
- }
701
- }
702
- // BLACKLIST: Otherwise, exclude based on excludeExtensions
703
- else if (excludeExts.includes(ext)) {
704
- this.stats.skippedCount++;
705
- continue;
706
- }
707
-
708
- // Get file size if requested
709
- let sizeInfo = '';
710
- if (showSizes) {
711
- try {
712
- const stats = await fs.stat(entryPath);
713
- sizeInfo = ` (${this.formatFileSize(stats.size)})`;
714
- } catch (error) {
715
- // Ignore size errors
716
- }
717
- }
718
-
719
- node.children.push({
720
- name: entry.name + sizeInfo,
721
- path: path.relative(basePath, entryPath),
722
- type: 'file',
723
- ext
724
- });
725
-
726
- this.stats.filesCount++;
727
- }
728
- }
729
-
730
- // Sort children: directories first, then files, both alphabetically
731
- node.children.sort((a, b) => {
732
- if (a.type === b.type) {
733
- return a.name.localeCompare(b.name);
734
- }
735
- return a.type === 'directory' ? -1 : 1;
736
- });
737
-
738
- return node;
739
-
740
- } catch (error) {
741
- this.logger?.error('Error building tree', {
742
- currentPath,
743
- error: error.message
744
- });
745
- return {
746
- name: path.basename(currentPath),
747
- path: path.relative(basePath, currentPath),
748
- type: 'directory',
749
- error: error.message,
750
- children: []
751
- };
752
- }
753
- }
754
-
755
- /**
756
- * Format tree as ASCII string
757
- * @param {Object} node - Tree node
758
- * @param {string} prefix - Prefix for current line
759
- * @param {boolean} isLast - Whether this is the last child
760
- * @param {boolean} isRoot - Whether this is the root node
761
- * @returns {string} Formatted tree string
762
- * @private
763
- */
764
- formatTree(node, prefix = '', isLast = true, isRoot = true) {
765
- if (!node) return '';
766
-
767
- const symbols = this.treeConfig.SYMBOLS;
768
- let result = '';
769
-
770
- // Root node special case
771
- if (isRoot) {
772
- result = `${node.name}\n`;
773
- } else {
774
- result = `${prefix}${isLast ? symbols.LAST_BRANCH : symbols.BRANCH}${node.name}\n`;
775
- }
776
-
777
- // Add children
778
- if (node.children && node.children.length > 0) {
779
- const childPrefix = isRoot ? '' : prefix + (isLast ? symbols.INDENT : symbols.VERTICAL);
780
-
781
- node.children.forEach((child, index) => {
782
- const isLastChild = index === node.children.length - 1;
783
- result += this.formatTree(child, childPrefix, isLastChild, false);
784
- });
785
- }
786
-
787
- return result;
788
- }
789
-
790
- /**
791
- * Format file size in human-readable format
792
- * @param {number} bytes - File size in bytes
793
- * @returns {string} Formatted size
794
- * @private
795
- */
796
- formatFileSize(bytes) {
797
- const KB = 1024;
798
- const MB = KB * 1024;
799
- const GB = MB * 1024;
800
-
801
- if (bytes >= GB) {
802
- return `${(bytes / GB).toFixed(2)} GB`;
803
- } else if (bytes >= MB) {
804
- return `${(bytes / MB).toFixed(2)} MB`;
805
- } else if (bytes >= KB) {
806
- return `${(bytes / KB).toFixed(2)} KB`;
807
- } else {
808
- return `${bytes} B`;
809
- }
810
- }
811
-
812
- /**
813
- * Generate summary text
814
- * @param {string} directory - Directory scanned
815
- * @param {Object} stats - Statistics object
816
- * @param {number} maxDepth - Maximum depth used
817
- * @returns {string} Summary text
818
- * @private
819
- */
820
- generateSummary(directory, stats, maxDepth) {
821
- return `
822
- Directory: ${directory}
823
- Max Depth: ${maxDepth}
824
- Files: ${stats.filesCount}
825
- Directories: ${stats.directoriesCount}
826
- Skipped: ${stats.skippedCount}
827
- `.trim();
828
- }
829
-
830
- /**
831
- * Resource cleanup
832
- * @param {string} operationId - Operation identifier
833
- */
834
- async cleanup(operationId) {
835
- // No persistent resources to clean up
836
- this.logger?.info('File tree tool cleanup completed', { operationId });
837
- }
838
- }
839
-
840
- export default FileTreeTool;
1
+ /**
2
+ * FileTreeTool - Generate hierarchical file tree representations
3
+ *
4
+ * Purpose:
5
+ * - Generate ASCII tree of project directory structure
6
+ * - Help agents understand project organization
7
+ * - Support filtering by file types (whitelist/blacklist)
8
+ * - Respect directory access permissions
9
+ * - Provide focused views of codebases
10
+ */
11
+
12
+ import { BaseTool } from './baseTool.js';
13
+ import { promises as fs } from 'fs';
14
+ import path from 'path';
15
+
16
+ // Configuration constants
17
+ const TREE_CONFIG = {
18
+ // Depth limits
19
+ DEFAULT_MAX_DEPTH: 3,
20
+ MAX_DEPTH_LIMIT: 10, // Absolute maximum to prevent performance issues
21
+
22
+ // Size limits
23
+ MAX_FILES_IN_TREE: 10000, // Maximum files to include
24
+ MAX_DIRECTORIES: 1000, // Maximum directories to scan
25
+
26
+ // Display settings
27
+ SHOW_FILES_DEFAULT: true,
28
+ SHOW_HIDDEN_DEFAULT: false,
29
+ SHOW_SIZES_DEFAULT: false,
30
+
31
+ // Tree symbols
32
+ SYMBOLS: {
33
+ BRANCH: '├── ',
34
+ LAST_BRANCH: '└── ',
35
+ VERTICAL: '│ ',
36
+ INDENT: ' '
37
+ }
38
+ };
39
+
40
+ // Default directories to ignore
41
+ const DEFAULT_IGNORE_DIRECTORIES = [
42
+ 'node_modules',
43
+ '.git',
44
+ 'dist',
45
+ 'build',
46
+ 'coverage',
47
+ '.next',
48
+ '.nuxt',
49
+ '.cache',
50
+ 'out',
51
+ 'target',
52
+ 'vendor',
53
+ 'bower_components',
54
+ '.vscode',
55
+ '.idea',
56
+ '.vs',
57
+ '__pycache__',
58
+ 'venv',
59
+ 'env',
60
+ '.env',
61
+ '.pytest_cache',
62
+ '.mypy_cache',
63
+ 'eggs',
64
+ '.eggs',
65
+ 'lib',
66
+ 'lib64',
67
+ 'parts',
68
+ 'sdist',
69
+ 'wheels',
70
+ '.tox',
71
+ '.nox',
72
+ 'htmlcov',
73
+ '.hypothesis',
74
+ 'tmp',
75
+ 'temp',
76
+ '.tmp',
77
+ '.temp'
78
+ ];
79
+
80
+ // Default file extensions to ignore (blacklist)
81
+ const DEFAULT_IGNORE_EXTENSIONS = [
82
+ '.map',
83
+ '.min.js',
84
+ '.min.css',
85
+ '.lock',
86
+ '.log',
87
+ '.tmp',
88
+ '.temp',
89
+ '.pyc',
90
+ '.pyo',
91
+ '.pyd',
92
+ '.so',
93
+ '.dll',
94
+ '.dylib',
95
+ '.exe',
96
+ '.obj',
97
+ '.o',
98
+ '.a',
99
+ '.class',
100
+ '.jar',
101
+ '.war'
102
+ ];
103
+
104
+ // Common binary/media file extensions to optionally ignore
105
+ const BINARY_EXTENSIONS = [
106
+ '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.svg',
107
+ '.pdf', '.zip', '.tar', '.gz', '.rar', '.7z',
108
+ '.mp3', '.mp4', '.avi', '.mov', '.wmv',
109
+ '.woff', '.woff2', '.ttf', '.eot',
110
+ '.bin', '.dat', '.db', '.sqlite'
111
+ ];
112
+
113
+ class FileTreeTool extends BaseTool {
114
+ constructor(config = {}, logger = null) {
115
+ super(config, logger);
116
+
117
+ // Override tool ID to match documentation (with hyphen)
118
+ this.id = 'file-tree';
119
+
120
+ // Tool metadata
121
+ this.requiresProject = true;
122
+ this.isAsync = true;
123
+ this.timeout = config.timeout || 120000; // 2 minutes default
124
+
125
+ // Merge config with defaults
126
+ this.treeConfig = {
127
+ ...TREE_CONFIG,
128
+ ...config.treeConfig
129
+ };
130
+
131
+ // Track statistics during tree generation
132
+ this.stats = {
133
+ filesCount: 0,
134
+ directoriesCount: 0,
135
+ skippedCount: 0
136
+ };
137
+ }
138
+
139
+ /**
140
+ * Get tool description for LLM consumption
141
+ * @returns {string} Tool description
142
+ */
143
+ getDescription() {
144
+ return `
145
+ File Tree Tool: Generate hierarchical tree representation of project directory structure.
146
+
147
+ USAGE:
148
+ \`\`\`json
149
+ {
150
+ "toolId": "file-tree",
151
+ "directory": "src",
152
+ "maxDepth": 4,
153
+ "includeExtensions": [".js", ".jsx", ".ts", ".tsx"],
154
+ "excludeExtensions": [".test.js", ".spec.js"],
155
+ "showFiles": true,
156
+ "showHidden": false
157
+ }
158
+ \`\`\`
159
+
160
+ PARAMETERS:
161
+
162
+ directory (optional):
163
+ - Directory to scan (default: working directory)
164
+ - Can be relative or absolute path
165
+ - Examples: "src", "src/components", "/home/user/project"
166
+
167
+ maxDepth (optional):
168
+ - Maximum depth to scan (default: ${TREE_CONFIG.DEFAULT_MAX_DEPTH})
169
+ - Range: 1-${TREE_CONFIG.MAX_DEPTH_LIMIT}
170
+ - Deeper = more detail, slower performance
171
+
172
+ includeExtensions (optional - WHITELIST):
173
+ - Include ONLY these file extensions
174
+ - Array of extensions
175
+ - Examples: [".js", ".jsx", ".ts", ".tsx"]
176
+ - Takes precedence over excludeExtensions
177
+
178
+ excludeExtensions (optional - BLACKLIST):
179
+ - Exclude these file extensions
180
+ - Array of extensions
181
+ - Examples: [".test.js", ".spec.js", ".min.js"]
182
+ - Only applies if includeExtensions is not set
183
+
184
+ excludeDirectories (optional):
185
+ - Additional directories to ignore
186
+ - Already ignores: node_modules, .git, dist, build, etc.
187
+ - Examples: ["tests", "fixtures", "mocks"]
188
+
189
+ showFiles (optional):
190
+ - Whether to show files (default: true)
191
+ - Set to false to show only directory structure
192
+
193
+ showHidden (optional):
194
+ - Whether to show hidden files/folders (default: false)
195
+ - Hidden = starts with '.'
196
+
197
+ showSizes (optional):
198
+ - Whether to show file sizes (default: false)
199
+ - Format: KB, MB
200
+
201
+ ignoreBinaryFiles (optional):
202
+ - Whether to ignore binary/media files (default: false)
203
+ - Ignores: images, videos, archives, fonts, etc.
204
+
205
+ EXAMPLES:
206
+
207
+ Example 1 - Basic tree:
208
+ \`\`\`json
209
+ {
210
+ "toolId": "file-tree",
211
+ "directory": "."
212
+ }
213
+ \`\`\`
214
+
215
+ Example 2 - JavaScript/TypeScript only:
216
+ \`\`\`json
217
+ {
218
+ "toolId": "file-tree",
219
+ "directory": "src",
220
+ "includeExtensions": [".js", ".jsx", ".ts", ".tsx"],
221
+ "maxDepth": 5
222
+ }
223
+ \`\`\`
224
+
225
+ Example 3 - Python project structure:
226
+ \`\`\`json
227
+ {
228
+ "toolId": "file-tree",
229
+ "directory": ".",
230
+ "includeExtensions": [".py"],
231
+ "excludeExtensions": [".pyc"],
232
+ "showFiles": true
233
+ }
234
+ \`\`\`
235
+
236
+ Example 4 - Directory structure only:
237
+ \`\`\`json
238
+ {
239
+ "toolId": "file-tree",
240
+ "directory": "src",
241
+ "showFiles": false,
242
+ "maxDepth": 3
243
+ }
244
+ \`\`\`
245
+
246
+ Example 5 - Exclude test files:
247
+ \`\`\`json
248
+ {
249
+ "toolId": "file-tree",
250
+ "directory": "src",
251
+ "excludeExtensions": [".test.js", ".spec.js", ".test.ts", ".spec.ts"],
252
+ "excludeDirectories": ["__tests__", "tests", "specs"]
253
+ }
254
+ \`\`\`
255
+
256
+ OUTPUT FORMAT:
257
+ src/
258
+ ├── components/
259
+ │ ├── Header.jsx
260
+ │ ├── Footer.jsx
261
+ │ └── Layout.jsx
262
+ ├── utils/
263
+ │ ├── helpers.js
264
+ │ └── config.js
265
+ └── index.js
266
+
267
+ AUTOMATIC IGNORES:
268
+ The tool automatically ignores common directories:
269
+ - node_modules, .git, dist, build, coverage
270
+ - .next, .nuxt, .cache, out, target
271
+ - .vscode, .idea, __pycache__, venv
272
+
273
+ LIMITATIONS:
274
+ - Maximum depth: ${TREE_CONFIG.MAX_DEPTH_LIMIT}
275
+ - Maximum files: ${TREE_CONFIG.MAX_FILES_IN_TREE}
276
+ - Maximum directories: ${TREE_CONFIG.MAX_DIRECTORIES}
277
+ - Binary files can be filtered with ignoreBinaryFiles option
278
+ `;
279
+ }
280
+
281
+ /**
282
+ * Parse parameters from tool command content
283
+ * @param {string} content - Raw tool command content
284
+ * @returns {Object} Parsed parameters
285
+ */
286
+ parseParameters(content) {
287
+ try {
288
+ // Try JSON first
289
+ if (content.trim().startsWith('{')) {
290
+ const parsed = JSON.parse(content);
291
+
292
+ return {
293
+ directory: parsed.directory || '.',
294
+ maxDepth: parsed.maxDepth || TREE_CONFIG.DEFAULT_MAX_DEPTH,
295
+ includeExtensions: parsed.includeExtensions || [],
296
+ excludeExtensions: parsed.excludeExtensions || [],
297
+ excludeDirectories: parsed.excludeDirectories || [],
298
+ showFiles: parsed.showFiles !== false,
299
+ showHidden: parsed.showHidden === true,
300
+ showSizes: parsed.showSizes === true,
301
+ ignoreBinaryFiles: parsed.ignoreBinaryFiles === true
302
+ };
303
+ }
304
+
305
+ // XML parsing
306
+ const params = {
307
+ directory: '.',
308
+ maxDepth: TREE_CONFIG.DEFAULT_MAX_DEPTH,
309
+ includeExtensions: [],
310
+ excludeExtensions: [],
311
+ excludeDirectories: [],
312
+ showFiles: true,
313
+ showHidden: false,
314
+ showSizes: false,
315
+ ignoreBinaryFiles: false
316
+ };
317
+
318
+ // Extract directory
319
+ const dirPattern = /<directory>(.*?)<\/directory>/i;
320
+ const dirMatch = dirPattern.exec(content);
321
+ if (dirMatch) {
322
+ params.directory = dirMatch[1].trim();
323
+ }
324
+
325
+ // Extract max-depth
326
+ const depthPattern = /<max-depth>(\d+)<\/max-depth>/i;
327
+ const depthMatch = depthPattern.exec(content);
328
+ if (depthMatch) {
329
+ params.maxDepth = parseInt(depthMatch[1], 10);
330
+ }
331
+
332
+ // Extract include-extensions (whitelist)
333
+ const includePattern = /<include-extensions>(.*?)<\/include-extensions>/i;
334
+ const includeMatch = includePattern.exec(content);
335
+ if (includeMatch) {
336
+ params.includeExtensions = includeMatch[1]
337
+ .split(',')
338
+ .map(ext => ext.trim())
339
+ .filter(ext => ext.length > 0);
340
+ }
341
+
342
+ // Extract exclude-extensions (blacklist)
343
+ const excludePattern = /<exclude-extensions>(.*?)<\/exclude-extensions>/i;
344
+ const excludeMatch = excludePattern.exec(content);
345
+ if (excludeMatch) {
346
+ params.excludeExtensions = excludeMatch[1]
347
+ .split(',')
348
+ .map(ext => ext.trim())
349
+ .filter(ext => ext.length > 0);
350
+ }
351
+
352
+ // Extract exclude-directories
353
+ const excludeDirsPattern = /<exclude-directories>(.*?)<\/exclude-directories>/i;
354
+ const excludeDirsMatch = excludeDirsPattern.exec(content);
355
+ if (excludeDirsMatch) {
356
+ params.excludeDirectories = excludeDirsMatch[1]
357
+ .split(',')
358
+ .map(dir => dir.trim())
359
+ .filter(dir => dir.length > 0);
360
+ }
361
+
362
+ // Extract boolean flags
363
+ const showFilesPattern = /<show-files>(.*?)<\/show-files>/i;
364
+ const showFilesMatch = showFilesPattern.exec(content);
365
+ if (showFilesMatch) {
366
+ params.showFiles = showFilesMatch[1].trim().toLowerCase() !== 'false';
367
+ }
368
+
369
+ const showHiddenPattern = /<show-hidden>(.*?)<\/show-hidden>/i;
370
+ const showHiddenMatch = showHiddenPattern.exec(content);
371
+ if (showHiddenMatch) {
372
+ params.showHidden = showHiddenMatch[1].trim().toLowerCase() === 'true';
373
+ }
374
+
375
+ const showSizesPattern = /<show-sizes>(.*?)<\/show-sizes>/i;
376
+ const showSizesMatch = showSizesPattern.exec(content);
377
+ if (showSizesMatch) {
378
+ params.showSizes = showSizesMatch[1].trim().toLowerCase() === 'true';
379
+ }
380
+
381
+ const ignoreBinaryPattern = /<ignore-binary-files>(.*?)<\/ignore-binary-files>/i;
382
+ const ignoreBinaryMatch = ignoreBinaryPattern.exec(content);
383
+ if (ignoreBinaryMatch) {
384
+ params.ignoreBinaryFiles = ignoreBinaryMatch[1].trim().toLowerCase() === 'true';
385
+ }
386
+
387
+ return params;
388
+
389
+ } catch (error) {
390
+ this.logger?.error('Failed to parse file-tree parameters', { error: error.message });
391
+ return {
392
+ directory: '.',
393
+ maxDepth: TREE_CONFIG.DEFAULT_MAX_DEPTH,
394
+ includeExtensions: [],
395
+ excludeExtensions: [],
396
+ excludeDirectories: [],
397
+ showFiles: true,
398
+ showHidden: false,
399
+ showSizes: false,
400
+ ignoreBinaryFiles: false,
401
+ parseError: error.message
402
+ };
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Get required parameters
408
+ * @returns {Array<string>} Array of required parameter names
409
+ */
410
+ getRequiredParameters() {
411
+ return []; // All parameters are optional
412
+ }
413
+
414
+ /**
415
+ * Custom parameter validation
416
+ * @param {Object} params - Parameters to validate
417
+ * @returns {Object} Validation result
418
+ */
419
+ customValidateParameters(params) {
420
+ const errors = [];
421
+
422
+ // Validate maxDepth
423
+ if (params.maxDepth !== undefined) {
424
+ if (typeof params.maxDepth !== 'number' || params.maxDepth < 1) {
425
+ errors.push('max-depth must be a positive number');
426
+ } else if (params.maxDepth > this.treeConfig.MAX_DEPTH_LIMIT) {
427
+ errors.push(`max-depth cannot exceed ${this.treeConfig.MAX_DEPTH_LIMIT}`);
428
+ }
429
+ }
430
+
431
+ // Validate directory path
432
+ if (params.directory && params.directory.includes('..')) {
433
+ errors.push('Path traversal (..) not allowed for security');
434
+ }
435
+
436
+ // Validate includeExtensions format
437
+ if (params.includeExtensions !== undefined && params.includeExtensions !== null) {
438
+ if (!Array.isArray(params.includeExtensions)) {
439
+ errors.push('includeExtensions must be an array');
440
+ } else {
441
+ for (const ext of params.includeExtensions) {
442
+ if (!ext.startsWith('.')) {
443
+ errors.push(`Extension "${ext}" must start with a dot (e.g., ".js")`);
444
+ }
445
+ }
446
+ }
447
+ }
448
+
449
+ // Validate excludeExtensions format
450
+ if (params.excludeExtensions !== undefined && params.excludeExtensions !== null) {
451
+ if (!Array.isArray(params.excludeExtensions)) {
452
+ errors.push('excludeExtensions must be an array');
453
+ } else {
454
+ for (const ext of params.excludeExtensions) {
455
+ if (!ext.startsWith('.')) {
456
+ errors.push(`Extension "${ext}" must start with a dot (e.g., ".js")`);
457
+ }
458
+ }
459
+ }
460
+ }
461
+
462
+ // Validate excludeDirectories format
463
+ if (params.excludeDirectories !== undefined && params.excludeDirectories !== null) {
464
+ if (!Array.isArray(params.excludeDirectories)) {
465
+ errors.push('excludeDirectories must be an array');
466
+ }
467
+ }
468
+
469
+ // Throw error if validation fails
470
+ if (errors.length > 0) {
471
+ throw new Error(`Parameter validation failed: ${errors.join(', ')}`);
472
+ }
473
+
474
+ return {
475
+ valid: true,
476
+ errors: []
477
+ };
478
+ }
479
+
480
+ /**
481
+ * Execute tool with parsed parameters
482
+ * @param {Object} params - Parsed parameters
483
+ * @param {Object} context - Execution context
484
+ * @returns {Promise<Object>} Execution result
485
+ */
486
+ async execute(params, context) {
487
+ // Reverse-forgiveness: accept plural {actions:[{...}]} envelope
488
+ // (cross-tool envelope unification).
489
+ if (Array.isArray(params?.actions) && params.actions.length > 0) {
490
+ const a = params.actions[0] || {};
491
+ params = { ...params, ...a };
492
+ }
493
+
494
+ // Extract params with defaults
495
+ const {
496
+ directory = '.',
497
+ maxDepth = TREE_CONFIG.DEFAULT_MAX_DEPTH,
498
+ includeExtensions = [],
499
+ excludeExtensions = [],
500
+ excludeDirectories = [],
501
+ showFiles = true,
502
+ showHidden = false,
503
+ showSizes = false,
504
+ ignoreBinaryFiles = false
505
+ } = params;
506
+ const { projectDir, agentId, directoryAccess } = context;
507
+
508
+ // Determine working directory (respect multi-directory access)
509
+ let workingDirectory = projectDir || process.cwd();
510
+
511
+ if (directoryAccess && directoryAccess.workingDirectory) {
512
+ workingDirectory = directoryAccess.workingDirectory;
513
+ this.logger?.info('Using agent configured working directory', {
514
+ workingDirectory: directoryAccess.workingDirectory,
515
+ agentId
516
+ });
517
+ }
518
+
519
+ // Resolve target directory
520
+ const targetDir = path.isAbsolute(directory)
521
+ ? directory
522
+ : path.resolve(workingDirectory, directory);
523
+
524
+ // Validate directory exists
525
+ try {
526
+ const stats = await fs.stat(targetDir);
527
+ if (!stats.isDirectory()) {
528
+ throw new Error('Path is not a directory');
529
+ }
530
+ } catch (error) {
531
+ throw new Error(`Directory does not exist or is inaccessible: ${directory}`, { cause: error });
532
+ }
533
+
534
+ this.logger?.info('Generating file tree', {
535
+ directory,
536
+ targetDir,
537
+ maxDepth,
538
+ includeExtensions: includeExtensions?.length || 0,
539
+ excludeExtensions: excludeExtensions?.length || 0,
540
+ agentId
541
+ });
542
+
543
+ // Reset statistics
544
+ this.stats = {
545
+ filesCount: 0,
546
+ directoriesCount: 0,
547
+ skippedCount: 0
548
+ };
549
+
550
+ // Build ignore lists (ensure arrays exist)
551
+ const ignoreDirs = [...DEFAULT_IGNORE_DIRECTORIES, ...(excludeDirectories || [])];
552
+ const ignoreExts = [...DEFAULT_IGNORE_EXTENSIONS];
553
+
554
+ if (ignoreBinaryFiles) {
555
+ ignoreExts.push(...BINARY_EXTENSIONS);
556
+ }
557
+
558
+ // Generate tree (ensure arrays exist)
559
+ const tree = await this.buildTree(
560
+ targetDir,
561
+ targetDir,
562
+ 0,
563
+ maxDepth,
564
+ ignoreDirs,
565
+ includeExtensions || [],
566
+ [...(excludeExtensions || []), ...ignoreExts],
567
+ showFiles,
568
+ showHidden,
569
+ showSizes
570
+ );
571
+
572
+ // Format tree as string
573
+ const treeString = this.formatTree(tree);
574
+
575
+ // Generate summary
576
+ const summary = this.generateSummary(directory, this.stats, maxDepth);
577
+
578
+ return {
579
+ success: true,
580
+ directory: targetDir,
581
+ tree: treeString,
582
+ summary,
583
+ maxDepth,
584
+ totalFiles: this.stats.filesCount,
585
+ totalDirectories: this.stats.directoriesCount,
586
+ skippedCount: this.stats.skippedCount,
587
+ statistics: { ...this.stats },
588
+ toolUsed: 'file-tree',
589
+ guidance: 'To understand the code structure of files shown above, use code-map skeleton. Example: {"toolId":"code-map","parameters":{"action":"skeleton","path":"src/","level":"B.0"}}'
590
+ };
591
+ }
592
+
593
+ /**
594
+ * Build tree data structure recursively
595
+ * @param {string} basePath - Base path for relative calculations
596
+ * @param {string} currentPath - Current directory being processed
597
+ * @param {number} currentDepth - Current depth in tree
598
+ * @param {number} maxDepth - Maximum depth to scan
599
+ * @param {Array<string>} ignoreDirs - Directories to ignore
600
+ * @param {Array<string>} includeExts - Extensions to include (whitelist)
601
+ * @param {Array<string>} excludeExts - Extensions to exclude (blacklist)
602
+ * @param {boolean} showFiles - Whether to show files
603
+ * @param {boolean} showHidden - Whether to show hidden files/folders
604
+ * @param {boolean} showSizes - Whether to show file sizes
605
+ * @returns {Promise<Object>} Tree node
606
+ * @private
607
+ */
608
+ async buildTree(
609
+ basePath,
610
+ currentPath,
611
+ currentDepth,
612
+ maxDepth,
613
+ ignoreDirs,
614
+ includeExts,
615
+ excludeExts,
616
+ showFiles,
617
+ showHidden,
618
+ showSizes
619
+ ) {
620
+ // Check depth limit
621
+ if (currentDepth > maxDepth) {
622
+ return null;
623
+ }
624
+
625
+ // Check directory count limit
626
+ if (this.stats.directoriesCount >= this.treeConfig.MAX_DIRECTORIES) {
627
+ this.logger?.warn('Maximum directory count reached', {
628
+ maxDirectories: this.treeConfig.MAX_DIRECTORIES
629
+ });
630
+ return null;
631
+ }
632
+
633
+ try {
634
+ const entries = await fs.readdir(currentPath, { withFileTypes: true });
635
+
636
+ const node = {
637
+ name: currentDepth === 0 ? path.basename(currentPath) + '/' : path.basename(currentPath),
638
+ path: path.relative(basePath, currentPath),
639
+ type: 'directory',
640
+ children: []
641
+ };
642
+
643
+ this.stats.directoriesCount++;
644
+
645
+ for (const entry of entries) {
646
+ // Check file count limit
647
+ if (this.stats.filesCount >= this.treeConfig.MAX_FILES_IN_TREE) {
648
+ this.logger?.warn('Maximum file count reached', {
649
+ maxFiles: this.treeConfig.MAX_FILES_IN_TREE
650
+ });
651
+ break;
652
+ }
653
+
654
+ // Skip hidden files/folders if not showing hidden
655
+ if (!showHidden && entry.name.startsWith('.')) {
656
+ this.stats.skippedCount++;
657
+ continue;
658
+ }
659
+
660
+ const entryPath = path.join(currentPath, entry.name);
661
+
662
+ if (entry.isDirectory()) {
663
+ // Skip ignored directories
664
+ if (ignoreDirs.includes(entry.name)) {
665
+ this.stats.skippedCount++;
666
+ continue;
667
+ }
668
+
669
+ // Recursively build subtree
670
+ const subTree = await this.buildTree(
671
+ basePath,
672
+ entryPath,
673
+ currentDepth + 1,
674
+ maxDepth,
675
+ ignoreDirs,
676
+ includeExts,
677
+ excludeExts,
678
+ showFiles,
679
+ showHidden,
680
+ showSizes
681
+ );
682
+
683
+ if (subTree && (subTree.children.length > 0 || currentDepth === 0)) {
684
+ node.children.push(subTree);
685
+ }
686
+ } else if (entry.isFile() && showFiles) {
687
+ // Files are children of current directory, so they're at currentDepth + 1
688
+ // Don't show files if they would exceed maxDepth
689
+ if (currentDepth + 1 > maxDepth) {
690
+ continue;
691
+ }
692
+
693
+ const ext = path.extname(entry.name);
694
+
695
+ // WHITELIST: If includeExtensions is specified, ONLY include those
696
+ if (includeExts.length > 0) {
697
+ if (!includeExts.includes(ext)) {
698
+ this.stats.skippedCount++;
699
+ continue;
700
+ }
701
+ }
702
+ // BLACKLIST: Otherwise, exclude based on excludeExtensions
703
+ else if (excludeExts.includes(ext)) {
704
+ this.stats.skippedCount++;
705
+ continue;
706
+ }
707
+
708
+ // Get file size if requested
709
+ let sizeInfo = '';
710
+ if (showSizes) {
711
+ try {
712
+ const stats = await fs.stat(entryPath);
713
+ sizeInfo = ` (${this.formatFileSize(stats.size)})`;
714
+ } catch {
715
+ // Ignore size errors
716
+ }
717
+ }
718
+
719
+ node.children.push({
720
+ name: entry.name + sizeInfo,
721
+ path: path.relative(basePath, entryPath),
722
+ type: 'file',
723
+ ext
724
+ });
725
+
726
+ this.stats.filesCount++;
727
+ }
728
+ }
729
+
730
+ // Sort children: directories first, then files, both alphabetically
731
+ node.children.sort((a, b) => {
732
+ if (a.type === b.type) {
733
+ return a.name.localeCompare(b.name);
734
+ }
735
+ return a.type === 'directory' ? -1 : 1;
736
+ });
737
+
738
+ return node;
739
+
740
+ } catch (error) {
741
+ this.logger?.error('Error building tree', {
742
+ currentPath,
743
+ error: error.message
744
+ });
745
+ return {
746
+ name: path.basename(currentPath),
747
+ path: path.relative(basePath, currentPath),
748
+ type: 'directory',
749
+ error: error.message,
750
+ children: []
751
+ };
752
+ }
753
+ }
754
+
755
+ /**
756
+ * Format tree as ASCII string
757
+ * @param {Object} node - Tree node
758
+ * @param {string} prefix - Prefix for current line
759
+ * @param {boolean} isLast - Whether this is the last child
760
+ * @param {boolean} isRoot - Whether this is the root node
761
+ * @returns {string} Formatted tree string
762
+ * @private
763
+ */
764
+ formatTree(node, prefix = '', isLast = true, isRoot = true) {
765
+ if (!node) return '';
766
+
767
+ const symbols = this.treeConfig.SYMBOLS;
768
+ let result = '';
769
+
770
+ // Root node special case
771
+ if (isRoot) {
772
+ result = `${node.name}\n`;
773
+ } else {
774
+ result = `${prefix}${isLast ? symbols.LAST_BRANCH : symbols.BRANCH}${node.name}\n`;
775
+ }
776
+
777
+ // Add children
778
+ if (node.children && node.children.length > 0) {
779
+ const childPrefix = isRoot ? '' : prefix + (isLast ? symbols.INDENT : symbols.VERTICAL);
780
+
781
+ node.children.forEach((child, index) => {
782
+ const isLastChild = index === node.children.length - 1;
783
+ result += this.formatTree(child, childPrefix, isLastChild, false);
784
+ });
785
+ }
786
+
787
+ return result;
788
+ }
789
+
790
+ /**
791
+ * Format file size in human-readable format
792
+ * @param {number} bytes - File size in bytes
793
+ * @returns {string} Formatted size
794
+ * @private
795
+ */
796
+ formatFileSize(bytes) {
797
+ const KB = 1024;
798
+ const MB = KB * 1024;
799
+ const GB = MB * 1024;
800
+
801
+ if (bytes >= GB) {
802
+ return `${(bytes / GB).toFixed(2)} GB`;
803
+ } else if (bytes >= MB) {
804
+ return `${(bytes / MB).toFixed(2)} MB`;
805
+ } else if (bytes >= KB) {
806
+ return `${(bytes / KB).toFixed(2)} KB`;
807
+ } else {
808
+ return `${bytes} B`;
809
+ }
810
+ }
811
+
812
+ /**
813
+ * Generate summary text
814
+ * @param {string} directory - Directory scanned
815
+ * @param {Object} stats - Statistics object
816
+ * @param {number} maxDepth - Maximum depth used
817
+ * @returns {string} Summary text
818
+ * @private
819
+ */
820
+ generateSummary(directory, stats, maxDepth) {
821
+ return `
822
+ Directory: ${directory}
823
+ Max Depth: ${maxDepth}
824
+ Files: ${stats.filesCount}
825
+ Directories: ${stats.directoriesCount}
826
+ Skipped: ${stats.skippedCount}
827
+ `.trim();
828
+ }
829
+
830
+ /**
831
+ * Resource cleanup
832
+ * @param {string} operationId - Operation identifier
833
+ */
834
+ async cleanup(operationId) {
835
+ // No persistent resources to clean up
836
+ this.logger?.info('File tree tool cleanup completed', { operationId });
837
+ }
838
+ }
839
+
840
+ export default FileTreeTool;