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,810 +1,810 @@
1
- import { ERROR_TYPES, HTTP_STATUS, AGENT_STATUS } from '../utilities/constants.js';
2
-
3
- /**
4
- * Comprehensive error handling service for the Loxia AI Agents System
5
- * Provides error classification, recovery strategies, and monitoring
6
- */
7
- export class ErrorHandler {
8
- constructor(config, logger) {
9
- this.config = config || {};
10
- this.logger = logger;
11
- this.errorStats = {
12
- totalErrors: 0,
13
- errorsByType: new Map(),
14
- errorsByAgent: new Map(),
15
- recoveryAttempts: 0,
16
- successfulRecoveries: 0,
17
- criticalErrors: 0
18
- };
19
-
20
- this.recoveryStrategies = new Map();
21
- this.errorSubscribers = new Set();
22
- this.errorQueue = [];
23
- this.isProcessingQueue = false;
24
-
25
- this.initializeRecoveryStrategies();
26
- this.setupErrorProcessing();
27
- }
28
-
29
- /**
30
- * Handle an error with appropriate classification and recovery
31
- * @param {Error|Object} error - Error object or error data
32
- * @param {Object} context - Error context information
33
- * @returns {Object} Error handling result
34
- */
35
- async handleError(error, context = {}) {
36
- try {
37
- const errorInfo = this.classifyError(error, context);
38
- const handlingResult = await this.processError(errorInfo);
39
-
40
- this.updateErrorStats(errorInfo);
41
- this.notifySubscribers(errorInfo, handlingResult);
42
-
43
- return handlingResult;
44
-
45
- } catch (handlingError) {
46
- this.logger.error('Error handling failed', {
47
- originalError: error.message,
48
- handlingError: handlingError.message
49
- });
50
-
51
- return {
52
- success: false,
53
- error: handlingError,
54
- recovery: null,
55
- severity: 'critical'
56
- };
57
- }
58
- }
59
-
60
- /**
61
- * Classify error by type, severity, and context
62
- * @param {Error|Object} error - Error to classify
63
- * @param {Object} context - Error context
64
- * @returns {Object} Classified error information
65
- */
66
- classifyError(error, context = {}) {
67
- const errorInfo = {
68
- id: this.generateErrorId(),
69
- timestamp: new Date().toISOString(),
70
- message: error.message || error.toString(),
71
- stack: error.stack || null,
72
- code: error.code || null,
73
- type: this.determineErrorType(error, context),
74
- severity: this.determineSeverity(error, context),
75
- context: { ...context },
76
- recoverable: true,
77
- retryCount: context.retryCount || 0,
78
- maxRetries: this.getMaxRetries(error, context)
79
- };
80
-
81
- // Additional classification based on context
82
- if (context.agentId) {
83
- errorInfo.agentId = context.agentId;
84
- }
85
-
86
- if (context.toolId) {
87
- errorInfo.toolId = context.toolId;
88
- }
89
-
90
- if (context.operationId) {
91
- errorInfo.operationId = context.operationId;
92
- }
93
-
94
- // Determine if error is recoverable
95
- errorInfo.recoverable = this.isRecoverable(errorInfo);
96
-
97
- return errorInfo;
98
- }
99
-
100
- /**
101
- * Process error with appropriate recovery strategy
102
- * @param {Object} errorInfo - Classified error information
103
- * @returns {Object} Processing result
104
- */
105
- async processError(errorInfo) {
106
- try {
107
- this.logger.error('Processing error', {
108
- errorId: errorInfo.id,
109
- type: errorInfo.type,
110
- severity: errorInfo.severity,
111
- agentId: errorInfo.agentId,
112
- message: errorInfo.message
113
- });
114
-
115
- // Check if this is a critical error requiring immediate attention
116
- if (errorInfo.severity === 'critical') {
117
- await this.handleCriticalError(errorInfo);
118
- }
119
-
120
- // Attempt recovery if error is recoverable
121
- let recoveryResult = null;
122
- if (errorInfo.recoverable && errorInfo.retryCount < errorInfo.maxRetries) {
123
- recoveryResult = await this.attemptRecovery(errorInfo);
124
- }
125
-
126
- // Log error for monitoring and analysis
127
- await this.logError(errorInfo, recoveryResult);
128
-
129
- return {
130
- success: recoveryResult?.success || false,
131
- errorId: errorInfo.id,
132
- errorType: errorInfo.type,
133
- severity: errorInfo.severity,
134
- recovery: recoveryResult,
135
- shouldRetry: this.shouldRetry(errorInfo, recoveryResult),
136
- retryDelay: this.calculateRetryDelay(errorInfo)
137
- };
138
-
139
- } catch (processingError) {
140
- this.logger.error('Error processing failed', {
141
- errorId: errorInfo.id,
142
- processingError: processingError.message
143
- });
144
-
145
- return {
146
- success: false,
147
- errorId: errorInfo.id,
148
- errorType: errorInfo.type,
149
- severity: 'critical',
150
- recovery: null,
151
- shouldRetry: false
152
- };
153
- }
154
- }
155
-
156
- /**
157
- * Attempt to recover from an error using appropriate strategy
158
- * @param {Object} errorInfo - Error information
159
- * @returns {Object} Recovery result
160
- */
161
- async attemptRecovery(errorInfo) {
162
- try {
163
- this.errorStats.recoveryAttempts++;
164
-
165
- const strategy = this.recoveryStrategies.get(errorInfo.type) ||
166
- this.recoveryStrategies.get('default');
167
-
168
- if (!strategy) {
169
- this.logger.warn('No recovery strategy found', { errorType: errorInfo.type });
170
- return { success: false, reason: 'No recovery strategy available' };
171
- }
172
-
173
- this.logger.info('Attempting error recovery', {
174
- errorId: errorInfo.id,
175
- errorType: errorInfo.type,
176
- strategy: strategy.name,
177
- retryCount: errorInfo.retryCount
178
- });
179
-
180
- const recoveryResult = await strategy.recover(errorInfo);
181
-
182
- if (recoveryResult.success) {
183
- this.errorStats.successfulRecoveries++;
184
- this.logger.info('Error recovery successful', {
185
- errorId: errorInfo.id,
186
- strategy: strategy.name
187
- });
188
- } else {
189
- this.logger.warn('Error recovery failed', {
190
- errorId: errorInfo.id,
191
- strategy: strategy.name,
192
- reason: recoveryResult.reason
193
- });
194
- }
195
-
196
- return recoveryResult;
197
-
198
- } catch (recoveryError) {
199
- this.logger.error('Recovery attempt failed', {
200
- errorId: errorInfo.id,
201
- recoveryError: recoveryError.message
202
- });
203
-
204
- return {
205
- success: false,
206
- reason: `Recovery attempt failed: ${recoveryError.message}`
207
- };
208
- }
209
- }
210
-
211
- /**
212
- * Handle critical errors that require immediate attention
213
- * @param {Object} errorInfo - Critical error information
214
- */
215
- async handleCriticalError(errorInfo) {
216
- try {
217
- this.errorStats.criticalErrors++;
218
-
219
- this.logger.error('Critical error detected', {
220
- errorId: errorInfo.id,
221
- message: errorInfo.message,
222
- context: errorInfo.context
223
- });
224
-
225
- // Emit critical error event
226
- if (typeof process !== 'undefined' && process.emit) {
227
- process.emit('criticalError', errorInfo);
228
- }
229
-
230
- // Take immediate protective actions based on error type
231
- switch (errorInfo.type) {
232
- case ERROR_TYPES.AUTHENTICATION_FAILED:
233
- await this.handleAuthenticationFailure(errorInfo);
234
- break;
235
-
236
- case ERROR_TYPES.RATE_LIMIT_EXCEEDED:
237
- await this.handleRateLimitExceeded(errorInfo);
238
- break;
239
-
240
- case ERROR_TYPES.OPERATION_TIMEOUT:
241
- await this.handleOperationTimeout(errorInfo);
242
- break;
243
-
244
- default:
245
- await this.handleGenericCriticalError(errorInfo);
246
- }
247
-
248
- } catch (criticalHandlingError) {
249
- this.logger.error('Critical error handling failed', {
250
- errorId: errorInfo.id,
251
- handlingError: criticalHandlingError.message
252
- });
253
- }
254
- }
255
-
256
- /**
257
- * Determine error type based on error and context
258
- * @param {Error|Object} error - Error object
259
- * @param {Object} context - Error context
260
- * @returns {string} Error type
261
- */
262
- determineErrorType(error, context) {
263
- // Check error code or HTTP status
264
- if (error.code === 'ENOENT' || error.status === HTTP_STATUS.NOT_FOUND) {
265
- return ERROR_TYPES.FILE_NOT_FOUND;
266
- }
267
-
268
- if (error.code === 'EACCES' || error.status === HTTP_STATUS.FORBIDDEN) {
269
- return ERROR_TYPES.PERMISSION_DENIED;
270
- }
271
-
272
- if (error.status === HTTP_STATUS.UNAUTHORIZED) {
273
- return ERROR_TYPES.AUTHENTICATION_FAILED;
274
- }
275
-
276
- if (error.status === HTTP_STATUS.TOO_MANY_REQUESTS) {
277
- return ERROR_TYPES.RATE_LIMIT_EXCEEDED;
278
- }
279
-
280
- // Check error message patterns
281
- const message = error.message?.toLowerCase() || '';
282
-
283
- if (message.includes('timeout') || message.includes('timed out')) {
284
- return ERROR_TYPES.OPERATION_TIMEOUT;
285
- }
286
-
287
- if (message.includes('validation') || message.includes('invalid')) {
288
- return ERROR_TYPES.VALIDATION_ERROR;
289
- }
290
-
291
- if (message.includes('config') || message.includes('configuration')) {
292
- return ERROR_TYPES.CONFIGURATION_ERROR;
293
- }
294
-
295
- // Check context for additional clues
296
- if (context.operation === 'file_operation') {
297
- return ERROR_TYPES.FILE_NOT_FOUND;
298
- }
299
-
300
- if (context.operation === 'api_request') {
301
- return ERROR_TYPES.RATE_LIMIT_EXCEEDED;
302
- }
303
-
304
- return ERROR_TYPES.UNKNOWN_ERROR;
305
- }
306
-
307
- /**
308
- * Determine error severity
309
- * @param {Error|Object} error - Error object
310
- * @param {Object} context - Error context
311
- * @returns {string} Error severity
312
- */
313
- determineSeverity(error, context) {
314
- const criticalTypes = [
315
- ERROR_TYPES.AUTHENTICATION_FAILED,
316
- ERROR_TYPES.CONFIGURATION_ERROR
317
- ];
318
-
319
- const highTypes = [
320
- ERROR_TYPES.RATE_LIMIT_EXCEEDED,
321
- ERROR_TYPES.OPERATION_TIMEOUT,
322
- ERROR_TYPES.PERMISSION_DENIED
323
- ];
324
-
325
- const errorType = this.determineErrorType(error, context);
326
-
327
- if (criticalTypes.includes(errorType)) {
328
- return 'critical';
329
- }
330
-
331
- if (highTypes.includes(errorType)) {
332
- return 'high';
333
- }
334
-
335
- // Check retry count
336
- const retryCount = (context && context.retryCount) || 0;
337
- if (retryCount >= 3) {
338
- return 'high';
339
- }
340
-
341
- // Check if error is affecting agent operation
342
- if (context && context.agentId && context.operation === 'agent_communication') {
343
- return 'medium';
344
- }
345
-
346
- return 'low';
347
- }
348
-
349
- /**
350
- * Check if error is recoverable
351
- * @param {Object} errorInfo - Error information
352
- * @returns {boolean} True if recoverable
353
- */
354
- isRecoverable(errorInfo) {
355
- const nonRecoverableTypes = [
356
- ERROR_TYPES.AUTHENTICATION_FAILED,
357
- ERROR_TYPES.CONFIGURATION_ERROR
358
- ];
359
-
360
- if (nonRecoverableTypes.includes(errorInfo.type)) {
361
- return false;
362
- }
363
-
364
- // Not recoverable if max retries exceeded
365
- if (errorInfo.retryCount >= errorInfo.maxRetries) {
366
- return false;
367
- }
368
-
369
- // Not recoverable if critical severity
370
- if (errorInfo.severity === 'critical') {
371
- return false;
372
- }
373
-
374
- return true;
375
- }
376
-
377
- /**
378
- * Get maximum retry attempts for error type
379
- * @param {Error|Object} error - Error object
380
- * @param {Object} context - Error context
381
- * @returns {number} Maximum retries
382
- */
383
- getMaxRetries(error, context) {
384
- const errorType = this.determineErrorType(error, context);
385
-
386
- const retryLimits = {
387
- [ERROR_TYPES.RATE_LIMIT_EXCEEDED]: 5,
388
- [ERROR_TYPES.OPERATION_TIMEOUT]: 3,
389
- [ERROR_TYPES.FILE_NOT_FOUND]: 2,
390
- [ERROR_TYPES.PERMISSION_DENIED]: 1,
391
- [ERROR_TYPES.VALIDATION_ERROR]: 2,
392
- [ERROR_TYPES.UNKNOWN_ERROR]: 3
393
- };
394
-
395
- return retryLimits[errorType] || 3;
396
- }
397
-
398
- /**
399
- * Determine if error should be retried
400
- * @param {Object} errorInfo - Error information
401
- * @param {Object} recoveryResult - Recovery result
402
- * @returns {boolean} True if should retry
403
- */
404
- shouldRetry(errorInfo, recoveryResult) {
405
- if (!errorInfo.recoverable) {
406
- return false;
407
- }
408
-
409
- if (errorInfo.retryCount >= errorInfo.maxRetries) {
410
- return false;
411
- }
412
-
413
- if (recoveryResult && recoveryResult.success) {
414
- return false; // Recovery succeeded, no need to retry
415
- }
416
-
417
- return true;
418
- }
419
-
420
- /**
421
- * Calculate retry delay based on error information
422
- * @param {Object} errorInfo - Error information
423
- * @returns {number} Delay in milliseconds
424
- */
425
- calculateRetryDelay(errorInfo) {
426
- const baseDelay = 1000; // 1 second
427
- const maxDelay = 30000; // 30 seconds
428
-
429
- // Exponential backoff with jitter
430
- const exponentialDelay = baseDelay * Math.pow(2, errorInfo.retryCount);
431
- const jitter = Math.random() * 1000; // Random jitter up to 1 second
432
-
433
- return Math.min(exponentialDelay + jitter, maxDelay);
434
- }
435
-
436
- /**
437
- * Initialize recovery strategies for different error types
438
- */
439
- initializeRecoveryStrategies() {
440
- // File not found recovery
441
- this.recoveryStrategies.set(ERROR_TYPES.FILE_NOT_FOUND, {
442
- name: 'file_not_found_recovery',
443
- recover: async (errorInfo) => {
444
- if (errorInfo.context.filePath) {
445
- // Try to check if file exists in different location
446
- // or create directory structure if needed
447
- return {
448
- success: false,
449
- reason: 'File recovery not implemented yet',
450
- suggestion: 'Check file path and permissions'
451
- };
452
- }
453
- return { success: false, reason: 'No file path provided' };
454
- }
455
- });
456
-
457
- // Rate limit recovery
458
- this.recoveryStrategies.set(ERROR_TYPES.RATE_LIMIT_EXCEEDED, {
459
- name: 'rate_limit_recovery',
460
- recover: async (errorInfo) => {
461
- const waitTime = this.calculateRateLimitWait(errorInfo);
462
- this.logger.info('Waiting for rate limit recovery', { waitTime });
463
-
464
- await new Promise(resolve => setTimeout(resolve, waitTime));
465
-
466
- return {
467
- success: true,
468
- action: 'waited_for_rate_limit',
469
- waitTime
470
- };
471
- }
472
- });
473
-
474
- // Operation timeout recovery
475
- this.recoveryStrategies.set(ERROR_TYPES.OPERATION_TIMEOUT, {
476
- name: 'timeout_recovery',
477
- recover: async (errorInfo) => {
478
- // Try to increase timeout for next attempt
479
- if (errorInfo.context.timeout) {
480
- const newTimeout = Math.min(errorInfo.context.timeout * 1.5, 300000); // Max 5 minutes
481
- return {
482
- success: true,
483
- action: 'increased_timeout',
484
- newTimeout
485
- };
486
- }
487
-
488
- return { success: false, reason: 'Cannot adjust timeout' };
489
- }
490
- });
491
-
492
- // Permission denied recovery
493
- this.recoveryStrategies.set(ERROR_TYPES.PERMISSION_DENIED, {
494
- name: 'permission_recovery',
495
- recover: async (errorInfo) => {
496
- return {
497
- success: false,
498
- reason: 'Permission errors require manual intervention',
499
- suggestion: 'Check file/directory permissions'
500
- };
501
- }
502
- });
503
-
504
- // Validation error recovery
505
- this.recoveryStrategies.set(ERROR_TYPES.VALIDATION_ERROR, {
506
- name: 'validation_recovery',
507
- recover: async (errorInfo) => {
508
- // Try to clean/sanitize input data
509
- if (errorInfo.context.inputData) {
510
- return {
511
- success: true,
512
- action: 'data_sanitization',
513
- suggestion: 'Input data was sanitized for retry'
514
- };
515
- }
516
-
517
- return { success: false, reason: 'No input data to sanitize' };
518
- }
519
- });
520
-
521
- // Default recovery strategy
522
- this.recoveryStrategies.set('default', {
523
- name: 'default_recovery',
524
- recover: async (errorInfo) => {
525
- // Generic recovery: wait and retry
526
- const delay = this.calculateRetryDelay(errorInfo);
527
- await new Promise(resolve => setTimeout(resolve, delay));
528
-
529
- return {
530
- success: true,
531
- action: 'delay_retry',
532
- delay
533
- };
534
- }
535
- });
536
- }
537
-
538
- /**
539
- * Handle authentication failure
540
- * @param {Object} errorInfo - Error information
541
- */
542
- async handleAuthenticationFailure(errorInfo) {
543
- this.logger.error('Authentication failure detected', { errorId: errorInfo.id });
544
-
545
- // Could trigger token refresh, re-authentication, etc.
546
- if (errorInfo.agentId) {
547
- // Pause agent until authentication is resolved
548
- // await this.orchestrator.pauseAgent(errorInfo.agentId, 300, 'Authentication failure');
549
- }
550
- }
551
-
552
- /**
553
- * Handle rate limit exceeded
554
- * @param {Object} errorInfo - Error information
555
- */
556
- async handleRateLimitExceeded(errorInfo) {
557
- const waitTime = this.calculateRateLimitWait(errorInfo);
558
-
559
- this.logger.warn('Rate limit exceeded, implementing backoff', {
560
- errorId: errorInfo.id,
561
- waitTime,
562
- agentId: errorInfo.agentId
563
- });
564
-
565
- if (errorInfo.agentId) {
566
- // Pause agent temporarily
567
- // await this.orchestrator.pauseAgent(errorInfo.agentId, waitTime / 1000, 'Rate limit exceeded');
568
- }
569
- }
570
-
571
- /**
572
- * Handle operation timeout
573
- * @param {Object} errorInfo - Error information
574
- */
575
- async handleOperationTimeout(errorInfo) {
576
- this.logger.error('Operation timeout detected', {
577
- errorId: errorInfo.id,
578
- operation: errorInfo.context.operation,
579
- timeout: errorInfo.context.timeout
580
- });
581
-
582
- // Could cancel ongoing operations, adjust timeouts, etc.
583
- }
584
-
585
- /**
586
- * Handle generic critical error
587
- * @param {Object} errorInfo - Error information
588
- */
589
- async handleGenericCriticalError(errorInfo) {
590
- this.logger.error('Generic critical error', {
591
- errorId: errorInfo.id,
592
- type: errorInfo.type,
593
- message: errorInfo.message
594
- });
595
-
596
- // Generic protective measures
597
- if (errorInfo.agentId) {
598
- // Could pause agent for safety
599
- this.logger.warn('Considering agent pause due to critical error', {
600
- agentId: errorInfo.agentId
601
- });
602
- }
603
- }
604
-
605
- /**
606
- * Calculate wait time for rate limit recovery
607
- * @param {Object} errorInfo - Error information
608
- * @returns {number} Wait time in milliseconds
609
- */
610
- calculateRateLimitWait(errorInfo) {
611
- const baseWait = 60000; // 1 minute
612
- const retryMultiplier = Math.pow(2, errorInfo.retryCount);
613
- const maxWait = 300000; // 5 minutes
614
-
615
- return Math.min(baseWait * retryMultiplier, maxWait);
616
- }
617
-
618
- /**
619
- * Log error for monitoring and analysis
620
- * @param {Object} errorInfo - Error information
621
- * @param {Object} recoveryResult - Recovery result
622
- */
623
- async logError(errorInfo, recoveryResult) {
624
- try {
625
- const logEntry = {
626
- errorId: errorInfo.id,
627
- timestamp: errorInfo.timestamp,
628
- type: errorInfo.type,
629
- severity: errorInfo.severity,
630
- message: errorInfo.message,
631
- agentId: errorInfo.agentId,
632
- toolId: errorInfo.toolId,
633
- operationId: errorInfo.operationId,
634
- retryCount: errorInfo.retryCount,
635
- recoveryAttempted: !!recoveryResult,
636
- recoverySuccess: recoveryResult?.success || false,
637
- recoveryAction: recoveryResult?.action || null
638
- };
639
-
640
- // Store in error queue for batch processing
641
- this.errorQueue.push(logEntry);
642
-
643
- // Process queue if not already processing
644
- if (!this.isProcessingQueue) {
645
- this.processErrorQueue();
646
- }
647
-
648
- } catch (loggingError) {
649
- this.logger.error('Error logging failed', {
650
- errorId: errorInfo.id,
651
- loggingError: loggingError.message
652
- });
653
- }
654
- }
655
-
656
- /**
657
- * Process error queue for batch operations
658
- */
659
- async processErrorQueue() {
660
- if (this.isProcessingQueue || this.errorQueue.length === 0) {
661
- return;
662
- }
663
-
664
- this.isProcessingQueue = true;
665
-
666
- try {
667
- while (this.errorQueue.length > 0) {
668
- const batch = this.errorQueue.splice(0, 10); // Process 10 at a time
669
-
670
- // Here you would typically save to database, send to monitoring service, etc.
671
- this.logger.debug('Processing error batch', { batchSize: batch.length });
672
-
673
- // Simulate async processing
674
- await new Promise(resolve => setTimeout(resolve, 100));
675
- }
676
- } catch (processingError) {
677
- this.logger.error('Error queue processing failed', { error: processingError.message });
678
- } finally {
679
- this.isProcessingQueue = false;
680
- }
681
- }
682
-
683
- /**
684
- * Setup error processing infrastructure
685
- */
686
- setupErrorProcessing() {
687
- // Setup periodic queue processing
688
- setInterval(() => {
689
- if (this.errorQueue.length > 0) {
690
- this.processErrorQueue();
691
- }
692
- }, 5000); // Process every 5 seconds
693
-
694
- // Setup global error handlers
695
- if (typeof process !== 'undefined') {
696
- process.on('uncaughtException', (error) => {
697
- this.handleError(error, {
698
- type: 'uncaught_exception',
699
- severity: 'critical'
700
- });
701
- });
702
-
703
- process.on('unhandledRejection', (reason, promise) => {
704
- this.handleError(new Error(`Unhandled Rejection: ${reason}`), {
705
- type: 'unhandled_rejection',
706
- severity: 'high',
707
- promise: promise.toString()
708
- });
709
- });
710
- }
711
- }
712
-
713
- /**
714
- * Update error statistics
715
- * @param {Object} errorInfo - Error information
716
- */
717
- updateErrorStats(errorInfo) {
718
- this.errorStats.totalErrors++;
719
-
720
- // Update error type statistics
721
- if (!this.errorStats.errorsByType.has(errorInfo.type)) {
722
- this.errorStats.errorsByType.set(errorInfo.type, 0);
723
- }
724
- this.errorStats.errorsByType.set(
725
- errorInfo.type,
726
- this.errorStats.errorsByType.get(errorInfo.type) + 1
727
- );
728
-
729
- // Update agent error statistics
730
- if (errorInfo.agentId) {
731
- if (!this.errorStats.errorsByAgent.has(errorInfo.agentId)) {
732
- this.errorStats.errorsByAgent.set(errorInfo.agentId, 0);
733
- }
734
- this.errorStats.errorsByAgent.set(
735
- errorInfo.agentId,
736
- this.errorStats.errorsByAgent.get(errorInfo.agentId) + 1
737
- );
738
- }
739
- }
740
-
741
- /**
742
- * Subscribe to error notifications
743
- * @param {Function} callback - Callback function
744
- */
745
- subscribe(callback) {
746
- this.errorSubscribers.add(callback);
747
- return () => this.errorSubscribers.delete(callback);
748
- }
749
-
750
- /**
751
- * Notify error subscribers
752
- * @param {Object} errorInfo - Error information
753
- * @param {Object} handlingResult - Handling result
754
- */
755
- notifySubscribers(errorInfo, handlingResult) {
756
- this.errorSubscribers.forEach(callback => {
757
- try {
758
- callback(errorInfo, handlingResult);
759
- } catch (callbackError) {
760
- this.logger.error('Error subscriber callback failed', {
761
- error: callbackError.message
762
- });
763
- }
764
- });
765
- }
766
-
767
- /**
768
- * Generate unique error ID
769
- * @returns {string} Error ID
770
- */
771
- generateErrorId() {
772
- return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
773
- }
774
-
775
- /**
776
- * Get error statistics
777
- * @returns {Object} Error statistics
778
- */
779
- getErrorStats() {
780
- return {
781
- totalErrors: this.errorStats.totalErrors,
782
- errorsByType: Object.fromEntries(this.errorStats.errorsByType),
783
- errorsByAgent: Object.fromEntries(this.errorStats.errorsByAgent),
784
- recoveryAttempts: this.errorStats.recoveryAttempts,
785
- successfulRecoveries: this.errorStats.successfulRecoveries,
786
- recoverySuccessRate: this.errorStats.recoveryAttempts > 0
787
- ? this.errorStats.successfulRecoveries / this.errorStats.recoveryAttempts
788
- : 0,
789
- criticalErrors: this.errorStats.criticalErrors,
790
- queueLength: this.errorQueue.length
791
- };
792
- }
793
-
794
- /**
795
- * Clear error statistics (for testing or reset)
796
- */
797
- clearErrorStats() {
798
- this.errorStats = {
799
- totalErrors: 0,
800
- errorsByType: new Map(),
801
- errorsByAgent: new Map(),
802
- recoveryAttempts: 0,
803
- successfulRecoveries: 0,
804
- criticalErrors: 0
805
- };
806
- this.errorQueue = [];
807
- }
808
- }
809
-
1
+ import { ERROR_TYPES, HTTP_STATUS } from '../utilities/constants.js';
2
+
3
+ /**
4
+ * Comprehensive error handling service for the Loxia AI Agents System
5
+ * Provides error classification, recovery strategies, and monitoring
6
+ */
7
+ export class ErrorHandler {
8
+ constructor(config, logger) {
9
+ this.config = config || {};
10
+ this.logger = logger;
11
+ this.errorStats = {
12
+ totalErrors: 0,
13
+ errorsByType: new Map(),
14
+ errorsByAgent: new Map(),
15
+ recoveryAttempts: 0,
16
+ successfulRecoveries: 0,
17
+ criticalErrors: 0
18
+ };
19
+
20
+ this.recoveryStrategies = new Map();
21
+ this.errorSubscribers = new Set();
22
+ this.errorQueue = [];
23
+ this.isProcessingQueue = false;
24
+
25
+ this.initializeRecoveryStrategies();
26
+ this.setupErrorProcessing();
27
+ }
28
+
29
+ /**
30
+ * Handle an error with appropriate classification and recovery
31
+ * @param {Error|Object} error - Error object or error data
32
+ * @param {Object} context - Error context information
33
+ * @returns {Object} Error handling result
34
+ */
35
+ async handleError(error, context = {}) {
36
+ try {
37
+ const errorInfo = this.classifyError(error, context);
38
+ const handlingResult = await this.processError(errorInfo);
39
+
40
+ this.updateErrorStats(errorInfo);
41
+ this.notifySubscribers(errorInfo, handlingResult);
42
+
43
+ return handlingResult;
44
+
45
+ } catch (handlingError) {
46
+ this.logger.error('Error handling failed', {
47
+ originalError: error.message,
48
+ handlingError: handlingError.message
49
+ });
50
+
51
+ return {
52
+ success: false,
53
+ error: handlingError,
54
+ recovery: null,
55
+ severity: 'critical'
56
+ };
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Classify error by type, severity, and context
62
+ * @param {Error|Object} error - Error to classify
63
+ * @param {Object} context - Error context
64
+ * @returns {Object} Classified error information
65
+ */
66
+ classifyError(error, context = {}) {
67
+ const errorInfo = {
68
+ id: this.generateErrorId(),
69
+ timestamp: new Date().toISOString(),
70
+ message: error.message || error.toString(),
71
+ stack: error.stack || null,
72
+ code: error.code || null,
73
+ type: this.determineErrorType(error, context),
74
+ severity: this.determineSeverity(error, context),
75
+ context: { ...context },
76
+ recoverable: true,
77
+ retryCount: context.retryCount || 0,
78
+ maxRetries: this.getMaxRetries(error, context)
79
+ };
80
+
81
+ // Additional classification based on context
82
+ if (context.agentId) {
83
+ errorInfo.agentId = context.agentId;
84
+ }
85
+
86
+ if (context.toolId) {
87
+ errorInfo.toolId = context.toolId;
88
+ }
89
+
90
+ if (context.operationId) {
91
+ errorInfo.operationId = context.operationId;
92
+ }
93
+
94
+ // Determine if error is recoverable
95
+ errorInfo.recoverable = this.isRecoverable(errorInfo);
96
+
97
+ return errorInfo;
98
+ }
99
+
100
+ /**
101
+ * Process error with appropriate recovery strategy
102
+ * @param {Object} errorInfo - Classified error information
103
+ * @returns {Object} Processing result
104
+ */
105
+ async processError(errorInfo) {
106
+ try {
107
+ this.logger.error('Processing error', {
108
+ errorId: errorInfo.id,
109
+ type: errorInfo.type,
110
+ severity: errorInfo.severity,
111
+ agentId: errorInfo.agentId,
112
+ message: errorInfo.message
113
+ });
114
+
115
+ // Check if this is a critical error requiring immediate attention
116
+ if (errorInfo.severity === 'critical') {
117
+ await this.handleCriticalError(errorInfo);
118
+ }
119
+
120
+ // Attempt recovery if error is recoverable
121
+ let recoveryResult = null;
122
+ if (errorInfo.recoverable && errorInfo.retryCount < errorInfo.maxRetries) {
123
+ recoveryResult = await this.attemptRecovery(errorInfo);
124
+ }
125
+
126
+ // Log error for monitoring and analysis
127
+ await this.logError(errorInfo, recoveryResult);
128
+
129
+ return {
130
+ success: recoveryResult?.success || false,
131
+ errorId: errorInfo.id,
132
+ errorType: errorInfo.type,
133
+ severity: errorInfo.severity,
134
+ recovery: recoveryResult,
135
+ shouldRetry: this.shouldRetry(errorInfo, recoveryResult),
136
+ retryDelay: this.calculateRetryDelay(errorInfo)
137
+ };
138
+
139
+ } catch (processingError) {
140
+ this.logger.error('Error processing failed', {
141
+ errorId: errorInfo.id,
142
+ processingError: processingError.message
143
+ });
144
+
145
+ return {
146
+ success: false,
147
+ errorId: errorInfo.id,
148
+ errorType: errorInfo.type,
149
+ severity: 'critical',
150
+ recovery: null,
151
+ shouldRetry: false
152
+ };
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Attempt to recover from an error using appropriate strategy
158
+ * @param {Object} errorInfo - Error information
159
+ * @returns {Object} Recovery result
160
+ */
161
+ async attemptRecovery(errorInfo) {
162
+ try {
163
+ this.errorStats.recoveryAttempts++;
164
+
165
+ const strategy = this.recoveryStrategies.get(errorInfo.type) ||
166
+ this.recoveryStrategies.get('default');
167
+
168
+ if (!strategy) {
169
+ this.logger.warn('No recovery strategy found', { errorType: errorInfo.type });
170
+ return { success: false, reason: 'No recovery strategy available' };
171
+ }
172
+
173
+ this.logger.info('Attempting error recovery', {
174
+ errorId: errorInfo.id,
175
+ errorType: errorInfo.type,
176
+ strategy: strategy.name,
177
+ retryCount: errorInfo.retryCount
178
+ });
179
+
180
+ const recoveryResult = await strategy.recover(errorInfo);
181
+
182
+ if (recoveryResult.success) {
183
+ this.errorStats.successfulRecoveries++;
184
+ this.logger.info('Error recovery successful', {
185
+ errorId: errorInfo.id,
186
+ strategy: strategy.name
187
+ });
188
+ } else {
189
+ this.logger.warn('Error recovery failed', {
190
+ errorId: errorInfo.id,
191
+ strategy: strategy.name,
192
+ reason: recoveryResult.reason
193
+ });
194
+ }
195
+
196
+ return recoveryResult;
197
+
198
+ } catch (recoveryError) {
199
+ this.logger.error('Recovery attempt failed', {
200
+ errorId: errorInfo.id,
201
+ recoveryError: recoveryError.message
202
+ });
203
+
204
+ return {
205
+ success: false,
206
+ reason: `Recovery attempt failed: ${recoveryError.message}`
207
+ };
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Handle critical errors that require immediate attention
213
+ * @param {Object} errorInfo - Critical error information
214
+ */
215
+ async handleCriticalError(errorInfo) {
216
+ try {
217
+ this.errorStats.criticalErrors++;
218
+
219
+ this.logger.error('Critical error detected', {
220
+ errorId: errorInfo.id,
221
+ message: errorInfo.message,
222
+ context: errorInfo.context
223
+ });
224
+
225
+ // Emit critical error event
226
+ if (typeof process !== 'undefined' && process.emit) {
227
+ process.emit('criticalError', errorInfo);
228
+ }
229
+
230
+ // Take immediate protective actions based on error type
231
+ switch (errorInfo.type) {
232
+ case ERROR_TYPES.AUTHENTICATION_FAILED:
233
+ await this.handleAuthenticationFailure(errorInfo);
234
+ break;
235
+
236
+ case ERROR_TYPES.RATE_LIMIT_EXCEEDED:
237
+ await this.handleRateLimitExceeded(errorInfo);
238
+ break;
239
+
240
+ case ERROR_TYPES.OPERATION_TIMEOUT:
241
+ await this.handleOperationTimeout(errorInfo);
242
+ break;
243
+
244
+ default:
245
+ await this.handleGenericCriticalError(errorInfo);
246
+ }
247
+
248
+ } catch (criticalHandlingError) {
249
+ this.logger.error('Critical error handling failed', {
250
+ errorId: errorInfo.id,
251
+ handlingError: criticalHandlingError.message
252
+ });
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Determine error type based on error and context
258
+ * @param {Error|Object} error - Error object
259
+ * @param {Object} context - Error context
260
+ * @returns {string} Error type
261
+ */
262
+ determineErrorType(error, context) {
263
+ // Check error code or HTTP status
264
+ if (error.code === 'ENOENT' || error.status === HTTP_STATUS.NOT_FOUND) {
265
+ return ERROR_TYPES.FILE_NOT_FOUND;
266
+ }
267
+
268
+ if (error.code === 'EACCES' || error.status === HTTP_STATUS.FORBIDDEN) {
269
+ return ERROR_TYPES.PERMISSION_DENIED;
270
+ }
271
+
272
+ if (error.status === HTTP_STATUS.UNAUTHORIZED) {
273
+ return ERROR_TYPES.AUTHENTICATION_FAILED;
274
+ }
275
+
276
+ if (error.status === HTTP_STATUS.TOO_MANY_REQUESTS) {
277
+ return ERROR_TYPES.RATE_LIMIT_EXCEEDED;
278
+ }
279
+
280
+ // Check error message patterns
281
+ const message = error.message?.toLowerCase() || '';
282
+
283
+ if (message.includes('timeout') || message.includes('timed out')) {
284
+ return ERROR_TYPES.OPERATION_TIMEOUT;
285
+ }
286
+
287
+ if (message.includes('validation') || message.includes('invalid')) {
288
+ return ERROR_TYPES.VALIDATION_ERROR;
289
+ }
290
+
291
+ if (message.includes('config') || message.includes('configuration')) {
292
+ return ERROR_TYPES.CONFIGURATION_ERROR;
293
+ }
294
+
295
+ // Check context for additional clues
296
+ if (context.operation === 'file_operation') {
297
+ return ERROR_TYPES.FILE_NOT_FOUND;
298
+ }
299
+
300
+ if (context.operation === 'api_request') {
301
+ return ERROR_TYPES.RATE_LIMIT_EXCEEDED;
302
+ }
303
+
304
+ return ERROR_TYPES.UNKNOWN_ERROR;
305
+ }
306
+
307
+ /**
308
+ * Determine error severity
309
+ * @param {Error|Object} error - Error object
310
+ * @param {Object} context - Error context
311
+ * @returns {string} Error severity
312
+ */
313
+ determineSeverity(error, context) {
314
+ const criticalTypes = [
315
+ ERROR_TYPES.AUTHENTICATION_FAILED,
316
+ ERROR_TYPES.CONFIGURATION_ERROR
317
+ ];
318
+
319
+ const highTypes = [
320
+ ERROR_TYPES.RATE_LIMIT_EXCEEDED,
321
+ ERROR_TYPES.OPERATION_TIMEOUT,
322
+ ERROR_TYPES.PERMISSION_DENIED
323
+ ];
324
+
325
+ const errorType = this.determineErrorType(error, context);
326
+
327
+ if (criticalTypes.includes(errorType)) {
328
+ return 'critical';
329
+ }
330
+
331
+ if (highTypes.includes(errorType)) {
332
+ return 'high';
333
+ }
334
+
335
+ // Check retry count
336
+ const retryCount = (context && context.retryCount) || 0;
337
+ if (retryCount >= 3) {
338
+ return 'high';
339
+ }
340
+
341
+ // Check if error is affecting agent operation
342
+ if (context && context.agentId && context.operation === 'agent_communication') {
343
+ return 'medium';
344
+ }
345
+
346
+ return 'low';
347
+ }
348
+
349
+ /**
350
+ * Check if error is recoverable
351
+ * @param {Object} errorInfo - Error information
352
+ * @returns {boolean} True if recoverable
353
+ */
354
+ isRecoverable(errorInfo) {
355
+ const nonRecoverableTypes = [
356
+ ERROR_TYPES.AUTHENTICATION_FAILED,
357
+ ERROR_TYPES.CONFIGURATION_ERROR
358
+ ];
359
+
360
+ if (nonRecoverableTypes.includes(errorInfo.type)) {
361
+ return false;
362
+ }
363
+
364
+ // Not recoverable if max retries exceeded
365
+ if (errorInfo.retryCount >= errorInfo.maxRetries) {
366
+ return false;
367
+ }
368
+
369
+ // Not recoverable if critical severity
370
+ if (errorInfo.severity === 'critical') {
371
+ return false;
372
+ }
373
+
374
+ return true;
375
+ }
376
+
377
+ /**
378
+ * Get maximum retry attempts for error type
379
+ * @param {Error|Object} error - Error object
380
+ * @param {Object} context - Error context
381
+ * @returns {number} Maximum retries
382
+ */
383
+ getMaxRetries(error, context) {
384
+ const errorType = this.determineErrorType(error, context);
385
+
386
+ const retryLimits = {
387
+ [ERROR_TYPES.RATE_LIMIT_EXCEEDED]: 5,
388
+ [ERROR_TYPES.OPERATION_TIMEOUT]: 3,
389
+ [ERROR_TYPES.FILE_NOT_FOUND]: 2,
390
+ [ERROR_TYPES.PERMISSION_DENIED]: 1,
391
+ [ERROR_TYPES.VALIDATION_ERROR]: 2,
392
+ [ERROR_TYPES.UNKNOWN_ERROR]: 3
393
+ };
394
+
395
+ return retryLimits[errorType] || 3;
396
+ }
397
+
398
+ /**
399
+ * Determine if error should be retried
400
+ * @param {Object} errorInfo - Error information
401
+ * @param {Object} recoveryResult - Recovery result
402
+ * @returns {boolean} True if should retry
403
+ */
404
+ shouldRetry(errorInfo, recoveryResult) {
405
+ if (!errorInfo.recoverable) {
406
+ return false;
407
+ }
408
+
409
+ if (errorInfo.retryCount >= errorInfo.maxRetries) {
410
+ return false;
411
+ }
412
+
413
+ if (recoveryResult && recoveryResult.success) {
414
+ return false; // Recovery succeeded, no need to retry
415
+ }
416
+
417
+ return true;
418
+ }
419
+
420
+ /**
421
+ * Calculate retry delay based on error information
422
+ * @param {Object} errorInfo - Error information
423
+ * @returns {number} Delay in milliseconds
424
+ */
425
+ calculateRetryDelay(errorInfo) {
426
+ const baseDelay = 1000; // 1 second
427
+ const maxDelay = 30000; // 30 seconds
428
+
429
+ // Exponential backoff with jitter
430
+ const exponentialDelay = baseDelay * Math.pow(2, errorInfo.retryCount);
431
+ const jitter = Math.random() * 1000; // Random jitter up to 1 second
432
+
433
+ return Math.min(exponentialDelay + jitter, maxDelay);
434
+ }
435
+
436
+ /**
437
+ * Initialize recovery strategies for different error types
438
+ */
439
+ initializeRecoveryStrategies() {
440
+ // File not found recovery
441
+ this.recoveryStrategies.set(ERROR_TYPES.FILE_NOT_FOUND, {
442
+ name: 'file_not_found_recovery',
443
+ recover: async (errorInfo) => {
444
+ if (errorInfo.context.filePath) {
445
+ // Try to check if file exists in different location
446
+ // or create directory structure if needed
447
+ return {
448
+ success: false,
449
+ reason: 'File recovery not implemented yet',
450
+ suggestion: 'Check file path and permissions'
451
+ };
452
+ }
453
+ return { success: false, reason: 'No file path provided' };
454
+ }
455
+ });
456
+
457
+ // Rate limit recovery
458
+ this.recoveryStrategies.set(ERROR_TYPES.RATE_LIMIT_EXCEEDED, {
459
+ name: 'rate_limit_recovery',
460
+ recover: async (errorInfo) => {
461
+ const waitTime = this.calculateRateLimitWait(errorInfo);
462
+ this.logger.info('Waiting for rate limit recovery', { waitTime });
463
+
464
+ await new Promise(resolve => setTimeout(resolve, waitTime));
465
+
466
+ return {
467
+ success: true,
468
+ action: 'waited_for_rate_limit',
469
+ waitTime
470
+ };
471
+ }
472
+ });
473
+
474
+ // Operation timeout recovery
475
+ this.recoveryStrategies.set(ERROR_TYPES.OPERATION_TIMEOUT, {
476
+ name: 'timeout_recovery',
477
+ recover: async (errorInfo) => {
478
+ // Try to increase timeout for next attempt
479
+ if (errorInfo.context.timeout) {
480
+ const newTimeout = Math.min(errorInfo.context.timeout * 1.5, 300000); // Max 5 minutes
481
+ return {
482
+ success: true,
483
+ action: 'increased_timeout',
484
+ newTimeout
485
+ };
486
+ }
487
+
488
+ return { success: false, reason: 'Cannot adjust timeout' };
489
+ }
490
+ });
491
+
492
+ // Permission denied recovery
493
+ this.recoveryStrategies.set(ERROR_TYPES.PERMISSION_DENIED, {
494
+ name: 'permission_recovery',
495
+ recover: async () => {
496
+ return {
497
+ success: false,
498
+ reason: 'Permission errors require manual intervention',
499
+ suggestion: 'Check file/directory permissions'
500
+ };
501
+ }
502
+ });
503
+
504
+ // Validation error recovery
505
+ this.recoveryStrategies.set(ERROR_TYPES.VALIDATION_ERROR, {
506
+ name: 'validation_recovery',
507
+ recover: async (errorInfo) => {
508
+ // Try to clean/sanitize input data
509
+ if (errorInfo.context.inputData) {
510
+ return {
511
+ success: true,
512
+ action: 'data_sanitization',
513
+ suggestion: 'Input data was sanitized for retry'
514
+ };
515
+ }
516
+
517
+ return { success: false, reason: 'No input data to sanitize' };
518
+ }
519
+ });
520
+
521
+ // Default recovery strategy
522
+ this.recoveryStrategies.set('default', {
523
+ name: 'default_recovery',
524
+ recover: async (errorInfo) => {
525
+ // Generic recovery: wait and retry
526
+ const delay = this.calculateRetryDelay(errorInfo);
527
+ await new Promise(resolve => setTimeout(resolve, delay));
528
+
529
+ return {
530
+ success: true,
531
+ action: 'delay_retry',
532
+ delay
533
+ };
534
+ }
535
+ });
536
+ }
537
+
538
+ /**
539
+ * Handle authentication failure
540
+ * @param {Object} errorInfo - Error information
541
+ */
542
+ async handleAuthenticationFailure(errorInfo) {
543
+ this.logger.error('Authentication failure detected', { errorId: errorInfo.id });
544
+
545
+ // Could trigger token refresh, re-authentication, etc.
546
+ if (errorInfo.agentId) {
547
+ // Pause agent until authentication is resolved
548
+ // await this.orchestrator.pauseAgent(errorInfo.agentId, 300, 'Authentication failure');
549
+ }
550
+ }
551
+
552
+ /**
553
+ * Handle rate limit exceeded
554
+ * @param {Object} errorInfo - Error information
555
+ */
556
+ async handleRateLimitExceeded(errorInfo) {
557
+ const waitTime = this.calculateRateLimitWait(errorInfo);
558
+
559
+ this.logger.warn('Rate limit exceeded, implementing backoff', {
560
+ errorId: errorInfo.id,
561
+ waitTime,
562
+ agentId: errorInfo.agentId
563
+ });
564
+
565
+ if (errorInfo.agentId) {
566
+ // Pause agent temporarily
567
+ // await this.orchestrator.pauseAgent(errorInfo.agentId, waitTime / 1000, 'Rate limit exceeded');
568
+ }
569
+ }
570
+
571
+ /**
572
+ * Handle operation timeout
573
+ * @param {Object} errorInfo - Error information
574
+ */
575
+ async handleOperationTimeout(errorInfo) {
576
+ this.logger.error('Operation timeout detected', {
577
+ errorId: errorInfo.id,
578
+ operation: errorInfo.context.operation,
579
+ timeout: errorInfo.context.timeout
580
+ });
581
+
582
+ // Could cancel ongoing operations, adjust timeouts, etc.
583
+ }
584
+
585
+ /**
586
+ * Handle generic critical error
587
+ * @param {Object} errorInfo - Error information
588
+ */
589
+ async handleGenericCriticalError(errorInfo) {
590
+ this.logger.error('Generic critical error', {
591
+ errorId: errorInfo.id,
592
+ type: errorInfo.type,
593
+ message: errorInfo.message
594
+ });
595
+
596
+ // Generic protective measures
597
+ if (errorInfo.agentId) {
598
+ // Could pause agent for safety
599
+ this.logger.warn('Considering agent pause due to critical error', {
600
+ agentId: errorInfo.agentId
601
+ });
602
+ }
603
+ }
604
+
605
+ /**
606
+ * Calculate wait time for rate limit recovery
607
+ * @param {Object} errorInfo - Error information
608
+ * @returns {number} Wait time in milliseconds
609
+ */
610
+ calculateRateLimitWait(errorInfo) {
611
+ const baseWait = 60000; // 1 minute
612
+ const retryMultiplier = Math.pow(2, errorInfo.retryCount);
613
+ const maxWait = 300000; // 5 minutes
614
+
615
+ return Math.min(baseWait * retryMultiplier, maxWait);
616
+ }
617
+
618
+ /**
619
+ * Log error for monitoring and analysis
620
+ * @param {Object} errorInfo - Error information
621
+ * @param {Object} recoveryResult - Recovery result
622
+ */
623
+ async logError(errorInfo, recoveryResult) {
624
+ try {
625
+ const logEntry = {
626
+ errorId: errorInfo.id,
627
+ timestamp: errorInfo.timestamp,
628
+ type: errorInfo.type,
629
+ severity: errorInfo.severity,
630
+ message: errorInfo.message,
631
+ agentId: errorInfo.agentId,
632
+ toolId: errorInfo.toolId,
633
+ operationId: errorInfo.operationId,
634
+ retryCount: errorInfo.retryCount,
635
+ recoveryAttempted: !!recoveryResult,
636
+ recoverySuccess: recoveryResult?.success || false,
637
+ recoveryAction: recoveryResult?.action || null
638
+ };
639
+
640
+ // Store in error queue for batch processing
641
+ this.errorQueue.push(logEntry);
642
+
643
+ // Process queue if not already processing
644
+ if (!this.isProcessingQueue) {
645
+ this.processErrorQueue();
646
+ }
647
+
648
+ } catch (loggingError) {
649
+ this.logger.error('Error logging failed', {
650
+ errorId: errorInfo.id,
651
+ loggingError: loggingError.message
652
+ });
653
+ }
654
+ }
655
+
656
+ /**
657
+ * Process error queue for batch operations
658
+ */
659
+ async processErrorQueue() {
660
+ if (this.isProcessingQueue || this.errorQueue.length === 0) {
661
+ return;
662
+ }
663
+
664
+ this.isProcessingQueue = true;
665
+
666
+ try {
667
+ while (this.errorQueue.length > 0) {
668
+ const batch = this.errorQueue.splice(0, 10); // Process 10 at a time
669
+
670
+ // Here you would typically save to database, send to monitoring service, etc.
671
+ this.logger.debug('Processing error batch', { batchSize: batch.length });
672
+
673
+ // Simulate async processing
674
+ await new Promise(resolve => setTimeout(resolve, 100));
675
+ }
676
+ } catch (processingError) {
677
+ this.logger.error('Error queue processing failed', { error: processingError.message });
678
+ } finally {
679
+ this.isProcessingQueue = false;
680
+ }
681
+ }
682
+
683
+ /**
684
+ * Setup error processing infrastructure
685
+ */
686
+ setupErrorProcessing() {
687
+ // Setup periodic queue processing
688
+ setInterval(() => {
689
+ if (this.errorQueue.length > 0) {
690
+ this.processErrorQueue();
691
+ }
692
+ }, 5000); // Process every 5 seconds
693
+
694
+ // Setup global error handlers
695
+ if (typeof process !== 'undefined') {
696
+ process.on('uncaughtException', (error) => {
697
+ this.handleError(error, {
698
+ type: 'uncaught_exception',
699
+ severity: 'critical'
700
+ });
701
+ });
702
+
703
+ process.on('unhandledRejection', (reason, promise) => {
704
+ this.handleError(new Error(`Unhandled Rejection: ${reason}`), {
705
+ type: 'unhandled_rejection',
706
+ severity: 'high',
707
+ promise: promise.toString()
708
+ });
709
+ });
710
+ }
711
+ }
712
+
713
+ /**
714
+ * Update error statistics
715
+ * @param {Object} errorInfo - Error information
716
+ */
717
+ updateErrorStats(errorInfo) {
718
+ this.errorStats.totalErrors++;
719
+
720
+ // Update error type statistics
721
+ if (!this.errorStats.errorsByType.has(errorInfo.type)) {
722
+ this.errorStats.errorsByType.set(errorInfo.type, 0);
723
+ }
724
+ this.errorStats.errorsByType.set(
725
+ errorInfo.type,
726
+ this.errorStats.errorsByType.get(errorInfo.type) + 1
727
+ );
728
+
729
+ // Update agent error statistics
730
+ if (errorInfo.agentId) {
731
+ if (!this.errorStats.errorsByAgent.has(errorInfo.agentId)) {
732
+ this.errorStats.errorsByAgent.set(errorInfo.agentId, 0);
733
+ }
734
+ this.errorStats.errorsByAgent.set(
735
+ errorInfo.agentId,
736
+ this.errorStats.errorsByAgent.get(errorInfo.agentId) + 1
737
+ );
738
+ }
739
+ }
740
+
741
+ /**
742
+ * Subscribe to error notifications
743
+ * @param {Function} callback - Callback function
744
+ */
745
+ subscribe(callback) {
746
+ this.errorSubscribers.add(callback);
747
+ return () => this.errorSubscribers.delete(callback);
748
+ }
749
+
750
+ /**
751
+ * Notify error subscribers
752
+ * @param {Object} errorInfo - Error information
753
+ * @param {Object} handlingResult - Handling result
754
+ */
755
+ notifySubscribers(errorInfo, handlingResult) {
756
+ this.errorSubscribers.forEach(callback => {
757
+ try {
758
+ callback(errorInfo, handlingResult);
759
+ } catch (callbackError) {
760
+ this.logger.error('Error subscriber callback failed', {
761
+ error: callbackError.message
762
+ });
763
+ }
764
+ });
765
+ }
766
+
767
+ /**
768
+ * Generate unique error ID
769
+ * @returns {string} Error ID
770
+ */
771
+ generateErrorId() {
772
+ return `err_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
773
+ }
774
+
775
+ /**
776
+ * Get error statistics
777
+ * @returns {Object} Error statistics
778
+ */
779
+ getErrorStats() {
780
+ return {
781
+ totalErrors: this.errorStats.totalErrors,
782
+ errorsByType: Object.fromEntries(this.errorStats.errorsByType),
783
+ errorsByAgent: Object.fromEntries(this.errorStats.errorsByAgent),
784
+ recoveryAttempts: this.errorStats.recoveryAttempts,
785
+ successfulRecoveries: this.errorStats.successfulRecoveries,
786
+ recoverySuccessRate: this.errorStats.recoveryAttempts > 0
787
+ ? this.errorStats.successfulRecoveries / this.errorStats.recoveryAttempts
788
+ : 0,
789
+ criticalErrors: this.errorStats.criticalErrors,
790
+ queueLength: this.errorQueue.length
791
+ };
792
+ }
793
+
794
+ /**
795
+ * Clear error statistics (for testing or reset)
796
+ */
797
+ clearErrorStats() {
798
+ this.errorStats = {
799
+ totalErrors: 0,
800
+ errorsByType: new Map(),
801
+ errorsByAgent: new Map(),
802
+ recoveryAttempts: 0,
803
+ successfulRecoveries: 0,
804
+ criticalErrors: 0
805
+ };
806
+ this.errorQueue = [];
807
+ }
808
+ }
809
+
810
810
  export default ErrorHandler;