snow-flow 2.0.2 → 2.0.4

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 (173) hide show
  1. package/{.claude/mcp-config.json → .mcp.json} +13 -12
  2. package/.releaserc.json +47 -0
  3. package/README.md +48 -1
  4. package/package.json +1 -1
  5. package/.claude/claude-settings.json +0 -15
  6. package/.claude/commands/analysis/README.md +0 -9
  7. package/.claude/commands/automation/README.md +0 -9
  8. package/.claude/commands/github/README.md +0 -11
  9. package/.claude/commands/helpers/standard-checkpoint-hooks.sh +0 -179
  10. package/.claude/commands/hooks/README.md +0 -11
  11. package/.claude/commands/monitoring/README.md +0 -9
  12. package/.claude/commands/optimization/README.md +0 -9
  13. package/.claude/commands/training/README.md +0 -9
  14. package/.claude/commands/workflows/README.md +0 -9
  15. package/.claude/config.json +0 -36
  16. package/.claude/helpers/github-setup.sh +0 -28
  17. package/.claude/helpers/quick-start.sh +0 -19
  18. package/.claude/helpers/setup-mcp.sh +0 -18
  19. package/.claude/settings.json +0 -114
  20. package/.claude/settings.local.json +0 -33
  21. package/.claude-flow/metrics/agent-metrics.json +0 -1
  22. package/.claude-flow/metrics/performance.json +0 -9
  23. package/.claude-flow/metrics/system-metrics.json +0 -15986
  24. package/.claude-flow/metrics/task-metrics.json +0 -10
  25. package/.roo/README.md +0 -402
  26. package/.roo/mcp-list.txt +0 -257
  27. package/.roo/mcp.json +0 -32
  28. package/.roo/workflows/basic-tdd.json +0 -32
  29. package/.roomodes +0 -201
  30. package/CLAUDE.md +0 -393
  31. package/bin/snow-flow.js +0 -3
  32. package/dist/cli.js.bak +0 -2052
  33. package/dist/config/snow-flow-config.d.ts +0 -1492
  34. package/dist/config/snow-flow-config.js +0 -938
  35. package/scripts/create-env.js +0 -91
  36. package/scripts/postinstall.js +0 -30
  37. package/scripts/register-mcp-servers.js +0 -210
  38. package/scripts/reset-mcp-servers.js +0 -246
  39. package/scripts/setup-mcp.js +0 -106
  40. package/scripts/update-version.js +0 -31
  41. package/src/agents/README.md +0 -192
  42. package/src/agents/base-agent.ts +0 -251
  43. package/src/agents/coordinator.ts +0 -971
  44. package/src/agents/index.ts +0 -18
  45. package/src/agents/queen-403-handler.ts +0 -230
  46. package/src/agents/queen-agent.ts +0 -1399
  47. package/src/agents/script-writer-agent.ts +0 -769
  48. package/src/agents/security-agent.ts +0 -726
  49. package/src/agents/widget-creator-agent.ts +0 -568
  50. package/src/api/error-handling.ts +0 -1758
  51. package/src/api/natural-language-mapper.ts +0 -630
  52. package/src/api/performance-optimizer.ts +0 -891
  53. package/src/api/transaction-manager.ts +0 -754
  54. package/src/cli/deploy-artifact.ts +0 -304
  55. package/src/cli/snow-flow-cli-integration.ts +0 -434
  56. package/src/cli.ts +0 -4455
  57. package/src/cli.ts.bak +0 -5616
  58. package/src/compliance/advanced-compliance-system.ts +0 -1268
  59. package/src/compliance/index.ts +0 -19
  60. package/src/config/snow-flow-config.ts +0 -1019
  61. package/src/documentation/index.ts +0 -16
  62. package/src/documentation/self-documenting-system.ts +0 -1421
  63. package/src/dynamic-version.ts +0 -44
  64. package/src/healing/index.ts +0 -20
  65. package/src/healing/self-healing-system.ts +0 -1435
  66. package/src/health/README.md +0 -161
  67. package/src/health/system-health.ts +0 -995
  68. package/src/index.ts +0 -60
  69. package/src/intelligence/acl-analyzer.ts +0 -377
  70. package/src/intelligence/auto-resolution-engine.ts +0 -643
  71. package/src/intelligence/gap-analysis-engine.ts +0 -488
  72. package/src/intelligence/manual-instructions-generator.ts +0 -744
  73. package/src/intelligence/mcp-coverage-analyzer.ts +0 -708
  74. package/src/intelligence/multi-pass-requirements-analyzer.ts +0 -603
  75. package/src/intelligence/performance-recommendations-engine.ts +0 -1223
  76. package/src/intelligence/requirements-analyzer.ts +0 -1148
  77. package/src/intelligence/task-analyzer.ts +0 -628
  78. package/src/managers/scope-manager.ts +0 -555
  79. package/src/mcp/advanced/servicenow-advanced-features-mcp.ts +0 -16110
  80. package/src/mcp/base-mcp-server.ts +0 -660
  81. package/src/mcp/http-transport-wrapper.ts +0 -426
  82. package/src/mcp/service-discovery-client.ts +0 -312
  83. package/src/mcp/servicenow-automation-mcp-refactored.ts +0 -678
  84. package/src/mcp/servicenow-automation-mcp.ts +0 -838
  85. package/src/mcp/servicenow-deployment-mcp-refactored.ts +0 -1292
  86. package/src/mcp/servicenow-deployment-mcp.ts +0 -7244
  87. package/src/mcp/servicenow-graph-memory-mcp-refactored.ts +0 -721
  88. package/src/mcp/servicenow-graph-memory-mcp.ts +0 -832
  89. package/src/mcp/servicenow-integration-mcp-refactored.ts +0 -655
  90. package/src/mcp/servicenow-integration-mcp.ts +0 -819
  91. package/src/mcp/servicenow-intelligent-mcp-refactored.ts +0 -977
  92. package/src/mcp/servicenow-intelligent-mcp.ts +0 -4638
  93. package/src/mcp/servicenow-mcp-server.ts +0 -728
  94. package/src/mcp/servicenow-memory-mcp.ts +0 -474
  95. package/src/mcp/servicenow-operations-mcp-refactored.ts +0 -1995
  96. package/src/mcp/servicenow-operations-mcp.ts +0 -3384
  97. package/src/mcp/servicenow-platform-development-mcp-refactored.ts +0 -611
  98. package/src/mcp/servicenow-platform-development-mcp.ts +0 -970
  99. package/src/mcp/servicenow-progressive-indexer.ts +0 -370
  100. package/src/mcp/servicenow-reporting-analytics-mcp-refactored.ts +0 -695
  101. package/src/mcp/servicenow-reporting-analytics-mcp.ts +0 -1123
  102. package/src/mcp/servicenow-security-compliance-mcp-refactored.ts +0 -642
  103. package/src/mcp/servicenow-security-compliance-mcp.ts +0 -1157
  104. package/src/mcp/servicenow-update-set-mcp-refactored.ts +0 -751
  105. package/src/mcp/servicenow-update-set-mcp.ts +0 -811
  106. package/src/mcp/shared/agent-context-provider.ts +0 -365
  107. package/src/mcp/shared/base-mcp-server.ts +0 -2463
  108. package/src/mcp/shared/mcp-memory-manager.ts +0 -540
  109. package/src/mcp/shared/mcp-resource-manager.ts +0 -367
  110. package/src/mcp/snow-flow-mcp.ts +0 -911
  111. package/src/mcp/start-all-mcp-servers.ts +0 -102
  112. package/src/mcp/start-servicenow-mcp.ts +0 -67
  113. package/src/monitoring/enhanced-monitoring-system.ts +0 -1345
  114. package/src/monitoring/performance-tracker.ts +0 -777
  115. package/src/optimization/cost-optimization-engine.ts +0 -1125
  116. package/src/optimization/index.ts +0 -10
  117. package/src/queen/README.md +0 -403
  118. package/src/queen/agent-factory.ts +0 -574
  119. package/src/queen/index.ts +0 -94
  120. package/src/queen/mcp-execution-bridge.ts +0 -681
  121. package/src/queen/neural-learning.ts +0 -319
  122. package/src/queen/parallel-agent-engine.ts +0 -848
  123. package/src/queen/queen-memory-system.ts +0 -490
  124. package/src/queen/queen-memory.ts +0 -456
  125. package/src/queen/servicenow-queen.ts +0 -1029
  126. package/src/queen/types.ts +0 -87
  127. package/src/rollback/smart-rollback-system.ts +0 -866
  128. package/src/schemas/deployment.schema.json +0 -58
  129. package/src/schemas/flow.schema.json +0 -79
  130. package/src/schemas/widget.schema.json +0 -72
  131. package/src/snow-flow-system.ts +0 -541
  132. package/src/sparc/sparc-help.ts +0 -49
  133. package/src/sparc/team-sparc.ts +0 -88
  134. package/src/strategies/global-scope-strategy.ts +0 -736
  135. package/src/templates/base/application.template.json +0 -45
  136. package/src/templates/base/business_rule.template.json +0 -33
  137. package/src/templates/base/script_include.template.json +0 -18
  138. package/src/templates/base/table.template.json +0 -64
  139. package/src/templates/base/widget.template.json +0 -25
  140. package/src/templates/patterns/composite.incident-management.template.json +0 -140
  141. package/src/templates/patterns/widget.dashboard.template.json +0 -238
  142. package/src/templates/patterns/widget.datatable.template.json +0 -292
  143. package/src/testing/integration-test-suite.ts +0 -1276
  144. package/src/types/index.ts +0 -183
  145. package/src/types/neo4j-driver.d.ts +0 -23
  146. package/src/types/servicenow.types.ts +0 -307
  147. package/src/types/snow-flow.types.ts +0 -186
  148. package/src/types/todo.types.ts +0 -70
  149. package/src/utils/action-type-cache.ts +0 -286
  150. package/src/utils/agent-detector.ts +0 -573
  151. package/src/utils/artifact-tracker.ts +0 -379
  152. package/src/utils/dependency-detector.ts +0 -233
  153. package/src/utils/deployment-metadata-handler.ts +0 -518
  154. package/src/utils/error-recovery.ts +0 -680
  155. package/src/utils/logger.ts +0 -60
  156. package/src/utils/mcp-auth-middleware.ts +0 -262
  157. package/src/utils/mcp-config-manager.ts +0 -270
  158. package/src/utils/mcp-server-manager.ts +0 -446
  159. package/src/utils/mcp-tool-registry.ts +0 -298
  160. package/src/utils/migrate-snow-flow.ts +0 -98
  161. package/src/utils/oauth-html-templates.ts +0 -188
  162. package/src/utils/scope-utils.ts +0 -443
  163. package/src/utils/servicenow-client.ts +0 -3321
  164. package/src/utils/servicenow-id-generator.ts +0 -181
  165. package/src/utils/snow-memory-manager.ts +0 -605
  166. package/src/utils/snow-oauth.ts +0 -797
  167. package/src/utils/template-engine.ts +0 -463
  168. package/src/utils/theme-manager.ts +0 -295
  169. package/src/utils/unified-auth-store.ts +0 -222
  170. package/src/utils/update-set-importer.ts +0 -422
  171. package/src/utils/update-set-xml-packager.ts +0 -371
  172. package/src/utils/widget-template-generator.ts +0 -1744
  173. package/src/version.ts +0 -1950
