snow-flow 1.3.1 ā 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.
- package/.claude-flow/queen/queen-memory.db +0 -0
- package/.env.example +249 -14
- package/CLAUDE.md +185 -24
- package/README.md +55 -5
- package/dist/api/error-handling.js +898 -4
- package/dist/api/performance-optimizer.js +3 -2
- package/dist/cli.js +590 -200
- package/dist/config/snow-flow-config.js +320 -8
- package/dist/health/system-health.js +288 -21
- package/dist/mcp/http-transport-wrapper.js +65 -4
- package/dist/mcp/servicenow-automation-mcp-refactored.js +90 -9
- package/dist/mcp/servicenow-deployment-mcp-refactored.js +151 -2
- package/dist/mcp/servicenow-deployment-mcp.js +828 -15
- package/dist/mcp/servicenow-integration-mcp-refactored.js +100 -9
- package/dist/mcp/servicenow-intelligent-mcp.js +198 -7
- package/dist/mcp/servicenow-memory-mcp.js +2 -1
- package/dist/mcp/servicenow-operations-mcp-refactored.js +3 -2
- package/dist/mcp/servicenow-xml-flow-mcp.js +671 -0
- package/dist/mcp/shared/base-mcp-server.js +1356 -8
- package/dist/mcp/shared/mcp-resource-manager.js +304 -0
- package/dist/queen/parallel-agent-engine.js +26 -8
- package/dist/queen/servicenow-queen.js +47 -44
- package/dist/sparc/sparc-help.js +37 -26
- package/dist/sparc/team-sparc.js +60 -16
- package/dist/utils/action-type-cache.js +2 -1
- package/dist/utils/mcp-config-manager.js +7 -3
- package/dist/utils/mcp-server-manager.js +7 -3
- package/dist/utils/servicenow-client.js +134 -107
- package/dist/utils/servicenow-id-generator.js +171 -0
- package/dist/utils/snow-oauth.js +13 -8
- package/dist/utils/widget-template-generator.js +1690 -0
- package/dist/utils/xml-first-flow-generator.js +473 -0
- package/flow-update-sets/flow_build_automated_approval_flow_with_notifications_flow.xml +203 -0
- package/flow-update-sets/flow_create_approval_flow_for_equipment_requests_flow.xml +206 -0
- package/flow-update-sets/flow_create_equipment_approval_flow_with_manager_approv_flow.xml +254 -0
- package/flow-update-sets/iphone_15_pro_approval_flow.xml +203 -0
- package/flow-update-sets/test_iphone_approval_flow_flow.xml +303 -0
- package/package.json +2 -1
- package/test-config.js +55 -0
- package/test-real-monitoring.js +184 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Resource Manager
|
|
4
|
+
* Comprehensive resource management for MCP servers
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MCPResourceManager = void 0;
|
|
8
|
+
const promises_1 = require("fs/promises");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const logger_js_1 = require("../../utils/logger.js");
|
|
11
|
+
class MCPResourceManager {
|
|
12
|
+
constructor(serverName = 'mcp-server') {
|
|
13
|
+
this.resourceCache = new Map();
|
|
14
|
+
this.resourceIndex = new Map();
|
|
15
|
+
this.categories = [];
|
|
16
|
+
this.logger = new logger_js_1.Logger(`ResourceManager:${serverName}`);
|
|
17
|
+
this.initializeCategories();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Initialize resource categories
|
|
21
|
+
*/
|
|
22
|
+
initializeCategories() {
|
|
23
|
+
const projectRoot = this.getProjectRoot();
|
|
24
|
+
this.categories = [
|
|
25
|
+
{
|
|
26
|
+
name: 'templates',
|
|
27
|
+
description: 'ServiceNow artifact templates (widgets, flows, scripts, etc.)',
|
|
28
|
+
basePath: (0, path_1.join)(projectRoot, 'src/templates'),
|
|
29
|
+
uriPrefix: 'servicenow://templates/'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'documentation',
|
|
33
|
+
description: 'Setup guides, deployment documentation, and API references',
|
|
34
|
+
basePath: projectRoot,
|
|
35
|
+
uriPrefix: 'servicenow://docs/'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'schemas',
|
|
39
|
+
description: 'Data validation schemas and API schemas',
|
|
40
|
+
basePath: (0, path_1.join)(projectRoot, 'src/schemas'),
|
|
41
|
+
uriPrefix: 'servicenow://schemas/'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'examples',
|
|
45
|
+
description: 'Example implementations and sample data',
|
|
46
|
+
basePath: (0, path_1.join)(projectRoot, 'src/templates/examples'),
|
|
47
|
+
uriPrefix: 'servicenow://examples/'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'help',
|
|
51
|
+
description: 'Help content and guidance documents',
|
|
52
|
+
basePath: (0, path_1.join)(projectRoot, 'src/sparc'),
|
|
53
|
+
uriPrefix: 'servicenow://help/'
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get project root directory
|
|
59
|
+
*/
|
|
60
|
+
getProjectRoot() {
|
|
61
|
+
// Use process.cwd() to get the current working directory
|
|
62
|
+
// This should be the project root when running the application
|
|
63
|
+
return process.cwd();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* List all available resources
|
|
67
|
+
*/
|
|
68
|
+
async listResources() {
|
|
69
|
+
if (this.resourceIndex.size === 0) {
|
|
70
|
+
await this.buildResourceIndex();
|
|
71
|
+
}
|
|
72
|
+
return Array.from(this.resourceIndex.values());
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Read a specific resource by URI
|
|
76
|
+
*/
|
|
77
|
+
async readResource(uri) {
|
|
78
|
+
this.logger.debug(`Reading resource: ${uri}`);
|
|
79
|
+
// Check cache first
|
|
80
|
+
if (this.resourceCache.has(uri)) {
|
|
81
|
+
this.logger.debug(`Resource found in cache: ${uri}`);
|
|
82
|
+
return this.resourceCache.get(uri);
|
|
83
|
+
}
|
|
84
|
+
// Parse URI and determine file path
|
|
85
|
+
const filePath = this.uriToFilePath(uri);
|
|
86
|
+
if (!filePath) {
|
|
87
|
+
throw new Error(`Invalid resource URI: ${uri}`);
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const content = await this.loadResourceContent(filePath, uri);
|
|
91
|
+
// Cache the content
|
|
92
|
+
this.resourceCache.set(uri, content);
|
|
93
|
+
return content;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
this.logger.error(`Failed to read resource ${uri}:`, error);
|
|
97
|
+
throw new Error(`Resource not found or inaccessible: ${uri}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build comprehensive resource index
|
|
102
|
+
*/
|
|
103
|
+
async buildResourceIndex() {
|
|
104
|
+
this.logger.info('Building resource index...');
|
|
105
|
+
for (const category of this.categories) {
|
|
106
|
+
try {
|
|
107
|
+
await this.indexCategory(category);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
this.logger.warn(`Failed to index category ${category.name}:`, error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
this.logger.info(`Resource index built: ${this.resourceIndex.size} resources`);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Index resources in a specific category
|
|
117
|
+
*/
|
|
118
|
+
async indexCategory(category) {
|
|
119
|
+
try {
|
|
120
|
+
const stats = await (0, promises_1.stat)(category.basePath);
|
|
121
|
+
if (!stats.isDirectory()) {
|
|
122
|
+
this.logger.debug(`Category path is not a directory: ${category.basePath}`);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
this.logger.debug(`Category path does not exist: ${category.basePath}`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (category.name === 'documentation') {
|
|
131
|
+
await this.indexDocumentationFiles(category);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
await this.indexDirectoryRecursive(category.basePath, category);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Index documentation files (special handling for .md files in root)
|
|
139
|
+
*/
|
|
140
|
+
async indexDocumentationFiles(category) {
|
|
141
|
+
try {
|
|
142
|
+
const files = await (0, promises_1.readdir)(category.basePath);
|
|
143
|
+
for (const file of files) {
|
|
144
|
+
if (file.endsWith('.md') && file.toUpperCase().includes('SERVICENOW')) {
|
|
145
|
+
const filePath = (0, path_1.join)(category.basePath, file);
|
|
146
|
+
const uri = `${category.uriPrefix}${file}`;
|
|
147
|
+
const resource = {
|
|
148
|
+
uri,
|
|
149
|
+
name: this.formatResourceName(file),
|
|
150
|
+
description: `ServiceNow documentation: ${this.formatResourceName(file)}`,
|
|
151
|
+
mimeType: this.getMimeType(file)
|
|
152
|
+
};
|
|
153
|
+
this.resourceIndex.set(uri, resource);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.logger.warn(`Failed to index documentation files:`, error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Index directory recursively
|
|
163
|
+
*/
|
|
164
|
+
async indexDirectoryRecursive(dirPath, category, relativePath = '') {
|
|
165
|
+
try {
|
|
166
|
+
const entries = await (0, promises_1.readdir)(dirPath);
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
const fullPath = (0, path_1.join)(dirPath, entry);
|
|
169
|
+
const entryRelativePath = relativePath ? (0, path_1.join)(relativePath, entry) : entry;
|
|
170
|
+
try {
|
|
171
|
+
const stats = await (0, promises_1.stat)(fullPath);
|
|
172
|
+
if (stats.isDirectory()) {
|
|
173
|
+
await this.indexDirectoryRecursive(fullPath, category, entryRelativePath);
|
|
174
|
+
}
|
|
175
|
+
else if (this.isResourceFile(entry)) {
|
|
176
|
+
const uri = `${category.uriPrefix}${entryRelativePath.replace(/\\/g, '/')}`;
|
|
177
|
+
const resource = {
|
|
178
|
+
uri,
|
|
179
|
+
name: this.formatResourceName(entry),
|
|
180
|
+
description: this.generateResourceDescription(entry, category.name),
|
|
181
|
+
mimeType: this.getMimeType(entry)
|
|
182
|
+
};
|
|
183
|
+
this.resourceIndex.set(uri, resource);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
this.logger.debug(`Failed to process ${fullPath}:`, error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
this.logger.warn(`Failed to read directory ${dirPath}:`, error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if file should be exposed as a resource
|
|
197
|
+
*/
|
|
198
|
+
isResourceFile(filename) {
|
|
199
|
+
const resourceExtensions = ['.json', '.md', '.yaml', '.yml', '.txt', '.ts', '.js'];
|
|
200
|
+
const ext = (0, path_1.extname)(filename).toLowerCase();
|
|
201
|
+
return resourceExtensions.includes(ext);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Convert URI to file path
|
|
205
|
+
*/
|
|
206
|
+
uriToFilePath(uri) {
|
|
207
|
+
for (const category of this.categories) {
|
|
208
|
+
if (uri.startsWith(category.uriPrefix)) {
|
|
209
|
+
const relativePath = uri.substring(category.uriPrefix.length);
|
|
210
|
+
if (category.name === 'documentation') {
|
|
211
|
+
// Documentation files are in root
|
|
212
|
+
return (0, path_1.join)(category.basePath, relativePath);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
return (0, path_1.join)(category.basePath, relativePath);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Load resource content from file
|
|
223
|
+
*/
|
|
224
|
+
async loadResourceContent(filePath, uri) {
|
|
225
|
+
const content = await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
226
|
+
const mimeType = this.getMimeType(filePath);
|
|
227
|
+
return {
|
|
228
|
+
uri,
|
|
229
|
+
mimeType,
|
|
230
|
+
text: content
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get MIME type for file
|
|
235
|
+
*/
|
|
236
|
+
getMimeType(filePath) {
|
|
237
|
+
const ext = (0, path_1.extname)(filePath).toLowerCase();
|
|
238
|
+
const mimeTypes = {
|
|
239
|
+
'.json': 'application/json',
|
|
240
|
+
'.md': 'text/markdown',
|
|
241
|
+
'.yaml': 'application/yaml',
|
|
242
|
+
'.yml': 'application/yaml',
|
|
243
|
+
'.txt': 'text/plain',
|
|
244
|
+
'.ts': 'text/typescript',
|
|
245
|
+
'.js': 'text/javascript',
|
|
246
|
+
'.html': 'text/html',
|
|
247
|
+
'.css': 'text/css'
|
|
248
|
+
};
|
|
249
|
+
return mimeTypes[ext] || 'text/plain';
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Format resource name for display
|
|
253
|
+
*/
|
|
254
|
+
formatResourceName(filename) {
|
|
255
|
+
const nameWithoutExt = (0, path_1.basename)(filename, (0, path_1.extname)(filename));
|
|
256
|
+
// Convert various naming conventions to readable names
|
|
257
|
+
return nameWithoutExt
|
|
258
|
+
.replace(/[-_]/g, ' ')
|
|
259
|
+
.replace(/\b\w/g, l => l.toUpperCase())
|
|
260
|
+
.replace(/\.(template|schema|example)/i, '');
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Generate resource description based on filename and category
|
|
264
|
+
*/
|
|
265
|
+
generateResourceDescription(filename, categoryName) {
|
|
266
|
+
const name = this.formatResourceName(filename);
|
|
267
|
+
const descriptions = {
|
|
268
|
+
'templates': `ServiceNow ${name} template`,
|
|
269
|
+
'documentation': `Documentation: ${name}`,
|
|
270
|
+
'schemas': `Validation schema for ${name}`,
|
|
271
|
+
'examples': `Example implementation: ${name}`,
|
|
272
|
+
'help': `Help content: ${name}`
|
|
273
|
+
};
|
|
274
|
+
return descriptions[categoryName] || `Resource: ${name}`;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Clear resource cache
|
|
278
|
+
*/
|
|
279
|
+
clearCache() {
|
|
280
|
+
this.resourceCache.clear();
|
|
281
|
+
this.resourceIndex.clear();
|
|
282
|
+
this.logger.debug('Resource cache cleared');
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Get resource statistics
|
|
286
|
+
*/
|
|
287
|
+
getResourceStats() {
|
|
288
|
+
const categories = {};
|
|
289
|
+
for (const resource of this.resourceIndex.values()) {
|
|
290
|
+
for (const category of this.categories) {
|
|
291
|
+
if (resource.uri.startsWith(category.uriPrefix)) {
|
|
292
|
+
categories[category.name] = (categories[category.name] || 0) + 1;
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
total: this.resourceIndex.size,
|
|
299
|
+
cached: this.resourceCache.size,
|
|
300
|
+
categories
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
exports.MCPResourceManager = MCPResourceManager;
|
|
@@ -40,10 +40,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
41
|
exports.ParallelAgentEngine = void 0;
|
|
42
42
|
const eventemitter3_1 = require("eventemitter3");
|
|
43
|
+
const logger_1 = require("../utils/logger");
|
|
43
44
|
const crypto = __importStar(require("crypto"));
|
|
44
45
|
class ParallelAgentEngine extends eventemitter3_1.EventEmitter {
|
|
45
46
|
constructor(memory) {
|
|
46
47
|
super();
|
|
48
|
+
this.logger = new logger_1.Logger('ParallelAgentEngine');
|
|
47
49
|
this.memory = memory;
|
|
48
50
|
this.activeExecutionPlans = new Map();
|
|
49
51
|
this.agentWorkloads = new Map();
|
|
@@ -55,7 +57,11 @@ class ParallelAgentEngine extends eventemitter3_1.EventEmitter {
|
|
|
55
57
|
* Main entry point: Analyze todos and detect parallelization opportunities
|
|
56
58
|
*/
|
|
57
59
|
async detectParallelizationOpportunities(todos, objectiveType, currentAgents) {
|
|
58
|
-
|
|
60
|
+
this.logger.info('š§ Analyzing parallelization opportunities', {
|
|
61
|
+
todoCount: todos.length,
|
|
62
|
+
objectiveType,
|
|
63
|
+
currentAgentCount: currentAgents.length
|
|
64
|
+
});
|
|
59
65
|
const opportunities = [];
|
|
60
66
|
// 1. Detect independent tasks (can run simultaneously)
|
|
61
67
|
const independentOpportunity = await this.detectIndependentTasks(todos);
|
|
@@ -77,7 +83,11 @@ class ParallelAgentEngine extends eventemitter3_1.EventEmitter {
|
|
|
77
83
|
const rankedOpportunities = opportunities
|
|
78
84
|
.filter(opp => opp.confidence > 0.5 && opp.estimatedSpeedup > 1.1) // Lower thresholds
|
|
79
85
|
.sort((a, b) => (b.confidence * b.estimatedSpeedup) - (a.confidence * a.estimatedSpeedup));
|
|
80
|
-
|
|
86
|
+
this.logger.info(`šÆ Found ${rankedOpportunities.length} high-confidence parallelization opportunities`, {
|
|
87
|
+
totalOpportunities: opportunities.length,
|
|
88
|
+
rankedCount: rankedOpportunities.length,
|
|
89
|
+
averageConfidence: rankedOpportunities.reduce((sum, opp) => sum + opp.confidence, 0) / rankedOpportunities.length || 0
|
|
90
|
+
});
|
|
81
91
|
// Store opportunities for learning
|
|
82
92
|
await this.storeOpportunities(todos, rankedOpportunities);
|
|
83
93
|
return rankedOpportunities;
|
|
@@ -103,18 +113,26 @@ class ParallelAgentEngine extends eventemitter3_1.EventEmitter {
|
|
|
103
113
|
failureRecovery: 'reassign'
|
|
104
114
|
};
|
|
105
115
|
this.activeExecutionPlans.set(planId, plan);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
this.logger.info(`š Created execution plan ${planId}`, {
|
|
117
|
+
planId,
|
|
118
|
+
strategy,
|
|
119
|
+
teamSize: agentTeam.length,
|
|
120
|
+
estimatedCompletion,
|
|
121
|
+
maxParallelism: plan.maxParallelism,
|
|
122
|
+
opportunityCount: opportunities.length
|
|
123
|
+
});
|
|
111
124
|
return plan;
|
|
112
125
|
}
|
|
113
126
|
/**
|
|
114
127
|
* Execute parallel plan and coordinate agents
|
|
115
128
|
*/
|
|
116
129
|
async executeParallelPlan(plan, spawnAgentCallback) {
|
|
117
|
-
|
|
130
|
+
this.logger.info(`š Executing parallel plan ${plan.planId}`, {
|
|
131
|
+
planId: plan.planId,
|
|
132
|
+
strategy: plan.executionStrategy,
|
|
133
|
+
agentTeamSize: plan.agentTeam.length,
|
|
134
|
+
maxParallelism: plan.maxParallelism
|
|
135
|
+
});
|
|
118
136
|
const spawnedAgents = [];
|
|
119
137
|
// Spawn agents based on plan
|
|
120
138
|
for (const workload of plan.agentTeam) {
|
|
@@ -45,6 +45,7 @@ const mcp_execution_bridge_1 = require("./mcp-execution-bridge");
|
|
|
45
45
|
const theme_manager_1 = require("../utils/theme-manager");
|
|
46
46
|
const dependency_detector_1 = require("../utils/dependency-detector");
|
|
47
47
|
const gap_analysis_engine_1 = require("../intelligence/gap-analysis-engine");
|
|
48
|
+
const logger_1 = require("../utils/logger");
|
|
48
49
|
const crypto = __importStar(require("crypto"));
|
|
49
50
|
class ServiceNowQueen {
|
|
50
51
|
constructor(config = {}) {
|
|
@@ -55,17 +56,19 @@ class ServiceNowQueen {
|
|
|
55
56
|
debugMode: config.debugMode || false,
|
|
56
57
|
autoPermissions: config.autoPermissions || false
|
|
57
58
|
};
|
|
59
|
+
// Initialize logger
|
|
60
|
+
this.logger = new logger_1.Logger('ServiceNowQueen');
|
|
58
61
|
// Initialize hive-mind components
|
|
59
62
|
this.memory = new queen_memory_1.QueenMemorySystem(this.config.memoryPath);
|
|
60
63
|
this.neuralLearning = new neural_learning_1.NeuralLearning(this.memory);
|
|
61
64
|
this.agentFactory = new agent_factory_1.AgentFactory(this.memory);
|
|
62
65
|
this.mcpBridge = new mcp_execution_bridge_1.MCPExecutionBridge(this.memory);
|
|
63
|
-
this.gapAnalysisEngine = new gap_analysis_engine_1.GapAnalysisEngine(this.mcpBridge,
|
|
66
|
+
this.gapAnalysisEngine = new gap_analysis_engine_1.GapAnalysisEngine(this.mcpBridge, this.logger, this.config.autoPermissions);
|
|
64
67
|
this.activeTasks = new Map();
|
|
65
68
|
if (this.config.debugMode) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
this.logger.info('š ServiceNow Queen Agent initialized with hive-mind intelligence');
|
|
70
|
+
this.logger.info('š MCP Execution Bridge connected for real ServiceNow operations');
|
|
71
|
+
this.logger.info('š§ Intelligent Gap Analysis Engine ready for beyond-MCP configurations');
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
/**
|
|
@@ -76,11 +79,11 @@ class ServiceNowQueen {
|
|
|
76
79
|
const startTime = Date.now();
|
|
77
80
|
try {
|
|
78
81
|
if (this.config.debugMode) {
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
this.logger.info(`šÆ Queen analyzing objective: ${objective}`);
|
|
83
|
+
this.logger.info(`šØ ENFORCING MCP-FIRST WORKFLOW`);
|
|
81
84
|
}
|
|
82
85
|
// šØ PHASE 1: MANDATORY MCP PRE-FLIGHT AUTHENTICATION CHECK
|
|
83
|
-
|
|
86
|
+
this.logger.info('š Step 1: Validating ServiceNow connection...');
|
|
84
87
|
const authCheck = await this.mcpBridge.executeAgentRecommendation({
|
|
85
88
|
type: 'mcp_call',
|
|
86
89
|
tool: 'snow_validate_live_connection',
|
|
@@ -98,12 +101,12 @@ class ServiceNowQueen {
|
|
|
98
101
|
|
|
99
102
|
ā Cannot proceed with Queen Agent operations until authentication works!
|
|
100
103
|
`;
|
|
101
|
-
|
|
104
|
+
this.logger.error('Authentication failed:', authError);
|
|
102
105
|
throw new Error(authError);
|
|
103
106
|
}
|
|
104
|
-
|
|
107
|
+
this.logger.info('ā
ServiceNow authentication validated');
|
|
105
108
|
// šØ PHASE 2: MANDATORY SMART DISCOVERY (Prevent Duplication)
|
|
106
|
-
|
|
109
|
+
this.logger.info('š Step 2: Discovering existing artifacts...');
|
|
107
110
|
const discovery = await this.mcpBridge.executeAgentRecommendation({
|
|
108
111
|
type: 'mcp_call',
|
|
109
112
|
tool: 'snow_comprehensive_search',
|
|
@@ -114,9 +117,9 @@ class ServiceNowQueen {
|
|
|
114
117
|
reasoning: 'MANDATORY: Check for existing artifacts before creating new ones'
|
|
115
118
|
});
|
|
116
119
|
if (discovery.success && discovery.result?.found?.length > 0) {
|
|
117
|
-
|
|
120
|
+
this.logger.info(`š Found ${discovery.result.found.length} existing artifacts that might be relevant:`);
|
|
118
121
|
discovery.result.found.forEach((artifact) => {
|
|
119
|
-
|
|
122
|
+
this.logger.info(`š” Consider reusing: ${artifact.name} (${artifact.sys_id})`);
|
|
120
123
|
});
|
|
121
124
|
}
|
|
122
125
|
// Phase 3: Initial Neural Analysis (informed by MCP discovery)
|
|
@@ -131,7 +134,7 @@ class ServiceNowQueen {
|
|
|
131
134
|
};
|
|
132
135
|
this.activeTasks.set(taskId, task);
|
|
133
136
|
// šØ PHASE 5: INTELLIGENT GAP ANALYSIS (Beyond MCP Tools)
|
|
134
|
-
|
|
137
|
+
this.logger.info('š§ Step 4: Running Intelligent Gap Analysis...');
|
|
135
138
|
let gapAnalysisResult = null;
|
|
136
139
|
try {
|
|
137
140
|
gapAnalysisResult = await this.gapAnalysisEngine.analyzeAndResolve(objective, {
|
|
@@ -141,35 +144,35 @@ class ServiceNowQueen {
|
|
|
141
144
|
includeManualGuides: true,
|
|
142
145
|
riskTolerance: 'medium'
|
|
143
146
|
});
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
this.logger.info(`š Gap Analysis Complete:`);
|
|
148
|
+
this.logger.info(` ⢠Total Requirements: ${gapAnalysisResult.totalRequirements}`);
|
|
149
|
+
this.logger.info(` ⢠MCP Coverage: ${gapAnalysisResult.mcpCoverage.coveragePercentage}%`);
|
|
150
|
+
this.logger.info(` ⢠Automated: ${gapAnalysisResult.summary.successfulAutomation} configurations`);
|
|
151
|
+
this.logger.info(` ⢠Manual Work: ${gapAnalysisResult.summary.requiresManualWork} items`);
|
|
149
152
|
// Display manual instructions if needed
|
|
150
153
|
if (gapAnalysisResult.summary.requiresManualWork > 0) {
|
|
151
|
-
|
|
152
|
-
gapAnalysisResult.nextSteps.manual.forEach(step =>
|
|
154
|
+
this.logger.info('\nš Manual Configuration Required:');
|
|
155
|
+
gapAnalysisResult.nextSteps.manual.forEach(step => this.logger.info(` ⢠${step}`));
|
|
153
156
|
if (gapAnalysisResult.manualGuides) {
|
|
154
|
-
|
|
157
|
+
this.logger.info('\nš Detailed manual guides available in gap analysis result');
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
// Display automation successes
|
|
158
161
|
if (gapAnalysisResult.summary.successfulAutomation > 0) {
|
|
159
|
-
|
|
160
|
-
gapAnalysisResult.nextSteps.automated.forEach(step =>
|
|
162
|
+
this.logger.info('\nā
Automated Configurations:');
|
|
163
|
+
gapAnalysisResult.nextSteps.automated.forEach(step => this.logger.info(` ⢠${step}`));
|
|
161
164
|
}
|
|
162
165
|
// Display recommendations
|
|
163
166
|
if (gapAnalysisResult.nextSteps.recommendations.length > 0) {
|
|
164
|
-
|
|
165
|
-
gapAnalysisResult.nextSteps.recommendations.forEach(rec =>
|
|
167
|
+
this.logger.info('\nš” Recommendations:');
|
|
168
|
+
gapAnalysisResult.nextSteps.recommendations.forEach(rec => this.logger.info(` ⢠${rec}`));
|
|
166
169
|
}
|
|
167
170
|
// Store gap analysis result in task for later reference
|
|
168
171
|
task.gapAnalysis = gapAnalysisResult;
|
|
169
172
|
}
|
|
170
173
|
catch (gapError) {
|
|
171
174
|
console.warn(`ā ļø Gap Analysis failed: ${gapError instanceof Error ? gapError.message : 'Unknown error'}`);
|
|
172
|
-
|
|
175
|
+
this.logger.info('š Continuing with standard MCP workflow...');
|
|
173
176
|
}
|
|
174
177
|
// Phase 6: Spawn optimal agent swarm
|
|
175
178
|
const agents = this.spawnOptimalSwarm(task, analysis);
|
|
@@ -182,7 +185,7 @@ class ServiceNowQueen {
|
|
|
182
185
|
task.status = 'completed';
|
|
183
186
|
task.result = result;
|
|
184
187
|
if (this.config.debugMode) {
|
|
185
|
-
|
|
188
|
+
this.logger.info(`ā
Queen completed objective in ${duration}ms`);
|
|
186
189
|
}
|
|
187
190
|
return result;
|
|
188
191
|
}
|
|
@@ -197,7 +200,7 @@ class ServiceNowQueen {
|
|
|
197
200
|
}
|
|
198
201
|
spawnOptimalSwarm(task, analysis) {
|
|
199
202
|
if (this.config.debugMode) {
|
|
200
|
-
|
|
203
|
+
this.logger.info(`š Spawning swarm for ${task.type} task (complexity: ${analysis.estimatedComplexity})`);
|
|
201
204
|
}
|
|
202
205
|
// Use learned patterns or optimal sequence
|
|
203
206
|
const agentTypes = analysis.suggestedPattern?.agentSequence ||
|
|
@@ -205,7 +208,7 @@ class ServiceNowQueen {
|
|
|
205
208
|
// Spawn agent swarm
|
|
206
209
|
const agents = this.agentFactory.spawnAgentSwarm(agentTypes, task.id);
|
|
207
210
|
if (this.config.debugMode) {
|
|
208
|
-
|
|
211
|
+
this.logger.info(`š„ Spawned ${agents.length} agents: ${agents.map(a => a.type).join(', ')}`);
|
|
209
212
|
}
|
|
210
213
|
return agents;
|
|
211
214
|
}
|
|
@@ -241,14 +244,14 @@ class ServiceNowQueen {
|
|
|
241
244
|
}
|
|
242
245
|
async executeAgentsInParallel(agents, objective) {
|
|
243
246
|
if (this.config.debugMode) {
|
|
244
|
-
|
|
247
|
+
this.logger.info('ā” Executing agents in parallel');
|
|
245
248
|
}
|
|
246
249
|
const promises = agents.map(agent => this.agentFactory.executeAgentTask(agent.id, objective));
|
|
247
250
|
return await Promise.all(promises);
|
|
248
251
|
}
|
|
249
252
|
async executeAgentsSequentially(agents, objective) {
|
|
250
253
|
if (this.config.debugMode) {
|
|
251
|
-
|
|
254
|
+
this.logger.info('š Executing agents sequentially');
|
|
252
255
|
}
|
|
253
256
|
const results = [];
|
|
254
257
|
for (const agent of agents) {
|
|
@@ -273,7 +276,7 @@ class ServiceNowQueen {
|
|
|
273
276
|
}
|
|
274
277
|
async executeFinalDeployment(task, agentResults, analysis) {
|
|
275
278
|
if (this.config.debugMode) {
|
|
276
|
-
|
|
279
|
+
this.logger.info('š Executing final deployment with MCP tools');
|
|
277
280
|
}
|
|
278
281
|
// The Queen coordinates the actual MCP tool calls based on agent recommendations
|
|
279
282
|
const deploymentPlan = this.createDeploymentPlan(task, agentResults, analysis);
|
|
@@ -609,7 +612,7 @@ function($scope) {
|
|
|
609
612
|
async executeDeploymentPlan(plan) {
|
|
610
613
|
// Execute real MCP tools through the bridge
|
|
611
614
|
if (this.config.debugMode) {
|
|
612
|
-
|
|
615
|
+
this.logger.info('š Executing deployment plan with MCP Bridge');
|
|
613
616
|
}
|
|
614
617
|
// Create agent recommendation from plan
|
|
615
618
|
const recommendation = {
|
|
@@ -665,9 +668,9 @@ function($scope) {
|
|
|
665
668
|
if (dependencies.length === 0) {
|
|
666
669
|
return; // No dependencies needed
|
|
667
670
|
}
|
|
668
|
-
|
|
671
|
+
this.logger.info(`\nš¦ Detected ${dependencies.length} external dependencies in widget:`);
|
|
669
672
|
dependencies.forEach(dep => {
|
|
670
|
-
|
|
673
|
+
this.logger.info(` ⢠${dep.name} - ${dep.description}`);
|
|
671
674
|
});
|
|
672
675
|
// Create MCP tools wrapper for theme manager
|
|
673
676
|
const mcpTools = {
|
|
@@ -735,22 +738,22 @@ function($scope) {
|
|
|
735
738
|
useMinified: true
|
|
736
739
|
});
|
|
737
740
|
if (result.success) {
|
|
738
|
-
|
|
741
|
+
this.logger.info(`ā
${result.message}`);
|
|
739
742
|
}
|
|
740
743
|
else {
|
|
741
|
-
|
|
742
|
-
|
|
744
|
+
this.logger.warn(`ā ļø Dependencies not installed: ${result.message}`);
|
|
745
|
+
this.logger.info('š” You may need to manually add these dependencies to your Service Portal theme');
|
|
743
746
|
}
|
|
744
747
|
}
|
|
745
748
|
catch (error) {
|
|
746
749
|
console.error('ā Error handling widget dependencies:', error.message);
|
|
747
750
|
// Don't fail the deployment, just warn
|
|
748
|
-
|
|
751
|
+
this.logger.warn('ā ļø Widget deployed successfully but dependencies may need manual installation');
|
|
749
752
|
}
|
|
750
753
|
}
|
|
751
754
|
async attemptRecovery(task, agents, error) {
|
|
752
755
|
if (this.config.debugMode) {
|
|
753
|
-
|
|
756
|
+
this.logger.info(`š Attempting recovery for task ${task.id}`);
|
|
754
757
|
}
|
|
755
758
|
// Try with reduced complexity or different agent sequence
|
|
756
759
|
const fallbackResult = {
|
|
@@ -775,7 +778,7 @@ function($scope) {
|
|
|
775
778
|
this.memory.recordTaskCompletion(task.id, task.objective, task.type, agentTypes, true, duration);
|
|
776
779
|
}
|
|
777
780
|
if (this.config.debugMode) {
|
|
778
|
-
|
|
781
|
+
this.logger.info(`š Queen learned from ${error ? 'failure' : 'success'}: ${task.objective}`);
|
|
779
782
|
}
|
|
780
783
|
}
|
|
781
784
|
async handleExecutionFailure(taskId, objective, error, duration) {
|
|
@@ -837,7 +840,7 @@ function($scope) {
|
|
|
837
840
|
importMemory(memoryData) {
|
|
838
841
|
this.memory.importMemory(memoryData);
|
|
839
842
|
if (this.config.debugMode) {
|
|
840
|
-
|
|
843
|
+
this.logger.info('š§ Queen hive-mind memory imported successfully');
|
|
841
844
|
}
|
|
842
845
|
}
|
|
843
846
|
clearMemory() {
|
|
@@ -845,7 +848,7 @@ function($scope) {
|
|
|
845
848
|
// Also reset neural learning weights
|
|
846
849
|
this.neuralLearning = new neural_learning_1.NeuralLearning(this.memory);
|
|
847
850
|
if (this.config.debugMode) {
|
|
848
|
-
|
|
851
|
+
this.logger.info('š§ Queen hive-mind memory cleared - starting fresh');
|
|
849
852
|
}
|
|
850
853
|
}
|
|
851
854
|
getLearningInsights() {
|
|
@@ -880,7 +883,7 @@ function($scope) {
|
|
|
880
883
|
}
|
|
881
884
|
async shutdown() {
|
|
882
885
|
if (this.config.debugMode) {
|
|
883
|
-
|
|
886
|
+
this.logger.info('š Shutting down ServiceNow Queen Agent');
|
|
884
887
|
}
|
|
885
888
|
// Clean up all agents
|
|
886
889
|
const activeAgents = this.agentFactory.getActiveAgents();
|