snow-flow 3.0.9 → 3.0.10

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 (294) hide show
  1. package/claude-flow.bat +0 -0
  2. package/claude-flow.ps1 +0 -0
  3. package/dist/mcp/servicenow-automation-mcp.js +0 -0
  4. package/dist/mcp/servicenow-deployment-mcp.js +0 -0
  5. package/dist/mcp/servicenow-integration-mcp.js +0 -0
  6. package/dist/mcp/servicenow-mcp-server.js +0 -0
  7. package/dist/mcp/servicenow-operations-mcp.js +0 -0
  8. package/dist/mcp/servicenow-platform-development-mcp.js +0 -0
  9. package/dist/mcp/servicenow-progressive-indexer.js +0 -0
  10. package/dist/mcp/servicenow-reporting-analytics-mcp.js +133 -19
  11. package/dist/mcp/servicenow-security-compliance-mcp.js +0 -0
  12. package/dist/mcp/servicenow-update-set-mcp.js +0 -0
  13. package/dist/mcp/start-all-mcp-servers.js +0 -0
  14. package/dist/mcp/start-servicenow-mcp.js +0 -0
  15. package/memory/agents/README.md +1 -1
  16. package/memory/claude-flow-data.json +1 -1
  17. package/memory/sessions/README.md +1 -1
  18. package/package.json +2 -2
  19. package/.mcp.json +0 -22
  20. package/claude-flow.config.json +0 -20
  21. package/dist/agents/app-creator.agent.d.ts +0 -55
  22. package/dist/agents/app-creator.agent.js +0 -1292
  23. package/dist/agents/base/base-snow-agent.d.ts +0 -75
  24. package/dist/agents/base/base-snow-agent.js +0 -169
  25. package/dist/agents/base-snow-agent.d.ts +0 -63
  26. package/dist/agents/base-snow-agent.js +0 -296
  27. package/dist/agents/coordinator.d.ts +0 -200
  28. package/dist/agents/coordinator.js +0 -777
  29. package/dist/agents/flow-builder-agent.d.ts +0 -18
  30. package/dist/agents/flow-builder-agent.js +0 -197
  31. package/dist/agents/queen-403-handler.d.ts +0 -47
  32. package/dist/agents/queen-403-handler.js +0 -175
  33. package/dist/agents/queen-agent-example.d.ts +0 -23
  34. package/dist/agents/queen-agent-example.js +0 -240
  35. package/dist/agents/queen-agent.test.d.ts +0 -6
  36. package/dist/agents/script-generator.agent.d.ts +0 -32
  37. package/dist/agents/script-generator.agent.js +0 -772
  38. package/dist/agents/script-writer-agent.d.ts +0 -22
  39. package/dist/agents/script-writer-agent.js +0 -695
  40. package/dist/agents/security-agent.d.ts +0 -23
  41. package/dist/agents/security-agent.js +0 -619
  42. package/dist/agents/specialists/automation-specialist.agent.d.ts +0 -44
  43. package/dist/agents/specialists/automation-specialist.agent.js +0 -204
  44. package/dist/agents/specialists/data-specialist.agent.d.ts +0 -165
  45. package/dist/agents/specialists/data-specialist.agent.js +0 -484
  46. package/dist/agents/specialists/integration-specialist.agent.d.ts +0 -227
  47. package/dist/agents/specialists/integration-specialist.agent.js +0 -725
  48. package/dist/agents/specialists/reporting-specialist.agent.d.ts +0 -54
  49. package/dist/agents/specialists/reporting-specialist.agent.js +0 -193
  50. package/dist/agents/specialists/security-specialist.agent.d.ts +0 -85
  51. package/dist/agents/specialists/security-specialist.agent.js +0 -309
  52. package/dist/agents/teams/adaptive/adaptive-coordinator.agent.d.ts +0 -111
  53. package/dist/agents/teams/adaptive/adaptive-coordinator.agent.js +0 -383
  54. package/dist/agents/teams/base-team.d.ts +0 -72
  55. package/dist/agents/teams/base-team.js +0 -253
  56. package/dist/agents/teams/team-types.d.ts +0 -265
  57. package/dist/agents/teams/team-types.js +0 -3
  58. package/dist/agents/teams/widget/widget-architect.agent.d.ts +0 -61
  59. package/dist/agents/teams/widget/widget-architect.agent.js +0 -436
  60. package/dist/agents/teams/widget/widget-backend.agent.d.ts +0 -74
  61. package/dist/agents/teams/widget/widget-backend.agent.js +0 -1531
  62. package/dist/agents/teams/widget/widget-frontend.agent.d.ts +0 -67
  63. package/dist/agents/teams/widget/widget-frontend.agent.js +0 -1014
  64. package/dist/agents/teams/widget/widget-platform.agent.d.ts +0 -90
  65. package/dist/agents/teams/widget/widget-platform.agent.js +0 -1190
  66. package/dist/agents/teams/widget/widget-uiux.agent.d.ts +0 -107
  67. package/dist/agents/teams/widget/widget-uiux.agent.js +0 -1033
  68. package/dist/agents/test-agent.d.ts +0 -26
  69. package/dist/agents/test-agent.js +0 -734
  70. package/dist/agents/test-agents.d.ts +0 -7
  71. package/dist/agents/test-agents.js +0 -64
  72. package/dist/agents/ui-builder.agent.d.ts +0 -50
  73. package/dist/agents/ui-builder.agent.js +0 -1539
  74. package/dist/agents/widget-builder.agent.d.ts +0 -32
  75. package/dist/agents/widget-builder.agent.js +0 -439
  76. package/dist/agents/widget-creator-agent.d.ts +0 -18
  77. package/dist/agents/widget-creator-agent.js +0 -498
  78. package/dist/agents/workflow-designer.agent.d.ts +0 -31
  79. package/dist/agents/workflow-designer.agent.js +0 -583
  80. package/dist/api/error-handling.d.ts +0 -325
  81. package/dist/api/error-handling.js +0 -1488
  82. package/dist/api/flow-designer-api.d.ts +0 -167
  83. package/dist/api/flow-designer-api.js +0 -554
  84. package/dist/api/natural-language-mapper.d.ts +0 -124
  85. package/dist/api/natural-language-mapper.js +0 -501
  86. package/dist/api/performance-optimizer.d.ts +0 -240
  87. package/dist/api/performance-optimizer.js +0 -706
  88. package/dist/api/transaction-manager.d.ts +0 -189
  89. package/dist/api/transaction-manager.js +0 -576
  90. package/dist/assembly/team-assembler.d.ts +0 -140
  91. package/dist/assembly/team-assembler.js +0 -502
  92. package/dist/benchmark-performance.d.ts +0 -41
  93. package/dist/benchmark-performance.js +0 -230
  94. package/dist/cli/snow-flow-cli-integration.d.ts +0 -30
  95. package/dist/cli/snow-flow-cli-integration.js +0 -396
  96. package/dist/coordination/coordination-engine.d.ts +0 -41
  97. package/dist/coordination/coordination-engine.js +0 -324
  98. package/dist/coordination/coordination.test.d.ts +0 -6
  99. package/dist/coordination/example.d.ts +0 -31
  100. package/dist/coordination/example.js +0 -394
  101. package/dist/coordination/execution-patterns.d.ts +0 -43
  102. package/dist/coordination/execution-patterns.js +0 -507
  103. package/dist/coordination/factory.d.ts +0 -94
  104. package/dist/coordination/factory.js +0 -433
  105. package/dist/coordination/index.d.ts +0 -71
  106. package/dist/coordination/index.js +0 -135
  107. package/dist/coordination/progress-monitor.d.ts +0 -71
  108. package/dist/coordination/progress-monitor.js +0 -505
  109. package/dist/coordination/quality-gates.d.ts +0 -124
  110. package/dist/coordination/quality-gates.js +0 -577
  111. package/dist/coordination/shared-memory.d.ts +0 -39
  112. package/dist/coordination/shared-memory.js +0 -289
  113. package/dist/coordination/task-dependencies.d.ts +0 -50
  114. package/dist/coordination/task-dependencies.js +0 -407
  115. package/dist/coordination/team-coordinator.d.ts +0 -59
  116. package/dist/coordination/team-coordinator.js +0 -550
  117. package/dist/coordination/types.d.ts +0 -152
  118. package/dist/coordination/types.js +0 -3
  119. package/dist/mcp/mcp-wrapper.d.ts +0 -8
  120. package/dist/mcp/mcp-wrapper.js +0 -77
  121. package/dist/mcp/servicenow-flow-composer-enhanced.js +0 -396
  122. package/dist/mcp/servicenow-flow-composer-mcp.d.ts +0 -7
  123. package/dist/mcp/servicenow-flow-composer-mcp.js +0 -3103
  124. package/dist/mcp/servicenow-graph-memory-mcp.d.ts +0 -7
  125. package/dist/mcp/servicenow-intelligent-mcp.d.ts +0 -143
  126. package/dist/mcp/servicenow-intelligent-mcp.js +0 -4156
  127. package/dist/mcp/servicenow-xml-flow-mcp.d.ts +0 -53
  128. package/dist/mcp/servicenow-xml-flow-mcp.js +0 -1704
  129. package/dist/mcp/singleton-check.js +0 -31
  130. package/dist/mcp/test-simple-mcp.d.ts +0 -6
  131. package/dist/mcp/test-simple-mcp.js +0 -63
  132. package/dist/memory/hierarchical-memory-system.d.ts +0 -90
  133. package/dist/memory/hierarchical-memory-system.js +0 -400
  134. package/dist/memory/index.d.ts +0 -9
  135. package/dist/memory/index.js +0 -20
  136. package/dist/memory/mcp-integration-example.d.ts +0 -6
  137. package/dist/memory/mcp-integration-example.js +0 -281
  138. package/dist/memory/memory-client.d.ts +0 -199
  139. package/dist/memory/memory-client.js +0 -364
  140. package/dist/memory/memory-manager.d.ts +0 -29
  141. package/dist/memory/memory-manager.js +0 -280
  142. package/dist/memory/memory-operations.d.ts +0 -179
  143. package/dist/memory/memory-operations.js +0 -691
  144. package/dist/memory/memory-system.d.ts +0 -153
  145. package/dist/memory/memory-system.js +0 -651
  146. package/dist/memory/memory-test.d.ts +0 -6
  147. package/dist/memory/memory-test.js +0 -161
  148. package/dist/memory/snow-flow-memory-patterns.d.ts +0 -213
  149. package/dist/memory/snow-flow-memory-patterns.js +0 -200
  150. package/dist/memory/snow-memory.d.ts +0 -54
  151. package/dist/memory/snow-memory.js +0 -301
  152. package/dist/memory/swarm-memory.d.ts +0 -135
  153. package/dist/memory/swarm-memory.js +0 -378
  154. package/dist/optimization/flow-performance-optimizer.js +0 -723
  155. package/dist/orchestration/discovery/service-discovery.d.ts +0 -81
  156. package/dist/orchestration/discovery/service-discovery.js +0 -808
  157. package/dist/orchestration/distributed-orchestrator.d.ts +0 -131
  158. package/dist/orchestration/distributed-orchestrator.js +0 -712
  159. package/dist/orchestration/distribution/task-distribution-engine.d.ts +0 -53
  160. package/dist/orchestration/distribution/task-distribution-engine.js +0 -586
  161. package/dist/orchestration/flow-update-orchestrator.js +0 -648
  162. package/dist/orchestration/interfaces/distributed-orchestration.interface.d.ts +0 -606
  163. package/dist/orchestration/interfaces/distributed-orchestration.interface.js +0 -65
  164. package/dist/orchestration/protocols/mcpx-protocol.d.ts +0 -71
  165. package/dist/orchestration/protocols/mcpx-protocol.js +0 -668
  166. package/dist/orchestration/state/distributed-state-manager.d.ts +0 -89
  167. package/dist/orchestration/state/distributed-state-manager.js +0 -716
  168. package/dist/orchestrator/flow-composer.d.ts +0 -105
  169. package/dist/orchestrator/flow-composer.js +0 -404
  170. package/dist/orchestrator/flow-pattern-templates.d.ts +0 -260
  171. package/dist/orchestrator/flow-pattern-templates.js +0 -908
  172. package/dist/orchestrator/flow-subflow-decision-engine.d.ts +0 -202
  173. package/dist/orchestrator/flow-subflow-decision-engine.js +0 -769
  174. package/dist/orchestrator/flow-validation-engine.d.ts +0 -169
  175. package/dist/orchestrator/flow-validation-engine.js +0 -913
  176. package/dist/orchestrator/snow-orchestrator.d.ts +0 -49
  177. package/dist/orchestrator/snow-orchestrator.js +0 -235
  178. package/dist/orchestrator/subflow-creation-handler.d.ts +0 -230
  179. package/dist/orchestrator/subflow-creation-handler.js +0 -791
  180. package/dist/patterns/adaptive-patterns.d.ts +0 -140
  181. package/dist/patterns/adaptive-patterns.js +0 -549
  182. package/dist/queen/advanced-integration-test.d.ts +0 -48
  183. package/dist/queen/advanced-integration-test.js +0 -473
  184. package/dist/queen/integration-example.d.ts +0 -82
  185. package/dist/queen/integration-example.js +0 -219
  186. package/dist/queen/integration-test.d.ts +0 -72
  187. package/dist/queen/integration-test.js +0 -563
  188. package/dist/queen/mock-mcp-client.d.ts +0 -71
  189. package/dist/queen/mock-mcp-client.js +0 -317
  190. package/dist/queen/run-integration-tests.d.ts +0 -9
  191. package/dist/queen/run-integration-tests.js +0 -27
  192. package/dist/sparc/coordinators/adaptive-coordinator.d.ts +0 -54
  193. package/dist/sparc/coordinators/adaptive-coordinator.js +0 -367
  194. package/dist/sparc/coordinators/team-coordinator.d.ts +0 -66
  195. package/dist/sparc/coordinators/team-coordinator.js +0 -402
  196. package/dist/sparc/modes/team-modes.d.ts +0 -33
  197. package/dist/sparc/modes/team-modes.js +0 -399
  198. package/dist/sparc/teams/application-team.d.ts +0 -73
  199. package/dist/sparc/teams/application-team.js +0 -463
  200. package/dist/sparc/teams/flow-team.d.ts +0 -67
  201. package/dist/sparc/teams/flow-team.js +0 -373
  202. package/dist/sparc/teams/widget-team.d.ts +0 -61
  203. package/dist/sparc/teams/widget-team.js +0 -280
  204. package/dist/specialists/app-specialists.d.ts +0 -93
  205. package/dist/specialists/app-specialists.js +0 -1639
  206. package/dist/specialists/base-specialist.d.ts +0 -19
  207. package/dist/specialists/base-specialist.js +0 -54
  208. package/dist/specialists/flow-specialists.d.ts +0 -113
  209. package/dist/specialists/flow-specialists.js +0 -1787
  210. package/dist/specialists/individual-specialists.d.ts +0 -67
  211. package/dist/specialists/individual-specialists.js +0 -632
  212. package/dist/specialists/widget-specialists.d.ts +0 -70
  213. package/dist/specialists/widget-specialists.js +0 -1264
  214. package/dist/src/utils/agent-detector.js +0 -655
  215. package/dist/teams/adaptive-team.d.ts +0 -81
  216. package/dist/teams/adaptive-team.js +0 -1153
  217. package/dist/teams/application-team.d.ts +0 -30
  218. package/dist/teams/application-team.js +0 -547
  219. package/dist/teams/base-team.d.ts +0 -55
  220. package/dist/teams/base-team.js +0 -243
  221. package/dist/teams/flow-team.d.ts +0 -28
  222. package/dist/teams/flow-team.js +0 -525
  223. package/dist/teams/widget-team.d.ts +0 -26
  224. package/dist/teams/widget-team.js +0 -459
  225. package/dist/templates/flow-template-system.js +0 -625
  226. package/dist/test-fetch-incidents.d.ts +0 -2
  227. package/dist/test-fetch-incidents.js +0 -84
  228. package/dist/test-incident-access.d.ts +0 -2
  229. package/dist/test-incident-access.js +0 -72
  230. package/dist/test-iphone-flow.js +0 -189
  231. package/dist/test-limit-problem.d.ts +0 -2
  232. package/dist/test-limit-problem.js +0 -60
  233. package/dist/test-ml-batch-fix.d.ts +0 -2
  234. package/dist/test-ml-batch-fix.js +0 -104
  235. package/dist/test-ml-batch.d.ts +0 -2
  236. package/dist/test-ml-batch.js +0 -87
  237. package/dist/test-ml-query.d.ts +0 -2
  238. package/dist/test-ml-query.js +0 -100
  239. package/dist/test-ml-training-fix.d.ts +0 -12
  240. package/dist/test-ml-training-fix.js +0 -113
  241. package/dist/test-ml-training.d.ts +0 -2
  242. package/dist/test-ml-training.js +0 -32
  243. package/dist/test-operations-query.d.ts +0 -2
  244. package/dist/test-operations-query.js +0 -84
  245. package/dist/test-performance-query.d.ts +0 -2
  246. package/dist/test-performance-query.js +0 -52
  247. package/dist/test-singleton-protection.d.ts +0 -8
  248. package/dist/test-singleton-protection.js +0 -110
  249. package/dist/test-smart-limits.d.ts +0 -13
  250. package/dist/test-smart-limits.js +0 -100
  251. package/dist/test-snow-query-incidents.d.ts +0 -2
  252. package/dist/test-snow-query-incidents.js +0 -66
  253. package/dist/test-universal-query.d.ts +0 -2
  254. package/dist/test-universal-query.js +0 -106
  255. package/dist/testing/flow-testing-automation.js +0 -641
  256. package/dist/utils/complete-flow-xml-generator.js +0 -1285
  257. package/dist/utils/file-storage-fallback.d.ts +0 -62
  258. package/dist/utils/file-storage-fallback.js +0 -289
  259. package/dist/utils/flow-api-discovery.d.ts +0 -151
  260. package/dist/utils/flow-api-discovery.js +0 -439
  261. package/dist/utils/flow-examples.js +0 -720
  262. package/dist/utils/flow-structure-builder.js +0 -677
  263. package/dist/utils/flow-xml-generator.d.ts +0 -41
  264. package/dist/utils/flow-xml-generator.js +0 -258
  265. package/dist/utils/improved-flow-xml-generator.js +0 -820
  266. package/dist/utils/mcp-process-manager.backup.d.ts +0 -58
  267. package/dist/utils/mcp-process-manager.backup.js +0 -220
  268. package/dist/utils/mcp-singleton-enforcer.d.ts +0 -36
  269. package/dist/utils/mcp-singleton-enforcer.js +0 -201
  270. package/dist/utils/mcp-timeout-fix.d.ts +0 -53
  271. package/dist/utils/mcp-timeout-fix.js +0 -221
  272. package/dist/utils/migrate-claude-flow.d.ts +0 -22
  273. package/dist/utils/migrate-claude-flow.js +0 -120
  274. package/dist/utils/scope-utils.d.ts +0 -72
  275. package/dist/utils/scope-utils.js +0 -386
  276. package/dist/utils/snow-oauth-old.d.ts +0 -65
  277. package/dist/utils/snow-oauth-old.js +0 -345
  278. package/dist/utils/xml-first-flow-generator.js +0 -513
  279. package/memory/servicenow_artifacts/000d9224c895221055906c7518aa2d3d.json +0 -30
  280. package/memory/servicenow_artifacts/0196b66173303010e46b4a2214f6a7a2.json +0 -36
  281. package/memory/servicenow_artifacts/125e5d1d837e2a102a7ea130ceaad397.json +0 -30
  282. package/memory/servicenow_artifacts/7637c1f2b7112210a5e5911cde11a972.json +0 -30
  283. package/memory/servicenow_artifacts/default_documentation_tables_1754056582292.json +0 -55
  284. package/memory/servicenow_artifacts/default_documentation_tables_1754057477189.json +0 -55
  285. package/memory/update-set-sessions/01f82af583faea102a7ea130ceaad3d4.json +0 -9
  286. package/memory/update-set-sessions/27718fb983faea102a7ea130ceaad34b.json +0 -9
  287. package/memory/update-set-sessions/412e9bf6833e22502a7ea130ceaad30a.json +0 -8
  288. package/memory/update-set-sessions/66fc5a79837aea102a7ea130ceaad3ab.json +0 -9
  289. package/memory/update-set-sessions/71a30ff5837eea102a7ea130ceaad37f.json +0 -9
  290. package/memory/update-set-sessions/74fba27983faea102a7ea130ceaad3bd.json +0 -9
  291. package/memory/update-set-sessions/a0b147b5837eea102a7ea130ceaad344.json +0 -58
  292. package/memory/update-set-sessions/b13f5eb983baea102a7ea130ceaad33e.json +0 -9
  293. package/reports/swarm-auto-centralized-1752649029776.json +0 -13
  294. package/src/memory/README.md +0 -240