@@ -1,2463 +0,0 @@
1
- /**
2
- * Base MCP Server with Agent Integration
3
- * Provides common functionality for all MCP servers in the agent ecosystem
4
- */
5
-
6
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
- import { ServiceNowClient } from '../../utils/servicenow-client.js';
8
- import { ServiceNowOAuth } from '../../utils/snow-oauth.js';
9
- import { Logger } from '../../utils/logger.js';
10
- import { AgentContextProvider } from './agent-context-provider.js';
11
- import { MCPMemoryManager, AgentContext } from './mcp-memory-manager.js';
12
- import { MCPResourceManager } from './mcp-resource-manager.js';
13
-
14
- export interface MCPToolResult {
15
- [key: string]: unknown;
16
- content: Array<{
17
- type: string;
18
- text?: string;
19
- data?: any;
20
- }>;
21
- metadata?: {
22
- agent_id?: string;
23
- session_id?: string;
24
- duration_ms?: number;
25
- artifacts_created?: string[];
26
- };
27
- _meta?: { [key: string]: unknown };
28
- }
29
-
30
- export abstract class BaseMCPServer {
31
- protected server: Server;
32
- protected client: ServiceNowClient;
33
- protected oauth: ServiceNowOAuth;
34
- protected logger: Logger;
35
- protected contextProvider: AgentContextProvider;
36
- protected memory: MCPMemoryManager;
37
- protected resourceManager: MCPResourceManager;
38
-
39
- constructor(name: string, version: string = '1.0.0') {
40
- this.server = new Server(
41
- {
42
- name,
43
- version,
44
- },
45
- {
46
- capabilities: {
47
- tools: {},
48
- resources: {},
49
- },
50
- }
51
- );
52
-
53
- this.client = new ServiceNowClient();
54
- this.oauth = new ServiceNowOAuth();
55
- this.logger = new Logger(name);
56
- this.contextProvider = new AgentContextProvider();
57
- this.memory = MCPMemoryManager.getInstance();
58
- this.resourceManager = new MCPResourceManager(name);
59
- }
60
-
61
- /**
62
- * Execute a tool with agent context tracking
63
- */
64
- protected async executeWithAgentContext<T>(
65
- toolName: string,
66
- args: any,
67
- operation: (context: AgentContext) => Promise<T>
68
- ): Promise<MCPToolResult> {
69
- // Extract agent context
70
- const agentContext = this.contextProvider.extractAgentContext(args);
71
-
72
- // Log operation start
73
- this.logger.info(`Executing ${toolName}`, {
74
- agent_id: agentContext.agent_id,
75
- session_id: agentContext.session_id
76
- });
77
-
78
- // Execute with context tracking
79
- const result = await this.contextProvider.executeWithContext(
80
- {
81
- ...agentContext,
82
- operation_name: toolName,
83
- mcp_server: (this.server as any).serverInfo?.name || 'unknown'
84
- },
85
- async () => operation(agentContext)
86
- );
87
-
88
- if (!result.success) {
89
- return {
90
- content: [
91
- {
92
- type: 'text',
93
- text: `❌ Operation failed: ${result.error}`
94
- }
95
- ],
96
- metadata: {
97
- agent_id: agentContext.agent_id,
98
- session_id: agentContext.session_id,
99
- duration_ms: result.duration_ms
100
- }
101
- };
102
- }
103
-
104
- return result.data as MCPToolResult;
105
- }
106
-
107
- /**
108
- * MANDATORY authentication and connection validation before ServiceNow operations
109
- */
110
- protected async validateServiceNowConnection(): Promise<{ success: boolean; error?: string }> {
111
- try {
112
- this.logger.info('🔍 Validating ServiceNow connection...');
113
-
114
- // 1. Check if we have valid credentials
115
- const credentials = await this.oauth.loadCredentials();
116
- if (!credentials) {
117
- return {
118
- success: false,
119
- error: 'No ServiceNow credentials found. Set up .env file and run "snow-flow auth login".'
120
- };
121
- }
122
-
123
- // 2. Check if we have access token (OAuth session)
124
- if (!credentials.accessToken) {
125
- return {
126
- success: false,
127
- error: 'OAuth authentication required. Run "snow-flow auth login" to authenticate.'
128
- };
129
- }
130
-
131
- // 3. Check if token is still valid
132
- const isAuth = await this.oauth.isAuthenticated();
133
- if (!isAuth) {
134
- this.logger.info('🔄 Token expired, attempting refresh...');
135
-
136
- // Try to refresh token
137
- const refreshResult = await this.oauth.refreshAccessToken();
138
- if (!refreshResult.success) {
139
- return {
140
- success: false,
141
- error: 'OAuth token expired and refresh failed. Run "snow-flow auth login" to re-authenticate.'
142
- };
143
- }
144
-
145
- this.logger.info('✅ Token refreshed successfully');
146
- }
147
-
148
- // 4. Test actual ServiceNow connection
149
- this.logger.info('🔧 About to call testConnection', {
150
- clientType: this.client.constructor.name,
151
- clientMethods: Object.getOwnPropertyNames(Object.getPrototypeOf(this.client)),
152
- hasTestConnection: typeof this.client.testConnection === 'function',
153
- hasMakeRequest: typeof this.client.makeRequest === 'function'
154
- });
155
-
156
- try {
157
- const connectionTest = await this.client.testConnection();
158
- if (!connectionTest.success) {
159
- return {
160
- success: false,
161
- error: `ServiceNow connection failed: ${connectionTest.error}`
162
- };
163
- }
164
- } catch (testError) {
165
- this.logger.error('🔧 testConnection error:', {
166
- error: testError.message,
167
- stack: testError.stack,
168
- clientInfo: {
169
- type: this.client.constructor.name,
170
- methods: Object.getOwnPropertyNames(Object.getPrototypeOf(this.client))
171
- }
172
- });
173
- throw testError;
174
- }
175
-
176
- this.logger.info('✅ ServiceNow connection validated');
177
- return { success: true };
178
-
179
- } catch (error) {
180
- this.logger.error('ServiceNow connection validation failed', error);
181
- return {
182
- success: false,
183
- error: error instanceof Error ? error.message : String(error)
184
- };
185
- }
186
- }
187
-
188
- /**
189
- * Check authentication with proper error handling (deprecated - use validateServiceNowConnection)
190
- */
191
- protected async checkAuthentication(): Promise<boolean> {
192
- const result = await this.validateServiceNowConnection();
193
- return result.success;
194
- }
195
-
196
- /**
197
- * Create standard authentication error response with detailed instructions
198
- */
199
- protected createAuthenticationError(error?: string): MCPToolResult {
200
- const errorText = error || 'Authentication validation failed';
201
-
202
- return {
203
- content: [
204
- {
205
- type: 'text',
206
- text: `❌ ServiceNow Connection Failed
207
-
208
- ${errorText}
209
-
210
- 🔧 To fix this:
211
-
212
- 1. Ensure .env file has OAuth credentials:
213
- SNOW_INSTANCE=your-instance.service-now.com
214
- SNOW_CLIENT_ID=your_oauth_client_id
215
- SNOW_CLIENT_SECRET=your_oauth_client_secret
216
-
217
- 2. Authenticate with ServiceNow:
218
- snow-flow auth login
219
-
220
- 3. If you still get errors, run diagnostics:
221
- snow_auth_diagnostics()
222
-
223
- 💡 To get OAuth credentials:
224
- • ServiceNow: System OAuth > Application Registry > New OAuth Application
225
- • Redirect URI: http://localhost:3005/callback (configurable via SNOW_REDIRECT_* env vars)
226
- • Scopes: useraccount write admin`
227
- }
228
- ]
229
- };
230
- }
231
-
232
- /**
233
- * Smart artifact discovery - check for existing artifacts before creating new ones
234
- */
235
- protected async discoverExistingArtifacts(
236
- type: string,
237
- name: string,
238
- searchTerms?: string[]
239
- ): Promise<{ found: boolean; artifacts: any[]; suggestions: string[] }> {
240
- try {
241
- this.logger.info(`🔍 Discovering existing ${type} artifacts...`);
242
-
243
- const suggestions: string[] = [];
244
- let artifacts: any[] = [];
245
-
246
- // Search by name
247
- const nameSearch = await this.client.searchRecords(
248
- this.getTableForType(type),
249
- `nameLIKE${name}`,
250
- 5
251
- );
252
-
253
- if (nameSearch.success && nameSearch.data?.result?.length > 0) {
254
- artifacts = nameSearch.data.result;
255
- suggestions.push(`Found ${artifacts.length} existing ${type}(s) with similar names`);
256
- suggestions.push(`Consider reusing: ${artifacts.map(a => a.name).join(', ')}`);
257
- }
258
-
259
- // Search by additional terms if provided
260
- if (searchTerms && searchTerms.length > 0) {
261
- for (const term of searchTerms) {
262
- const termSearch = await this.client.searchRecords(
263
- this.getTableForType(type),
264
- `nameLIKE${term}^ORdescriptionLIKE${term}`,
265
- 3
266
- );
267
-
268
- if (termSearch.success && termSearch.data?.result?.length > 0) {
269
- const newArtifacts = termSearch.data.result.filter(
270
- (new_artifact: any) => !artifacts.some(existing => existing.sys_id === new_artifact.sys_id)
271
- );
272
- artifacts.push(...newArtifacts);
273
-
274
- if (newArtifacts.length > 0) {
275
- suggestions.push(`Found ${newArtifacts.length} related ${type}(s) for "${term}"`);
276
- }
277
- }
278
- }
279
- }
280
-
281
- return {
282
- found: artifacts.length > 0,
283
- artifacts,
284
- suggestions
285
- };
286
-
287
- } catch (error) {
288
- this.logger.warn('Artifact discovery failed', error);
289
- return { found: false, artifacts: [], suggestions: [] };
290
- }
291
- }
292
-
293
- /**
294
- * Ensure active Update Set for tracking changes
295
- */
296
- protected async ensureUpdateSet(context: AgentContext, purpose?: string): Promise<string | null> {
297
- try {
298
- this.logger.info('📦 Ensuring active Update Set...');
299
-
300
- // Check current update set
301
- const currentUpdateSet = await this.client.getCurrentUpdateSet();
302
-
303
- if (currentUpdateSet.success && currentUpdateSet.data) {
304
- this.logger.info(`✅ Using existing Update Set: ${currentUpdateSet.data.name}`);
305
- return currentUpdateSet.data.sys_id;
306
- }
307
-
308
- // Create new update set
309
- const updateSetName = purpose
310
- ? `Snow-Flow ${purpose} - ${new Date().toISOString().split('T')[0]}`
311
- : `Snow-Flow Changes - ${new Date().toISOString().split('T')[0]}`;
312
-
313
- this.logger.info(`📦 Creating new Update Set: ${updateSetName}`);
314
-
315
- const newUpdateSet = await this.client.createUpdateSet({
316
- name: updateSetName,
317
- description: `Automated changes from Snow-Flow Agent (${context.agent_id})`,
318
- state: 'in_progress'
319
- });
320
-
321
- if (newUpdateSet.success && newUpdateSet.data) {
322
- // Set it as current
323
- await this.client.setCurrentUpdateSet(newUpdateSet.data.sys_id);
324
- this.logger.info(`✅ Update Set created and activated: ${newUpdateSet.data.sys_id}`);
325
- return newUpdateSet.data.sys_id;
326
- }
327
-
328
- this.logger.warn('⚠️ Could not create Update Set, changes will not be tracked');
329
- return null;
330
-
331
- } catch (error) {
332
- this.logger.warn('Update Set creation failed', error);
333
- return null;
334
- }
335
- }
336
-
337
- /**
338
- * Automatically track artifact in Update Set
339
- */
340
- protected async trackArtifact(
341
- sysId: string,
342
- type: string,
343
- name: string,
344
- updateSetId?: string
345
- ): Promise<void> {
346
- try {
347
- if (!updateSetId) {
348
- this.logger.warn('No Update Set ID provided for artifact tracking');
349
- return;
350
- }
351
-
352
- this.logger.info(`📋 Tracking ${type} artifact: ${name} (${sysId})`);
353
-
354
- // Add artifact to update set tracking (this is handled automatically by ServiceNow
355
- // when artifacts are created/modified, but we can log it for visibility)
356
- this.logger.info(`✅ Artifact tracked in Update Set: ${updateSetId}`);
357
-
358
- } catch (error) {
359
- this.logger.warn('Artifact tracking failed', error);
360
- }
361
- }
362
-
363
- /**
364
- * Get ServiceNow table name for artifact type
365
- */
366
- protected getTableForType(type: string): string {
367
- const tableMap: { [key: string]: string } = {
368
- 'widget': 'sp_widget',
369
- 'flow': 'sys_hub_flow',
370
- 'subflow': 'sys_hub_flow',
371
- 'action': 'sys_hub_action_type_definition',
372
- 'script': 'sys_script_include',
373
- 'business_rule': 'sys_script',
374
- 'table': 'sys_db_object',
375
- 'application': 'sys_app'
376
- };
377
-
378
- return tableMap[type] || 'sys_metadata';
379
- }
380
-
381
- /**
382
- * Report progress during long operations
383
- */
384
- protected async reportProgress(
385
- context: AgentContext,
386
- progress: number,
387
- phase: string
388
- ): Promise<void> {
389
- await this.contextProvider.reportProgress(context, progress, phase);
390
- }
391
-
392
- /**
393
- * Store artifact with agent tracking
394
- */
395
- protected async storeArtifact(
396
- context: AgentContext,
397
- artifact: {
398
- sys_id: string;
399
- type: string;
400
- name: string;
401
- description?: string;
402
- config?: any;
403
- update_set_id?: string;
404
- }
405
- ): Promise<void> {
406
- await this.contextProvider.storeArtifact(context, artifact);
407
- }
408
-
409
- /**
410
- * Notify handoff to another agent
411
- */
412
- protected async notifyHandoff(
413
- context: AgentContext,
414
- to_agent: string,
415
- artifact_info: {
416
- type: string;
417
- sys_id: string;
418
- next_steps: string[];
419
- }
420
- ): Promise<void> {
421
- await this.contextProvider.notifyHandoff(context, to_agent, artifact_info);
422
- }
423
-
424
- /**
425
- * Request Queen intervention for issues
426
- */
427
- protected async requestQueenIntervention(
428
- context: AgentContext,
429
- issue: {
430
- type: string;
431
- priority: 'low' | 'medium' | 'high' | 'critical';
432
- description: string;
433
- attempted_solutions?: string[];
434
- }
435
- ): Promise<void> {
436
- await this.contextProvider.requestQueenIntervention(context, issue);
437
- }
438
-
439
- /**
440
- * Get session context for coordination
441
- */
442
- protected async getSessionContext(session_id: string): Promise<any> {
443
- return await this.contextProvider.getSessionContext(session_id);
444
- }
445
-
446
- /**
447
- * Create success response with metadata
448
- */
449
- protected createSuccessResponse(
450
- message: string,
451
- data?: any,
452
- metadata?: any
453
- ): MCPToolResult {
454
- const content: any[] = [
455
- {
456
- type: 'text',
457
- text: `✅ ${message}`
458
- }
459
- ];
460
-
461
- if (data) {
462
- content.push({
463
- type: 'text',
464
- text: JSON.stringify(data, null, 2)
465
- });
466
- }
467
-
468
- return {
469
- content,
470
- metadata
471
- };
472
- }
473
-
474
- /**
475
- * Create error response with metadata
476
- */
477
- protected createErrorResponse(
478
- message: string,
479
- error?: any,
480
- metadata?: any
481
- ): MCPToolResult {
482
- const content: any[] = [
483
- {
484
- type: 'text',
485
- text: `❌ ${message}`
486
- }
487
- ];
488
-
489
- if (error) {
490
- content.push({
491
- type: 'text',
492
- text: `Error details: ${error instanceof Error ? error.message : String(error)}`
493
- });
494
- }
495
-
496
- return {
497
- content,
498
- metadata
499
- };
500
- }
501
-
502
- /**
503
- * Enhanced error handling with intelligent recovery strategies
504
- */
505
- protected async handleServiceNowError(
506
- error: any,
507
- operation: string,
508
- context: AgentContext,
509
- fallbackOptions?: {
510
- enableRetry?: boolean;
511
- enableScopeEscalation?: boolean;
512
- enableManualSteps?: boolean;
513
- }
514
- ): Promise<MCPToolResult> {
515
- this.logger.error(`ServiceNow operation failed: ${operation}`, error);
516
-
517
- const errorMessage = error instanceof Error ? error.message : String(error);
518
- const errorCode = this.extractErrorCode(errorMessage);
519
-
520
- // Categorize error and determine recovery strategy
521
- const errorCategory = this.categorizeError(errorMessage, errorCode);
522
-
523
- switch (errorCategory) {
524
- case 'authentication':
525
- return this.handleAuthenticationError(error, operation, context);
526
-
527
- case 'permissions':
528
- return this.handlePermissionError(error, operation, context, fallbackOptions);
529
-
530
- case 'network':
531
- return this.handleNetworkError(error, operation, context, fallbackOptions);
532
-
533
- case 'validation':
534
- return this.handleValidationError(error, operation, context);
535
-
536
- case 'scope':
537
- return this.handleScopeError(error, operation, context, fallbackOptions);
538
-
539
- default:
540
- return this.handleGenericError(error, operation, context, fallbackOptions);
541
- }
542
- }
543
-
544
- /**
545
- * Categorize error for appropriate recovery strategy
546
- */
547
- private categorizeError(errorMessage: string, errorCode?: string): string {
548
- const msgLower = errorMessage.toLowerCase();
549
-
550
- // Authentication errors
551
- if (msgLower.includes('unauthorized') ||
552
- msgLower.includes('invalid_grant') ||
553
- msgLower.includes('authentication') ||
554
- errorCode === '401' || errorCode === '403') {
555
- return 'authentication';
556
- }
557
-
558
- // Permission errors
559
- if (msgLower.includes('insufficient privileges') ||
560
- msgLower.includes('access denied') ||
561
- msgLower.includes('acl')) {
562
- return 'permissions';
563
- }
564
-
565
- // Network errors
566
- if (msgLower.includes('network') ||
567
- msgLower.includes('timeout') ||
568
- msgLower.includes('connection') ||
569
- msgLower.includes('econnrefused')) {
570
- return 'network';
571
- }
572
-
573
- // Validation errors
574
- if (msgLower.includes('invalid') ||
575
- msgLower.includes('required field') ||
576
- msgLower.includes('constraint') ||
577
- msgLower.includes('validation')) {
578
- return 'validation';
579
- }
580
-
581
- // Scope errors
582
- if (msgLower.includes('scope') ||
583
- msgLower.includes('application') ||
584
- msgLower.includes('global')) {
585
- return 'scope';
586
- }
587
-
588
- return 'generic';
589
- }
590
-
591
- /**
592
- * Handle authentication errors with automatic recovery
593
- */
594
- private async handleAuthenticationError(
595
- error: any,
596
- operation: string,
597
- context: AgentContext
598
- ): Promise<MCPToolResult> {
599
- this.logger.info('🔄 Attempting automatic authentication recovery...');
600
-
601
- // Try to refresh token automatically
602
- try {
603
- const refreshResult = await this.oauth.refreshAccessToken();
604
- if (refreshResult.success) {
605
- this.logger.info('✅ Token refreshed successfully, retry operation');
606
-
607
- // Store recovery in context for coordination
608
- await this.memory.updateSharedContext({
609
- session_id: context.session_id,
610
- context_key: `auth_recovery_${operation}`,
611
- context_value: JSON.stringify({
612
- recovery_action: 'token_refresh',
613
- timestamp: new Date().toISOString(),
614
- operation: operation
615
- }),
616
- created_by_agent: context.agent_id
617
- });
618
-
619
- return this.createSuccessResponse(
620
- 'Authentication recovered - token refreshed',
621
- {
622
- recovery_action: 'token_refresh',
623
- next_step: 'retry_operation',
624
- can_continue: true
625
- }
626
- );
627
- }
628
- } catch (refreshError) {
629
- this.logger.warn('Token refresh failed', refreshError);
630
- }
631
-
632
- // Request Queen intervention for authentication issues
633
- await this.requestQueenIntervention(context, {
634
- type: 'authentication_failure',
635
- priority: 'high',
636
- description: `Authentication failed for ${operation}`,
637
- attempted_solutions: ['token_refresh']
638
- });
639
-
640
- return this.createAuthenticationError(`Authentication failed during ${operation}. Automatic recovery failed.`);
641
- }
642
-
643
- /**
644
- * Handle permission errors with scope escalation
645
- */
646
- private async handlePermissionError(
647
- error: any,
648
- operation: string,
649
- context: AgentContext,
650
- fallbackOptions?: any
651
- ): Promise<MCPToolResult> {
652
- const errorMessage = error instanceof Error ? error.message : String(error);
653
-
654
- // Try scope escalation if enabled
655
- if (fallbackOptions?.enableScopeEscalation) {
656
- this.logger.info('🔝 Attempting scope escalation...');
657
-
658
- try {
659
- // Try to escalate to global scope
660
- const escalationResult = await this.escalateToGlobalScope(operation, context);
661
- if (escalationResult.success) {
662
- return this.createSuccessResponse(
663
- 'Permission issue resolved via scope escalation',
664
- escalationResult
665
- );
666
- }
667
- } catch (escalationError) {
668
- this.logger.warn('Scope escalation failed', escalationError);
669
- }
670
- }
671
-
672
- // Request permission elevation
673
- await this.requestQueenIntervention(context, {
674
- type: 'permission_elevation_needed',
675
- priority: 'high',
676
- description: `Insufficient privileges for ${operation}: ${errorMessage}`,
677
- attempted_solutions: fallbackOptions?.enableScopeEscalation ? ['scope_escalation'] : []
678
- });
679
-
680
- return this.createErrorResponse(
681
- `Permission error during ${operation}`,
682
- {
683
- error: errorMessage,
684
- recovery_options: [
685
- '1. Request admin privileges from Queen Agent',
686
- '2. Try scope escalation to global',
687
- '3. Create manual Update Set instructions',
688
- '4. Use alternative deployment approach'
689
- ],
690
- next_steps: [
691
- 'Contact ServiceNow admin for elevated permissions',
692
- 'Or use snow_deploy with fallback_strategy="manual_steps"'
693
- ]
694
- }
695
- );
696
- }
697
-
698
- /**
699
- * Handle network errors with intelligent retry
700
- */
701
- private async handleNetworkError(
702
- error: any,
703
- operation: string,
704
- context: AgentContext,
705
- fallbackOptions?: any
706
- ): Promise<MCPToolResult> {
707
- if (fallbackOptions?.enableRetry) {
708
- this.logger.info('🔄 Network error - attempting retry with backoff...');
709
-
710
- // Implement exponential backoff retry
711
- const maxRetries = 3;
712
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
713
- await this.delay(Math.pow(2, attempt) * 1000); // Exponential backoff
714
-
715
- try {
716
- // Test connection
717
- const connectionTest = await this.client.testConnection();
718
- if (connectionTest.success) {
719
- this.logger.info(`✅ Network recovered after ${attempt} attempts`);
720
-
721
- return this.createSuccessResponse(
722
- 'Network error recovered - connection restored',
723
- {
724
- recovery_action: 'network_retry',
725
- attempts: attempt,
726
- can_continue: true
727
- }
728
- );
729
- }
730
- } catch (retryError) {
731
- this.logger.warn(`Retry attempt ${attempt} failed`, retryError);
732
- }
733
- }
734
- }
735
-
736
- return this.createErrorResponse(
737
- `Network error during ${operation}`,
738
- {
739
- error: error instanceof Error ? error.message : String(error),
740
- recovery_options: [
741
- '1. Check ServiceNow instance availability',
742
- '2. Verify network connectivity',
743
- '3. Check firewall/proxy settings',
744
- '4. Retry operation in a few minutes'
745
- ],
746
- next_steps: [
747
- 'Wait for network recovery and retry',
748
- 'Or check ServiceNow instance status'
749
- ]
750
- }
751
- );
752
- }
753
-
754
- /**
755
- * Handle validation errors with correction suggestions
756
- */
757
- private async handleValidationError(
758
- error: any,
759
- operation: string,
760
- context: AgentContext
761
- ): Promise<MCPToolResult> {
762
- const errorMessage = error instanceof Error ? error.message : String(error);
763
-
764
- // Extract field information from validation error
765
- const fieldInfo = this.extractFieldInfoFromError(errorMessage);
766
-
767
- return this.createErrorResponse(
768
- `Validation error during ${operation}`,
769
- {
770
- error: errorMessage,
771
- field_issues: fieldInfo,
772
- recovery_options: [
773
- '1. Fix required fields and retry',
774
- '2. Check field constraints and formats',
775
- '3. Use snow_validate_deployment() first',
776
- '4. Review ServiceNow table schema'
777
- ],
778
- next_steps: [
779
- 'Update configuration with correct field values',
780
- 'Validate against ServiceNow table requirements'
781
- ]
782
- }
783
- );
784
- }
785
-
786
- /**
787
- * Handle scope errors with automatic fallback
788
- */
789
- private async handleScopeError(
790
- error: any,
791
- operation: string,
792
- context: AgentContext,
793
- fallbackOptions?: any
794
- ): Promise<MCPToolResult> {
795
- if (fallbackOptions?.enableScopeEscalation) {
796
- this.logger.info('🌐 Scope error - attempting global scope fallback...');
797
-
798
- try {
799
- const scopeFallback = await this.fallbackToGlobalScope(operation, context);
800
- if (scopeFallback.success) {
801
- return this.createSuccessResponse(
802
- 'Scope error resolved - using global scope',
803
- scopeFallback
804
- );
805
- }
806
- } catch (scopeError) {
807
- this.logger.warn('Global scope fallback failed', scopeError);
808
- }
809
- }
810
-
811
- return this.createErrorResponse(
812
- `Scope error during ${operation}`,
813
- {
814
- error: error instanceof Error ? error.message : String(error),
815
- recovery_options: [
816
- '1. Deploy to global scope instead',
817
- '2. Create scoped application first',
818
- '3. Use manual deployment approach',
819
- '4. Check application scope permissions'
820
- ],
821
- next_steps: [
822
- 'Try snow_deploy with scope_strategy="global"',
823
- 'Or create application scope manually first'
824
- ]
825
- }
826
- );
827
- }
828
-
829
- /**
830
- * Handle generic errors with comprehensive guidance
831
- */
832
- private async handleGenericError(
833
- error: any,
834
- operation: string,
835
- context: AgentContext,
836
- fallbackOptions?: any
837
- ): Promise<MCPToolResult> {
838
- const errorMessage = error instanceof Error ? error.message : String(error);
839
-
840
- // Generate contextual recovery options based on operation type
841
- const recoveryOptions = this.generateRecoveryOptions(operation, errorMessage);
842
-
843
- // Store error for pattern analysis
844
- await this.memory.updateSharedContext({
845
- session_id: context.session_id,
846
- context_key: `error_${operation}_${Date.now()}`,
847
- context_value: JSON.stringify({
848
- error: errorMessage,
849
- operation: operation,
850
- timestamp: new Date().toISOString(),
851
- recovery_attempted: Object.keys(fallbackOptions || {})
852
- }),
853
- created_by_agent: context.agent_id
854
- });
855
-
856
- return this.createErrorResponse(
857
- `Unexpected error during ${operation}`,
858
- {
859
- error: errorMessage,
860
- recovery_options: recoveryOptions,
861
- next_steps: [
862
- 'Review error details and try alternative approach',
863
- 'Use snow_deployment_debug() for diagnostics',
864
- 'Contact Queen Agent for intervention'
865
- ],
866
- fallback_available: fallbackOptions?.enableManualSteps || false
867
- }
868
- );
869
- }
870
-
871
- /**
872
- * Helper methods for error handling
873
- */
874
- private extractErrorCode(errorMessage: string): string | undefined {
875
- const codeMatch = errorMessage.match(/(\d{3})/);
876
- return codeMatch ? codeMatch[1] : undefined;
877
- }
878
-
879
- private extractFieldInfoFromError(errorMessage: string): any {
880
- const fieldMatch = errorMessage.match(/field[:\s]+([a-z_]+)/i);
881
- const requiredMatch = errorMessage.match(/required/i);
882
-
883
- return {
884
- field: fieldMatch ? fieldMatch[1] : null,
885
- is_required: !!requiredMatch,
886
- raw_message: errorMessage
887
- };
888
- }
889
-
890
- private generateRecoveryOptions(operation: string, errorMessage: string): string[] {
891
- const options = [
892
- '1. Review error message and fix configuration',
893
- '2. Check ServiceNow instance status and permissions'
894
- ];
895
-
896
- if (operation.includes('deploy')) {
897
- options.push('3. Use snow_validate_deployment() before retrying');
898
- options.push('4. Try manual deployment with Update Set');
899
- }
900
-
901
- if (operation.includes('search') || operation.includes('find')) {
902
- options.push('3. Try alternative search terms');
903
- options.push('4. Use snow_comprehensive_search() for broader search');
904
- }
905
-
906
- options.push('5. Request Queen Agent intervention for complex issues');
907
-
908
- return options;
909
- }
910
-
911
- private async escalateToGlobalScope(operation: string, context: AgentContext): Promise<any> {
912
- this.logger.info(`🔝 Attempting permission escalation for ${operation}`);
913
-
914
- try {
915
- // Enhanced authentication validation
916
- const authValidation = await this.validateServiceNowConnection();
917
- if (!authValidation.success) {
918
- return {
919
- success: false,
920
- reason: 'Authentication validation failed before escalation',
921
- recovery_action: 'Run: snow-flow auth login',
922
- auth_error: authValidation.error
923
- };
924
- }
925
-
926
- // Get current user information with enhanced OAuth scope handling
927
- this.logger.info('🔍 Analyzing current user permissions and OAuth scopes...');
928
-
929
- let currentUser: any = null;
930
- let currentRoles: string[] = [];
931
- let oAuthScopes: string[] = [];
932
-
933
- try {
934
- // Get current user details
935
- const userResponse = await this.client.makeRequest({
936
- method: 'GET',
937
- endpoint: '/api/now/v2/table/sys_user',
938
- params: {
939
- sysparm_query: 'active=true^user_name=javascript:gs.getUserName()',
940
- sysparm_fields: 'sys_id,user_name,name,email,active,locked_out,roles',
941
- sysparm_limit: 1
942
- }
943
- });
944
-
945
- if (userResponse.data?.result?.[0]) {
946
- currentUser = userResponse.data.result[0];
947
- this.logger.info(`👤 Current user: ${currentUser.name} (${currentUser.user_name})`);
948
- }
949
-
950
- // Get detailed role information
951
- const rolesResponse = await this.client.makeRequest({
952
- method: 'GET',
953
- endpoint: '/api/now/v2/table/sys_user_has_role',
954
- params: {
955
- sysparm_query: `user.user_name=${currentUser?.user_name || 'javascript:gs.getUserName()'}`,
956
- sysparm_fields: 'role.name,role.description,state,inherited',
957
- sysparm_limit: 100
958
- }
959
- });
960
-
961
- if (rolesResponse.data?.result) {
962
- currentRoles = rolesResponse.data.result
963
- .filter((r: any) => r.state === 'active')
964
- .map((r: any) => r['role.name'])
965
- .filter(Boolean);
966
-
967
- this.logger.info(`🛡️ Active roles: ${currentRoles.join(', ')}`);
968
- }
969
-
970
- // Check OAuth token scopes if available
971
- try {
972
- // Attempt to get token info if method exists
973
- if (typeof (this.oauth as any).getTokenInfo === 'function') {
974
- const tokenInfo = await (this.oauth as any).getTokenInfo();
975
- if (tokenInfo?.scope) {
976
- oAuthScopes = tokenInfo.scope.split(' ');
977
- this.logger.info(`🔑 OAuth scopes: ${oAuthScopes.join(', ')}`);
978
- }
979
- } else {
980
- this.logger.debug('OAuth getTokenInfo method not available');
981
- }
982
- } catch (scopeError) {
983
- this.logger.debug('Could not retrieve OAuth scope information', { error: scopeError });
984
- }
985
-
986
- } catch (roleError) {
987
- this.logger.warn('Could not fetch complete user information', { error: roleError });
988
- // Continue with limited information
989
- }
990
-
991
- // Enhanced role _analysis based on operation type
992
- const requiredRoles = this.determineRequiredRoles(operation);
993
- const requiredScopes = this.determineRequiredOAuthScopes(operation);
994
- const missingRoles = requiredRoles.filter(role => !currentRoles.includes(role));
995
- const missingScopes = requiredScopes.filter(scope => !oAuthScopes.includes(scope));
996
-
997
- this.logger.info(`📊 Permission Analysis:`, {
998
- required_roles: requiredRoles,
999
- current_roles: currentRoles,
1000
- missing_roles: missingRoles,
1001
- required_scopes: requiredScopes,
1002
- current_scopes: oAuthScopes,
1003
- missing_scopes: missingScopes
1004
- });
1005
-
1006
- // Check if user has sufficient permissions
1007
- if (missingRoles.length === 0 && missingScopes.length === 0) {
1008
- // User has all required permissions, issue might be elsewhere
1009
- return {
1010
- success: true,
1011
- reason: 'User has all required roles and scopes - permission issue may be configuration related',
1012
- current_roles: currentRoles,
1013
- current_scopes: oAuthScopes,
1014
- diagnostic_actions: [
1015
- 'Check ACL rules for the specific table/operation',
1016
- 'Verify application scope permissions',
1017
- 'Check domain separation settings',
1018
- 'Review field-level security',
1019
- 'Validate write permissions for target table'
1020
- ]
1021
- };
1022
- }
1023
-
1024
- // Enhanced automatic role assignment with better error handling
1025
- let autoAssignmentAttempted = false;
1026
- const canAutoAssign = currentRoles.includes('admin') ||
1027
- currentRoles.includes('user_admin') ||
1028
- currentRoles.includes('system_administrator');
1029
-
1030
- if (canAutoAssign && missingRoles.length > 0) {
1031
- this.logger.info('🤖 Attempting automatic role assignment...');
1032
-
1033
- try {
1034
- const assignmentResult = await this.attemptEnhancedRoleAssignment(
1035
- currentUser?.sys_id,
1036
- missingRoles,
1037
- context
1038
- );
1039
-
1040
- if (assignmentResult.success) {
1041
- autoAssignmentAttempted = true;
1042
-
1043
- // Update context with successful assignment
1044
- await this.memory.updateSharedContext({
1045
- session_id: context.session_id,
1046
- context_key: `permission_escalation_${operation}`,
1047
- context_value: JSON.stringify({
1048
- escalation_type: 'automatic_role_assignment',
1049
- assigned_roles: assignmentResult.assigned_roles,
1050
- timestamp: new Date().toISOString(),
1051
- operation: operation
1052
- }),
1053
- created_by_agent: context.agent_id
1054
- });
1055
-
1056
- return {
1057
- success: true,
1058
- reason: 'Roles automatically assigned successfully',
1059
- assigned_roles: assignmentResult.assigned_roles,
1060
- assignment_details: assignmentResult.details,
1061
- recommended_action: 'Retry the original operation - new permissions are active'
1062
- };
1063
- }
1064
- } catch (assignError) {
1065
- this.logger.warn('Automatic role assignment failed', { error: assignError });
1066
- autoAssignmentAttempted = true; // We tried
1067
- }
1068
- }
1069
-
1070
- // Enhanced OAuth scope elevation attempt
1071
- if (missingScopes.length > 0) {
1072
- this.logger.info('🔑 Attempting OAuth scope elevation...');
1073
-
1074
- try {
1075
- const scopeElevationResult = await this.attemptOAuthScopeElevation(
1076
- missingScopes,
1077
- operation,
1078
- context
1079
- );
1080
-
1081
- if (scopeElevationResult.success) {
1082
- return {
1083
- success: true,
1084
- reason: 'OAuth scopes elevated successfully',
1085
- elevated_scopes: scopeElevationResult.elevated_scopes,
1086
- recommended_action: 'Retry the original operation with elevated OAuth permissions'
1087
- };
1088
- }
1089
- } catch (scopeError) {
1090
- this.logger.warn('OAuth scope elevation failed', { error: scopeError });
1091
- }
1092
- }
1093
-
1094
- // Request Queen intervention for complex permission issues
1095
- await this.requestQueenIntervention(context, {
1096
- type: 'permission_escalation_required',
1097
- priority: 'high',
1098
- description: `Permission escalation needed for ${operation}. Missing roles: ${missingRoles.join(', ')}. Missing OAuth scopes: ${missingScopes.join(', ')}.`,
1099
- attempted_solutions: [
1100
- ...(autoAssignmentAttempted ? ['automatic_role_assignment'] : []),
1101
- ...(missingScopes.length > 0 ? ['oauth_scope_elevation'] : [])
1102
- ]
1103
- });
1104
-
1105
- // Comprehensive manual escalation instructions
1106
- const manualSteps = [
1107
- `1. ServiceNow Administrator Actions Required:`,
1108
- ` • Navigate to User Administration > Users`,
1109
- ` • Find user: ${currentUser?.name || 'Current User'} (${currentUser?.user_name || 'unknown'})`,
1110
- ` • Add missing roles: ${missingRoles.join(', ')}`,
1111
- ...missingScopes.length > 0 ? [
1112
- `2. OAuth Application Configuration:`,
1113
- ` • Update OAuth application scopes to include: ${missingScopes.join(', ')}`,
1114
- ` • Re-authorize application with elevated permissions`
1115
- ] : [],
1116
- `${missingScopes.length > 0 ? '3' : '2'}. Verification Steps:`,
1117
- ` • Test permissions: snow_validate_live_connection({ test_level: "permissions" })`,
1118
- ` • Retry operation: ${operation}`
1119
- ];
1120
-
1121
- return {
1122
- success: false,
1123
- reason: 'Manual permission escalation required',
1124
- current_user: currentUser,
1125
- current_roles: currentRoles,
1126
- missing_roles: missingRoles,
1127
- current_oauth_scopes: oAuthScopes,
1128
- missing_oauth_scopes: missingScopes,
1129
- escalation_required: true,
1130
- auto_assignment_attempted: autoAssignmentAttempted,
1131
- manual_steps: manualSteps,
1132
- estimated_time: `${5 + (missingRoles.length * 2)}–${10 + (missingRoles.length * 3)} minutes with admin access`,
1133
- priority: missingRoles.includes('admin') || missingRoles.includes('system_administrator') ? 'critical' : 'high'
1134
- };
1135
-
1136
- } catch (error) {
1137
- this.logger.error('🚨 Permission escalation process failed', { error, operation, context });
1138
-
1139
- return {
1140
- success: false,
1141
- reason: 'Critical error during permission escalation',
1142
- error: error instanceof Error ? error.message : String(error),
1143
- error_type: this.categorizeError(error instanceof Error ? error.message : String(error)),
1144
- recovery_actions: [
1145
- '1. Verify ServiceNow connection: snow_validate_live_connection()',
1146
- '2. Check authentication status: snow_auth_diagnostics()',
1147
- '3. Confirm API access is enabled in ServiceNow',
1148
- '4. Contact ServiceNow administrator for manual role assignment',
1149
- '5. Review system logs for additional error details'
1150
- ],
1151
- escalation_required: true,
1152
- contact_admin: true
1153
- };
1154
- }
1155
- }
1156
-
1157
- /**
1158
- * Determine required roles based on operation type
1159
- */
1160
- private determineRequiredRoles(operation: string): string[] {
1161
- const roles: string[] = [];
1162
-
1163
- // Base roles for most operations
1164
- if (operation.includes('deploy') || operation.includes('create') || operation.includes('update')) {
1165
- roles.push('rest_service', 'web_service_admin');
1166
- }
1167
-
1168
- // Widget operations
1169
- if (operation.includes('widget')) {
1170
- roles.push('sp_admin', 'sp_portal_admin');
1171
- }
1172
-
1173
- // Flow operations
1174
- if (operation.includes('flow') || operation.includes('workflow')) {
1175
- roles.push('flow_designer', 'admin');
1176
- }
1177
-
1178
- // Application operations
1179
- if (operation.includes('application') || operation.includes('app')) {
1180
- roles.push('app_creator', 'admin');
1181
- }
1182
-
1183
- // Update set operations
1184
- if (operation.includes('update_set')) {
1185
- roles.push('admin');
1186
- }
1187
-
1188
- // Global scope operations
1189
- if (operation.includes('global')) {
1190
- roles.push('admin', 'system_administrator');
1191
- }
1192
-
1193
- return Array.from(new Set(roles)); // Remove duplicates
1194
- }
1195
-
1196
- /**
1197
- * Determine required OAuth scopes based on operation type
1198
- */
1199
- private determineRequiredOAuthScopes(operation: string): string[] {
1200
- const scopes: string[] = ['useraccount']; // Base scope for most operations
1201
-
1202
- // Operations that require write access
1203
- if (operation.includes('deploy') || operation.includes('create') || operation.includes('update')) {
1204
- scopes.push('write');
1205
- }
1206
-
1207
- // Administrative operations
1208
- if (operation.includes('admin') || operation.includes('global') || operation.includes('system')) {
1209
- scopes.push('admin');
1210
- }
1211
-
1212
- // Flow Designer operations may need specific scopes
1213
- if (operation.includes('flow') || operation.includes('workflow')) {
1214
- scopes.push('write', 'admin');
1215
- }
1216
-
1217
- return Array.from(new Set(scopes)); // Remove duplicates
1218
- }
1219
-
1220
- /**
1221
- * Enhanced role assignment with better validation
1222
- */
1223
- private async attemptEnhancedRoleAssignment(
1224
- userSysId: string,
1225
- roles: string[],
1226
- context: AgentContext
1227
- ): Promise<{success: boolean, assigned_roles?: string[], details?: any, error?: string}> {
1228
- try {
1229
- const assignedRoles: string[] = [];
1230
- const assignmentDetails: any[] = [];
1231
-
1232
- for (const roleName of roles) {
1233
- try {
1234
- // Get the role sys_id with enhanced validation
1235
- const roleResponse = await this.client.makeRequest({
1236
- method: 'GET',
1237
- endpoint: '/api/now/v2/table/sys_user_role',
1238
- params: {
1239
- sysparm_query: `name=${roleName}^active=true`,
1240
- sysparm_fields: 'sys_id,name,description,can_delegate',
1241
- sysparm_limit: 1
1242
- }
1243
- });
1244
-
1245
- if (roleResponse.data?.result?.[0]) {
1246
- const role = roleResponse.data.result[0];
1247
-
1248
- // Check if user already has this role
1249
- const existingRoleResponse = await this.client.makeRequest({
1250
- method: 'GET',
1251
- endpoint: '/api/now/v2/table/sys_user_has_role',
1252
- params: {
1253
- sysparm_query: `user=${userSysId}^role=${role.sys_id}`,
1254
- sysparm_limit: 1
1255
- }
1256
- });
1257
-
1258
- if (existingRoleResponse.data?.result?.length > 0) {
1259
- this.logger.info(`User already has role: ${roleName}`);
1260
- assignedRoles.push(roleName);
1261
- continue;
1262
- }
1263
-
1264
- // Attempt to assign role
1265
- const assignmentResponse = await this.client.makeRequest({
1266
- method: 'POST',
1267
- endpoint: '/api/now/v2/table/sys_user_has_role',
1268
- data: {
1269
- user: userSysId,
1270
- role: role.sys_id,
1271
- state: 'active',
1272
- granted_by: 'snow_flow_automation'
1273
- }
1274
- });
1275
-
1276
- if (assignmentResponse.data?.result) {
1277
- assignedRoles.push(roleName);
1278
- assignmentDetails.push({
1279
- role: roleName,
1280
- sys_id: assignmentResponse.data.result.sys_id,
1281
- status: 'assigned'
1282
- });
1283
- this.logger.info(`Successfully assigned role: ${roleName}`);
1284
- }
1285
- } else {
1286
- this.logger.warn(`Role not found: ${roleName}`);
1287
- }
1288
- } catch (roleError) {
1289
- this.logger.warn(`Failed to assign role ${roleName}`, { error: roleError });
1290
- assignmentDetails.push({
1291
- role: roleName,
1292
- status: 'failed',
1293
- error: roleError instanceof Error ? roleError.message : String(roleError)
1294
- });
1295
- }
1296
- }
1297
-
1298
- return {
1299
- success: assignedRoles.length > 0,
1300
- assigned_roles: assignedRoles,
1301
- details: assignmentDetails
1302
- };
1303
- } catch (error) {
1304
- return {
1305
- success: false,
1306
- error: error instanceof Error ? error.message : String(error)
1307
- };
1308
- }
1309
- }
1310
-
1311
- /**
1312
- * Attempt OAuth scope elevation
1313
- */
1314
- private async attemptOAuthScopeElevation(
1315
- missingScopes: string[],
1316
- operation: string,
1317
- context: AgentContext
1318
- ): Promise<{success: boolean, elevated_scopes?: string[], error?: string}> {
1319
- try {
1320
- this.logger.info('Requesting OAuth scope elevation...', { missing_scopes: missingScopes });
1321
-
1322
- // In most ServiceNow OAuth implementations, scope elevation requires
1323
- // re-authorization through the OAuth flow. We can't dynamically elevate
1324
- // scopes without user interaction.
1325
-
1326
- // Check if we can refresh token with additional scopes
1327
- let currentToken = null;
1328
- try {
1329
- if (typeof (this.oauth as any).getTokenInfo === 'function') {
1330
- currentToken = await (this.oauth as any).getTokenInfo();
1331
- }
1332
- } catch (error) {
1333
- this.logger.debug('Could not get current token info', { error });
1334
- }
1335
-
1336
- if (!currentToken) {
1337
- return {
1338
- success: false,
1339
- error: 'No active OAuth token found or method not available'
1340
- };
1341
- }
1342
-
1343
- // Attempt token refresh - this typically won't add new scopes
1344
- // but might refresh existing elevated permissions
1345
- const refreshResult = await this.oauth.refreshAccessToken();
1346
- if (!refreshResult.success) {
1347
- return {
1348
- success: false,
1349
- error: 'Failed to refresh OAuth token'
1350
- };
1351
- }
1352
-
1353
- // Check if the refresh gave us the scopes we need
1354
- let newTokenInfo = null;
1355
- try {
1356
- if (typeof (this.oauth as any).getTokenInfo === 'function') {
1357
- newTokenInfo = await (this.oauth as any).getTokenInfo();
1358
- }
1359
- } catch (error) {
1360
- this.logger.debug('Could not get new token info after refresh', { error });
1361
- }
1362
-
1363
- const newScopes = newTokenInfo?.scope?.split(' ') || [];
1364
- const actuallyMissing = missingScopes.filter(scope => !newScopes.includes(scope));
1365
-
1366
- if (actuallyMissing.length === 0) {
1367
- return {
1368
- success: true,
1369
- elevated_scopes: missingScopes
1370
- };
1371
- }
1372
-
1373
- // For missing scopes, we need manual re-authorization
1374
- return {
1375
- success: false,
1376
- error: `OAuth scopes require manual re-authorization: ${actuallyMissing.join(', ')}`
1377
- };
1378
-
1379
- } catch (error) {
1380
- return {
1381
- success: false,
1382
- error: error instanceof Error ? error.message : String(error)
1383
- };
1384
- }
1385
- }
1386
-
1387
- /**
1388
- * Enhanced deployment context extraction
1389
- */
1390
- private async extractEnhancedDeploymentContext(operation: string, context: AgentContext): Promise<any> {
1391
- try {
1392
- // Extract from agent context
1393
- const contextData = context as any;
1394
-
1395
- // Enhanced artifact type detection
1396
- const artifactType = this.extractArtifactType(operation);
1397
- const artifactName = contextData.artifact_name ||
1398
- this.extractArtifactName(operation) ||
1399
- `fallback_${artifactType}_${Date.now()}`;
1400
-
1401
- // Determine current scope from various sources
1402
- let currentScope = contextData.current_scope || 'scoped_application';
1403
- if (contextData.deployment_config?.sys_scope) {
1404
- currentScope = contextData.deployment_config.sys_scope;
1405
- }
1406
-
1407
- // Analyze original error for better global scope strategy
1408
- const originalError = contextData.original_error || 'Scoped deployment failed';
1409
- const globalScopeStrategy = this.analyzeErrorForGlobalScopeStrategy(originalError);
1410
-
1411
- return {
1412
- artifact_type: artifactType,
1413
- artifact_name: artifactName,
1414
- current_scope: currentScope,
1415
- original_error: originalError,
1416
- global_scope_strategy: globalScopeStrategy,
1417
- deployment_config: contextData.deployment_config || {},
1418
- operation_context: {
1419
- session_id: context.session_id,
1420
- agent_id: context.agent_id,
1421
- timestamp: new Date().toISOString()
1422
- }
1423
- };
1424
- } catch (error) {
1425
- this.logger.warn('Failed to extract enhanced deployment context', { error });
1426
- return null;
1427
- }
1428
- }
1429
-
1430
- /**
1431
- * Analyze error for global scope strategy
1432
- */
1433
- private analyzeErrorForGlobalScopeStrategy(error: string): string {
1434
- const errorLower = error.toLowerCase();
1435
-
1436
- if (errorLower.includes('scope') || errorLower.includes('application')) {
1437
- return 'direct_global_deployment';
1438
- }
1439
- if (errorLower.includes('permission') || errorLower.includes('access')) {
1440
- return 'elevated_permissions_deployment';
1441
- }
1442
- if (errorLower.includes('table') || errorLower.includes('field')) {
1443
- return 'schema_aware_deployment';
1444
- }
1445
-
1446
- return 'standard_global_deployment';
1447
- }
1448
-
1449
- /**
1450
- * Validate global scope deployment permissions
1451
- */
1452
- private async validateGlobalScopePermissions(
1453
- artifactType: string,
1454
- context: AgentContext
1455
- ): Promise<{canProceed: boolean, missing_permissions?: string[], recommended_actions?: string[]}> {
1456
- try {
1457
- // Check basic global scope permissions
1458
- const requiredRoles = ['admin'];
1459
- const requiredScopes = ['write', 'admin'];
1460
-
1461
- // Get current user roles (simplified check)
1462
- let hasAdminRole = false;
1463
- try {
1464
- const rolesResponse = await this.client.makeRequest({
1465
- method: 'GET',
1466
- endpoint: '/api/now/v2/table/sys_user_has_role',
1467
- params: {
1468
- sysparm_query: 'user.user_name=javascript:gs.getUserName()^role.name=admin',
1469
- sysparm_limit: 1
1470
- }
1471
- });
1472
- hasAdminRole = rolesResponse.data?.result?.length > 0;
1473
- } catch (roleCheckError) {
1474
- this.logger.warn('Could not verify admin role', { error: roleCheckError });
1475
- }
1476
-
1477
- if (!hasAdminRole) {
1478
- return {
1479
- canProceed: false,
1480
- missing_permissions: ['admin'],
1481
- recommended_actions: [
1482
- 'Request admin role from ServiceNow administrator',
1483
- 'Use snow_escalate_permissions() for automatic elevation',
1484
- 'Consider scoped deployment alternative'
1485
- ]
1486
- };
1487
- }
1488
-
1489
- return { canProceed: true };
1490
- } catch (error) {
1491
- this.logger.warn('Permission validation failed', { error });
1492
- return {
1493
- canProceed: false,
1494
- missing_permissions: ['unknown'],
1495
- recommended_actions: ['Check authentication and try again']
1496
- };
1497
- }
1498
- }
1499
-
1500
- /**
1501
- * Determine global deployment strategy
1502
- */
1503
- private determineGlobalDeploymentStrategy(deploymentContext: any): any {
1504
- const strategies = {
1505
- direct_global_deployment: {
1506
- name: 'Direct Global Deployment',
1507
- reasons: ['Scope-related error detected', 'Standard global scope approach'],
1508
- estimated_success_rate: 0.75
1509
- },
1510
- elevated_permissions_deployment: {
1511
- name: 'Elevated Permissions Deployment',
1512
- reasons: ['Permission error detected', 'Admin-level deployment required'],
1513
- estimated_success_rate: 0.60
1514
- },
1515
- schema_aware_deployment: {
1516
- name: 'Schema-Aware Deployment',
1517
- reasons: ['Table/field error detected', 'Enhanced validation required'],
1518
- estimated_success_rate: 0.80
1519
- },
1520
- standard_global_deployment: {
1521
- name: 'Standard Global Deployment',
1522
- reasons: ['Generic error', 'Default global scope approach'],
1523
- estimated_success_rate: 0.65
1524
- }
1525
- };
1526
-
1527
- return strategies[deploymentContext.global_scope_strategy] || strategies.standard_global_deployment;
1528
- }
1529
-
1530
- /**
1531
- * Attempt automatic role assignment (usually requires admin privileges)
1532
- */
1533
- private async attemptRoleAssignment(userId: string, roles: string[]): Promise<{success: boolean, error?: string}> {
1534
- try {
1535
- // This typically fails in most ServiceNow instances for security reasons
1536
- // But we attempt it for completeness
1537
- for (const roleName of roles) {
1538
- // First, get the role sys_id
1539
- const roleResponse = await this.client.makeRequest({
1540
- method: 'GET',
1541
- endpoint: '/api/now/v2/table/sys_user_role',
1542
- params: {
1543
- sysparm_query: `name=${roleName}`,
1544
- sysparm_fields: 'sys_id,name',
1545
- sysparm_limit: 1
1546
- }
1547
- });
1548
-
1549
- if (roleResponse.data?.result?.[0]) {
1550
- const roleSysId = roleResponse.data.result[0].sys_id;
1551
-
1552
- // Attempt to assign role to user
1553
- await this.client.makeRequest({
1554
- method: 'POST',
1555
- endpoint: '/api/now/v2/table/sys_user_has_role',
1556
- data: {
1557
- user: userId,
1558
- role: roleSysId
1559
- }
1560
- });
1561
- }
1562
- }
1563
-
1564
- return { success: true };
1565
- } catch (error) {
1566
- return {
1567
- success: false,
1568
- error: error instanceof Error ? error.message : String(error)
1569
- };
1570
- }
1571
- }
1572
-
1573
- private async fallbackToGlobalScope(operation: string, context: AgentContext): Promise<any> {
1574
- this.logger.info(`🌐 Attempting intelligent global scope fallback for ${operation}`);
1575
-
1576
- try {
1577
- // Enhanced pre-flight validation
1578
- const authValidation = await this.validateServiceNowConnection();
1579
- if (!authValidation.success) {
1580
- return {
1581
- success: false,
1582
- reason: 'Authentication validation failed before global scope fallback',
1583
- auth_error: authValidation.error,
1584
- recovery_action: 'Fix authentication first, then retry global scope deployment'
1585
- };
1586
- }
1587
-
1588
- // Comprehensive deployment context extraction with validation
1589
- const deploymentContext = await this.extractEnhancedDeploymentContext(operation, context);
1590
-
1591
- if (!deploymentContext) {
1592
- this.logger.warn('Unable to extract deployment context - attempting generic global scope deployment');
1593
- return await this.attemptGenericGlobalScopeDeployment(operation, context);
1594
- }
1595
-
1596
- // Validate global scope deployment permissions
1597
- const globalScopeValidation = await this.validateGlobalScopePermissions(
1598
- deploymentContext.artifact_type,
1599
- context
1600
- );
1601
-
1602
- if (!globalScopeValidation.canProceed) {
1603
- return {
1604
- success: false,
1605
- reason: 'Insufficient permissions for global scope deployment',
1606
- missing_permissions: globalScopeValidation.missing_permissions,
1607
- recommended_actions: globalScopeValidation.recommended_actions,
1608
- escalation_required: true
1609
- };
1610
- }
1611
-
1612
- this.logger.info('🔧 Configuring global scope deployment', {
1613
- original_scope: deploymentContext.current_scope,
1614
- artifact_type: deploymentContext.artifact_type,
1615
- artifact_name: deploymentContext.artifact_name,
1616
- global_scope_strategy: deploymentContext.global_scope_strategy
1617
- });
1618
-
1619
- // Enhanced deployment strategy based on artifact type and complexity
1620
- let globalDeploymentResult;
1621
- const deploymentStrategy = this.determineGlobalDeploymentStrategy(deploymentContext);
1622
-
1623
- this.logger.info(`📋 Using deployment strategy: ${deploymentStrategy.name}`, {
1624
- reasons: deploymentStrategy.reasons,
1625
- estimated_success_rate: deploymentStrategy.estimated_success_rate
1626
- });
1627
-
1628
- switch (deploymentContext.artifact_type.toLowerCase()) {
1629
- case 'widget':
1630
- globalDeploymentResult = await this.deployWidgetInGlobalScopeEnhanced(
1631
- deploymentContext,
1632
- deploymentStrategy
1633
- );
1634
- break;
1635
-
1636
- case 'flow':
1637
- case 'workflow':
1638
- globalDeploymentResult = await this.deployFlowInGlobalScopeEnhanced(
1639
- deploymentContext,
1640
- deploymentStrategy
1641
- );
1642
- break;
1643
-
1644
- case 'script':
1645
- case 'script_include':
1646
- globalDeploymentResult = await this.deployScriptInGlobalScopeEnhanced(
1647
- deploymentContext,
1648
- deploymentStrategy
1649
- );
1650
- break;
1651
-
1652
- case 'business_rule':
1653
- globalDeploymentResult = await this.deployBusinessRuleInGlobalScopeEnhanced(
1654
- deploymentContext,
1655
- deploymentStrategy
1656
- );
1657
- break;
1658
-
1659
- case 'table':
1660
- globalDeploymentResult = await this.deployTableInGlobalScopeEnhanced(
1661
- deploymentContext,
1662
- deploymentStrategy
1663
- );
1664
- break;
1665
-
1666
- case 'application':
1667
- // Enhanced application scope handling
1668
- return await this.handleApplicationScopeFallback(deploymentContext, context);
1669
-
1670
- default:
1671
- globalDeploymentResult = await this.deployGenericArtifactInGlobalScopeEnhanced(
1672
- deploymentContext,
1673
- deploymentStrategy
1674
- );
1675
- }
1676
-
1677
- // Enhanced result processing with comprehensive validation
1678
- if (globalDeploymentResult.success) {
1679
- this.logger.info('✅ Global scope deployment successful', {
1680
- sys_id: globalDeploymentResult.sys_id,
1681
- artifact_type: deploymentContext.artifact_type,
1682
- deployment_time_ms: globalDeploymentResult.deployment_time_ms,
1683
- strategy_used: deploymentStrategy.name
1684
- });
1685
-
1686
- // Enhanced context update with deployment tracking
1687
- await this.updateContextWithEnhancedGlobalDeployment(context, {
1688
- ...globalDeploymentResult,
1689
- deployment_context: deploymentContext,
1690
- strategy_used: deploymentStrategy
1691
- });
1692
-
1693
- // Post-deployment validation
1694
- const validationResult = await this.validateGlobalDeployment(
1695
- globalDeploymentResult.sys_id,
1696
- deploymentContext.artifact_type
1697
- );
1698
-
1699
- return {
1700
- success: true,
1701
- reason: 'Successfully deployed in global scope with validation',
1702
- deployment_details: {
1703
- sys_id: globalDeploymentResult.sys_id,
1704
- scope: 'global',
1705
- artifact_type: deploymentContext.artifact_type,
1706
- artifact_name: deploymentContext.artifact_name,
1707
- fallback_reason: deploymentContext.original_error,
1708
- strategy_used: deploymentStrategy.name,
1709
- deployment_time_ms: globalDeploymentResult.deployment_time_ms,
1710
- validation_status: validationResult.status,
1711
- functional_verification: validationResult.functional_tests
1712
- },
1713
- next_steps: [
1714
- '1. Verify artifact functionality in global scope',
1715
- '2. Review and update ACL permissions if needed',
1716
- '3. Document scope change for future reference',
1717
- '4. Test integration with other components',
1718
- '5. Consider long-term scope strategy'
1719
- ],
1720
- warnings: validationResult.warnings || [],
1721
- recommendations: this.generateGlobalScopeRecommendations(deploymentContext, globalDeploymentResult)
1722
- };
1723
- } else {
1724
- // Enhanced failure handling with intelligent retry suggestions
1725
- const failureAnalysis = await this.analyzeGlobalScopeFailure(
1726
- globalDeploymentResult,
1727
- deploymentContext,
1728
- deploymentStrategy
1729
- );
1730
-
1731
- this.logger.error('❌ Global scope deployment failed', {
1732
- original_error: deploymentContext.original_error,
1733
- global_deployment_error: globalDeploymentResult.error,
1734
- failure__analysis: failureAnalysis
1735
- });
1736
-
1737
- return {
1738
- success: false,
1739
- reason: 'Global scope deployment failed after comprehensive attempts',
1740
- original_error: deploymentContext.original_error,
1741
- global_deployment_error: globalDeploymentResult.error,
1742
- failure__analysis: failureAnalysis,
1743
- alternative_strategies: [
1744
- '1. Manual Update Set creation and deployment',
1745
- '2. Phased deployment (create components separately)',
1746
- '3. XML-based deployment approach',
1747
- '4. ServiceNow Studio development environment',
1748
- '5. Direct database approach (requires elevated access)'
1749
- ],
1750
- diagnostic_commands: [
1751
- 'snow_deployment_debug() - Get detailed error _analysis',
1752
- 'snow_validate_deployment() - Pre-deployment validation',
1753
- 'snow_auth_diagnostics() - Check authentication and permissions',
1754
- 'snow_comprehensive_search() - Find similar existing artifacts'
1755
- ],
1756
- manual_options: failureAnalysis.manual_steps,
1757
- escalation_required: failureAnalysis.requires_admin_intervention,
1758
- estimated_manual_effort: failureAnalysis.estimated_manual_time
1759
- };
1760
- }
1761
-
1762
- } catch (error) {
1763
- this.logger.error('🚨 Global scope fallback process failed critically', {
1764
- error,
1765
- operation,
1766
- context,
1767
- stack: error instanceof Error ? error.stack : 'No stack trace available'
1768
- });
1769
-
1770
- // Request immediate Queen intervention for critical failures
1771
- await this.requestQueenIntervention(context, {
1772
- type: 'global_scope_fallback_failure',
1773
- priority: 'critical',
1774
- description: `Critical failure during global scope fallback for ${operation}: ${error instanceof Error ? error.message : String(error)}`,
1775
- attempted_solutions: ['global_scope_deployment', 'enhanced_validation']
1776
- });
1777
-
1778
- return {
1779
- success: false,
1780
- reason: 'Critical error during global scope fallback process',
1781
- error: error instanceof Error ? error.message : String(error),
1782
- error_type: this.categorizeError(error instanceof Error ? error.message : String(error)),
1783
- stack_trace: error instanceof Error ? error.stack : null,
1784
- recovery_actions: [
1785
- '1. Emergency: Verify ServiceNow instance connectivity',
1786
- '2. Critical: Check authentication and API access',
1787
- '3. High: Review deployment configuration for errors',
1788
- '4. Medium: Contact ServiceNow administrator immediately',
1789
- '5. Low: Review system logs for additional context'
1790
- ],
1791
- emergency_contact: true,
1792
- requires_immediate_attention: true,
1793
- fallback_options: [
1794
- 'Switch to manual deployment process',
1795
- 'Use ServiceNow Studio for development',
1796
- 'Create support ticket with ServiceNow',
1797
- 'Engage emergency deployment procedures'
1798
- ]
1799
- };
1800
- }
1801
- }
1802
-
1803
- /**
1804
- * Extract deployment context from operation and context
1805
- */
1806
- private extractDeploymentContext(operation: string, context: AgentContext): any {
1807
- try {
1808
- // Try to extract context from agent context or operation string
1809
- const contextData = context as any; // Allow access to additional properties
1810
-
1811
- return {
1812
- artifact_type: this.extractArtifactType(operation),
1813
- artifact_name: contextData.artifact_name || this.extractArtifactName(operation),
1814
- current_scope: contextData.current_scope || 'scoped_application',
1815
- original_error: contextData.original_error || 'Scoped deployment failed',
1816
- deployment_config: contextData.deployment_config || {}
1817
- };
1818
- } catch (error) {
1819
- this.logger.warn('Failed to extract deployment context', { error });
1820
- return null;
1821
- }
1822
- }
1823
-
1824
- /**
1825
- * Extract artifact type from operation string
1826
- */
1827
- private extractArtifactType(operation: string): string {
1828
- const patterns = [
1829
- { pattern: /widget/i, type: 'widget' },
1830
- { pattern: /flow|workflow/i, type: 'flow' },
1831
- { pattern: /script.*include/i, type: 'script_include' },
1832
- { pattern: /business.*rule/i, type: 'business_rule' },
1833
- { pattern: /application|app/i, type: 'application' },
1834
- { pattern: /script/i, type: 'script' }
1835
- ];
1836
-
1837
- for (const { pattern, type } of patterns) {
1838
- if (pattern.test(operation)) {
1839
- return type;
1840
- }
1841
- }
1842
-
1843
- return 'unknown';
1844
- }
1845
-
1846
- /**
1847
- * Extract artifact name from operation string
1848
- */
1849
- private extractArtifactName(operation: string): string {
1850
- // Try to extract name from common patterns
1851
- const nameMatch = operation.match(/deploy(?:ing)?\s+([a-zA-Z0-9_\-\s]+)/i);
1852
- return nameMatch ? nameMatch[1].trim() : 'fallback_artifact';
1853
- }
1854
-
1855
- /**
1856
- * Deploy widget in global scope
1857
- */
1858
- private async deployWidgetInGlobalScope(context: any): Promise<any> {
1859
- try {
1860
- const widgetData = {
1861
- ...context.deployment_config,
1862
- name: context.artifact_name,
1863
- sys_scope: 'global' // Force global scope
1864
- };
1865
-
1866
- const response = await this.client.makeRequest({
1867
- method: 'POST',
1868
- endpoint: '/api/now/v2/table/sp_widget',
1869
- data: widgetData
1870
- });
1871
-
1872
- if (response.data?.result) {
1873
- return {
1874
- success: true,
1875
- sys_id: response.data.result.sys_id,
1876
- name: response.data.result.name
1877
- };
1878
- }
1879
-
1880
- return { success: false, error: 'No result returned from widget creation' };
1881
- } catch (error) {
1882
- return {
1883
- success: false,
1884
- error: error instanceof Error ? error.message : String(error)
1885
- };
1886
- }
1887
- }
1888
-
1889
- /**
1890
- * Deploy flow in global scope
1891
- */
1892
- private async deployFlowInGlobalScope(context: any): Promise<any> {
1893
- try {
1894
- const flowData = {
1895
- ...context.deployment_config,
1896
- name: context.artifact_name,
1897
- sys_scope: 'global' // Force global scope
1898
- };
1899
-
1900
- const response = await this.client.makeRequest({
1901
- method: 'POST',
1902
- endpoint: '/api/now/v2/table/wf_workflow',
1903
- data: flowData
1904
- });
1905
-
1906
- if (response.data?.result) {
1907
- return {
1908
- success: true,
1909
- sys_id: response.data.result.sys_id,
1910
- name: response.data.result.name
1911
- };
1912
- }
1913
-
1914
- return { success: false, error: 'No result returned from flow creation' };
1915
- } catch (error) {
1916
- return {
1917
- success: false,
1918
- error: error instanceof Error ? error.message : String(error)
1919
- };
1920
- }
1921
- }
1922
-
1923
- /**
1924
- * Deploy script include in global scope
1925
- */
1926
- private async deployScriptInGlobalScope(context: any): Promise<any> {
1927
- try {
1928
- const scriptData = {
1929
- ...context.deployment_config,
1930
- name: context.artifact_name,
1931
- sys_scope: 'global' // Force global scope
1932
- };
1933
-
1934
- const response = await this.client.makeRequest({
1935
- method: 'POST',
1936
- endpoint: '/api/now/v2/table/sys_script_include',
1937
- data: scriptData
1938
- });
1939
-
1940
- if (response.data?.result) {
1941
- return {
1942
- success: true,
1943
- sys_id: response.data.result.sys_id,
1944
- name: response.data.result.name
1945
- };
1946
- }
1947
-
1948
- return { success: false, error: 'No result returned from script creation' };
1949
- } catch (error) {
1950
- return {
1951
- success: false,
1952
- error: error instanceof Error ? error.message : String(error)
1953
- };
1954
- }
1955
- }
1956
-
1957
- /**
1958
- * Deploy business rule in global scope
1959
- */
1960
- private async deployBusinessRuleInGlobalScope(context: any): Promise<any> {
1961
- try {
1962
- const ruleData = {
1963
- ...context.deployment_config,
1964
- name: context.artifact_name,
1965
- sys_scope: 'global' // Force global scope
1966
- };
1967
-
1968
- const response = await this.client.makeRequest({
1969
- method: 'POST',
1970
- endpoint: '/api/now/v2/table/sys_script',
1971
- data: ruleData
1972
- });
1973
-
1974
- if (response.data?.result) {
1975
- return {
1976
- success: true,
1977
- sys_id: response.data.result.sys_id,
1978
- name: response.data.result.name
1979
- };
1980
- }
1981
-
1982
- return { success: false, error: 'No result returned from business rule creation' };
1983
- } catch (error) {
1984
- return {
1985
- success: false,
1986
- error: error instanceof Error ? error.message : String(error)
1987
- };
1988
- }
1989
- }
1990
-
1991
- /**
1992
- * Generic global scope deployment for unknown artifact types
1993
- */
1994
- private async deployGenericArtifactInGlobalScope(context: any): Promise<any> {
1995
- try {
1996
- // Attempt deployment based on common table patterns
1997
- const possibleTables = [
1998
- 'sys_script_include',
1999
- 'sys_script',
2000
- 'sys_ui_script',
2001
- 'sys_ui_page'
2002
- ];
2003
-
2004
- for (const table of possibleTables) {
2005
- try {
2006
- const data = {
2007
- ...context.deployment_config,
2008
- name: context.artifact_name,
2009
- sys_scope: 'global'
2010
- };
2011
-
2012
- const response = await this.client.makeRequest({
2013
- method: 'POST',
2014
- endpoint: `/api/now/v2/table/${table}`,
2015
- data
2016
- });
2017
-
2018
- if (response.data?.result) {
2019
- return {
2020
- success: true,
2021
- sys_id: response.data.result.sys_id,
2022
- name: response.data.result.name,
2023
- table_used: table
2024
- };
2025
- }
2026
- } catch (tableError) {
2027
- // Continue to next table
2028
- this.logger.debug(`Failed to deploy to ${table}`, { error: tableError });
2029
- }
2030
- }
2031
-
2032
- return { success: false, error: 'No suitable table found for deployment' };
2033
- } catch (error) {
2034
- return {
2035
- success: false,
2036
- error: error instanceof Error ? error.message : String(error)
2037
- };
2038
- }
2039
- }
2040
-
2041
- /**
2042
- * Update context with global deployment information
2043
- */
2044
- private async updateContextWithGlobalDeployment(context: AgentContext, deploymentResult: any): Promise<void> {
2045
- try {
2046
- // Store deployment information in memory for coordination
2047
- await this.memory.updateSharedContext({
2048
- session_id: context.session_id,
2049
- context_key: 'global_deployment_fallback',
2050
- context_value: JSON.stringify({
2051
- original_context: context,
2052
- global_deployment: deploymentResult,
2053
- timestamp: new Date().toISOString()
2054
- }),
2055
- created_by_agent: context.agent_id
2056
- });
2057
- } catch (error) {
2058
- this.logger.warn('Failed to update context with global deployment', { error });
2059
- }
2060
- }
2061
-
2062
- /**
2063
- * Enhanced context update with deployment tracking
2064
- */
2065
- private async updateContextWithEnhancedGlobalDeployment(context: AgentContext, deploymentResult: any): Promise<void> {
2066
- try {
2067
- await this.memory.updateSharedContext({
2068
- session_id: context.session_id,
2069
- context_key: 'enhanced_global_deployment',
2070
- context_value: JSON.stringify({
2071
- deployment_result: deploymentResult,
2072
- context: context,
2073
- timestamp: new Date().toISOString()
2074
- }),
2075
- created_by_agent: context.agent_id
2076
- });
2077
- } catch (error) {
2078
- this.logger.warn('Failed to update enhanced global deployment context', { error });
2079
- }
2080
- }
2081
-
2082
- /**
2083
- * Enhanced widget deployment in global scope
2084
- */
2085
- private async deployWidgetInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2086
- try {
2087
- const startTime = Date.now();
2088
- const result = await this.deployWidgetInGlobalScope(context);
2089
-
2090
- return {
2091
- ...result,
2092
- deployment_time_ms: Date.now() - startTime,
2093
- strategy_applied: strategy.name
2094
- };
2095
- } catch (error) {
2096
- return {
2097
- success: false,
2098
- error: error instanceof Error ? error.message : String(error),
2099
- deployment_time_ms: 0
2100
- };
2101
- }
2102
- }
2103
-
2104
- /**
2105
- * Enhanced flow deployment in global scope
2106
- */
2107
- private async deployFlowInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2108
- try {
2109
- const startTime = Date.now();
2110
- const result = await this.deployFlowInGlobalScope(context);
2111
-
2112
- return {
2113
- ...result,
2114
- deployment_time_ms: Date.now() - startTime,
2115
- strategy_applied: strategy.name
2116
- };
2117
- } catch (error) {
2118
- return {
2119
- success: false,
2120
- error: error instanceof Error ? error.message : String(error),
2121
- deployment_time_ms: 0
2122
- };
2123
- }
2124
- }
2125
-
2126
- /**
2127
- * Enhanced script deployment in global scope
2128
- */
2129
- private async deployScriptInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2130
- try {
2131
- const startTime = Date.now();
2132
- const result = await this.deployScriptInGlobalScope(context);
2133
-
2134
- return {
2135
- ...result,
2136
- deployment_time_ms: Date.now() - startTime,
2137
- strategy_applied: strategy.name
2138
- };
2139
- } catch (error) {
2140
- return {
2141
- success: false,
2142
- error: error instanceof Error ? error.message : String(error),
2143
- deployment_time_ms: 0
2144
- };
2145
- }
2146
- }
2147
-
2148
- /**
2149
- * Enhanced business rule deployment in global scope
2150
- */
2151
- private async deployBusinessRuleInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2152
- try {
2153
- const startTime = Date.now();
2154
- const result = await this.deployBusinessRuleInGlobalScope(context);
2155
-
2156
- return {
2157
- ...result,
2158
- deployment_time_ms: Date.now() - startTime,
2159
- strategy_applied: strategy.name
2160
- };
2161
- } catch (error) {
2162
- return {
2163
- success: false,
2164
- error: error instanceof Error ? error.message : String(error),
2165
- deployment_time_ms: 0
2166
- };
2167
- }
2168
- }
2169
-
2170
- /**
2171
- * Enhanced table deployment in global scope
2172
- */
2173
- private async deployTableInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2174
- try {
2175
- const startTime = Date.now();
2176
-
2177
- const tableData = {
2178
- ...context.deployment_config,
2179
- name: context.artifact_name,
2180
- sys_scope: 'global'
2181
- };
2182
-
2183
- const response = await this.client.makeRequest({
2184
- method: 'POST',
2185
- endpoint: '/api/now/v2/table/sys_db_object',
2186
- data: tableData
2187
- });
2188
-
2189
- if (response.data?.result) {
2190
- return {
2191
- success: true,
2192
- sys_id: response.data.result.sys_id,
2193
- name: response.data.result.name,
2194
- deployment_time_ms: Date.now() - startTime,
2195
- strategy_applied: strategy.name
2196
- };
2197
- }
2198
-
2199
- return {
2200
- success: false,
2201
- error: 'No result returned from table creation',
2202
- deployment_time_ms: Date.now() - startTime
2203
- };
2204
- } catch (error) {
2205
- return {
2206
- success: false,
2207
- error: error instanceof Error ? error.message : String(error),
2208
- deployment_time_ms: 0
2209
- };
2210
- }
2211
- }
2212
-
2213
- /**
2214
- * Enhanced generic artifact deployment in global scope
2215
- */
2216
- private async deployGenericArtifactInGlobalScopeEnhanced(context: any, strategy: any): Promise<any> {
2217
- try {
2218
- const startTime = Date.now();
2219
- const result = await this.deployGenericArtifactInGlobalScope(context);
2220
-
2221
- return {
2222
- ...result,
2223
- deployment_time_ms: Date.now() - startTime,
2224
- strategy_applied: strategy.name
2225
- };
2226
- } catch (error) {
2227
- return {
2228
- success: false,
2229
- error: error instanceof Error ? error.message : String(error),
2230
- deployment_time_ms: 0
2231
- };
2232
- }
2233
- }
2234
-
2235
- /**
2236
- * Handle application scope fallback
2237
- */
2238
- private async handleApplicationScopeFallback(deploymentContext: any, context: AgentContext): Promise<any> {
2239
- try {
2240
- this.logger.info('🏢 Handling application scope fallback...');
2241
-
2242
- return {
2243
- success: false,
2244
- reason: 'Applications require special scope handling - cannot deploy in global scope',
2245
- alternative_strategies: [
2246
- '1. Create scoped application with broader permissions',
2247
- '2. Deploy individual components separately in global scope',
2248
- '3. Request administrator to configure application scope',
2249
- '4. Use ServiceNow Studio for application development'
2250
- ],
2251
- manual_steps: [
2252
- 'Navigate to System Applications > Studio',
2253
- 'Create new scoped application',
2254
- 'Configure appropriate scope permissions',
2255
- 'Deploy components within application scope'
2256
- ],
2257
- estimated_time: '15-30 minutes with proper permissions'
2258
- };
2259
- } catch (error) {
2260
- return {
2261
- success: false,
2262
- error: error instanceof Error ? error.message : String(error),
2263
- reason: 'Failed to analyze application scope requirements'
2264
- };
2265
- }
2266
- }
2267
-
2268
- /**
2269
- * Attempt generic global scope deployment
2270
- */
2271
- private async attemptGenericGlobalScopeDeployment(operation: string, context: AgentContext): Promise<any> {
2272
- try {
2273
- this.logger.info('🌐 Attempting generic global scope deployment...');
2274
-
2275
- return {
2276
- success: false,
2277
- reason: 'Generic global scope deployment requires more specific context',
2278
- recommended_actions: [
2279
- 'Provide more specific deployment context',
2280
- 'Use artifact-specific deployment methods',
2281
- 'Check deployment configuration',
2282
- 'Contact administrator for manual deployment'
2283
- ]
2284
- };
2285
- } catch (error) {
2286
- return {
2287
- success: false,
2288
- error: error instanceof Error ? error.message : String(error)
2289
- };
2290
- }
2291
- }
2292
-
2293
- /**
2294
- * Validate global deployment
2295
- */
2296
- private async validateGlobalDeployment(sysId: string, artifactType: string): Promise<any> {
2297
- try {
2298
- const table = this.getTableForType(artifactType);
2299
-
2300
- const validationResponse = await this.client.makeRequest({
2301
- method: 'GET',
2302
- endpoint: `/api/now/v2/table/${table}/${sysId}`,
2303
- params: {
2304
- sysparm_fields: 'sys_id,name,active,sys_scope'
2305
- }
2306
- });
2307
-
2308
- if (validationResponse.data?.result) {
2309
- const artifact = validationResponse.data.result;
2310
- return {
2311
- status: 'validated',
2312
- functional_tests: [
2313
- `Artifact exists: ${artifact.name}`,
2314
- `Scope: ${artifact.sys_scope || 'global'}`,
2315
- `Active: ${artifact.active || 'unknown'}`
2316
- ],
2317
- warnings: artifact.sys_scope !== 'global' ? ['Artifact may not be in global scope'] : []
2318
- };
2319
- }
2320
-
2321
- return {
2322
- status: 'validation_failed',
2323
- functional_tests: [],
2324
- warnings: ['Could not validate artifact deployment']
2325
- };
2326
- } catch (error) {
2327
- return {
2328
- status: 'validation_error',
2329
- functional_tests: [],
2330
- warnings: [`Validation error: ${error instanceof Error ? error.message : String(error)}`]
2331
- };
2332
- }
2333
- }
2334
-
2335
- /**
2336
- * Generate global scope recommendations
2337
- */
2338
- private generateGlobalScopeRecommendations(deploymentContext: any, deploymentResult: any): string[] {
2339
- const recommendations = [
2340
- '✅ Document this global scope deployment for future reference',
2341
- '🔍 Review ACL permissions to ensure proper access control',
2342
- '📋 Consider creating Update Set for deployment tracking'
2343
- ];
2344
-
2345
- if (deploymentContext.artifact_type === 'widget') {
2346
- recommendations.push('🎨 Test widget rendering in Service Portal');
2347
- }
2348
-
2349
- if (deploymentContext.artifact_type === 'flow') {
2350
- recommendations.push('⚡ Activate flow and test trigger conditions');
2351
- }
2352
-
2353
- return recommendations;
2354
- }
2355
-
2356
- /**
2357
- * Analyze global scope failure
2358
- */
2359
- private async analyzeGlobalScopeFailure(deploymentResult: any, deploymentContext: any, strategy: any): Promise<any> {
2360
- const errorMessage = deploymentResult.error || 'Unknown error';
2361
- const errorType = this.categorizeError(errorMessage);
2362
-
2363
- return {
2364
- error_category: errorType,
2365
- strategy_used: strategy.name,
2366
- requires_admin_intervention: errorType === 'permissions' || errorType === 'authentication',
2367
- estimated_manual_time: '10-30 minutes',
2368
- manual_steps: [
2369
- '1. Review ServiceNow system logs for detailed error information',
2370
- '2. Check user permissions and roles',
2371
- '3. Verify artifact configuration meets ServiceNow requirements',
2372
- '4. Consider alternative deployment approaches',
2373
- '5. Contact ServiceNow administrator if permission issues persist'
2374
- ],
2375
- technical_details: {
2376
- original_error: deploymentContext.original_error,
2377
- global_deployment_error: errorMessage,
2378
- artifact_type: deploymentContext.artifact_type,
2379
- deployment_strategy: strategy.name
2380
- }
2381
- };
2382
- }
2383
-
2384
- private async delay(ms: number): Promise<void> {
2385
- return new Promise(resolve => setTimeout(resolve, ms));
2386
- }
2387
-
2388
- /**
2389
- * Handle mock data removal - ensure real operations only
2390
- */
2391
- protected assertNoMockData(operation: string): void {
2392
- if (process.env.SNOW_FLOW_MOCK_MODE === 'true') {
2393
- throw new Error(`Mock mode is not supported for ${operation}. All operations must use real ServiceNow instance.`);
2394
- }
2395
- }
2396
-
2397
- /**
2398
- * List available MCP resources
2399
- */
2400
- protected async listMCPResources(): Promise<any> {
2401
- try {
2402
- const resources = await this.resourceManager.listResources();
2403
- this.logger.debug(`Listed ${resources.length} MCP resources`);
2404
-
2405
- return {
2406
- resources: resources.map(resource => ({
2407
- uri: resource.uri,
2408
- name: resource.name,
2409
- description: resource.description,
2410
- mimeType: resource.mimeType
2411
- }))
2412
- };
2413
- } catch (error) {
2414
- this.logger.error('Failed to list MCP resources:', error);
2415
- return { resources: [] };
2416
- }
2417
- }
2418
-
2419
- /**
2420
- * Read a specific MCP resource by URI
2421
- */
2422
- protected async readMCPResource(uri: string): Promise<any> {
2423
- try {
2424
- const resource = await this.resourceManager.readResource(uri);
2425
- this.logger.debug(`Read MCP resource: ${uri}`);
2426
-
2427
- return {
2428
- contents: [{
2429
- uri: resource.uri,
2430
- mimeType: resource.mimeType,
2431
- text: resource.text
2432
- }]
2433
- };
2434
- } catch (error) {
2435
- this.logger.error(`Failed to read MCP resource ${uri}:`, error);
2436
- throw new Error(`Resource not found or inaccessible: ${uri}`);
2437
- }
2438
- }
2439
-
2440
- /**
2441
- * Get resource manager statistics
2442
- */
2443
- protected getMCPResourceStats(): any {
2444
- return this.resourceManager.getResourceStats();
2445
- }
2446
-
2447
- /**
2448
- * Clear resource cache (useful for development)
2449
- */
2450
- protected clearMCPResourceCache(): void {
2451
- this.resourceManager.clearCache();
2452
- this.logger.debug('MCP resource cache cleared');
2453
- }
2454
-
2455
- /**
2456
- * Start the MCP server
2457
- */
2458
- async start(): Promise<void> {
2459
- const transport = new (await import('@modelcontextprotocol/sdk/server/stdio.js')).StdioServerTransport();
2460
- await this.server.connect(transport);
2461
- this.logger.info(`${(this.server as any).serverInfo?.name || 'Unknown'} MCP server started`);
2462
- }
2463
- }