snow-flow 1.3.0 → 1.3.2

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 (42) hide show
  1. package/.claude-flow/queen/queen-memory.db +0 -0
  2. package/.env.example +249 -14
  3. package/CLAUDE.md +185 -24
  4. package/README.md +55 -5
  5. package/dist/api/error-handling.js +898 -4
  6. package/dist/api/performance-optimizer.js +3 -2
  7. package/dist/cli.js +590 -200
  8. package/dist/config/snow-flow-config.js +320 -8
  9. package/dist/health/system-health.js +288 -21
  10. package/dist/mcp/base-mcp-server.js +2 -0
  11. package/dist/mcp/http-transport-wrapper.js +65 -4
  12. package/dist/mcp/servicenow-automation-mcp-refactored.js +90 -9
  13. package/dist/mcp/servicenow-deployment-mcp-refactored.js +151 -2
  14. package/dist/mcp/servicenow-deployment-mcp.js +828 -15
  15. package/dist/mcp/servicenow-integration-mcp-refactored.js +100 -9
  16. package/dist/mcp/servicenow-intelligent-mcp.js +198 -7
  17. package/dist/mcp/servicenow-memory-mcp.js +2 -1
  18. package/dist/mcp/servicenow-operations-mcp-refactored.js +3 -2
  19. package/dist/mcp/servicenow-xml-flow-mcp.js +671 -0
  20. package/dist/mcp/shared/base-mcp-server.js +1356 -8
  21. package/dist/mcp/shared/mcp-resource-manager.js +304 -0
  22. package/dist/queen/parallel-agent-engine.js +26 -8
  23. package/dist/queen/servicenow-queen.js +47 -44
  24. package/dist/sparc/sparc-help.js +37 -26
  25. package/dist/sparc/team-sparc.js +60 -16
  26. package/dist/utils/action-type-cache.js +2 -1
  27. package/dist/utils/mcp-config-manager.js +7 -3
  28. package/dist/utils/mcp-server-manager.js +7 -3
  29. package/dist/utils/servicenow-client.js +134 -107
  30. package/dist/utils/servicenow-id-generator.js +171 -0
  31. package/dist/utils/snow-oauth.js +13 -8
  32. package/dist/utils/widget-template-generator.js +1690 -0
  33. package/dist/utils/xml-first-flow-generator.js +473 -0
  34. package/dist/version.js +7 -1
  35. package/flow-update-sets/flow_build_automated_approval_flow_with_notifications_flow.xml +203 -0
  36. package/flow-update-sets/flow_create_approval_flow_for_equipment_requests_flow.xml +206 -0
  37. package/flow-update-sets/flow_create_equipment_approval_flow_with_manager_approv_flow.xml +254 -0
  38. package/flow-update-sets/iphone_15_pro_approval_flow.xml +203 -0
  39. package/flow-update-sets/test_iphone_approval_flow_flow.xml +303 -0
  40. package/package.json +2 -1
  41. package/test-config.js +55 -0
  42. package/test-real-monitoring.js +184 -0
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * ServiceNow ID Generator - Dynamic sys_id and identifier generation
5
+ *
6
+ * Replaces hardcoded sys_ids with proper dynamic generation
7
+ * Ensures consistent ServiceNow-compatible identifiers across the system
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.COMMON_NOTIFICATION_TEMPLATES = void 0;
14
+ exports.generateServiceNowSysId = generateServiceNowSysId;
15
+ exports.generateMultipleSysIds = generateMultipleSysIds;
16
+ exports.generateDeterministicSysId = generateDeterministicSysId;
17
+ exports.generateMockSysId = generateMockSysId;
18
+ exports.generateUpdateSetName = generateUpdateSetName;
19
+ exports.generateTestUserName = generateTestUserName;
20
+ exports.generateTestGroupName = generateTestGroupName;
21
+ exports.generateCatalogItemName = generateCatalogItemName;
22
+ exports.generateRequestNumber = generateRequestNumber;
23
+ exports.generateIncidentNumber = generateIncidentNumber;
24
+ exports.isValidServiceNowSysId = isValidServiceNowSysId;
25
+ exports.generateMockRecords = generateMockRecords;
26
+ exports.generateFlowIdentifiers = generateFlowIdentifiers;
27
+ exports.getNotificationTemplateSysId = getNotificationTemplateSysId;
28
+ const uuid_1 = require("uuid");
29
+ const crypto_1 = __importDefault(require("crypto"));
30
+ /**
31
+ * Generate a ServiceNow-compatible sys_id (32-character hex string)
32
+ * ServiceNow uses lowercase 32-character hex strings without dashes
33
+ */
34
+ function generateServiceNowSysId() {
35
+ return (0, uuid_1.v4)().replace(/-/g, '').toLowerCase();
36
+ }
37
+ /**
38
+ * Generate multiple unique sys_ids at once
39
+ */
40
+ function generateMultipleSysIds(count) {
41
+ return Array.from({ length: count }, () => generateServiceNowSysId());
42
+ }
43
+ /**
44
+ * Generate a deterministic sys_id based on input string
45
+ * Useful for generating consistent sys_ids for the same input
46
+ */
47
+ function generateDeterministicSysId(input) {
48
+ const hash = crypto_1.default.createHash('md5').update(input).digest('hex');
49
+ return hash.toLowerCase();
50
+ }
51
+ /**
52
+ * Generate a prefixed sys_id for mock/test scenarios
53
+ * Maintains the 32-character requirement while being identifiable
54
+ */
55
+ function generateMockSysId(prefix = 'mock') {
56
+ const timestamp = Date.now().toString(16);
57
+ const random = Math.random().toString(16).substring(2, 10);
58
+ const base = `${prefix}_${timestamp}_${random}`;
59
+ // Ensure it's exactly 32 characters by padding or truncating
60
+ const hash = crypto_1.default.createHash('md5').update(base).digest('hex');
61
+ return hash.toLowerCase();
62
+ }
63
+ /**
64
+ * Generate dynamic update set names with timestamp
65
+ */
66
+ function generateUpdateSetName(prefix = 'Auto') {
67
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '_');
68
+ return `${prefix}_${timestamp}`;
69
+ }
70
+ /**
71
+ * Generate dynamic user names for testing
72
+ */
73
+ function generateTestUserName(prefix = 'test_user') {
74
+ const timestamp = Date.now();
75
+ const random = Math.random().toString(36).substring(7);
76
+ return `${prefix}_${timestamp}_${random}`;
77
+ }
78
+ /**
79
+ * Generate dynamic group names
80
+ */
81
+ function generateTestGroupName(prefix = 'test_group') {
82
+ const timestamp = Date.now();
83
+ const random = Math.random().toString(36).substring(7);
84
+ return `${prefix}_${timestamp}_${random}`;
85
+ }
86
+ /**
87
+ * Generate dynamic catalog item names
88
+ */
89
+ function generateCatalogItemName(baseType) {
90
+ const timestamp = Date.now();
91
+ const random = Math.random().toString(36).substring(7);
92
+ return `${baseType}_${timestamp}_${random}`;
93
+ }
94
+ /**
95
+ * Generate dynamic request numbers in ServiceNow format
96
+ */
97
+ function generateRequestNumber(prefix = 'REQ') {
98
+ const number = Math.floor(Math.random() * 999999).toString().padStart(7, '0');
99
+ return `${prefix}${number}`;
100
+ }
101
+ /**
102
+ * Generate dynamic incident numbers in ServiceNow format
103
+ */
104
+ function generateIncidentNumber(prefix = 'INC') {
105
+ const number = Math.floor(Math.random() * 999999).toString().padStart(7, '0');
106
+ return `${prefix}${number}`;
107
+ }
108
+ /**
109
+ * Validate if a string is a valid ServiceNow sys_id format
110
+ */
111
+ function isValidServiceNowSysId(sysId) {
112
+ const sysIdPattern = /^[a-f0-9]{32}$/;
113
+ return sysIdPattern.test(sysId);
114
+ }
115
+ function generateMockRecords(count, type) {
116
+ return Array.from({ length: count }, (_, index) => ({
117
+ sys_id: generateServiceNowSysId(),
118
+ name: `${type}_${index + 1}_${Date.now()}`,
119
+ type
120
+ }));
121
+ }
122
+ /**
123
+ * Generate workflow/flow-related identifiers
124
+ */
125
+ function generateFlowIdentifiers(flowName) {
126
+ const baseSysId = generateDeterministicSysId(flowName);
127
+ return {
128
+ flowSysId: baseSysId,
129
+ triggerSysId: generateDeterministicSysId(`${flowName}_trigger`),
130
+ updateSetSysId: generateServiceNowSysId(),
131
+ updateSetName: generateUpdateSetName(`Flow_${flowName.replace(/\s+/g, '_')}`)
132
+ };
133
+ }
134
+ /**
135
+ * ServiceNow system notification IDs - for common notification templates
136
+ * These should be looked up dynamically in real implementations
137
+ */
138
+ exports.COMMON_NOTIFICATION_TEMPLATES = {
139
+ // Generic notification template - should be replaced with actual lookup
140
+ generic_notification: '3c7d23a4db01030077c9a4d3ca961985',
141
+ // Default fallback - generates a deterministic sys_id for consistent behavior
142
+ default: generateDeterministicSysId('default_notification_template')
143
+ };
144
+ /**
145
+ * Get a notification template sys_id
146
+ * In production, this should query ServiceNow for actual notification templates
147
+ */
148
+ function getNotificationTemplateSysId(templateName = 'default') {
149
+ if (templateName in exports.COMMON_NOTIFICATION_TEMPLATES) {
150
+ return exports.COMMON_NOTIFICATION_TEMPLATES[templateName];
151
+ }
152
+ // Generate a consistent sys_id for unknown templates
153
+ return generateDeterministicSysId(`notification_template_${templateName}`);
154
+ }
155
+ exports.default = {
156
+ generateServiceNowSysId,
157
+ generateMultipleSysIds,
158
+ generateDeterministicSysId,
159
+ generateMockSysId,
160
+ generateUpdateSetName,
161
+ generateTestUserName,
162
+ generateTestGroupName,
163
+ generateCatalogItemName,
164
+ generateRequestNumber,
165
+ generateIncidentNumber,
166
+ isValidServiceNowSysId,
167
+ generateMockRecords,
168
+ generateFlowIdentifiers,
169
+ getNotificationTemplateSysId,
170
+ COMMON_NOTIFICATION_TEMPLATES: exports.COMMON_NOTIFICATION_TEMPLATES
171
+ };
@@ -11,15 +11,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.ServiceNowOAuth = void 0;
12
12
  const fs_1 = require("fs");