@@ -1,1488 +0,0 @@
1
- "use strict";
2
- /**
3
- * Comprehensive Error Handling and Rollback System
4
- * Advanced error handling with automatic rollback capabilities
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.FlowErrorHandler = exports.ErrorSeverity = exports.ErrorType = void 0;
8
- const logger_js_1 = require("../utils/logger.js");
9
- var ErrorType;
10
- (function (ErrorType) {
11
- ErrorType["VALIDATION_ERROR"] = "validation_error";
12
- ErrorType["API_ERROR"] = "api_error";
13
- ErrorType["AUTHENTICATION_ERROR"] = "authentication_error";
14
- ErrorType["AUTHORIZATION_ERROR"] = "authorization_error";
15
- ErrorType["NETWORK_ERROR"] = "network_error";
16
- ErrorType["TIMEOUT_ERROR"] = "timeout_error";
17
- ErrorType["RATE_LIMIT_ERROR"] = "rate_limit_error";
18
- ErrorType["RESOURCE_NOT_FOUND"] = "resource_not_found";
19
- ErrorType["CONFLICT_ERROR"] = "conflict_error";
20
- ErrorType["SERVICE_UNAVAILABLE"] = "service_unavailable";
21
- ErrorType["FLOW_LOGIC_ERROR"] = "flow_logic_error";
22
- ErrorType["ROLLBACK_ERROR"] = "rollback_error";
23
- ErrorType["UNKNOWN_ERROR"] = "unknown_error";
24
- })(ErrorType || (exports.ErrorType = ErrorType = {}));
25
- var ErrorSeverity;
26
- (function (ErrorSeverity) {
27
- ErrorSeverity["CRITICAL"] = "critical";
28
- ErrorSeverity["HIGH"] = "high";
29
- ErrorSeverity["MEDIUM"] = "medium";
30
- ErrorSeverity["LOW"] = "low";
31
- })(ErrorSeverity || (exports.ErrorSeverity = ErrorSeverity = {}));
32
- class FlowErrorHandler {
33
- constructor(client) {
34
- this.transactions = new Map();
35
- this.errorHistory = [];
36
- this.maxErrorHistory = 1000;
37
- this.retryDelays = [1000, 2000, 5000, 10000, 30000]; // Exponential backoff
38
- this.client = client;
39
- this.logger = new logger_js_1.Logger('FlowErrorHandler');
40
- }
41
- /**
42
- * Handle an error with automatic recovery
43
- */
44
- async handleError(error, context) {
45
- const flowError = this.classifyError(error, context);
46
- this.errorHistory.push(flowError);
47
- // Limit error history size
48
- if (this.errorHistory.length > this.maxErrorHistory) {
49
- this.errorHistory.shift();
50
- }
51
- this.logger.error('Flow error occurred', {
52
- type: flowError.type,
53
- severity: flowError.severity,
54
- message: flowError.message,
55
- context: flowError.context
56
- });
57
- // Determine recovery strategy
58
- const recoveryActions = this.determineRecoveryActions(flowError);
59
- const result = {
60
- success: false,
61
- recovered: false,
62
- actions_taken: []
63
- };
64
- // Execute recovery actions
65
- for (const action of recoveryActions) {
66
- try {
67
- const actionResult = await this.executeRecoveryAction(action, flowError);
68
- result.actions_taken.push(action);
69
- if (actionResult.success) {
70
- result.success = true;
71
- result.recovered = true;
72
- result.final_state = actionResult.final_state;
73
- break;
74
- }
75
- }
76
- catch (recoveryError) {
77
- this.logger.error('Recovery action failed', {
78
- action: action.type,
79
- error: recoveryError
80
- });
81
- }
82
- }
83
- // Generate user-friendly message
84
- result.user_message = this.generateUserMessage(flowError, result);
85
- result.technical_details = this.generateTechnicalDetails(flowError, result);
86
- return result;
87
- }
88
- /**
89
- * Start a new transaction
90
- */
91
- startTransaction(flowId) {
92
- const transactionId = this.generateTransactionId();
93
- const transaction = {
94
- id: transactionId,
95
- flow_id: flowId,
96
- operations: [],
97
- status: 'active',
98
- start_time: new Date(),
99
- checkpoints: []
100
- };
101
- this.transactions.set(transactionId, transaction);
102
- this.logger.info('Transaction started', { transactionId, flowId });
103
- return transactionId;
104
- }
105
- /**
106
- * Add operation to transaction
107
- */
108
- addOperation(transactionId, operation) {
109
- const transaction = this.transactions.get(transactionId);
110
- if (!transaction) {
111
- throw new Error(`Transaction ${transactionId} not found`);
112
- }
113
- const rollbackOperation = {
114
- ...operation,
115
- id: this.generateOperationId(),
116
- timestamp: new Date()
117
- };
118
- transaction.operations.push(rollbackOperation);
119
- this.logger.debug('Operation added to transaction', { transactionId, operationId: rollbackOperation.id });
120
- }
121
- /**
122
- * Create checkpoint in transaction
123
- */
124
- createCheckpoint(transactionId, description) {
125
- const transaction = this.transactions.get(transactionId);
126
- if (!transaction) {
127
- throw new Error(`Transaction ${transactionId} not found`);
128
- }
129
- const checkpoint = {
130
- id: this.generateCheckpointId(),
131
- timestamp: new Date(),
132
- operation_count: transaction.operations.length,
133
- state_snapshot: this.captureStateSnapshot(transaction),
134
- description
135
- };
136
- transaction.checkpoints.push(checkpoint);
137
- this.logger.info('Checkpoint created', { transactionId, checkpointId: checkpoint.id, description });
138
- return checkpoint.id;
139
- }
140
- /**
141
- * Commit transaction
142
- */
143
- async commitTransaction(transactionId) {
144
- const transaction = this.transactions.get(transactionId);
145
- if (!transaction) {
146
- throw new Error(`Transaction ${transactionId} not found`);
147
- }
148
- transaction.status = 'committed';
149
- transaction.end_time = new Date();
150
- this.logger.info('Transaction committed', {
151
- transactionId,
152
- operationCount: transaction.operations.length,
153
- duration: transaction.end_time.getTime() - transaction.start_time.getTime()
154
- });
155
- // Clean up transaction after some time
156
- setTimeout(() => {
157
- this.transactions.delete(transactionId);
158
- }, 300000); // 5 minutes
159
- }
160
- /**
161
- * Rollback transaction
162
- */
163
- async rollbackTransaction(transactionId, toCheckpoint) {
164
- const transaction = this.transactions.get(transactionId);
165
- if (!transaction) {
166
- throw new Error(`Transaction ${transactionId} not found`);
167
- }
168
- this.logger.info('Starting transaction rollback', { transactionId, toCheckpoint });
169
- let operationsToRollback = transaction.operations.slice();
170
- // If rolling back to a checkpoint, only rollback operations after that checkpoint
171
- if (toCheckpoint) {
172
- const checkpoint = transaction.checkpoints.find(cp => cp.id === toCheckpoint);
173
- if (checkpoint) {
174
- operationsToRollback = transaction.operations.slice(checkpoint.operation_count);
175
- }
176
- }
177
- // Rollback operations in reverse order
178
- operationsToRollback.reverse();
179
- const rollbackErrors = [];
180
- for (const operation of operationsToRollback) {
181
- try {
182
- await this.rollbackOperation(operation);
183
- this.logger.debug('Operation rolled back', { operationId: operation.id });
184
- }
185
- catch (error) {
186
- rollbackErrors.push(error instanceof Error ? error : new Error(String(error)));
187
- this.logger.error('Rollback operation failed', { operationId: operation.id, error });
188
- }
189
- }
190
- transaction.status = rollbackErrors.length > 0 ? 'failed' : 'rolled_back';
191
- transaction.end_time = new Date();
192
- if (rollbackErrors.length > 0) {
193
- throw new Error(`Rollback failed with ${rollbackErrors.length} errors: ${rollbackErrors.map(e => e.message).join(', ')}`);
194
- }
195
- this.logger.info('Transaction rollback completed', { transactionId });
196
- }
197
- /**
198
- * Rollback a single operation
199
- */
200
- async rollbackOperation(operation) {
201
- switch (operation.type) {
202
- case 'create':
203
- // Delete the created record
204
- if (operation.record_id) {
205
- await this.client.deleteRecord(operation.table, operation.record_id);
206
- }
207
- break;
208
- case 'update':
209
- // Restore original data
210
- if (operation.record_id && operation.original_data) {
211
- await this.client.updateRecord(operation.table, operation.record_id, operation.original_data);
212
- }
213
- break;
214
- case 'delete':
215
- // Recreate the deleted record
216
- if (operation.original_data) {
217
- await this.client.createRecord(operation.table, operation.original_data);
218
- }
219
- break;
220
- }
221
- // Execute custom rollback function if provided
222
- if (operation.rollback_function) {
223
- await operation.rollback_function();
224
- }
225
- }
226
- /**
227
- * Classify error type and severity
228
- */
229
- classifyError(error, context) {
230
- let type = ErrorType.UNKNOWN_ERROR;
231
- let severity = ErrorSeverity.MEDIUM;
232
- let recoverable = true;
233
- let suggestedActions = [];
234
- const errorMessage = error.message.toLowerCase();
235
- // Classify by error message patterns
236
- if (errorMessage.includes('validation') || errorMessage.includes('invalid')) {
237
- type = ErrorType.VALIDATION_ERROR;
238
- severity = ErrorSeverity.HIGH;
239
- suggestedActions = [
240
- { type: 'fallback', description: 'Use fallback values', priority: 'high' },
241
- { type: 'notify', description: 'Notify user of validation issues', priority: 'medium' }
242
- ];
243
- }
244
- else if (errorMessage.includes('unauthorized') || errorMessage.includes('authentication')) {
245
- type = ErrorType.AUTHENTICATION_ERROR;
246
- severity = ErrorSeverity.CRITICAL;
247
- recoverable = false;
248
- suggestedActions = [
249
- { type: 'notify', description: 'Request user to re-authenticate', priority: 'high' }
250
- ];
251
- }
252
- else if (errorMessage.includes('forbidden') || errorMessage.includes('access denied')) {
253
- type = ErrorType.AUTHORIZATION_ERROR;
254
- severity = ErrorSeverity.HIGH;
255
- recoverable = false;
256
- suggestedActions = [
257
- { type: 'notify', description: 'Inform user of insufficient permissions', priority: 'high' }
258
- ];
259
- }
260
- else if (errorMessage.includes('network') || errorMessage.includes('connection')) {
261
- type = ErrorType.NETWORK_ERROR;
262
- severity = ErrorSeverity.MEDIUM;
263
- suggestedActions = [
264
- { type: 'retry', description: 'Retry with exponential backoff', priority: 'high' },
265
- { type: 'fallback', description: 'Use cached data if available', priority: 'medium' }
266
- ];
267
- }
268
- else if (errorMessage.includes('timeout')) {
269
- type = ErrorType.TIMEOUT_ERROR;
270
- severity = ErrorSeverity.MEDIUM;
271
- suggestedActions = [
272
- { type: 'retry', description: 'Retry with increased timeout', priority: 'high' }
273
- ];
274
- }
275
- else if (errorMessage.includes('rate limit') || errorMessage.includes('too many requests')) {
276
- type = ErrorType.RATE_LIMIT_ERROR;
277
- severity = ErrorSeverity.LOW;
278
- suggestedActions = [
279
- { type: 'retry', description: 'Retry after delay', priority: 'high', parameters: { delay: 60000 } }
280
- ];
281
- }
282
- else if (errorMessage.includes('not found') || errorMessage.includes('404')) {
283
- type = ErrorType.RESOURCE_NOT_FOUND;
284
- severity = ErrorSeverity.HIGH;
285
- suggestedActions = [
286
- { type: 'fallback', description: 'Create missing resource', priority: 'high' },
287
- { type: 'notify', description: 'Inform user of missing resource', priority: 'medium' }
288
- ];
289
- }
290
- else if (errorMessage.includes('conflict') || errorMessage.includes('409')) {
291
- type = ErrorType.CONFLICT_ERROR;
292
- severity = ErrorSeverity.MEDIUM;
293
- suggestedActions = [
294
- { type: 'retry', description: 'Retry after resolving conflict', priority: 'high' },
295
- { type: 'fallback', description: 'Use alternative approach', priority: 'medium' }
296
- ];
297
- }
298
- else if (errorMessage.includes('service unavailable') || errorMessage.includes('503')) {
299
- type = ErrorType.SERVICE_UNAVAILABLE;
300
- severity = ErrorSeverity.HIGH;
301
- suggestedActions = [
302
- { type: 'retry', description: 'Retry after service recovery', priority: 'high' },
303
- { type: 'notify', description: 'Inform user of service unavailability', priority: 'medium' }
304
- ];
305
- }
306
- // Determine if rollback is needed
307
- if (context.flow_id && ['create', 'update', 'delete'].includes(context.operation)) {
308
- suggestedActions.unshift({
309
- type: 'rollback',
310
- description: 'Rollback partial changes',
311
- priority: 'high'
312
- });
313
- }
314
- return {
315
- type,
316
- severity,
317
- message: error.message,
318
- context,
319
- original_error: error,
320
- recoverable,
321
- suggested_actions: suggestedActions,
322
- retry_count: 0,
323
- max_retries: this.getMaxRetries(type)
324
- };
325
- }
326
- /**
327
- * Determine recovery actions based on error
328
- */
329
- determineRecoveryActions(error) {
330
- const actions = [];
331
- // Sort suggested actions by priority
332
- const sortedActions = error.suggested_actions.sort((a, b) => {
333
- const priorityOrder = { high: 3, medium: 2, low: 1 };
334
- return priorityOrder[b.priority] - priorityOrder[a.priority];
335
- });
336
- // Add retry logic for recoverable errors
337
- if (error.recoverable && error.retry_count < error.max_retries) {
338
- actions.push({
339
- type: 'retry',
340
- description: `Retry operation (attempt ${error.retry_count + 1}/${error.max_retries})`,
341
- priority: 'high',
342
- parameters: {
343
- delay: this.retryDelays[Math.min(error.retry_count, this.retryDelays.length - 1)]
344
- }
345
- });
346
- }
347
- // Add suggested actions
348
- actions.push(...sortedActions);
349
- return actions;
350
- }
351
- /**
352
- * Execute a recovery action
353
- */
354
- async executeRecoveryAction(action, error) {
355
- switch (action.type) {
356
- case 'retry':
357
- return await this.executeRetry(action, error);
358
- case 'rollback':
359
- return await this.executeRollback(action, error);
360
- case 'fallback':
361
- return await this.executeFallback(action, error);
362
- case 'skip':
363
- return await this.executeSkip(action, error);
364
- case 'notify':
365
- return await this.executeNotify(action, error);
366
- default:
367
- return { success: false };
368
- }
369
- }
370
- /**
371
- * Execute retry action
372
- */
373
- async executeRetry(action, error) {
374
- const delay = action.parameters?.delay || 1000;
375
- this.logger.info('Executing retry', { delay, retryCount: error.retry_count });
376
- // Wait before retry
377
- await new Promise(resolve => setTimeout(resolve, delay));
378
- try {
379
- // Retry the original operation
380
- const result = await this.retryOriginalOperation(error);
381
- return { success: true, final_state: result };
382
- }
383
- catch (retryError) {
384
- error.retry_count = (error.retry_count || 0) + 1;
385
- return { success: false };
386
- }
387
- }
388
- /**
389
- * Execute rollback action
390
- */
391
- async executeRollback(action, error) {
392
- if (!error.context.flow_id) {
393
- return { success: false };
394
- }
395
- // Find transaction for this flow
396
- const transaction = Array.from(this.transactions.values())
397
- .find(t => t.flow_id === error.context.flow_id && t.status === 'active');
398
- if (!transaction) {
399
- return { success: false };
400
- }
401
- try {
402
- await this.rollbackTransaction(transaction.id);
403
- return { success: true, final_state: 'rolled_back' };
404
- }
405
- catch (rollbackError) {
406
- return { success: false };
407
- }
408
- }
409
- /**
410
- * Execute fallback action
411
- */
412
- async executeFallback(action, error) {
413
- // Implement fallback logic based on error type
414
- switch (error.type) {
415
- case ErrorType.RESOURCE_NOT_FOUND:
416
- return await this.createMissingResource(error);
417
- case ErrorType.VALIDATION_ERROR:
418
- return await this.useFallbackValues(error);
419
- case ErrorType.NETWORK_ERROR:
420
- return await this.useCachedData(error);
421
- default:
422
- return { success: false };
423
- }
424
- }
425
- /**
426
- * Execute skip action
427
- */
428
- async executeSkip(action, error) {
429
- this.logger.info('Skipping failed operation', { error: error.type });
430
- return { success: true, final_state: 'skipped' };
431
- }
432
- /**
433
- * Execute notify action
434
- */
435
- async executeNotify(action, error) {
436
- // Create notification record
437
- try {
438
- await this.client.createRecord('sys_email', {
439
- to: 'admin@company.com',
440
- subject: `Flow Error: ${error.type}`,
441
- body: `An error occurred in flow operation: ${error.message}`
442
- });
443
- return { success: true, final_state: 'notified' };
444
- }
445
- catch (notifyError) {
446
- return { success: false };
447
- }
448
- }
449
- /**
450
- * Retry original operation with exponential backoff
451
- */
452
- async retryOriginalOperation(error) {
453
- const maxRetries = error.max_retries || 3;
454
- const currentRetryCount = error.retry_count || 0;
455
- this.logger.info(`Attempting retry ${currentRetryCount + 1}/${maxRetries} for operation`, {
456
- operation: error.context.operation,
457
- error_type: error.type,
458
- previous_attempts: currentRetryCount
459
- });
460
- // Check if we've exceeded max retries
461
- if (currentRetryCount >= maxRetries) {
462
- this.logger.error('Maximum retry attempts exceeded', {
463
- operation: error.context.operation,
464
- total_attempts: currentRetryCount,
465
- final_error: error.message
466
- });
467
- return {
468
- success: false,
469
- final_state: null,
470
- retry_exhausted: true,
471
- total_attempts: currentRetryCount,
472
- last_error: error.message,
473
- suggested_actions: [
474
- 'Review the operation configuration',
475
- 'Check ServiceNow system status',
476
- 'Contact administrator for manual intervention',
477
- 'Consider alternative approach'
478
- ]
479
- };
480
- }
481
- // Calculate retry delay using exponential backoff
482
- const baseDelay = this.retryDelays[Math.min(currentRetryCount, this.retryDelays.length - 1)];
483
- const jitterDelay = baseDelay + Math.random() * 1000; // Add jitter to prevent thundering herd
484
- this.logger.info(`Waiting ${Math.round(jitterDelay)}ms before retry attempt`, {
485
- retry_count: currentRetryCount + 1,
486
- base_delay: baseDelay,
487
- actual_delay: Math.round(jitterDelay)
488
- });
489
- // Wait before retry
490
- await this.delay(jitterDelay);
491
- try {
492
- // Determine retry strategy based on error type
493
- const retryResult = await this.executeRetryBasedOnErrorType(error);
494
- if (retryResult.success) {
495
- this.logger.info('Retry attempt successful', {
496
- operation: error.context.operation,
497
- retry_count: currentRetryCount + 1,
498
- success_after_attempts: currentRetryCount + 1
499
- });
500
- return {
501
- success: true,
502
- final_state: retryResult.data,
503
- retry_count: currentRetryCount + 1,
504
- recovery_method: 'retry_with_backoff'
505
- };
506
- }
507
- else {
508
- // Update error with new retry count and continue retry cycle
509
- const updatedError = {
510
- ...error,
511
- retry_count: currentRetryCount + 1,
512
- message: retryResult.error || error.message
513
- };
514
- // Recursively retry if not at max attempts
515
- return await this.retryOriginalOperation(updatedError);
516
- }
517
- }
518
- catch (retryError) {
519
- this.logger.error('Error during retry attempt', {
520
- retry_count: currentRetryCount + 1,
521
- error: retryError instanceof Error ? retryError.message : String(retryError)
522
- });
523
- // Create updated error for next retry or final failure
524
- const updatedError = {
525
- ...error,
526
- retry_count: currentRetryCount + 1,
527
- message: retryError instanceof Error ? retryError.message : String(retryError),
528
- original_error: retryError instanceof Error ? retryError : new Error(String(retryError))
529
- };
530
- // Continue retry cycle
531
- return await this.retryOriginalOperation(updatedError);
532
- }
533
- }
534
- /**
535
- * Execute retry based on specific error type
536
- */
537
- async executeRetryBasedOnErrorType(error) {
538
- try {
539
- switch (error.type) {
540
- case ErrorType.AUTHENTICATION_ERROR:
541
- return await this.retryAuthenticationOperation(error);
542
- case ErrorType.NETWORK_ERROR:
543
- case ErrorType.TIMEOUT_ERROR:
544
- return await this.retryNetworkOperation(error);
545
- case ErrorType.RATE_LIMIT_ERROR:
546
- return await this.retryRateLimitedOperation(error);
547
- case ErrorType.SERVICE_UNAVAILABLE:
548
- return await this.retryServiceUnavailableOperation(error);
549
- case ErrorType.API_ERROR:
550
- return await this.retryAPIOperation(error);
551
- case ErrorType.CONFLICT_ERROR:
552
- return await this.retryConflictOperation(error);
553
- case ErrorType.RESOURCE_NOT_FOUND:
554
- return await this.retryResourceOperation(error);
555
- default:
556
- return await this.retryGenericOperation(error);
557
- }
558
- }
559
- catch (executeError) {
560
- return {
561
- success: false,
562
- error: executeError instanceof Error ? executeError.message : String(executeError)
563
- };
564
- }
565
- }
566
- /**
567
- * Retry authentication operations
568
- */
569
- async retryAuthenticationOperation(error) {
570
- try {
571
- this.logger.info('Retrying authentication operation');
572
- // Try to refresh authentication
573
- const credentials = this.client.credentialsInstance;
574
- if (credentials?.refreshToken) {
575
- // Attempt token refresh
576
- const refreshResult = await this.client.oauth?.refreshAccessToken();
577
- if (refreshResult?.success) {
578
- // Retry the original operation with new token
579
- return await this.retryWithNewAuthentication(error);
580
- }
581
- }
582
- return {
583
- success: false,
584
- error: 'Authentication refresh failed - manual re-authentication required'
585
- };
586
- }
587
- catch (authError) {
588
- return {
589
- success: false,
590
- error: authError instanceof Error ? authError.message : String(authError)
591
- };
592
- }
593
- }
594
- /**
595
- * Retry network operations
596
- */
597
- async retryNetworkOperation(error) {
598
- try {
599
- this.logger.info('Retrying network operation');
600
- // For network errors, simply retry the original request
601
- return await this.executeOriginalOperation(error);
602
- }
603
- catch (networkError) {
604
- return {
605
- success: false,
606
- error: networkError instanceof Error ? networkError.message : String(networkError)
607
- };
608
- }
609
- }
610
- /**
611
- * Retry rate limited operations with longer delay
612
- */
613
- async retryRateLimitedOperation(error) {
614
- try {
615
- this.logger.info('Retrying rate limited operation with extended delay');
616
- // Rate limit errors need longer delays
617
- const rateLimitDelay = 30000 + Math.random() * 10000; // 30-40 seconds
618
- await this.delay(rateLimitDelay);
619
- return await this.executeOriginalOperation(error);
620
- }
621
- catch (rateLimitError) {
622
- return {
623
- success: false,
624
- error: rateLimitError instanceof Error ? rateLimitError.message : String(rateLimitError)
625
- };
626
- }
627
- }
628
- /**
629
- * Retry service unavailable operations
630
- */
631
- async retryServiceUnavailableOperation(error) {
632
- try {
633
- this.logger.info('Retrying operation after service unavailability');
634
- // Check service health before retry
635
- const healthCheck = await this.performServiceHealthCheck();
636
- if (!healthCheck.healthy) {
637
- return {
638
- success: false,
639
- error: `Service still unavailable: ${healthCheck.reason}`
640
- };
641
- }
642
- return await this.executeOriginalOperation(error);
643
- }
644
- catch (serviceError) {
645
- return {
646
- success: false,
647
- error: serviceError instanceof Error ? serviceError.message : String(serviceError)
648
- };
649
- }
650
- }
651
- /**
652
- * Retry API operations
653
- */
654
- async retryAPIOperation(error) {
655
- try {
656
- this.logger.info('Retrying API operation');
657
- // API errors might be transient, retry with same parameters
658
- return await this.executeOriginalOperation(error);
659
- }
660
- catch (apiError) {
661
- return {
662
- success: false,
663
- error: apiError instanceof Error ? apiError.message : String(apiError)
664
- };
665
- }
666
- }
667
- /**
668
- * Retry conflict operations with modified data
669
- */
670
- async retryConflictOperation(error) {
671
- try {
672
- this.logger.info('Retrying conflict operation with modifications');
673
- // For conflicts, try to modify the operation slightly
674
- const modifiedOperation = await this.modifyOperationForConflictResolution(error);
675
- return await this.executeModifiedOperation(error, modifiedOperation);
676
- }
677
- catch (conflictError) {
678
- return {
679
- success: false,
680
- error: conflictError instanceof Error ? conflictError.message : String(conflictError)
681
- };
682
- }
683
- }
684
- /**
685
- * Retry resource operations
686
- */
687
- async retryResourceOperation(error) {
688
- try {
689
- this.logger.info('Retrying resource operation');
690
- // For resource not found, try to create the resource first
691
- const resourceCreated = await this.ensureResourceExists(error);
692
- if (resourceCreated.success) {
693
- return await this.executeOriginalOperation(error);
694
- }
695
- return {
696
- success: false,
697
- error: `Failed to create required resource: ${resourceCreated.error}`
698
- };
699
- }
700
- catch (resourceError) {
701
- return {
702
- success: false,
703
- error: resourceError instanceof Error ? resourceError.message : String(resourceError)
704
- };
705
- }
706
- }
707
- /**
708
- * Generic retry operation
709
- */
710
- async retryGenericOperation(error) {
711
- try {
712
- this.logger.info('Performing generic retry operation');
713
- // Generic retry - just execute the original operation again
714
- return await this.executeOriginalOperation(error);
715
- }
716
- catch (genericError) {
717
- return {
718
- success: false,
719
- error: genericError instanceof Error ? genericError.message : String(genericError)
720
- };
721
- }
722
- }
723
- /**
724
- * Execute the original operation that failed
725
- */
726
- async executeOriginalOperation(error) {
727
- try {
728
- // This would reconstruct and execute the original operation
729
- // For now, we'll simulate the operation based on context
730
- const operation = error.context.operation;
731
- const operationType = this.extractOperationType(operation);
732
- switch (operationType) {
733
- case 'deploy':
734
- return await this.retryDeployOperation(error);
735
- case 'search':
736
- return await this.retrySearchOperation(error);
737
- case 'create':
738
- return await this.retryCreateOperation(error);
739
- case 'update':
740
- return await this.retryUpdateOperation(error);
741
- default:
742
- // Generic HTTP request retry
743
- return await this.retryHTTPRequest(error);
744
- }
745
- }
746
- catch (executeError) {
747
- return {
748
- success: false,
749
- error: executeError instanceof Error ? executeError.message : String(executeError)
750
- };
751
- }
752
- }
753
- // Helper methods for specific operation types
754
- async retryDeployOperation(error) {
755
- try {
756
- this.logger.info('Retrying deployment operation', {
757
- component_type: error.context.component_type,
758
- component_id: error.context.component_id
759
- });
760
- // Extract deployment parameters from context
761
- const deploymentData = error.context.user_input;
762
- if (!deploymentData) {
763
- return { success: false, error: 'No deployment data available for retry' };
764
- }
765
- // Retry based on component type
766
- switch (error.context.component_type) {
767
- case 'widget':
768
- return await this.retryWidgetDeployment(deploymentData, error);
769
- case 'flow':
770
- return await this.retryFlowDeployment(deploymentData, error);
771
- case 'application':
772
- return await this.retryApplicationDeployment(deploymentData, error);
773
- case 'script':
774
- return await this.retryScriptDeployment(deploymentData, error);
775
- default:
776
- return await this.retryGenericDeployment(deploymentData, error);
777
- }
778
- }
779
- catch (deployError) {
780
- return {
781
- success: false,
782
- error: deployError instanceof Error ? deployError.message : String(deployError)
783
- };
784
- }
785
- }
786
- async retrySearchOperation(error) {
787
- try {
788
- this.logger.info('Retrying search operation', { operation: error.context.operation });
789
- const searchParams = error.context.user_input;
790
- if (!searchParams) {
791
- return { success: false, error: 'No search parameters available for retry' };
792
- }
793
- // Modify search parameters if this is a retry to avoid same failure
794
- const modifiedParams = {
795
- ...searchParams,
796
- sysparm_limit: Math.min(searchParams.sysparm_limit || 100, 50), // Reduce limit
797
- sysparm_offset: searchParams.sysparm_offset || 0,
798
- retry_attempt: (error.retry_count || 0) + 1
799
- };
800
- // Perform the search request
801
- const result = await this.client.makeRequest({
802
- method: 'GET',
803
- endpoint: searchParams.endpoint || '/api/now/table/sys_metadata',
804
- params: modifiedParams
805
- });
806
- if (result.status === 200) {
807
- return { success: true, data: result.data };
808
- }
809
- else {
810
- return { success: false, error: `Search failed with status: ${result.status}` };
811
- }
812
- }
813
- catch (searchError) {
814
- return {
815
- success: false,
816
- error: searchError instanceof Error ? searchError.message : String(searchError)
817
- };
818
- }
819
- }
820
- async retryCreateOperation(error) {
821
- try {
822
- this.logger.info('Retrying create operation', {
823
- table: error.context.component_type,
824
- retry_count: error.retry_count
825
- });
826
- const createData = error.context.user_input;
827
- if (!createData || !createData.table) {
828
- return { success: false, error: 'No create data or table specified for retry' };
829
- }
830
- // Modify data for conflict resolution if needed
831
- const retryData = { ...createData.data };
832
- // If this is a conflict retry, modify unique fields
833
- if (error.type === ErrorType.CONFLICT_ERROR && error.retry_count > 0) {
834
- const timestamp = Date.now();
835
- if (retryData.name) {
836
- retryData.name = `${retryData.name}_retry_${timestamp}`;
837
- }
838
- if (retryData.sys_name) {
839
- retryData.sys_name = `${retryData.sys_name}_retry_${timestamp}`;
840
- }
841
- }
842
- // Perform the create request
843
- const result = await this.client.createRecord(createData.table, retryData);
844
- if (result && result.sys_id) {
845
- this.logger.info('Create operation retry successful', { sys_id: result.sys_id });
846
- return { success: true, data: result };
847
- }
848
- else {
849
- return { success: false, error: 'Create operation failed - no sys_id returned' };
850
- }
851
- }
852
- catch (createError) {
853
- return {
854
- success: false,
855
- error: createError instanceof Error ? createError.message : String(createError)
856
- };
857
- }
858
- }
859
- async retryUpdateOperation(error) {
860
- try {
861
- this.logger.info('Retrying update operation', {
862
- table: error.context.component_type,
863
- record_id: error.context.component_id
864
- });
865
- const updateData = error.context.user_input;
866
- if (!updateData || !updateData.table || !updateData.record_id) {
867
- return { success: false, error: 'No update data, table, or record ID available for retry' };
868
- }
869
- // First, verify the record still exists
870
- try {
871
- const existingRecord = await this.client.getRecord(updateData.table, updateData.record_id);
872
- if (!existingRecord) {
873
- return { success: false, error: 'Record no longer exists for update' };
874
- }
875
- }
876
- catch (getError) {
877
- return { success: false, error: 'Cannot verify record existence for update retry' };
878
- }
879
- // Perform the update request
880
- const result = await this.client.updateRecord(updateData.table, updateData.record_id, updateData.data);
881
- if (result) {
882
- this.logger.info('Update operation retry successful', { sys_id: updateData.record_id });
883
- return { success: true, data: result };
884
- }
885
- else {
886
- return { success: false, error: 'Update operation failed' };
887
- }
888
- }
889
- catch (updateError) {
890
- return {
891
- success: false,
892
- error: updateError instanceof Error ? updateError.message : String(updateError)
893
- };
894
- }
895
- }
896
- async retryHTTPRequest(error) {
897
- try {
898
- this.logger.info('Retrying HTTP request', { operation: error.context.operation });
899
- const requestData = error.context.user_input;
900
- if (!requestData) {
901
- return { success: false, error: 'No request data available for HTTP retry' };
902
- }
903
- // Construct request with retry-safe parameters
904
- const requestConfig = {
905
- method: requestData.method || 'GET',
906
- endpoint: requestData.endpoint || requestData.url,
907
- params: requestData.params,
908
- data: requestData.data,
909
- timeout: Math.min((requestData.timeout || 30000) * 1.5, 60000), // Increase timeout
910
- retry_attempt: (error.retry_count || 0) + 1
911
- };
912
- // Add retry headers
913
- const headers = {
914
- ...requestData.headers,
915
- 'X-Retry-Attempt': String(requestConfig.retry_attempt),
916
- 'X-Request-ID': `retry_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
917
- };
918
- const result = await this.client.makeRequest({
919
- ...requestConfig,
920
- headers
921
- });
922
- if (result.status >= 200 && result.status < 300) {
923
- return { success: true, data: result.data };
924
- }
925
- else {
926
- return {
927
- success: false,
928
- error: `HTTP request failed with status: ${result.status} - ${result.statusText}`
929
- };
930
- }
931
- }
932
- catch (httpError) {
933
- return {
934
- success: false,
935
- error: httpError instanceof Error ? httpError.message : String(httpError)
936
- };
937
- }
938
- }
939
- // Additional helper methods
940
- async retryWithNewAuthentication(error) {
941
- // Retry with refreshed authentication
942
- return await this.executeOriginalOperation(error);
943
- }
944
- async performServiceHealthCheck() {
945
- try {
946
- // Basic health check - try to access ServiceNow instance
947
- const response = await this.client.makeRequest({
948
- method: 'GET',
949
- endpoint: '/api/now/v2/table/sys_user',
950
- params: { sysparm_limit: 1 }
951
- });
952
- return { healthy: response.status === 200 };
953
- }
954
- catch (healthError) {
955
- return {
956
- healthy: false,
957
- reason: healthError instanceof Error ? healthError.message : 'Unknown health check error'
958
- };
959
- }
960
- }
961
- async modifyOperationForConflictResolution(error) {
962
- // Modify operation to resolve conflicts (e.g., add timestamp to name)
963
- const timestamp = Date.now();
964
- return {
965
- ...error.context.system_state,
966
- name: `${error.context.system_state?.name || 'item'}_${timestamp}`,
967
- modified_for_conflict: true
968
- };
969
- }
970
- async executeModifiedOperation(error, modifiedData) {
971
- try {
972
- this.logger.info('Executing modified operation for conflict resolution', {
973
- original_operation: error.context.operation,
974
- modifications: modifiedData.modified_for_conflict ? 'conflict_resolution' : 'standard'
975
- });
976
- // Execute the operation with modified data based on operation type
977
- const operationType = this.extractOperationType(error.context.operation);
978
- switch (operationType) {
979
- case 'create':
980
- const table = error.context.component_type || 'sys_metadata';
981
- const result = await this.client.createRecord(table, modifiedData);
982
- return { success: true, data: result };
983
- case 'update':
984
- if (!error.context.component_id) {
985
- return { success: false, error: 'No component ID for update operation' };
986
- }
987
- const updateResult = await this.client.updateRecord(error.context.component_type || 'sys_metadata', error.context.component_id, modifiedData);
988
- return { success: true, data: updateResult };
989
- case 'deploy':
990
- // For deployment operations, use the deployment data structure
991
- return await this.retryGenericDeployment(modifiedData, error);
992
- default:
993
- return { success: false, error: 'Unsupported operation type for modification' };
994
- }
995
- }
996
- catch (executeError) {
997
- return {
998
- success: false,
999
- error: executeError instanceof Error ? executeError.message : String(executeError)
1000
- };
1001
- }
1002
- }
1003
- async ensureResourceExists(error) {
1004
- try {
1005
- this.logger.info('Attempting to create missing resource', {
1006
- resource_type: error.context.component_type,
1007
- resource_id: error.context.component_id
1008
- });
1009
- // Extract resource information from context
1010
- const resourceData = error.context.user_input;
1011
- if (!resourceData) {
1012
- return { success: false, error: 'No resource data available for creation' };
1013
- }
1014
- // Determine resource type and create accordingly
1015
- switch (error.context.component_type) {
1016
- case 'table':
1017
- return await this.createMissingTable(resourceData);
1018
- case 'field':
1019
- return await this.createMissingField(resourceData);
1020
- case 'user':
1021
- return await this.createMissingUser(resourceData);
1022
- case 'group':
1023
- return await this.createMissingGroup(resourceData);
1024
- default:
1025
- // Generic resource creation
1026
- return await this.createGenericResource(resourceData);
1027
- }
1028
- }
1029
- catch (resourceError) {
1030
- return {
1031
- success: false,
1032
- error: resourceError instanceof Error ? resourceError.message : String(resourceError)
1033
- };
1034
- }
1035
- }
1036
- async delay(ms) {
1037
- return new Promise(resolve => setTimeout(resolve, ms));
1038
- }
1039
- /**
1040
- * Create missing resource
1041
- */
1042
- async createMissingResource(error) {
1043
- // Implementation depends on the specific resource type
1044
- return { success: false };
1045
- }
1046
- /**
1047
- * Use fallback values
1048
- */
1049
- async useFallbackValues(error) {
1050
- // Implementation depends on the specific validation error
1051
- return { success: false };
1052
- }
1053
- /**
1054
- * Use cached data
1055
- */
1056
- async useCachedData(error) {
1057
- // Implementation depends on the specific cached data available
1058
- return { success: false };
1059
- }
1060
- /**
1061
- * Generate user-friendly error message
1062
- */
1063
- generateUserMessage(error, result) {
1064
- if (result.recovered) {
1065
- return `The operation encountered an issue but was automatically recovered. ${error.message}`;
1066
- }
1067
- switch (error.type) {
1068
- case ErrorType.AUTHENTICATION_ERROR:
1069
- return 'Authentication failed. Please check your credentials and try again.';
1070
- case ErrorType.AUTHORIZATION_ERROR:
1071
- return 'You do not have permission to perform this operation.';
1072
- case ErrorType.VALIDATION_ERROR:
1073
- return 'The provided data is invalid. Please check your inputs and try again.';
1074
- case ErrorType.NETWORK_ERROR:
1075
- return 'Network connection failed. Please check your connection and try again.';
1076
- case ErrorType.RESOURCE_NOT_FOUND:
1077
- return 'The requested resource was not found. It may have been deleted or moved.';
1078
- default:
1079
- return `An error occurred: ${error.message}`;
1080
- }
1081
- }
1082
- /**
1083
- * Generate technical details
1084
- */
1085
- generateTechnicalDetails(error, result) {
1086
- const details = {
1087
- error_type: error.type,
1088
- severity: error.severity,
1089
- message: error.message,
1090
- context: error.context,
1091
- actions_taken: result.actions_taken.map(a => a.type),
1092
- recovered: result.recovered,
1093
- timestamp: new Date().toISOString()
1094
- };
1095
- return JSON.stringify(details, null, 2);
1096
- }
1097
- /**
1098
- * Get max retries for error type
1099
- */
1100
- getMaxRetries(errorType) {
1101
- switch (errorType) {
1102
- case ErrorType.NETWORK_ERROR:
1103
- case ErrorType.TIMEOUT_ERROR:
1104
- return 3;
1105
- case ErrorType.RATE_LIMIT_ERROR:
1106
- return 2;
1107
- case ErrorType.SERVICE_UNAVAILABLE:
1108
- return 5;
1109
- default:
1110
- return 1;
1111
- }
1112
- }
1113
- /**
1114
- * Capture state snapshot
1115
- */
1116
- captureStateSnapshot(transaction) {
1117
- return {
1118
- transaction_id: transaction.id,
1119
- flow_id: transaction.flow_id,
1120
- operation_count: transaction.operations.length,
1121
- status: transaction.status,
1122
- timestamp: new Date().toISOString()
1123
- };
1124
- }
1125
- /**
1126
- * Generate transaction ID
1127
- */
1128
- generateTransactionId() {
1129
- return `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1130
- }
1131
- /**
1132
- * Generate operation ID
1133
- */
1134
- generateOperationId() {
1135
- return `op_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1136
- }
1137
- /**
1138
- * Generate checkpoint ID
1139
- */
1140
- generateCheckpointId() {
1141
- return `cp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1142
- }
1143
- /**
1144
- * Get error statistics
1145
- */
1146
- getErrorStatistics() {
1147
- const stats = {
1148
- total_errors: this.errorHistory.length,
1149
- errors_by_type: {},
1150
- errors_by_severity: {},
1151
- recovery_rate: 0
1152
- };
1153
- let recoveredCount = 0;
1154
- for (const error of this.errorHistory) {
1155
- // Count by type
1156
- stats.errors_by_type[error.type] = (stats.errors_by_type[error.type] || 0) + 1;
1157
- // Count by severity
1158
- stats.errors_by_severity[error.severity] = (stats.errors_by_severity[error.severity] || 0) + 1;
1159
- // Count recovered errors
1160
- if (error.recoverable) {
1161
- recoveredCount++;
1162
- }
1163
- }
1164
- stats.recovery_rate = stats.total_errors > 0 ? recoveredCount / stats.total_errors : 0;
1165
- return stats;
1166
- }
1167
- /**
1168
- * Get active transactions
1169
- */
1170
- getActiveTransactions() {
1171
- return Array.from(this.transactions.values())
1172
- .filter(t => t.status === 'active');
1173
- }
1174
- // =====================================
1175
- // DEPLOYMENT RETRY METHODS
1176
- // =====================================
1177
- /**
1178
- * Retry widget deployment
1179
- */
1180
- async retryWidgetDeployment(deploymentData, error) {
1181
- try {
1182
- this.logger.info('Retrying widget deployment', { widget_name: deploymentData.name });
1183
- // Construct widget data with retry modifications
1184
- const widgetData = {
1185
- name: deploymentData.name,
1186
- title: deploymentData.title,
1187
- template: deploymentData.template,
1188
- server_script: deploymentData.server_script,
1189
- client_script: deploymentData.client_script,
1190
- css: deploymentData.css,
1191
- category: deploymentData.category || 'custom',
1192
- roles: deploymentData.roles || '',
1193
- public: deploymentData.public !== false
1194
- };
1195
- // If this is a conflict retry, modify the name
1196
- if (error.type === ErrorType.CONFLICT_ERROR && (error.retry_count || 0) > 0) {
1197
- widgetData.name = `${widgetData.name}_retry_${Date.now()}`;
1198
- }
1199
- const result = await this.client.createRecord('sp_widget', widgetData);
1200
- return { success: true, data: result };
1201
- }
1202
- catch (widgetError) {
1203
- return {
1204
- success: false,
1205
- error: widgetError instanceof Error ? widgetError.message : String(widgetError)
1206
- };
1207
- }
1208
- }
1209
- /**
1210
- * Retry flow deployment
1211
- */
1212
- async retryFlowDeployment(deploymentData, error) {
1213
- try {
1214
- this.logger.info('Retrying flow deployment', { flow_name: deploymentData.name });
1215
- const flowData = {
1216
- name: deploymentData.name,
1217
- description: deploymentData.description,
1218
- active: deploymentData.active !== false,
1219
- flow_designer: deploymentData.flow_definition || '{}',
1220
- trigger_conditions: deploymentData.trigger_conditions,
1221
- table: deploymentData.table
1222
- };
1223
- // Handle conflict retry
1224
- if (error.type === ErrorType.CONFLICT_ERROR && (error.retry_count || 0) > 0) {
1225
- flowData.name = `${flowData.name}_retry_${Date.now()}`;
1226
- }
1227
- const result = await this.client.createRecord('sys_hub_flow', flowData);
1228
- return { success: true, data: result };
1229
- }
1230
- catch (flowError) {
1231
- return {
1232
- success: false,
1233
- error: flowError instanceof Error ? flowError.message : String(flowError)
1234
- };
1235
- }
1236
- }
1237
- /**
1238
- * Retry application deployment
1239
- */
1240
- async retryApplicationDeployment(deploymentData, error) {
1241
- try {
1242
- this.logger.info('Retrying application deployment', { app_name: deploymentData.name });
1243
- const appData = {
1244
- name: deploymentData.name,
1245
- short_description: deploymentData.short_description,
1246
- description: deploymentData.description,
1247
- version: deploymentData.version || '1.0.0',
1248
- vendor: deploymentData.vendor || 'Custom',
1249
- vendor_prefix: deploymentData.vendor_prefix,
1250
- active: deploymentData.active !== false
1251
- };
1252
- // Handle conflict retry
1253
- if (error.type === ErrorType.CONFLICT_ERROR && (error.retry_count || 0) > 0) {
1254
- appData.name = `${appData.name}_retry_${Date.now()}`;
1255
- }
1256
- const result = await this.client.createRecord('sys_app', appData);
1257
- return { success: true, data: result };
1258
- }
1259
- catch (appError) {
1260
- return {
1261
- success: false,
1262
- error: appError instanceof Error ? appError.message : String(appError)
1263
- };
1264
- }
1265
- }
1266
- /**
1267
- * Retry script deployment
1268
- */
1269
- async retryScriptDeployment(deploymentData, error) {
1270
- try {
1271
- this.logger.info('Retrying script deployment', { script_name: deploymentData.name });
1272
- const scriptData = {
1273
- name: deploymentData.name,
1274
- script: deploymentData.script,
1275
- description: deploymentData.description,
1276
- api_name: deploymentData.api_name,
1277
- client_callable: deploymentData.client_callable || false,
1278
- active: deploymentData.active !== false
1279
- };
1280
- // Handle conflict retry
1281
- if (error.type === ErrorType.CONFLICT_ERROR && (error.retry_count || 0) > 0) {
1282
- scriptData.name = `${scriptData.name}_retry_${Date.now()}`;
1283
- }
1284
- const result = await this.client.createRecord('sys_script_include', scriptData);
1285
- return { success: true, data: result };
1286
- }
1287
- catch (scriptError) {
1288
- return {
1289
- success: false,
1290
- error: scriptError instanceof Error ? scriptError.message : String(scriptError)
1291
- };
1292
- }
1293
- }
1294
- /**
1295
- * Generic deployment retry
1296
- */
1297
- async retryGenericDeployment(deploymentData, error) {
1298
- try {
1299
- this.logger.info('Retrying generic deployment', {
1300
- component_type: error.context.component_type,
1301
- data_keys: Object.keys(deploymentData)
1302
- });
1303
- // Determine table from component type or data
1304
- const table = deploymentData.table ||
1305
- this.getTableFromComponentType(error.context.component_type) ||
1306
- 'sys_metadata';
1307
- const result = await this.client.createRecord(table, deploymentData);
1308
- return { success: true, data: result };
1309
- }
1310
- catch (genericError) {
1311
- return {
1312
- success: false,
1313
- error: genericError instanceof Error ? genericError.message : String(genericError)
1314
- };
1315
- }
1316
- }
1317
- // =====================================
1318
- // RESOURCE CREATION METHODS
1319
- // =====================================
1320
- /**
1321
- * Create missing table
1322
- */
1323
- async createMissingTable(resourceData) {
1324
- try {
1325
- const tableData = {
1326
- name: resourceData.table_name || resourceData.name,
1327
- label: resourceData.label || resourceData.table_name,
1328
- super_class: resourceData.super_class || 'sys_metadata',
1329
- is_extendable: resourceData.is_extendable !== false
1330
- };
1331
- await this.client.createRecord('sys_db_object', tableData);
1332
- return { success: true };
1333
- }
1334
- catch (error) {
1335
- return { success: false, error: error instanceof Error ? error.message : String(error) };
1336
- }
1337
- }
1338
- /**
1339
- * Create missing field
1340
- */
1341
- async createMissingField(resourceData) {
1342
- try {
1343
- const fieldData = {
1344
- table: resourceData.table,
1345
- column_name: resourceData.field_name,
1346
- column_label: resourceData.label || resourceData.field_name,
1347
- internal_type: resourceData.type || 'string',
1348
- max_length: resourceData.max_length || 40
1349
- };
1350
- await this.client.createRecord('sys_dictionary', fieldData);
1351
- return { success: true };
1352
- }
1353
- catch (error) {
1354
- return { success: false, error: error instanceof Error ? error.message : String(error) };
1355
- }
1356
- }
1357
- /**
1358
- * Create missing user
1359
- */
1360
- async createMissingUser(resourceData) {
1361
- try {
1362
- const userData = {
1363
- user_name: resourceData.user_name,
1364
- first_name: resourceData.first_name || 'Unknown',
1365
- last_name: resourceData.last_name || 'User',
1366
- email: resourceData.email,
1367
- active: resourceData.active !== false
1368
- };
1369
- await this.client.createRecord('sys_user', userData);
1370
- return { success: true };
1371
- }
1372
- catch (error) {
1373
- return { success: false, error: error instanceof Error ? error.message : String(error) };
1374
- }
1375
- }
1376
- /**
1377
- * Create missing group
1378
- */
1379
- async createMissingGroup(resourceData) {
1380
- try {
1381
- const groupData = {
1382
- name: resourceData.group_name || resourceData.name,
1383
- description: resourceData.description || `Group ${resourceData.name}`,
1384
- active: resourceData.active !== false
1385
- };
1386
- await this.client.createRecord('sys_user_group', groupData);
1387
- return { success: true };
1388
- }
1389
- catch (error) {
1390
- return { success: false, error: error instanceof Error ? error.message : String(error) };
1391
- }
1392
- }
1393
- /**
1394
- * Create generic resource
1395
- */
1396
- async createGenericResource(resourceData) {
1397
- try {
1398
- const table = resourceData.table || 'sys_metadata';
1399
- await this.client.createRecord(table, resourceData);
1400
- return { success: true };
1401
- }
1402
- catch (error) {
1403
- return { success: false, error: error instanceof Error ? error.message : String(error) };
1404
- }
1405
- }
1406
- // =====================================
1407
- // UTILITY METHODS
1408
- // =====================================
1409
- /**
1410
- * Get ServiceNow table name from component type
1411
- */
1412
- getTableFromComponentType(componentType) {
1413
- if (!componentType)
1414
- return null;
1415
- const tableMap = {
1416
- 'widget': 'sp_widget',
1417
- 'flow': 'sys_hub_flow',
1418
- 'application': 'sys_app',
1419
- 'script': 'sys_script_include',
1420
- 'business_rule': 'sys_script',
1421
- 'client_script': 'sys_script_client',
1422
- 'ui_policy': 'sys_ui_policy',
1423
- 'ui_action': 'sys_ui_action',
1424
- 'table': 'sys_db_object',
1425
- 'field': 'sys_dictionary',
1426
- 'user': 'sys_user',
1427
- 'group': 'sys_user_group'
1428
- };
1429
- return tableMap[componentType.toLowerCase()] || null;
1430
- }
1431
- /**
1432
- * Enhanced operation type extraction
1433
- */
1434
- extractOperationType(operation) {
1435
- const op = operation.toLowerCase();
1436
- // More specific operation detection
1437
- if (op.includes('deploy') || op.includes('create_') || op.includes('snow_deploy'))
1438
- return 'deploy';
1439
- if (op.includes('search') || op.includes('find') || op.includes('query') || op.includes('discover'))
1440
- return 'search';
1441
- if (op.includes('create') || op.includes('insert') || op.includes('add'))
1442
- return 'create';
1443
- if (op.includes('update') || op.includes('modify') || op.includes('edit') || op.includes('patch'))
1444
- return 'update';
1445
- if (op.includes('delete') || op.includes('remove'))
1446
- return 'delete';
1447
- if (op.includes('get') || op.includes('fetch') || op.includes('retrieve'))
1448
- return 'read';
1449
- if (op.includes('authenticate') || op.includes('login') || op.includes('auth'))
1450
- return 'auth';
1451
- if (op.includes('http') || op.includes('request') || op.includes('api'))
1452
- return 'http';
1453
- return 'generic';
1454
- }
1455
- /**
1456
- * Check if error type is retryable
1457
- */
1458
- isRetryableError(errorType) {
1459
- const retryableErrors = [
1460
- ErrorType.NETWORK_ERROR,
1461
- ErrorType.TIMEOUT_ERROR,
1462
- ErrorType.RATE_LIMIT_ERROR,
1463
- ErrorType.SERVICE_UNAVAILABLE,
1464
- ErrorType.API_ERROR,
1465
- ErrorType.CONFLICT_ERROR
1466
- ];
1467
- return retryableErrors.includes(errorType);
1468
- }
1469
- /**
1470
- * Get circuit breaker status for operation
1471
- */
1472
- getCircuitBreakerStatus(operation) {
1473
- // Simple circuit breaker implementation
1474
- const recentErrors = this.errorHistory
1475
- .filter(error => error.context.operation === operation &&
1476
- error.context.timestamp.getTime() > Date.now() - 300000 // Last 5 minutes
1477
- );
1478
- const failureCount = recentErrors.length;
1479
- const isOpen = failureCount >= 5; // Open circuit after 5 failures
1480
- return {
1481
- isOpen,
1482
- failureCount,
1483
- lastFailureTime: recentErrors.length > 0 ? recentErrors[recentErrors.length - 1].context.timestamp : undefined
1484
- };
1485
- }
1486
- }
1487
- exports.FlowErrorHandler = FlowErrorHandler;
1488
- //# sourceMappingURL=error-handling.js.map