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,1343 @@
1
+ /**
2
+ * AgentCommunicationTool - Enables inter-agent communication with safety mechanisms
3
+ *
4
+ * Purpose:
5
+ * - Allow agents to discover and communicate with other active agents
6
+ * - Manage message threads with reply tracking
7
+ * - Prevent conversation loops and exponential message growth
8
+ * - Support file attachments for rich communication
9
+ *
10
+ * Design Principles:
11
+ * - Loosely coupled with system components
12
+ * - Message persistence for async communication
13
+ * - Conversation limits to prevent runaway threads
14
+ * - Agent lifecycle awareness
15
+ */
16
+
17
+ import { BaseTool } from './baseTool.js';
18
+ import { promises as fs } from 'fs';
19
+ import path from 'path';
20
+ import crypto from 'crypto';
21
+
22
+ class AgentCommunicationTool extends BaseTool {
23
+ constructor(config = {}) {
24
+ super('agentcommunication', 'Agent Communication', 'communication');
25
+
26
+ // Configuration with safety defaults
27
+ this.config = {
28
+ maxConversationDepth: config.maxConversationDepth || 10,
29
+ maxRecipientsPerMessage: config.maxRecipientsPerMessage || 3,
30
+ maxAttachmentSize: config.maxAttachmentSize || 10 * 1024 * 1024, // 10MB
31
+ maxAttachmentsPerMessage: config.maxAttachmentsPerMessage || 5,
32
+ conversationTimeout: config.conversationTimeout || 3600000, // 1 hour
33
+ messageRetentionPeriod: config.messageRetentionPeriod || 86400000, // 24 hours
34
+ enableBroadcast: config.enableBroadcast || false,
35
+ storageDir: config.storageDir || '.loxia-messages'
36
+ };
37
+
38
+ // Message storage - in production, this would be a database
39
+ this.messages = new Map(); // messageId -> message object
40
+ this.conversations = new Map(); // conversationId -> conversation metadata
41
+ this.agentInboxes = new Map(); // agentId -> Set of messageIds
42
+ this.agentConversations = new Map(); // agentId -> Set of conversationIds
43
+
44
+ // Safety tracking
45
+ this.conversationDepths = new Map(); // conversationId -> current depth
46
+ this.lastActivityTimes = new Map(); // conversationId -> timestamp
47
+ this.agentMessageCounts = new Map(); // agentId -> { sent: number, received: number }
48
+
49
+ // Initialize storage directory
50
+ this._initializeStorage();
51
+ }
52
+
53
+ /**
54
+ * Get tool description for agent system prompts
55
+ */
56
+ getDescription() {
57
+ return `
58
+ Agent Communication Tool: Enables communication between active agents.
59
+
60
+ USAGE:
61
+ \`\`\`json
62
+ {
63
+ "toolId": "agentcommunication",
64
+ "actions": [{"type": "action-name", ...params}]
65
+ }
66
+ \`\`\`
67
+
68
+ ACTIONS:
69
+ - get-available-agents: List active agents
70
+ - send-message: Send message (recipient, subject, message, priority, requiresReply)
71
+ - reply-to-message: Reply to message (messageId, message)
72
+ - get-unreplied-messages: Get pending messages
73
+ - mark-conversation-ended: End conversation (conversationId, reason)
74
+
75
+ requiresReply PARAMETER (send-message):
76
+ - Defaults to true. Set to false ONLY for fire-and-forget notifications where you do NOT need a response.
77
+ - When true, the recipient agent will be explicitly instructed to reply back to you.
78
+ - When false, the recipient will handle the message but is not expected to reply.
79
+
80
+ EXAMPLES:
81
+
82
+ Get available agents:
83
+ \`\`\`json
84
+ {"toolId": "agentcommunication", "actions": [{"type": "get-available-agents"}]}
85
+ \`\`\`
86
+
87
+ Send a message:
88
+ \`\`\`json
89
+ {
90
+ "toolId": "agentcommunication",
91
+ "actions": [{
92
+ "type": "send-message",
93
+ "recipient": "agent-fullstack-developer-1234567890123",
94
+ "subject": "Code review needed",
95
+ "message": "Please review the authentication module",
96
+ "priority": "normal",
97
+ "requiresReply": true
98
+ }]
99
+ }
100
+ \`\`\`
101
+
102
+ Reply to a message:
103
+ \`\`\`json
104
+ {
105
+ "toolId": "agentcommunication",
106
+ "actions": [{
107
+ "type": "reply-to-message",
108
+ "messageId": "msg-789",
109
+ "message": "Review complete. All issues addressed."
110
+ }]
111
+ }
112
+ \`\`\`
113
+
114
+ IMPORTANT: Use full agent ID from get-available-agents as recipient.
115
+
116
+ LIMITS:
117
+ - Max ${this.config.maxConversationDepth} replies per thread
118
+ - Max ${this.config.maxRecipientsPerMessage} recipients per message
119
+ - Conversations expire after ${this.config.conversationTimeout / 60000} minutes
120
+ `.trim();
121
+ }
122
+
123
+ /**
124
+ * Parse tool parameters from command content
125
+ */
126
+ parseParameters(content) {
127
+ // Handle JSON format (for direct tool calls)
128
+ if (typeof content === 'object' && content !== null) {
129
+ // If it's already an object, extract the parameters
130
+ if (content.actions && Array.isArray(content.actions) && content.actions.length > 0) {
131
+ // Handle format: {"actions": [{"type": "get-available-agents", ...}]}
132
+ const action = content.actions[0];
133
+ return {
134
+ action: action.type,
135
+ ...action
136
+ };
137
+ } else if (content.action || content.type) {
138
+ // Handle format: {"action": "get-available-agents", ...}
139
+ return {
140
+ action: content.action || content.type,
141
+ ...content
142
+ };
143
+ }
144
+ return content;
145
+ }
146
+
147
+ // Handle string content (could be JSON string or XML)
148
+ if (typeof content === 'string') {
149
+ // Try parsing as JSON first
150
+ if (content.trim().startsWith('{')) {
151
+ try {
152
+ const parsed = JSON.parse(content);
153
+ return this.parseParameters(parsed); // Recursive call to handle the parsed object
154
+ } catch (error) {
155
+ // Not valid JSON, continue to XML parsing
156
+ }
157
+ }
158
+
159
+ // Parse XML-style commands for agent communication
160
+ const parameters = {};
161
+
162
+ // Extract action parameter
163
+ const actionMatch = content.match(/<action[^>]*>([^<]+)<\/action>/);
164
+ if (actionMatch) {
165
+ parameters.action = actionMatch[1].trim();
166
+ }
167
+
168
+ // Extract other parameters like recipient, subject, message, etc.
169
+ const tags = [
170
+ 'recipient', 'recipients', 'subject', 'message', 'attachments',
171
+ 'priority', 'requires-reply', 'message-id', 'cc-recipients',
172
+ 'include-low-priority', 'conversation-id', 'reason', 'mark-resolved'
173
+ ];
174
+
175
+ for (const tag of tags) {
176
+ const regex = new RegExp(`<${tag.replace('-', '\\-')}[^>]*>(.*?)<\\/${tag.replace('-', '\\-')}>`, 's');
177
+ const match = content.match(regex);
178
+ if (match) {
179
+ let value = match[1].trim();
180
+ // Try to parse JSON values
181
+ if (value.startsWith('[') || value.startsWith('{') || value === 'true' || value === 'false') {
182
+ try {
183
+ value = JSON.parse(value);
184
+ } catch {
185
+ // Keep as string if JSON parsing fails
186
+ }
187
+ }
188
+ // Convert kebab-case to camelCase for parameter names
189
+ const paramName = tag.replace(/-(.)/g, (_, char) => char.toUpperCase());
190
+ parameters[paramName] = value;
191
+ }
192
+ }
193
+
194
+ // Extract attributes from action tag if present
195
+ const actionWithAttribs = content.match(/<action([^>]*)>([^<]+)<\/action>/);
196
+ if (actionWithAttribs && actionWithAttribs[1]) {
197
+ // Parse attributes like priority="high", requires-reply="true"
198
+ const attribMatches = actionWithAttribs[1].matchAll(/([\w-]+)=["']([^"']+)["']/g);
199
+ for (const match of attribMatches) {
200
+ const key = match[1].replace(/-(.)/g, (_, char) => char.toUpperCase()); // Convert kebab-case to camelCase
201
+ parameters[key] = match[2];
202
+ }
203
+ }
204
+
205
+ return parameters;
206
+ }
207
+
208
+ // Fallback
209
+ return content || {};
210
+ }
211
+
212
+ /**
213
+ * Execute the tool action
214
+ */
215
+ async execute(parameters = {}, context = {}) {
216
+ const { action } = parameters;
217
+
218
+ if (!action) {
219
+ throw new Error('Action parameter is required');
220
+ }
221
+
222
+ // Validate requesting agent exists
223
+ const requestingAgentId = context.agentId;
224
+ if (!requestingAgentId) {
225
+ throw new Error('Agent ID is required in context');
226
+ }
227
+
228
+ // Route to appropriate action handler
229
+ switch (action.toLowerCase()) {
230
+ case 'get-available-agents':
231
+ return await this.getAvailableAgents(requestingAgentId, parameters, context);
232
+
233
+ case 'send-message':
234
+ return await this.sendMessage(requestingAgentId, parameters, context);
235
+
236
+ case 'reply-to-message':
237
+ return await this.replyToMessage(requestingAgentId, parameters, context);
238
+
239
+ case 'get-unreplied-messages':
240
+ return await this.getUnrepliedMessages(requestingAgentId, parameters, context);
241
+
242
+ case 'mark-conversation-ended':
243
+ return await this.markConversationEnded(requestingAgentId, parameters, context);
244
+
245
+ default:
246
+ throw new Error(`Unknown action: ${action}`);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Get list of available agents
252
+ */
253
+ async getAvailableAgents(requestingAgentId, parameters, context) {
254
+ try {
255
+ // Get agent pool from context
256
+ const agentPool = context.agentPool;
257
+ if (!agentPool) {
258
+ throw new Error('Agent pool not available in context');
259
+ }
260
+
261
+ // Get all active agents
262
+ const agents = await agentPool.listActiveAgents();
263
+
264
+ // Filter out requesting agent and format response
265
+ const availableAgents = agents
266
+ .filter(agent => agent.id !== requestingAgentId && !agent.isPaused)
267
+ .map(agent => ({
268
+ id: agent.id,
269
+ name: agent.name,
270
+ type: agent.type,
271
+ capabilities: agent.capabilities,
272
+ status: agent.status,
273
+ messageStats: this.agentMessageCounts.get(agent.id) || { sent: 0, received: 0 },
274
+ activeConversations: (this.agentConversations.get(agent.id) || new Set()).size
275
+ }));
276
+
277
+ return {
278
+ success: true,
279
+ agents: availableAgents,
280
+ totalActive: availableAgents.length,
281
+ timestamp: new Date().toISOString()
282
+ };
283
+
284
+ } catch (error) {
285
+ return {
286
+ success: false,
287
+ error: error.message
288
+ };
289
+ }
290
+ }
291
+
292
+ /**
293
+ * Send a message to another agent
294
+ */
295
+ async sendMessage(senderAgentId, parameters, context) {
296
+ try {
297
+ const {
298
+ recipient,
299
+ recipients, // Support both single and multiple
300
+ subject,
301
+ message,
302
+ attachments,
303
+ priority = 'normal',
304
+ 'requires-reply': requiresReply = true
305
+ } = parameters;
306
+
307
+ // Validate required fields
308
+ if (!subject || !message) {
309
+ throw new Error('Subject and message are required');
310
+ }
311
+
312
+ // Determine recipients
313
+ const recipientList = this._parseRecipients(recipient, recipients);
314
+ if (recipientList.length === 0) {
315
+ throw new Error('At least one recipient is required');
316
+ }
317
+
318
+ // Validate recipient count
319
+ if (recipientList.length > this.config.maxRecipientsPerMessage) {
320
+ throw new Error(`Maximum ${this.config.maxRecipientsPerMessage} recipients allowed`);
321
+ }
322
+
323
+ // Get agent pool and sender agent
324
+ const agentPool = context.agentPool;
325
+ const senderAgent = await agentPool.getAgent(senderAgentId);
326
+ if (!senderAgent) {
327
+ throw new Error('Sender agent not found');
328
+ }
329
+
330
+ // CRITICAL: Check if sender can send messages to recipients
331
+ const blockedRecipients = [];
332
+ for (const recipientId of recipientList) {
333
+ const canSend = await this._canSendMessage(senderAgent, recipientId, context);
334
+ if (!canSend.allowed) {
335
+ blockedRecipients.push({
336
+ recipientId,
337
+ reason: canSend.reason,
338
+ waitUntil: canSend.waitUntil
339
+ });
340
+ }
341
+ }
342
+
343
+ // If any recipients are blocked, apply delay and return
344
+ if (blockedRecipients.length > 0) {
345
+ const earliestAllowedTime = Math.max(...blockedRecipients.map(b => b.waitUntil || 0));
346
+ const delayUntil = new Date(earliestAllowedTime);
347
+
348
+ // Apply delay using existing infrastructure
349
+ await agentPool.updateAgent(senderAgentId, {
350
+ delayEndTime: delayUntil.toISOString()
351
+ });
352
+
353
+ const delaySeconds = Math.ceil((earliestAllowedTime - Date.now()) / 1000);
354
+
355
+ return {
356
+ success: true,
357
+ delayed: true,
358
+ delayUntil: delayUntil.toISOString(),
359
+ delaySeconds,
360
+ message: `Waiting ${delaySeconds}s before next message. Recipients need time to respond.`,
361
+ blockedRecipients: blockedRecipients.map(b => ({
362
+ recipientId: b.recipientId,
363
+ reason: b.reason
364
+ }))
365
+ };
366
+ }
367
+
368
+ // Validate recipients exist and get their names
369
+ const recipientAgents = {};
370
+ const invalidRecipients = [];
371
+
372
+ for (const recipientId of recipientList) {
373
+ const agent = await agentPool.getAgent(recipientId);
374
+ if (!agent) {
375
+ invalidRecipients.push(recipientId);
376
+ } else {
377
+ recipientAgents[recipientId] = agent.name;
378
+ }
379
+ }
380
+
381
+ // If any recipients are invalid, provide helpful error with suggestions
382
+ if (invalidRecipients.length > 0) {
383
+ const availableAgents = await agentPool.listActiveAgents();
384
+ const suggestions = availableAgents
385
+ .filter(agent => agent.id !== senderAgentId && !agent.isPaused)
386
+ .map(agent => `- ${agent.name} (ID: ${agent.id})`)
387
+ .join('\n');
388
+
389
+ return {
390
+ success: false,
391
+ error: `Recipient agent(s) not found: ${invalidRecipients.join(', ')}`,
392
+ suggestion: `Available agents you can message:\n${suggestions}`,
393
+ availableAgents: availableAgents.map(agent => ({
394
+ id: agent.id,
395
+ name: agent.name,
396
+ capabilities: agent.capabilities
397
+ }))
398
+ };
399
+ }
400
+
401
+ // Get sender agent name
402
+ const senderName = senderAgent ? senderAgent.name : senderAgentId;
403
+
404
+ // Process attachments if provided
405
+ const processedAttachments = await this._processAttachments(attachments, senderAgentId);
406
+
407
+ // Create message object
408
+ const messageId = this._generateMessageId();
409
+ const conversationId = this._generateConversationId();
410
+ const timestamp = new Date().toISOString();
411
+
412
+ const messageObj = {
413
+ id: messageId,
414
+ conversationId,
415
+ sender: senderAgentId,
416
+ senderName,
417
+ recipients: recipientList,
418
+ recipientNames: recipientAgents,
419
+ subject,
420
+ content: message,
421
+ attachments: processedAttachments,
422
+ priority,
423
+ requiresReply,
424
+ timestamp,
425
+ status: 'sent',
426
+ replies: [],
427
+ metadata: {
428
+ depth: 0,
429
+ isRoot: true
430
+ }
431
+ };
432
+
433
+ // Store message
434
+ this.messages.set(messageId, messageObj);
435
+
436
+ // Initialize conversation
437
+ this.conversations.set(conversationId, {
438
+ id: conversationId,
439
+ rootMessageId: messageId,
440
+ participants: [senderAgentId, ...recipientList],
441
+ startTime: timestamp,
442
+ lastActivity: timestamp,
443
+ status: 'active',
444
+ messageCount: 1
445
+ });
446
+
447
+ // Update inboxes
448
+ for (const recipientId of recipientList) {
449
+ if (!this.agentInboxes.has(recipientId)) {
450
+ this.agentInboxes.set(recipientId, new Set());
451
+ }
452
+ this.agentInboxes.get(recipientId).add(messageId);
453
+
454
+ // Track conversations
455
+ if (!this.agentConversations.has(recipientId)) {
456
+ this.agentConversations.set(recipientId, new Set());
457
+ }
458
+ this.agentConversations.get(recipientId).add(conversationId);
459
+ }
460
+
461
+ // Track sender's conversation
462
+ if (!this.agentConversations.has(senderAgentId)) {
463
+ this.agentConversations.set(senderAgentId, new Set());
464
+ }
465
+ this.agentConversations.get(senderAgentId).add(conversationId);
466
+
467
+ // Update message counts
468
+ this._updateMessageCounts(senderAgentId, 'sent');
469
+ for (const recipientId of recipientList) {
470
+ this._updateMessageCounts(recipientId, 'received');
471
+ }
472
+
473
+ // CRITICAL: Update inter-agent conversation tracking
474
+ for (const recipientId of recipientList) {
475
+ await this._updateConversationTracking(senderAgentId, recipientId, 'sent', context);
476
+ }
477
+
478
+ // Notify recipients through agent pool
479
+ await this._notifyRecipients(messageObj, context);
480
+
481
+ // Broadcast to WebSocket for UI visibility
482
+ await this._broadcastToUI(messageObj, 'agent-message-sent', context);
483
+
484
+ return {
485
+ success: true,
486
+ messageId,
487
+ conversationId,
488
+ recipients: recipientList,
489
+ timestamp,
490
+ message: 'Message sent successfully'
491
+ };
492
+
493
+ } catch (error) {
494
+ return {
495
+ success: false,
496
+ error: error.message
497
+ };
498
+ }
499
+ }
500
+
501
+ /**
502
+ * Reply to an existing message
503
+ */
504
+ async replyToMessage(senderAgentId, parameters, context) {
505
+ try {
506
+ const {
507
+ 'message-id': originalMessageId,
508
+ message,
509
+ 'cc-recipients': ccRecipients,
510
+ attachments,
511
+ 'mark-resolved': markResolved = false
512
+ } = parameters;
513
+
514
+ // Validate required fields
515
+ if (!originalMessageId || !message) {
516
+ throw new Error('Original message ID and reply content are required');
517
+ }
518
+
519
+ // Get original message
520
+ const originalMessage = this.messages.get(originalMessageId);
521
+ if (!originalMessage) {
522
+ throw new Error(`Original message not found: ${originalMessageId}`);
523
+ }
524
+
525
+ // Verify sender was a recipient or sender of original message
526
+ const isParticipant = originalMessage.sender === senderAgentId ||
527
+ originalMessage.recipients.includes(senderAgentId);
528
+ if (!isParticipant) {
529
+ throw new Error('You are not a participant in this conversation');
530
+ }
531
+
532
+ // Check conversation depth to prevent infinite loops
533
+ const conversation = this.conversations.get(originalMessage.conversationId);
534
+ const currentDepth = this._getConversationDepth(originalMessage.conversationId);
535
+
536
+ if (currentDepth >= this.config.maxConversationDepth) {
537
+ return {
538
+ success: false,
539
+ error: `Conversation depth limit reached (${this.config.maxConversationDepth}). Please start a new conversation.`,
540
+ suggestion: 'Consider marking this conversation as ended and starting fresh if needed.'
541
+ };
542
+ }
543
+
544
+ // Determine reply recipients
545
+ let replyRecipients = [originalMessage.sender];
546
+ if (originalMessage.sender === senderAgentId) {
547
+ // If replying to own message, reply to original recipients
548
+ replyRecipients = originalMessage.recipients;
549
+ }
550
+
551
+ // Add CC recipients if specified
552
+ if (ccRecipients) {
553
+ const ccList = this._parseRecipients(null, ccRecipients);
554
+ replyRecipients = [...new Set([...replyRecipients, ...ccList])];
555
+ }
556
+
557
+ // Remove sender from recipients
558
+ replyRecipients = replyRecipients.filter(id => id !== senderAgentId);
559
+
560
+ // Validate recipient count
561
+ if (replyRecipients.length > this.config.maxRecipientsPerMessage) {
562
+ throw new Error(`Maximum ${this.config.maxRecipientsPerMessage} recipients allowed`);
563
+ }
564
+
565
+ // Get agent names
566
+ const agentPool = context.agentPool;
567
+ const senderAgent = await agentPool.getAgent(senderAgentId);
568
+ const senderName = senderAgent ? senderAgent.name : senderAgentId;
569
+
570
+ const recipientAgents = {};
571
+ for (const recipientId of replyRecipients) {
572
+ const agent = await agentPool.getAgent(recipientId);
573
+ if (agent) {
574
+ recipientAgents[recipientId] = agent.name;
575
+ }
576
+ }
577
+
578
+ // Process attachments
579
+ const processedAttachments = await this._processAttachments(attachments, senderAgentId);
580
+
581
+ // Create reply message
582
+ const replyMessageId = this._generateMessageId();
583
+ const timestamp = new Date().toISOString();
584
+
585
+ const replyMessage = {
586
+ id: replyMessageId,
587
+ conversationId: originalMessage.conversationId,
588
+ sender: senderAgentId,
589
+ senderName,
590
+ recipients: replyRecipients,
591
+ recipientNames: recipientAgents,
592
+ subject: `Re: ${originalMessage.subject}`,
593
+ content: message,
594
+ attachments: processedAttachments,
595
+ priority: originalMessage.priority,
596
+ requiresReply: !markResolved,
597
+ timestamp,
598
+ status: 'sent',
599
+ replies: [],
600
+ metadata: {
601
+ depth: currentDepth + 1,
602
+ isRoot: false,
603
+ inReplyTo: originalMessageId
604
+ }
605
+ };
606
+
607
+ // Store reply
608
+ this.messages.set(replyMessageId, replyMessage);
609
+ originalMessage.replies.push(replyMessageId);
610
+
611
+ // Update conversation
612
+ conversation.lastActivity = timestamp;
613
+ conversation.messageCount++;
614
+ if (markResolved) {
615
+ conversation.status = 'resolved';
616
+ }
617
+
618
+ // Update inboxes
619
+ for (const recipientId of replyRecipients) {
620
+ if (!this.agentInboxes.has(recipientId)) {
621
+ this.agentInboxes.set(recipientId, new Set());
622
+ }
623
+ this.agentInboxes.get(recipientId).add(replyMessageId);
624
+ }
625
+
626
+ // Update message counts
627
+ this._updateMessageCounts(senderAgentId, 'sent');
628
+ for (const recipientId of replyRecipients) {
629
+ this._updateMessageCounts(recipientId, 'received');
630
+ }
631
+
632
+ // CRITICAL: Update inter-agent conversation tracking for replies
633
+ for (const recipientId of replyRecipients) {
634
+ await this._updateConversationTracking(senderAgentId, recipientId, 'replied', context);
635
+ }
636
+
637
+ // Notify recipients
638
+ await this._notifyRecipients(replyMessage, context);
639
+
640
+ // Broadcast to WebSocket for UI visibility
641
+ await this._broadcastToUI(replyMessage, 'agent-message-reply', context);
642
+
643
+ return {
644
+ success: true,
645
+ messageId: replyMessageId,
646
+ conversationId: originalMessage.conversationId,
647
+ recipients: replyRecipients,
648
+ depth: currentDepth + 1,
649
+ timestamp,
650
+ conversationStatus: conversation.status
651
+ };
652
+
653
+ } catch (error) {
654
+ return {
655
+ success: false,
656
+ error: error.message
657
+ };
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Get unreplied messages for an agent
663
+ */
664
+ async getUnrepliedMessages(agentId, parameters, context) {
665
+ try {
666
+ const {
667
+ 'include-low-priority': includeLowPriority = false,
668
+ 'max-age-hours': maxAgeHours = 24
669
+ } = parameters;
670
+
671
+ const inbox = this.agentInboxes.get(agentId) || new Set();
672
+ const unrepliedMessages = [];
673
+ const maxAge = Date.now() - (maxAgeHours * 3600000);
674
+
675
+ for (const messageId of inbox) {
676
+ const message = this.messages.get(messageId);
677
+ if (!message) continue;
678
+
679
+ // Skip old messages
680
+ if (new Date(message.timestamp).getTime() < maxAge) continue;
681
+
682
+ // Skip low priority if not requested
683
+ if (message.priority === 'low' && !includeLowPriority) continue;
684
+
685
+ // Check if message requires reply and hasn't been replied to by this agent
686
+ if (message.requiresReply) {
687
+ const hasReplied = this._hasAgentReplied(agentId, message);
688
+ if (!hasReplied) {
689
+ const conversation = this.conversations.get(message.conversationId);
690
+ unrepliedMessages.push({
691
+ messageId: message.id,
692
+ conversationId: message.conversationId,
693
+ sender: message.sender,
694
+ subject: message.subject,
695
+ preview: message.content.substring(0, 100) + '...',
696
+ priority: message.priority,
697
+ timestamp: message.timestamp,
698
+ hasAttachments: message.attachments.length > 0,
699
+ conversationStatus: conversation?.status || 'unknown',
700
+ depth: message.metadata.depth
701
+ });
702
+ }
703
+ }
704
+ }
705
+
706
+ // Sort by priority and timestamp
707
+ unrepliedMessages.sort((a, b) => {
708
+ const priorityOrder = { high: 0, normal: 1, low: 2 };
709
+ const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
710
+ if (priorityDiff !== 0) return priorityDiff;
711
+ return new Date(b.timestamp) - new Date(a.timestamp);
712
+ });
713
+
714
+ return {
715
+ success: true,
716
+ messages: unrepliedMessages,
717
+ total: unrepliedMessages.length,
718
+ inbox: {
719
+ total: inbox.size,
720
+ activeConversations: (this.agentConversations.get(agentId) || new Set()).size
721
+ }
722
+ };
723
+
724
+ } catch (error) {
725
+ return {
726
+ success: false,
727
+ error: error.message
728
+ };
729
+ }
730
+ }
731
+
732
+ /**
733
+ * Mark a conversation as ended
734
+ */
735
+ async markConversationEnded(agentId, parameters, context) {
736
+ try {
737
+ const {
738
+ 'conversation-id': conversationId,
739
+ reason = 'Conversation ended by agent'
740
+ } = parameters;
741
+
742
+ if (!conversationId) {
743
+ throw new Error('Conversation ID is required');
744
+ }
745
+
746
+ const conversation = this.conversations.get(conversationId);
747
+ if (!conversation) {
748
+ throw new Error(`Conversation not found: ${conversationId}`);
749
+ }
750
+
751
+ // Verify agent is a participant
752
+ if (!conversation.participants.includes(agentId)) {
753
+ throw new Error('You are not a participant in this conversation');
754
+ }
755
+
756
+ // Update conversation status
757
+ conversation.status = 'ended';
758
+ conversation.endTime = new Date().toISOString();
759
+ conversation.endReason = reason;
760
+ conversation.endedBy = agentId;
761
+
762
+ // Remove from active conversations for all participants
763
+ for (const participantId of conversation.participants) {
764
+ const agentConvs = this.agentConversations.get(participantId);
765
+ if (agentConvs) {
766
+ agentConvs.delete(conversationId);
767
+ }
768
+ }
769
+
770
+ return {
771
+ success: true,
772
+ conversationId,
773
+ status: 'ended',
774
+ reason,
775
+ timestamp: conversation.endTime
776
+ };
777
+
778
+ } catch (error) {
779
+ return {
780
+ success: false,
781
+ error: error.message
782
+ };
783
+ }
784
+ }
785
+
786
+ /**
787
+ * Initialize storage directory
788
+ * @private
789
+ */
790
+ async _initializeStorage() {
791
+ try {
792
+ await fs.mkdir(this.config.storageDir, { recursive: true });
793
+ const attachmentsDir = path.join(this.config.storageDir, 'attachments');
794
+ await fs.mkdir(attachmentsDir, { recursive: true });
795
+ } catch (error) {
796
+ console.error('Failed to initialize message storage:', error);
797
+ }
798
+ }
799
+
800
+ /**
801
+ * Parse recipients from parameters
802
+ * @private
803
+ */
804
+ _parseRecipients(recipient, recipients) {
805
+ let recipientList = [];
806
+
807
+ if (recipient) {
808
+ recipientList.push(recipient);
809
+ }
810
+
811
+ if (recipients) {
812
+ if (typeof recipients === 'string') {
813
+ try {
814
+ const parsed = JSON.parse(recipients);
815
+ recipientList = [...recipientList, ...(Array.isArray(parsed) ? parsed : [parsed])];
816
+ } catch {
817
+ recipientList.push(recipients);
818
+ }
819
+ } else if (Array.isArray(recipients)) {
820
+ recipientList = [...recipientList, ...recipients];
821
+ }
822
+ }
823
+
824
+ // Remove duplicates
825
+ return [...new Set(recipientList)];
826
+ }
827
+
828
+ /**
829
+ * Process and validate attachments
830
+ * @private
831
+ */
832
+ async _processAttachments(attachments, agentId) {
833
+ if (!attachments) return [];
834
+
835
+ let attachmentList = [];
836
+ if (typeof attachments === 'string') {
837
+ try {
838
+ attachmentList = JSON.parse(attachments);
839
+ } catch {
840
+ return [];
841
+ }
842
+ } else {
843
+ attachmentList = attachments;
844
+ }
845
+
846
+ if (!Array.isArray(attachmentList)) {
847
+ attachmentList = [attachmentList];
848
+ }
849
+
850
+ // Validate attachment count
851
+ if (attachmentList.length > this.config.maxAttachmentsPerMessage) {
852
+ throw new Error(`Maximum ${this.config.maxAttachmentsPerMessage} attachments allowed`);
853
+ }
854
+
855
+ const processedAttachments = [];
856
+
857
+ for (const attachment of attachmentList) {
858
+ if (!attachment.path) continue;
859
+
860
+ try {
861
+ // Check file exists and size
862
+ const stats = await fs.stat(attachment.path);
863
+ if (stats.size > this.config.maxAttachmentSize) {
864
+ throw new Error(`Attachment exceeds size limit: ${attachment.path}`);
865
+ }
866
+
867
+ // Copy to storage
868
+ const attachmentId = this._generateAttachmentId();
869
+ const ext = path.extname(attachment.path);
870
+ const storagePath = path.join(this.config.storageDir, 'attachments', `${attachmentId}${ext}`);
871
+
872
+ await fs.copyFile(attachment.path, storagePath);
873
+
874
+ processedAttachments.push({
875
+ id: attachmentId,
876
+ originalPath: attachment.path,
877
+ storagePath,
878
+ type: attachment.type || 'file',
879
+ size: stats.size,
880
+ name: path.basename(attachment.path)
881
+ });
882
+
883
+ } catch (error) {
884
+ console.error(`Failed to process attachment: ${attachment.path}`, error);
885
+ }
886
+ }
887
+
888
+ return processedAttachments;
889
+ }
890
+
891
+ /**
892
+ * Notify recipients of new message
893
+ * @private
894
+ */
895
+ async _notifyRecipients(message, context) {
896
+ const agentPool = context.agentPool;
897
+ if (!agentPool) return;
898
+
899
+ for (const recipientId of message.recipients) {
900
+ try {
901
+ // Send both a notification AND inject message into conversation
902
+
903
+ // 1. Standard notification (for system awareness)
904
+ await agentPool.notifyAgent(recipientId, {
905
+ type: 'agent-communication',
906
+ from: message.sender,
907
+ conversationId: message.conversationId,
908
+ content: `📨 New message from ${message.senderName}: "${message.subject}"`,
909
+ messageId: message.id,
910
+ priority: message.priority,
911
+ requiresResponse: message.requiresReply
912
+ });
913
+
914
+ // 2. Inject the actual message content directly into recipient's conversation
915
+ const recipient = await agentPool.getAgent(recipientId);
916
+ if (recipient) {
917
+ const messageContent = `📨 **Inter-Agent Message**
918
+ **From:** ${message.senderName} (${message.sender})
919
+ **Subject:** ${message.subject}
920
+ **Priority:** ${message.priority}
921
+ **Requires Reply:** ${message.requiresReply ? 'Yes' : 'No'}
922
+
923
+ **Message:**
924
+ ${message.content}
925
+
926
+ ${message.attachments.length > 0 ? `**Attachments:** ${message.attachments.length} file(s)` : ''}
927
+
928
+ *You can reply using the agentcommunication tool with action="reply-to-message" and message-id="${message.id}"*`;
929
+
930
+ const directMessage = {
931
+ id: `agent-comm-${message.id}`,
932
+ conversationId: message.conversationId,
933
+ agentId: message.sender,
934
+ content: messageContent,
935
+ role: 'system', // System message so it's clearly visible
936
+ timestamp: message.timestamp,
937
+ type: 'agent-communication',
938
+ metadata: {
939
+ originalMessageId: message.id,
940
+ fromAgent: message.sender,
941
+ requiresResponse: message.requiresReply,
942
+ priority: message.priority
943
+ }
944
+ };
945
+
946
+ // Add to full conversation
947
+ recipient.conversations.full.messages.push(directMessage);
948
+ recipient.conversations.full.lastUpdated = new Date().toISOString();
949
+
950
+ // Add to current model conversation if active
951
+ if (recipient.currentModel && recipient.conversations[recipient.currentModel]) {
952
+ recipient.conversations[recipient.currentModel].messages.push(directMessage);
953
+ recipient.conversations[recipient.currentModel].lastUpdated = new Date().toISOString();
954
+ }
955
+
956
+ // Persist the updated state
957
+ await agentPool.persistAgentState(recipientId);
958
+
959
+ // Queue message using new architecture
960
+ console.log(`📬 Queueing inter-agent message for scheduler processing`, {
961
+ recipientId,
962
+ sender: message.sender,
963
+ subject: message.subject,
964
+ hasSessionId: !!context.sessionId
965
+ });
966
+
967
+ await agentPool.addInterAgentMessage(recipientId, {
968
+ id: message.id,
969
+ messageId: message.id,
970
+ sender: message.sender,
971
+ senderName: message.senderName,
972
+ subject: message.subject,
973
+ content: message.content,
974
+ attachments: message.attachments,
975
+ priority: message.priority,
976
+ requiresReply: message.requiresReply,
977
+ conversationId: message.conversationId,
978
+ sessionId: context.sessionId,
979
+ timestamp: new Date().toISOString()
980
+ });
981
+
982
+ console.log(`Direct message injected and queued for processing: ${recipientId}`, {
983
+ messageId: message.id,
984
+ fromAgent: message.sender,
985
+ subject: message.subject,
986
+ priority: message.priority
987
+ });
988
+ }
989
+
990
+ } catch (error) {
991
+ console.error(`Failed to notify agent ${recipientId}:`, error);
992
+ }
993
+ }
994
+ }
995
+
996
+ /**
997
+ * Check if agent has replied to a message
998
+ * @private
999
+ */
1000
+ _hasAgentReplied(agentId, message) {
1001
+ for (const replyId of message.replies) {
1002
+ const reply = this.messages.get(replyId);
1003
+ if (reply && reply.sender === agentId) {
1004
+ return true;
1005
+ }
1006
+ // Recursively check nested replies
1007
+ if (reply && this._hasAgentReplied(agentId, reply)) {
1008
+ return true;
1009
+ }
1010
+ }
1011
+ return false;
1012
+ }
1013
+
1014
+ /**
1015
+ * Get conversation depth
1016
+ * @private
1017
+ */
1018
+ _getConversationDepth(conversationId) {
1019
+ const conversation = this.conversations.get(conversationId);
1020
+ if (!conversation) return 0;
1021
+
1022
+ let maxDepth = 0;
1023
+ const rootMessage = this.messages.get(conversation.rootMessageId);
1024
+ if (rootMessage) {
1025
+ maxDepth = this._getMessageDepth(rootMessage);
1026
+ }
1027
+
1028
+ return maxDepth;
1029
+ }
1030
+
1031
+ /**
1032
+ * Get message depth recursively
1033
+ * @private
1034
+ */
1035
+ _getMessageDepth(message, currentDepth = 0) {
1036
+ if (message.replies.length === 0) {
1037
+ return currentDepth;
1038
+ }
1039
+
1040
+ let maxDepth = currentDepth;
1041
+ for (const replyId of message.replies) {
1042
+ const reply = this.messages.get(replyId);
1043
+ if (reply) {
1044
+ const depth = this._getMessageDepth(reply, currentDepth + 1);
1045
+ maxDepth = Math.max(maxDepth, depth);
1046
+ }
1047
+ }
1048
+
1049
+ return maxDepth;
1050
+ }
1051
+
1052
+ /**
1053
+ * Update message counts for agent
1054
+ * @private
1055
+ */
1056
+ _updateMessageCounts(agentId, type) {
1057
+ if (!this.agentMessageCounts.has(agentId)) {
1058
+ this.agentMessageCounts.set(agentId, { sent: 0, received: 0 });
1059
+ }
1060
+
1061
+ const counts = this.agentMessageCounts.get(agentId);
1062
+ if (type === 'sent') {
1063
+ counts.sent++;
1064
+ } else {
1065
+ counts.received++;
1066
+ }
1067
+ }
1068
+
1069
+ /**
1070
+ * Generate unique message ID
1071
+ * @private
1072
+ */
1073
+ _generateMessageId() {
1074
+ return `msg-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
1075
+ }
1076
+
1077
+ /**
1078
+ * Generate unique conversation ID
1079
+ * @private
1080
+ */
1081
+ _generateConversationId() {
1082
+ return `conv-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
1083
+ }
1084
+
1085
+ /**
1086
+ * Generate unique attachment ID
1087
+ * @private
1088
+ */
1089
+ _generateAttachmentId() {
1090
+ return `att-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
1091
+ }
1092
+
1093
+ /**
1094
+ * Cleanup old messages and conversations
1095
+ * Called periodically to prevent memory growth
1096
+ */
1097
+ async cleanup() {
1098
+ const now = Date.now();
1099
+ const retentionCutoff = now - this.config.messageRetentionPeriod;
1100
+
1101
+ // Clean up old messages
1102
+ for (const [messageId, message] of this.messages.entries()) {
1103
+ const messageTime = new Date(message.timestamp).getTime();
1104
+ if (messageTime < retentionCutoff) {
1105
+ // Clean up attachments
1106
+ for (const attachment of message.attachments) {
1107
+ try {
1108
+ await fs.unlink(attachment.storagePath);
1109
+ } catch (error) {
1110
+ // Ignore errors for missing files
1111
+ }
1112
+ }
1113
+
1114
+ // Remove from inboxes
1115
+ for (const [agentId, inbox] of this.agentInboxes.entries()) {
1116
+ inbox.delete(messageId);
1117
+ }
1118
+
1119
+ this.messages.delete(messageId);
1120
+ }
1121
+ }
1122
+
1123
+ // Clean up old conversations
1124
+ for (const [conversationId, conversation] of this.conversations.entries()) {
1125
+ const lastActivity = new Date(conversation.lastActivity).getTime();
1126
+ if (lastActivity < retentionCutoff || conversation.status === 'ended') {
1127
+ // Remove from agent conversations
1128
+ for (const [agentId, convs] of this.agentConversations.entries()) {
1129
+ convs.delete(conversationId);
1130
+ }
1131
+
1132
+ this.conversations.delete(conversationId);
1133
+ }
1134
+ }
1135
+ }
1136
+
1137
+ /**
1138
+ * Broadcast message to WebSocket for UI visibility
1139
+ * @private
1140
+ */
1141
+ async _broadcastToUI(message, eventType, context) {
1142
+ try {
1143
+ // Build a formatted message for UI display
1144
+ const uiMessage = {
1145
+ type: 'agent-communication',
1146
+ eventType,
1147
+ timestamp: message.timestamp,
1148
+ messageId: message.id,
1149
+ conversationId: message.conversationId,
1150
+ sender: {
1151
+ id: message.sender,
1152
+ name: message.senderName
1153
+ },
1154
+ recipients: Object.entries(message.recipientNames || {}).map(([id, name]) => ({
1155
+ id,
1156
+ name
1157
+ })),
1158
+ subject: message.subject,
1159
+ content: message.content,
1160
+ priority: message.priority,
1161
+ requiresReply: message.requiresReply,
1162
+ hasAttachments: message.attachments && message.attachments.length > 0,
1163
+ attachmentCount: message.attachments ? message.attachments.length : 0,
1164
+ metadata: message.metadata
1165
+ };
1166
+
1167
+ // Try multiple broadcast methods
1168
+ // Method 1: Through agentPool if available
1169
+ if (context.agentPool && context.agentPool.messageProcessor) {
1170
+ const messageProcessor = context.agentPool.messageProcessor;
1171
+ if (messageProcessor && messageProcessor.orchestrator && messageProcessor.orchestrator.webServer) {
1172
+ // Use broadcastToSession - it will fallback to all connections if session not found
1173
+ messageProcessor.orchestrator.webServer.broadcastToSession(context.sessionId || 'web-session', {
1174
+ type: 'agent-communication',
1175
+ action: 'agent-communication',
1176
+ data: uiMessage
1177
+ });
1178
+ return;
1179
+ }
1180
+ }
1181
+
1182
+ // Method 2: Direct orchestrator access
1183
+ if (context.orchestrator && context.orchestrator.webServer) {
1184
+ context.orchestrator.webServer.broadcastToSession(context.sessionId || 'web-session', {
1185
+ type: 'agent-communication',
1186
+ action: 'agent-communication',
1187
+ data: uiMessage
1188
+ });
1189
+ return;
1190
+ }
1191
+
1192
+ // Method 3: Through global reference (if set during initialization)
1193
+ if (global.loxiaWebServer) {
1194
+ global.loxiaWebServer.broadcastToSession(context.sessionId || 'web-session', {
1195
+ type: 'agent-communication',
1196
+ action: 'agent-communication',
1197
+ data: uiMessage
1198
+ });
1199
+ }
1200
+ } catch (error) {
1201
+ // Don't fail the operation if broadcast fails
1202
+ console.error('Failed to broadcast agent message to UI:', error);
1203
+ }
1204
+ }
1205
+
1206
+ /**
1207
+ * Check if sender can send message to recipient
1208
+ * @private
1209
+ */
1210
+ async _canSendMessage(senderAgent, recipientId, context) {
1211
+ const agentPool = context.agentPool;
1212
+
1213
+ // Ensure interAgentTracking is a Map (defensive - may be plain object from JSON)
1214
+ if (!senderAgent.interAgentTracking || !(senderAgent.interAgentTracking instanceof Map)) {
1215
+ if (senderAgent.interAgentTracking && typeof senderAgent.interAgentTracking === 'object') {
1216
+ senderAgent.interAgentTracking = new Map(Object.entries(senderAgent.interAgentTracking));
1217
+ } else {
1218
+ senderAgent.interAgentTracking = new Map();
1219
+ }
1220
+ }
1221
+
1222
+ const tracking = senderAgent.interAgentTracking;
1223
+
1224
+ // Initialize tracking for this recipient if needed
1225
+ if (!tracking.has(recipientId)) {
1226
+ tracking.set(recipientId, {
1227
+ lastSent: null,
1228
+ lastReceived: null,
1229
+ lastType: null
1230
+ });
1231
+ }
1232
+
1233
+ const recipientTracking = tracking.get(recipientId);
1234
+ const now = Date.now();
1235
+ const MIN_INTERVAL = 60 * 1000; // 1 minute
1236
+
1237
+ // Rule 1: Always allow if recipient has replied since our last message
1238
+ if (recipientTracking.lastType === 'received' ||
1239
+ (recipientTracking.lastReceived && recipientTracking.lastReceived > recipientTracking.lastSent)) {
1240
+ return { allowed: true };
1241
+ }
1242
+
1243
+ // Rule 2: Allow if minimum time has passed since last send
1244
+ if (recipientTracking.lastSent) {
1245
+ const timeSinceLastSend = now - recipientTracking.lastSent;
1246
+ if (timeSinceLastSend >= MIN_INTERVAL) {
1247
+ return { allowed: true };
1248
+ }
1249
+
1250
+ // Calculate when next send is allowed
1251
+ const nextAllowedTime = recipientTracking.lastSent + MIN_INTERVAL;
1252
+ return {
1253
+ allowed: false,
1254
+ reason: `Must wait ${Math.ceil((nextAllowedTime - now) / 1000)}s since last message`,
1255
+ waitUntil: nextAllowedTime
1256
+ };
1257
+ }
1258
+
1259
+ // Rule 3: First message to this recipient is always allowed
1260
+ return { allowed: true };
1261
+ }
1262
+
1263
+ /**
1264
+ * Update conversation tracking after message sent/received
1265
+ * @private
1266
+ */
1267
+ async _updateConversationTracking(senderAgentId, recipientId, action, context) {
1268
+ const agentPool = context.agentPool;
1269
+ const senderAgent = await agentPool.getAgent(senderAgentId);
1270
+ if (!senderAgent) return;
1271
+
1272
+ const now = Date.now();
1273
+
1274
+ // Ensure sender's interAgentTracking is a Map
1275
+ if (!senderAgent.interAgentTracking || !(senderAgent.interAgentTracking instanceof Map)) {
1276
+ if (senderAgent.interAgentTracking && typeof senderAgent.interAgentTracking === 'object') {
1277
+ senderAgent.interAgentTracking = new Map(Object.entries(senderAgent.interAgentTracking));
1278
+ } else {
1279
+ senderAgent.interAgentTracking = new Map();
1280
+ }
1281
+ }
1282
+
1283
+ // Update sender's tracking
1284
+ if (!senderAgent.interAgentTracking.has(recipientId)) {
1285
+ senderAgent.interAgentTracking.set(recipientId, {
1286
+ lastSent: null,
1287
+ lastReceived: null,
1288
+ lastType: null
1289
+ });
1290
+ }
1291
+
1292
+ const tracking = senderAgent.interAgentTracking.get(recipientId);
1293
+
1294
+ if (action === 'sent') {
1295
+ tracking.lastSent = now;
1296
+ tracking.lastType = 'sent';
1297
+ } else if (action === 'replied') {
1298
+ tracking.lastSent = now;
1299
+ tracking.lastType = 'sent'; // Reply is still a send action
1300
+ }
1301
+
1302
+ // Update recipient's tracking (they received a message)
1303
+ const recipientAgent = await agentPool.getAgent(recipientId);
1304
+ if (recipientAgent) {
1305
+ // Ensure recipient's interAgentTracking is a Map
1306
+ if (!recipientAgent.interAgentTracking || !(recipientAgent.interAgentTracking instanceof Map)) {
1307
+ if (recipientAgent.interAgentTracking && typeof recipientAgent.interAgentTracking === 'object') {
1308
+ recipientAgent.interAgentTracking = new Map(Object.entries(recipientAgent.interAgentTracking));
1309
+ } else {
1310
+ recipientAgent.interAgentTracking = new Map();
1311
+ }
1312
+ }
1313
+
1314
+ if (!recipientAgent.interAgentTracking.has(senderAgentId)) {
1315
+ recipientAgent.interAgentTracking.set(senderAgentId, {
1316
+ lastSent: null,
1317
+ lastReceived: null,
1318
+ lastType: null
1319
+ });
1320
+ }
1321
+
1322
+ const recipientTracking = recipientAgent.interAgentTracking.get(senderAgentId);
1323
+ recipientTracking.lastReceived = now;
1324
+ recipientTracking.lastType = 'received';
1325
+
1326
+ // Persist recipient agent state
1327
+ await agentPool.persistAgentState(recipientId);
1328
+ }
1329
+
1330
+ // Persist sender agent state
1331
+ await agentPool.persistAgentState(senderAgentId);
1332
+ }
1333
+
1334
+ /**
1335
+ * Set message processor for broadcasting
1336
+ * Called during tool initialization
1337
+ */
1338
+ setMessageProcessor(messageProcessor) {
1339
+ this.messageProcessor = messageProcessor;
1340
+ }
1341
+ }
1342
+
1343
+ export default AgentCommunicationTool;