13
13
  const path_1 = require("path");
14
+ const os_1 = __importDefault(require("os"));
14
15
  const http_1 = require("http");
15
16
  const url_1 = require("url");
16
17
  const axios_1 = __importDefault(require("axios"));
17
18
  const net_1 = __importDefault(require("net"));
18
19
  const crypto_1 = __importDefault(require("crypto"));
20
+ const snow_flow_config_js_1 = require("../config/snow-flow-config.js");
19
21
  class ServiceNowOAuth {
20
22
  constructor() {
21
23
  // Store tokens in user's home directory
22
- const configDir = (0, path_1.join)(process.env.HOME || process.env.USERPROFILE || '', '.snow-flow');
24
+ const configDir = process.env.SNOW_FLOW_HOME || (0, path_1.join)(os_1.default.homedir(), '.snow-flow');
23
25
  this.tokenPath = (0, path_1.join)(configDir, 'auth.json');
24
26
  }
25
27
  /**
@@ -75,9 +77,12 @@ class ServiceNowOAuth {
75
77
  error: secretValidation.reason
76
78
  };
77
79
  }
78
- // Use fixed port 3005 for ServiceNow OAuth
79
- const port = 3005;
80
- const redirectUri = `http://localhost:${port}/callback`;
80
+ // Get OAuth redirect configuration from environment or use defaults
81
+ const oauthConfig = snow_flow_config_js_1.snowFlowConfig.servicenow.oauth;
82
+ const port = oauthConfig.redirectPort;
83
+ const host = oauthConfig.redirectHost;
84
+ const path = oauthConfig.redirectPath;
85
+ const redirectUri = `http://${host}:${port}${path}`;
81
86
  // Check if port is available
82
87
  const isPortAvailable = await this.checkPortAvailable(port);
83
88
  if (!isPortAvailable) {
@@ -156,7 +161,7 @@ class ServiceNowOAuth {
156
161
  return new Promise((resolve) => {
157
162
  const server = (0, http_1.createServer)(async (req, res) => {
158
163
  try {
159
- const url = new url_1.URL(req.url, `http://localhost:${port}`);
164
+ const url = new url_1.URL(req.url, `http://${snow_flow_config_js_1.snowFlowConfig.servicenow.oauth.redirectHost}:${port}`);
160
165
  if (url.pathname === '/callback') {
161
166
  const code = url.searchParams.get('code');
162
167
  const error = url.searchParams.get('error');
@@ -265,7 +270,7 @@ class ServiceNowOAuth {
265
270
  }
266
271
  });
267
272
  server.listen(port, () => {
268
- console.log(`🌐 OAuth callback server started on http://localhost:${port}`);
273
+ console.log(`🌐 OAuth callback server started on http://${snow_flow_config_js_1.snowFlowConfig.servicenow.oauth.redirectHost}:${port}`);
269
274
  console.log('🚀 Please open the authorization URL in your browser...');
270
275
  console.log('⏳ Waiting for OAuth callback...');
271
276
  // Auto-open browser if possible
@@ -343,7 +348,7 @@ class ServiceNowOAuth {
343
348
  */
344
349
  async saveTokens(tokenData) {
345
350
  try {
346
- const configDir = (0, path_1.join)(process.env.HOME || process.env.USERPROFILE || '', '.snow-flow');
351
+ const configDir = process.env.SNOW_FLOW_HOME || (0, path_1.join)(os_1.default.homedir(), '.snow-flow');
347
352
  await fs_1.promises.mkdir(configDir, { recursive: true });
348
353
  const expiresAt = new Date();
349
354
  expiresAt.setSeconds(expiresAt.getSeconds() + tokenData.expiresIn);
@@ -586,7 +591,7 @@ class ServiceNowOAuth {
586
591
  console.error('');
587
592
  console.error('💡 To get OAuth credentials:');
588
593
  console.error(' • ServiceNow: System OAuth > Application Registry > New OAuth Application');
589
- console.error(' • Redirect URI: http://localhost:3005/callback');
594
+ console.error(` • Redirect URI: http://${snow_flow_config_js_1.snowFlowConfig.servicenow.oauth.redirectHost}:${snow_flow_config_js_1.snowFlowConfig.servicenow.oauth.redirectPort}${snow_flow_config_js_1.snowFlowConfig.servicenow.oauth.redirectPath}`);
590
595
  console.error(' • Scopes: useraccount write admin');
591
596
  console.error('');
592
597
  return null;