snow-flow 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.claude-flow/queen/queen-memory.db +0 -0
  2. package/.env.example +249 -14
  3. package/CLAUDE.md +185 -24
  4. package/README.md +55 -5
  5. package/dist/api/error-handling.js +898 -4
  6. package/dist/api/performance-optimizer.js +3 -2
  7. package/dist/cli.js +590 -200
  8. package/dist/config/snow-flow-config.js +320 -8
  9. package/dist/health/system-health.js +288 -21
  10. package/dist/mcp/base-mcp-server.js +2 -0
  11. package/dist/mcp/http-transport-wrapper.js +65 -4
  12. package/dist/mcp/servicenow-automation-mcp-refactored.js +90 -9
  13. package/dist/mcp/servicenow-deployment-mcp-refactored.js +151 -2
  14. package/dist/mcp/servicenow-deployment-mcp.js +828 -15
  15. package/dist/mcp/servicenow-integration-mcp-refactored.js +100 -9
  16. package/dist/mcp/servicenow-intelligent-mcp.js +198 -7
  17. package/dist/mcp/servicenow-memory-mcp.js +2 -1
  18. package/dist/mcp/servicenow-operations-mcp-refactored.js +3 -2
  19. package/dist/mcp/servicenow-xml-flow-mcp.js +671 -0
  20. package/dist/mcp/shared/base-mcp-server.js +1356 -8
  21. package/dist/mcp/shared/mcp-resource-manager.js +304 -0
  22. package/dist/queen/parallel-agent-engine.js +26 -8
  23. package/dist/queen/servicenow-queen.js +47 -44
  24. package/dist/sparc/sparc-help.js +37 -26
  25. package/dist/sparc/team-sparc.js +60 -16
  26. package/dist/utils/action-type-cache.js +2 -1
  27. package/dist/utils/mcp-config-manager.js +7 -3
  28. package/dist/utils/mcp-server-manager.js +7 -3
  29. package/dist/utils/servicenow-client.js +134 -107
  30. package/dist/utils/servicenow-id-generator.js +171 -0
  31. package/dist/utils/snow-oauth.js +13 -8
  32. package/dist/utils/widget-template-generator.js +1690 -0
  33. package/dist/utils/xml-first-flow-generator.js +473 -0
  34. package/dist/version.js +7 -1
  35. package/flow-update-sets/flow_build_automated_approval_flow_with_notifications_flow.xml +203 -0
  36. package/flow-update-sets/flow_create_approval_flow_for_equipment_requests_flow.xml +206 -0
  37. package/flow-update-sets/flow_create_equipment_approval_flow_with_manager_approv_flow.xml +254 -0
  38. package/flow-update-sets/iphone_15_pro_approval_flow.xml +203 -0
  39. package/flow-update-sets/test_iphone_approval_flow_flow.xml +303 -0
  40. package/package.json +2 -1
  41. package/test-config.js +55 -0
  42. package/test-real-monitoring.js +184 -0
@@ -44,6 +44,7 @@ const snow_oauth_js_1 = require("../../utils/snow-oauth.js");
44
44
  const logger_js_1 = require("../../utils/logger.js");
45
45
  const agent_context_provider_js_1 = require("./agent-context-provider.js");
46
46
  const mcp_memory_manager_js_1 = require("./mcp-memory-manager.js");
47
+ const mcp_resource_manager_js_1 = require("./mcp-resource-manager.js");
47
48
  class BaseMCPServer {
48
49
  constructor(name, version = '1.0.0') {
49
50
  this.server = new index_js_1.Server({
@@ -52,6 +53,7 @@ class BaseMCPServer {
52
53
  }, {
53
54
  capabilities: {
54
55
  tools: {},
56
+ resources: {},
55
57
  },
56
58
  });
57
59
  this.client = new servicenow_client_js_1.ServiceNowClient();
@@ -59,6 +61,7 @@ class BaseMCPServer {
59
61
  this.logger = new logger_js_1.Logger(name);
60
62
  this.contextProvider = new agent_context_provider_js_1.AgentContextProvider();
61
63
  this.memory = mcp_memory_manager_js_1.MCPMemoryManager.getInstance();
64
+ this.resourceManager = new mcp_resource_manager_js_1.MCPResourceManager(name);
62
65
  }
63
66
  /**
64
67
  * Execute a tool with agent context tracking
@@ -202,7 +205,7 @@ ${errorText}
202
205
 
203
206
  💡 To get OAuth credentials:
204
207
  • ServiceNow: System OAuth > Application Registry > New OAuth Application
205
- • Redirect URI: http://localhost:3005/callback
208
+ • Redirect URI: http://localhost:3005/callback (configurable via SNOW_REDIRECT_* env vars)
206
209
  • Scopes: useraccount write admin`
207
210
  }
208
211
  ]
@@ -689,15 +692,1306 @@ ${errorText}
689
692
  return options;
690
693
  }
691
694
  async escalateToGlobalScope(operation, context) {
692
- // Implementation would escalate permissions or scope
693
- // This is a placeholder for actual escalation logic
694
- this.logger.info(`Attempting scope escalation for ${operation}`);
695
- return { success: false, reason: 'Escalation not implemented yet' };
695
+ this.logger.info(`🔝 Attempting permission escalation for ${operation}`);
696
+ try {
697
+ // Enhanced authentication validation
698
+ const authValidation = await this.validateServiceNowConnection();
699
+ if (!authValidation.success) {
700
+ return {
701
+ success: false,
702
+ reason: 'Authentication validation failed before escalation',
703
+ recovery_action: 'Run: snow-flow auth login',
704
+ auth_error: authValidation.error
705
+ };
706
+ }
707
+ // Get current user information with enhanced OAuth scope handling
708
+ this.logger.info('🔍 Analyzing current user permissions and OAuth scopes...');
709
+ let currentUser = null;
710
+ let currentRoles = [];
711
+ let oAuthScopes = [];
712
+ try {
713
+ // Get current user details
714
+ const userResponse = await this.client.makeRequest({
715
+ method: 'GET',
716
+ endpoint: '/api/now/v2/table/sys_user',
717
+ params: {
718
+ sysparm_query: 'active=true^user_name=javascript:gs.getUserName()',
719
+ sysparm_fields: 'sys_id,user_name,name,email,active,locked_out,roles',
720
+ sysparm_limit: 1
721
+ }
722
+ });
723
+ if (userResponse.data?.result?.[0]) {
724
+ currentUser = userResponse.data.result[0];
725
+ this.logger.info(`👤 Current user: ${currentUser.name} (${currentUser.user_name})`);
726
+ }
727
+ // Get detailed role information
728
+ const rolesResponse = await this.client.makeRequest({
729
+ method: 'GET',
730
+ endpoint: '/api/now/v2/table/sys_user_has_role',
731
+ params: {
732
+ sysparm_query: `user.user_name=${currentUser?.user_name || 'javascript:gs.getUserName()'}`,
733
+ sysparm_fields: 'role.name,role.description,state,inherited',
734
+ sysparm_limit: 100
735
+ }
736
+ });
737
+ if (rolesResponse.data?.result) {
738
+ currentRoles = rolesResponse.data.result
739
+ .filter((r) => r.state === 'active')
740
+ .map((r) => r['role.name'])
741
+ .filter(Boolean);
742
+ this.logger.info(`🛡️ Active roles: ${currentRoles.join(', ')}`);
743
+ }
744
+ // Check OAuth token scopes if available
745
+ try {
746
+ // Attempt to get token info if method exists
747
+ if (typeof this.oauth.getTokenInfo === 'function') {
748
+ const tokenInfo = await this.oauth.getTokenInfo();
749
+ if (tokenInfo?.scope) {
750
+ oAuthScopes = tokenInfo.scope.split(' ');
751
+ this.logger.info(`🔑 OAuth scopes: ${oAuthScopes.join(', ')}`);
752
+ }
753
+ }
754
+ else {
755
+ this.logger.debug('OAuth getTokenInfo method not available');
756
+ }
757
+ }
758
+ catch (scopeError) {
759
+ this.logger.debug('Could not retrieve OAuth scope information', { error: scopeError });
760
+ }
761
+ }
762
+ catch (roleError) {
763
+ this.logger.warn('Could not fetch complete user information', { error: roleError });
764
+ // Continue with limited information
765
+ }
766
+ // Enhanced role analysis based on operation type
767
+ const requiredRoles = this.determineRequiredRoles(operation);
768
+ const requiredScopes = this.determineRequiredOAuthScopes(operation);
769
+ const missingRoles = requiredRoles.filter(role => !currentRoles.includes(role));
770
+ const missingScopes = requiredScopes.filter(scope => !oAuthScopes.includes(scope));
771
+ this.logger.info(`📊 Permission Analysis:`, {
772
+ required_roles: requiredRoles,
773
+ current_roles: currentRoles,
774
+ missing_roles: missingRoles,
775
+ required_scopes: requiredScopes,
776
+ current_scopes: oAuthScopes,
777
+ missing_scopes: missingScopes
778
+ });
779
+ // Check if user has sufficient permissions
780
+ if (missingRoles.length === 0 && missingScopes.length === 0) {
781
+ // User has all required permissions, issue might be elsewhere
782
+ return {
783
+ success: true,
784
+ reason: 'User has all required roles and scopes - permission issue may be configuration related',
785
+ current_roles: currentRoles,
786
+ current_scopes: oAuthScopes,
787
+ diagnostic_actions: [
788
+ 'Check ACL rules for the specific table/operation',
789
+ 'Verify application scope permissions',
790
+ 'Check domain separation settings',
791
+ 'Review field-level security',
792
+ 'Validate write permissions for target table'
793
+ ]
794
+ };
795
+ }
796
+ // Enhanced automatic role assignment with better error handling
797
+ let autoAssignmentAttempted = false;
798
+ const canAutoAssign = currentRoles.includes('admin') ||
799
+ currentRoles.includes('user_admin') ||
800
+ currentRoles.includes('system_administrator');
801
+ if (canAutoAssign && missingRoles.length > 0) {
802
+ this.logger.info('🤖 Attempting automatic role assignment...');
803
+ try {
804
+ const assignmentResult = await this.attemptEnhancedRoleAssignment(currentUser?.sys_id, missingRoles, context);
805
+ if (assignmentResult.success) {
806
+ autoAssignmentAttempted = true;
807
+ // Update context with successful assignment
808
+ await this.memory.updateSharedContext({
809
+ session_id: context.session_id,
810
+ context_key: `permission_escalation_${operation}`,
811
+ context_value: JSON.stringify({
812
+ escalation_type: 'automatic_role_assignment',
813
+ assigned_roles: assignmentResult.assigned_roles,
814
+ timestamp: new Date().toISOString(),
815
+ operation: operation
816
+ }),
817
+ created_by_agent: context.agent_id
818
+ });
819
+ return {
820
+ success: true,
821
+ reason: 'Roles automatically assigned successfully',
822
+ assigned_roles: assignmentResult.assigned_roles,
823
+ assignment_details: assignmentResult.details,
824
+ recommended_action: 'Retry the original operation - new permissions are active'
825
+ };
826
+ }
827
+ }
828
+ catch (assignError) {
829
+ this.logger.warn('Automatic role assignment failed', { error: assignError });
830
+ autoAssignmentAttempted = true; // We tried
831
+ }
832
+ }
833
+ // Enhanced OAuth scope elevation attempt
834
+ if (missingScopes.length > 0) {
835
+ this.logger.info('🔑 Attempting OAuth scope elevation...');
836
+ try {
837
+ const scopeElevationResult = await this.attemptOAuthScopeElevation(missingScopes, operation, context);
838
+ if (scopeElevationResult.success) {
839
+ return {
840
+ success: true,
841
+ reason: 'OAuth scopes elevated successfully',
842
+ elevated_scopes: scopeElevationResult.elevated_scopes,
843
+ recommended_action: 'Retry the original operation with elevated OAuth permissions'
844
+ };
845
+ }
846
+ }
847
+ catch (scopeError) {
848
+ this.logger.warn('OAuth scope elevation failed', { error: scopeError });
849
+ }
850
+ }
851
+ // Request Queen intervention for complex permission issues
852
+ await this.requestQueenIntervention(context, {
853
+ type: 'permission_escalation_required',
854
+ priority: 'high',
855
+ description: `Permission escalation needed for ${operation}. Missing roles: ${missingRoles.join(', ')}. Missing OAuth scopes: ${missingScopes.join(', ')}.`,
856
+ attempted_solutions: [
857
+ ...(autoAssignmentAttempted ? ['automatic_role_assignment'] : []),
858
+ ...(missingScopes.length > 0 ? ['oauth_scope_elevation'] : [])
859
+ ]
860
+ });
861
+ // Comprehensive manual escalation instructions
862
+ const manualSteps = [
863
+ `1. ServiceNow Administrator Actions Required:`,
864
+ ` • Navigate to User Administration > Users`,
865
+ ` • Find user: ${currentUser?.name || 'Current User'} (${currentUser?.user_name || 'unknown'})`,
866
+ ` • Add missing roles: ${missingRoles.join(', ')}`,
867
+ ...missingScopes.length > 0 ? [
868
+ `2. OAuth Application Configuration:`,
869
+ ` • Update OAuth application scopes to include: ${missingScopes.join(', ')}`,
870
+ ` • Re-authorize application with elevated permissions`
871
+ ] : [],
872
+ `${missingScopes.length > 0 ? '3' : '2'}. Verification Steps:`,
873
+ ` • Test permissions: snow_validate_live_connection({ test_level: "permissions" })`,
874
+ ` • Retry operation: ${operation}`
875
+ ];
876
+ return {
877
+ success: false,
878
+ reason: 'Manual permission escalation required',
879
+ current_user: currentUser,
880
+ current_roles: currentRoles,
881
+ missing_roles: missingRoles,
882
+ current_oauth_scopes: oAuthScopes,
883
+ missing_oauth_scopes: missingScopes,
884
+ escalation_required: true,
885
+ auto_assignment_attempted: autoAssignmentAttempted,
886
+ manual_steps: manualSteps,
887
+ estimated_time: `${5 + (missingRoles.length * 2)}–${10 + (missingRoles.length * 3)} minutes with admin access`,
888
+ priority: missingRoles.includes('admin') || missingRoles.includes('system_administrator') ? 'critical' : 'high'
889
+ };
890
+ }
891
+ catch (error) {
892
+ this.logger.error('🚨 Permission escalation process failed', { error, operation, context });
893
+ return {
894
+ success: false,
895
+ reason: 'Critical error during permission escalation',
896
+ error: error instanceof Error ? error.message : String(error),
897
+ error_type: this.categorizeError(error instanceof Error ? error.message : String(error)),
898
+ recovery_actions: [
899
+ '1. Verify ServiceNow connection: snow_validate_live_connection()',
900
+ '2. Check authentication status: snow_auth_diagnostics()',
901
+ '3. Confirm API access is enabled in ServiceNow',
902
+ '4. Contact ServiceNow administrator for manual role assignment',
903
+ '5. Review system logs for additional error details'
904
+ ],
905
+ escalation_required: true,
906
+ contact_admin: true
907
+ };
908
+ }
909
+ }
910
+ /**
911
+ * Determine required roles based on operation type
912
+ */
913
+ determineRequiredRoles(operation) {
914
+ const roles = [];
915
+ // Base roles for most operations
916
+ if (operation.includes('deploy') || operation.includes('create') || operation.includes('update')) {
917
+ roles.push('rest_service', 'web_service_admin');
918
+ }
919
+ // Widget operations
920
+ if (operation.includes('widget')) {
921
+ roles.push('sp_admin', 'sp_portal_admin');
922
+ }
923
+ // Flow operations
924
+ if (operation.includes('flow') || operation.includes('workflow')) {
925
+ roles.push('flow_designer', 'admin');
926
+ }
927
+ // Application operations
928
+ if (operation.includes('application') || operation.includes('app')) {
929
+ roles.push('app_creator', 'admin');
930
+ }
931
+ // Update set operations
932
+ if (operation.includes('update_set')) {
933
+ roles.push('admin');
934
+ }
935
+ // Global scope operations
936
+ if (operation.includes('global')) {
937
+ roles.push('admin', 'system_administrator');
938
+ }
939
+ return Array.from(new Set(roles)); // Remove duplicates
940
+ }
941
+ /**
942
+ * Determine required OAuth scopes based on operation type
943
+ */
944
+ determineRequiredOAuthScopes(operation) {
945
+ const scopes = ['useraccount']; // Base scope for most operations
946
+ // Operations that require write access
947
+ if (operation.includes('deploy') || operation.includes('create') || operation.includes('update')) {
948
+ scopes.push('write');
949
+ }
950
+ // Administrative operations
951
+ if (operation.includes('admin') || operation.includes('global') || operation.includes('system')) {
952
+ scopes.push('admin');
953
+ }
954
+ // Flow Designer operations may need specific scopes
955
+ if (operation.includes('flow') || operation.includes('workflow')) {
956
+ scopes.push('write', 'admin');
957
+ }
958
+ return Array.from(new Set(scopes)); // Remove duplicates
959
+ }
960
+ /**
961
+ * Enhanced role assignment with better validation
962
+ */
963
+ async attemptEnhancedRoleAssignment(userSysId, roles, context) {
964
+ try {
965
+ const assignedRoles = [];
966
+ const assignmentDetails = [];
967
+ for (const roleName of roles) {
968
+ try {
969
+ // Get the role sys_id with enhanced validation
970
+ const roleResponse = await this.client.makeRequest({
971
+ method: 'GET',
972
+ endpoint: '/api/now/v2/table/sys_user_role',
973
+ params: {
974
+ sysparm_query: `name=${roleName}^active=true`,
975
+ sysparm_fields: 'sys_id,name,description,can_delegate',
976
+ sysparm_limit: 1
977
+ }
978
+ });
979
+ if (roleResponse.data?.result?.[0]) {
980
+ const role = roleResponse.data.result[0];
981
+ // Check if user already has this role
982
+ const existingRoleResponse = await this.client.makeRequest({
983
+ method: 'GET',
984
+ endpoint: '/api/now/v2/table/sys_user_has_role',
985
+ params: {
986
+ sysparm_query: `user=${userSysId}^role=${role.sys_id}`,
987
+ sysparm_limit: 1
988
+ }
989
+ });
990
+ if (existingRoleResponse.data?.result?.length > 0) {
991
+ this.logger.info(`User already has role: ${roleName}`);
992
+ assignedRoles.push(roleName);
993
+ continue;
994
+ }
995
+ // Attempt to assign role
996
+ const assignmentResponse = await this.client.makeRequest({
997
+ method: 'POST',
998
+ endpoint: '/api/now/v2/table/sys_user_has_role',
999
+ data: {
1000
+ user: userSysId,
1001
+ role: role.sys_id,
1002
+ state: 'active',
1003
+ granted_by: 'snow_flow_automation'
1004
+ }
1005
+ });
1006
+ if (assignmentResponse.data?.result) {
1007
+ assignedRoles.push(roleName);
1008
+ assignmentDetails.push({
1009
+ role: roleName,
1010
+ sys_id: assignmentResponse.data.result.sys_id,
1011
+ status: 'assigned'
1012
+ });
1013
+ this.logger.info(`Successfully assigned role: ${roleName}`);
1014
+ }
1015
+ }
1016
+ else {
1017
+ this.logger.warn(`Role not found: ${roleName}`);
1018
+ }
1019
+ }
1020
+ catch (roleError) {
1021
+ this.logger.warn(`Failed to assign role ${roleName}`, { error: roleError });
1022
+ assignmentDetails.push({
1023
+ role: roleName,
1024
+ status: 'failed',
1025
+ error: roleError instanceof Error ? roleError.message : String(roleError)
1026
+ });
1027
+ }
1028
+ }
1029
+ return {
1030
+ success: assignedRoles.length > 0,
1031
+ assigned_roles: assignedRoles,
1032
+ details: assignmentDetails
1033
+ };
1034
+ }
1035
+ catch (error) {
1036
+ return {
1037
+ success: false,
1038
+ error: error instanceof Error ? error.message : String(error)
1039
+ };
1040
+ }
1041
+ }
1042
+ /**
1043
+ * Attempt OAuth scope elevation
1044
+ */
1045
+ async attemptOAuthScopeElevation(missingScopes, operation, context) {
1046
+ try {
1047
+ this.logger.info('Requesting OAuth scope elevation...', { missing_scopes: missingScopes });
1048
+ // In most ServiceNow OAuth implementations, scope elevation requires
1049
+ // re-authorization through the OAuth flow. We can't dynamically elevate
1050
+ // scopes without user interaction.
1051
+ // Check if we can refresh token with additional scopes
1052
+ let currentToken = null;
1053
+ try {
1054
+ if (typeof this.oauth.getTokenInfo === 'function') {
1055
+ currentToken = await this.oauth.getTokenInfo();
1056
+ }
1057
+ }
1058
+ catch (error) {
1059
+ this.logger.debug('Could not get current token info', { error });
1060
+ }
1061
+ if (!currentToken) {
1062
+ return {
1063
+ success: false,
1064
+ error: 'No active OAuth token found or method not available'
1065
+ };
1066
+ }
1067
+ // Attempt token refresh - this typically won't add new scopes
1068
+ // but might refresh existing elevated permissions
1069
+ const refreshResult = await this.oauth.refreshAccessToken();
1070
+ if (!refreshResult.success) {
1071
+ return {
1072
+ success: false,
1073
+ error: 'Failed to refresh OAuth token'
1074
+ };
1075
+ }
1076
+ // Check if the refresh gave us the scopes we need
1077
+ let newTokenInfo = null;
1078
+ try {
1079
+ if (typeof this.oauth.getTokenInfo === 'function') {
1080
+ newTokenInfo = await this.oauth.getTokenInfo();
1081
+ }
1082
+ }
1083
+ catch (error) {
1084
+ this.logger.debug('Could not get new token info after refresh', { error });
1085
+ }
1086
+ const newScopes = newTokenInfo?.scope?.split(' ') || [];
1087
+ const actuallyMissing = missingScopes.filter(scope => !newScopes.includes(scope));
1088
+ if (actuallyMissing.length === 0) {
1089
+ return {
1090
+ success: true,
1091
+ elevated_scopes: missingScopes
1092
+ };
1093
+ }
1094
+ // For missing scopes, we need manual re-authorization
1095
+ return {
1096
+ success: false,
1097
+ error: `OAuth scopes require manual re-authorization: ${actuallyMissing.join(', ')}`
1098
+ };
1099
+ }
1100
+ catch (error) {
1101
+ return {
1102
+ success: false,
1103
+ error: error instanceof Error ? error.message : String(error)
1104
+ };
1105
+ }
1106
+ }
1107
+ /**
1108
+ * Enhanced deployment context extraction
1109
+ */
1110
+ async extractEnhancedDeploymentContext(operation, context) {
1111
+ try {
1112
+ // Extract from agent context
1113
+ const contextData = context;
1114
+ // Enhanced artifact type detection
1115
+ const artifactType = this.extractArtifactType(operation);
1116
+ const artifactName = contextData.artifact_name ||
1117
+ this.extractArtifactName(operation) ||
1118
+ `fallback_${artifactType}_${Date.now()}`;
1119
+ // Determine current scope from various sources
1120
+ let currentScope = contextData.current_scope || 'scoped_application';
1121
+ if (contextData.deployment_config?.sys_scope) {
1122
+ currentScope = contextData.deployment_config.sys_scope;
1123
+ }
1124
+ // Analyze original error for better global scope strategy
1125
+ const originalError = contextData.original_error || 'Scoped deployment failed';
1126
+ const globalScopeStrategy = this.analyzeErrorForGlobalScopeStrategy(originalError);
1127
+ return {
1128
+ artifact_type: artifactType,
1129
+ artifact_name: artifactName,
1130
+ current_scope: currentScope,
1131
+ original_error: originalError,
1132
+ global_scope_strategy: globalScopeStrategy,
1133
+ deployment_config: contextData.deployment_config || {},
1134
+ operation_context: {
1135
+ session_id: context.session_id,
1136
+ agent_id: context.agent_id,
1137
+ timestamp: new Date().toISOString()
1138
+ }
1139
+ };
1140
+ }
1141
+ catch (error) {
1142
+ this.logger.warn('Failed to extract enhanced deployment context', { error });
1143
+ return null;
1144
+ }
1145
+ }
1146
+ /**
1147
+ * Analyze error for global scope strategy
1148
+ */
1149
+ analyzeErrorForGlobalScopeStrategy(error) {
1150
+ const errorLower = error.toLowerCase();
1151
+ if (errorLower.includes('scope') || errorLower.includes('application')) {
1152
+ return 'direct_global_deployment';
1153
+ }
1154
+ if (errorLower.includes('permission') || errorLower.includes('access')) {
1155
+ return 'elevated_permissions_deployment';
1156
+ }
1157
+ if (errorLower.includes('table') || errorLower.includes('field')) {
1158
+ return 'schema_aware_deployment';
1159
+ }
1160
+ return 'standard_global_deployment';
1161
+ }
1162
+ /**
1163
+ * Validate global scope deployment permissions
1164
+ */
1165
+ async validateGlobalScopePermissions(artifactType, context) {
1166
+ try {
1167
+ // Check basic global scope permissions
1168
+ const requiredRoles = ['admin'];
1169
+ const requiredScopes = ['write', 'admin'];
1170
+ // Get current user roles (simplified check)
1171
+ let hasAdminRole = false;
1172
+ try {
1173
+ const rolesResponse = await this.client.makeRequest({
1174
+ method: 'GET',
1175
+ endpoint: '/api/now/v2/table/sys_user_has_role',
1176
+ params: {
1177
+ sysparm_query: 'user.user_name=javascript:gs.getUserName()^role.name=admin',
1178
+ sysparm_limit: 1
1179
+ }
1180
+ });
1181
+ hasAdminRole = rolesResponse.data?.result?.length > 0;
1182
+ }
1183
+ catch (roleCheckError) {
1184
+ this.logger.warn('Could not verify admin role', { error: roleCheckError });
1185
+ }
1186
+ if (!hasAdminRole) {
1187
+ return {
1188
+ canProceed: false,
1189
+ missing_permissions: ['admin'],
1190
+ recommended_actions: [
1191
+ 'Request admin role from ServiceNow administrator',
1192
+ 'Use snow_escalate_permissions() for automatic elevation',
1193
+ 'Consider scoped deployment alternative'
1194
+ ]
1195
+ };
1196
+ }
1197
+ return { canProceed: true };
1198
+ }
1199
+ catch (error) {
1200
+ this.logger.warn('Permission validation failed', { error });
1201
+ return {
1202
+ canProceed: false,
1203
+ missing_permissions: ['unknown'],
1204
+ recommended_actions: ['Check authentication and try again']
1205
+ };
1206
+ }
1207
+ }
1208
+ /**
1209
+ * Determine global deployment strategy
1210
+ */
1211
+ determineGlobalDeploymentStrategy(deploymentContext) {
1212
+ const strategies = {
1213
+ direct_global_deployment: {
1214
+ name: 'Direct Global Deployment',
1215
+ reasons: ['Scope-related error detected', 'Standard global scope approach'],
1216
+ estimated_success_rate: 0.75
1217
+ },
1218
+ elevated_permissions_deployment: {
1219
+ name: 'Elevated Permissions Deployment',
1220
+ reasons: ['Permission error detected', 'Admin-level deployment required'],
1221
+ estimated_success_rate: 0.60
1222
+ },
1223
+ schema_aware_deployment: {
1224
+ name: 'Schema-Aware Deployment',
1225
+ reasons: ['Table/field error detected', 'Enhanced validation required'],
1226
+ estimated_success_rate: 0.80
1227
+ },
1228
+ standard_global_deployment: {
1229
+ name: 'Standard Global Deployment',
1230
+ reasons: ['Generic error', 'Default global scope approach'],
1231
+ estimated_success_rate: 0.65
1232
+ }
1233
+ };
1234
+ return strategies[deploymentContext.global_scope_strategy] || strategies.standard_global_deployment;
1235
+ }
1236
+ /**
1237
+ * Attempt automatic role assignment (usually requires admin privileges)
1238
+ */
1239
+ async attemptRoleAssignment(userId, roles) {
1240
+ try {
1241
+ // This typically fails in most ServiceNow instances for security reasons
1242
+ // But we attempt it for completeness
1243
+ for (const roleName of roles) {
1244
+ // First, get the role sys_id
1245
+ const roleResponse = await this.client.makeRequest({
1246
+ method: 'GET',
1247
+ endpoint: '/api/now/v2/table/sys_user_role',
1248
+ params: {
1249
+ sysparm_query: `name=${roleName}`,
1250
+ sysparm_fields: 'sys_id,name',
1251
+ sysparm_limit: 1
1252
+ }
1253
+ });
1254
+ if (roleResponse.data?.result?.[0]) {
1255
+ const roleSysId = roleResponse.data.result[0].sys_id;
1256
+ // Attempt to assign role to user
1257
+ await this.client.makeRequest({
1258
+ method: 'POST',
1259
+ endpoint: '/api/now/v2/table/sys_user_has_role',
1260
+ data: {
1261
+ user: userId,
1262
+ role: roleSysId
1263
+ }
1264
+ });
1265
+ }
1266
+ }
1267
+ return { success: true };
1268
+ }
1269
+ catch (error) {
1270
+ return {
1271
+ success: false,
1272
+ error: error instanceof Error ? error.message : String(error)
1273
+ };
1274
+ }
696
1275
  }
697
1276
  async fallbackToGlobalScope(operation, context) {
698
- // Implementation would fallback to global scope deployment
699
- this.logger.info(`Attempting global scope fallback for ${operation}`);
700
- return { success: false, reason: 'Global scope fallback not implemented yet' };
1277
+ this.logger.info(`🌐 Attempting intelligent global scope fallback for ${operation}`);
1278
+ try {
1279
+ // Enhanced pre-flight validation
1280
+ const authValidation = await this.validateServiceNowConnection();
1281
+ if (!authValidation.success) {
1282
+ return {
1283
+ success: false,
1284
+ reason: 'Authentication validation failed before global scope fallback',
1285
+ auth_error: authValidation.error,
1286
+ recovery_action: 'Fix authentication first, then retry global scope deployment'
1287
+ };
1288
+ }
1289
+ // Comprehensive deployment context extraction with validation
1290
+ const deploymentContext = await this.extractEnhancedDeploymentContext(operation, context);
1291
+ if (!deploymentContext) {
1292
+ this.logger.warn('Unable to extract deployment context - attempting generic global scope deployment');
1293
+ return await this.attemptGenericGlobalScopeDeployment(operation, context);
1294
+ }
1295
+ // Validate global scope deployment permissions
1296
+ const globalScopeValidation = await this.validateGlobalScopePermissions(deploymentContext.artifact_type, context);
1297
+ if (!globalScopeValidation.canProceed) {
1298
+ return {
1299
+ success: false,
1300
+ reason: 'Insufficient permissions for global scope deployment',
1301
+ missing_permissions: globalScopeValidation.missing_permissions,
1302
+ recommended_actions: globalScopeValidation.recommended_actions,
1303
+ escalation_required: true
1304
+ };
1305
+ }
1306
+ this.logger.info('🔧 Configuring global scope deployment', {
1307
+ original_scope: deploymentContext.current_scope,
1308
+ artifact_type: deploymentContext.artifact_type,
1309
+ artifact_name: deploymentContext.artifact_name,
1310
+ global_scope_strategy: deploymentContext.global_scope_strategy
1311
+ });
1312
+ // Enhanced deployment strategy based on artifact type and complexity
1313
+ let globalDeploymentResult;
1314
+ const deploymentStrategy = this.determineGlobalDeploymentStrategy(deploymentContext);
1315
+ this.logger.info(`📋 Using deployment strategy: ${deploymentStrategy.name}`, {
1316
+ reasons: deploymentStrategy.reasons,
1317
+ estimated_success_rate: deploymentStrategy.estimated_success_rate
1318
+ });
1319
+ switch (deploymentContext.artifact_type.toLowerCase()) {
1320
+ case 'widget':
1321
+ globalDeploymentResult = await this.deployWidgetInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1322
+ break;
1323
+ case 'flow':
1324
+ case 'workflow':
1325
+ globalDeploymentResult = await this.deployFlowInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1326
+ break;
1327
+ case 'script':
1328
+ case 'script_include':
1329
+ globalDeploymentResult = await this.deployScriptInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1330
+ break;
1331
+ case 'business_rule':
1332
+ globalDeploymentResult = await this.deployBusinessRuleInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1333
+ break;
1334
+ case 'table':
1335
+ globalDeploymentResult = await this.deployTableInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1336
+ break;
1337
+ case 'application':
1338
+ // Enhanced application scope handling
1339
+ return await this.handleApplicationScopeFallback(deploymentContext, context);
1340
+ default:
1341
+ globalDeploymentResult = await this.deployGenericArtifactInGlobalScopeEnhanced(deploymentContext, deploymentStrategy);
1342
+ }
1343
+ // Enhanced result processing with comprehensive validation
1344
+ if (globalDeploymentResult.success) {
1345
+ this.logger.info('✅ Global scope deployment successful', {
1346
+ sys_id: globalDeploymentResult.sys_id,
1347
+ artifact_type: deploymentContext.artifact_type,
1348
+ deployment_time_ms: globalDeploymentResult.deployment_time_ms,
1349
+ strategy_used: deploymentStrategy.name
1350
+ });
1351
+ // Enhanced context update with deployment tracking
1352
+ await this.updateContextWithEnhancedGlobalDeployment(context, {
1353
+ ...globalDeploymentResult,
1354
+ deployment_context: deploymentContext,
1355
+ strategy_used: deploymentStrategy
1356
+ });
1357
+ // Post-deployment validation
1358
+ const validationResult = await this.validateGlobalDeployment(globalDeploymentResult.sys_id, deploymentContext.artifact_type);
1359
+ return {
1360
+ success: true,
1361
+ reason: 'Successfully deployed in global scope with validation',
1362
+ deployment_details: {
1363
+ sys_id: globalDeploymentResult.sys_id,
1364
+ scope: 'global',
1365
+ artifact_type: deploymentContext.artifact_type,
1366
+ artifact_name: deploymentContext.artifact_name,
1367
+ fallback_reason: deploymentContext.original_error,
1368
+ strategy_used: deploymentStrategy.name,
1369
+ deployment_time_ms: globalDeploymentResult.deployment_time_ms,
1370
+ validation_status: validationResult.status,
1371
+ functional_verification: validationResult.functional_tests
1372
+ },
1373
+ next_steps: [
1374
+ '1. Verify artifact functionality in global scope',
1375
+ '2. Review and update ACL permissions if needed',
1376
+ '3. Document scope change for future reference',
1377
+ '4. Test integration with other components',
1378
+ '5. Consider long-term scope strategy'
1379
+ ],
1380
+ warnings: validationResult.warnings || [],
1381
+ recommendations: this.generateGlobalScopeRecommendations(deploymentContext, globalDeploymentResult)
1382
+ };
1383
+ }
1384
+ else {
1385
+ // Enhanced failure handling with intelligent retry suggestions
1386
+ const failureAnalysis = await this.analyzeGlobalScopeFailure(globalDeploymentResult, deploymentContext, deploymentStrategy);
1387
+ this.logger.error('❌ Global scope deployment failed', {
1388
+ original_error: deploymentContext.original_error,
1389
+ global_deployment_error: globalDeploymentResult.error,
1390
+ failure_analysis: failureAnalysis
1391
+ });
1392
+ return {
1393
+ success: false,
1394
+ reason: 'Global scope deployment failed after comprehensive attempts',
1395
+ original_error: deploymentContext.original_error,
1396
+ global_deployment_error: globalDeploymentResult.error,
1397
+ failure_analysis: failureAnalysis,
1398
+ alternative_strategies: [
1399
+ '1. Manual Update Set creation and deployment',
1400
+ '2. Phased deployment (create components separately)',
1401
+ '3. XML-based deployment approach',
1402
+ '4. ServiceNow Studio development environment',
1403
+ '5. Direct database approach (requires elevated access)'
1404
+ ],
1405
+ diagnostic_commands: [
1406
+ 'snow_deployment_debug() - Get detailed error analysis',
1407
+ 'snow_validate_deployment() - Pre-deployment validation',
1408
+ 'snow_auth_diagnostics() - Check authentication and permissions',
1409
+ 'snow_comprehensive_search() - Find similar existing artifacts'
1410
+ ],
1411
+ manual_options: failureAnalysis.manual_steps,
1412
+ escalation_required: failureAnalysis.requires_admin_intervention,
1413
+ estimated_manual_effort: failureAnalysis.estimated_manual_time
1414
+ };
1415
+ }
1416
+ }
1417
+ catch (error) {
1418
+ this.logger.error('🚨 Global scope fallback process failed critically', {
1419
+ error,
1420
+ operation,
1421
+ context,
1422
+ stack: error instanceof Error ? error.stack : 'No stack trace available'
1423
+ });
1424
+ // Request immediate Queen intervention for critical failures
1425
+ await this.requestQueenIntervention(context, {
1426
+ type: 'global_scope_fallback_failure',
1427
+ priority: 'critical',
1428
+ description: `Critical failure during global scope fallback for ${operation}: ${error instanceof Error ? error.message : String(error)}`,
1429
+ attempted_solutions: ['global_scope_deployment', 'enhanced_validation']
1430
+ });
1431
+ return {
1432
+ success: false,
1433
+ reason: 'Critical error during global scope fallback process',
1434
+ error: error instanceof Error ? error.message : String(error),
1435
+ error_type: this.categorizeError(error instanceof Error ? error.message : String(error)),
1436
+ stack_trace: error instanceof Error ? error.stack : null,
1437
+ recovery_actions: [
1438
+ '1. Emergency: Verify ServiceNow instance connectivity',
1439
+ '2. Critical: Check authentication and API access',
1440
+ '3. High: Review deployment configuration for errors',
1441
+ '4. Medium: Contact ServiceNow administrator immediately',
1442
+ '5. Low: Review system logs for additional context'
1443
+ ],
1444
+ emergency_contact: true,
1445
+ requires_immediate_attention: true,
1446
+ fallback_options: [
1447
+ 'Switch to manual deployment process',
1448
+ 'Use ServiceNow Studio for development',
1449
+ 'Create support ticket with ServiceNow',
1450
+ 'Engage emergency deployment procedures'
1451
+ ]
1452
+ };
1453
+ }
1454
+ }
1455
+ /**
1456
+ * Extract deployment context from operation and context
1457
+ */
1458
+ extractDeploymentContext(operation, context) {
1459
+ try {
1460
+ // Try to extract context from agent context or operation string
1461
+ const contextData = context; // Allow access to additional properties
1462
+ return {
1463
+ artifact_type: this.extractArtifactType(operation),
1464
+ artifact_name: contextData.artifact_name || this.extractArtifactName(operation),
1465
+ current_scope: contextData.current_scope || 'scoped_application',
1466
+ original_error: contextData.original_error || 'Scoped deployment failed',
1467
+ deployment_config: contextData.deployment_config || {}
1468
+ };
1469
+ }
1470
+ catch (error) {
1471
+ this.logger.warn('Failed to extract deployment context', { error });
1472
+ return null;
1473
+ }
1474
+ }
1475
+ /**
1476
+ * Extract artifact type from operation string
1477
+ */
1478
+ extractArtifactType(operation) {
1479
+ const patterns = [
1480
+ { pattern: /widget/i, type: 'widget' },
1481
+ { pattern: /flow|workflow/i, type: 'flow' },
1482
+ { pattern: /script.*include/i, type: 'script_include' },
1483
+ { pattern: /business.*rule/i, type: 'business_rule' },
1484
+ { pattern: /application|app/i, type: 'application' },
1485
+ { pattern: /script/i, type: 'script' }
1486
+ ];
1487
+ for (const { pattern, type } of patterns) {
1488
+ if (pattern.test(operation)) {
1489
+ return type;
1490
+ }
1491
+ }
1492
+ return 'unknown';
1493
+ }
1494
+ /**
1495
+ * Extract artifact name from operation string
1496
+ */
1497
+ extractArtifactName(operation) {
1498
+ // Try to extract name from common patterns
1499
+ const nameMatch = operation.match(/deploy(?:ing)?\s+([a-zA-Z0-9_\-\s]+)/i);
1500
+ return nameMatch ? nameMatch[1].trim() : 'fallback_artifact';
1501
+ }
1502
+ /**
1503
+ * Deploy widget in global scope
1504
+ */
1505
+ async deployWidgetInGlobalScope(context) {
1506
+ try {
1507
+ const widgetData = {
1508
+ ...context.deployment_config,
1509
+ name: context.artifact_name,
1510
+ sys_scope: 'global' // Force global scope
1511
+ };
1512
+ const response = await this.client.makeRequest({
1513
+ method: 'POST',
1514
+ endpoint: '/api/now/v2/table/sp_widget',
1515
+ data: widgetData
1516
+ });
1517
+ if (response.data?.result) {
1518
+ return {
1519
+ success: true,
1520
+ sys_id: response.data.result.sys_id,
1521
+ name: response.data.result.name
1522
+ };
1523
+ }
1524
+ return { success: false, error: 'No result returned from widget creation' };
1525
+ }
1526
+ catch (error) {
1527
+ return {
1528
+ success: false,
1529
+ error: error instanceof Error ? error.message : String(error)
1530
+ };
1531
+ }
1532
+ }
1533
+ /**
1534
+ * Deploy flow in global scope
1535
+ */
1536
+ async deployFlowInGlobalScope(context) {
1537
+ try {
1538
+ const flowData = {
1539
+ ...context.deployment_config,
1540
+ name: context.artifact_name,
1541
+ sys_scope: 'global' // Force global scope
1542
+ };
1543
+ const response = await this.client.makeRequest({
1544
+ method: 'POST',
1545
+ endpoint: '/api/now/v2/table/wf_workflow',
1546
+ data: flowData
1547
+ });
1548
+ if (response.data?.result) {
1549
+ return {
1550
+ success: true,
1551
+ sys_id: response.data.result.sys_id,
1552
+ name: response.data.result.name
1553
+ };
1554
+ }
1555
+ return { success: false, error: 'No result returned from flow creation' };
1556
+ }
1557
+ catch (error) {
1558
+ return {
1559
+ success: false,
1560
+ error: error instanceof Error ? error.message : String(error)
1561
+ };
1562
+ }
1563
+ }
1564
+ /**
1565
+ * Deploy script include in global scope
1566
+ */
1567
+ async deployScriptInGlobalScope(context) {
1568
+ try {
1569
+ const scriptData = {
1570
+ ...context.deployment_config,
1571
+ name: context.artifact_name,
1572
+ sys_scope: 'global' // Force global scope
1573
+ };
1574
+ const response = await this.client.makeRequest({
1575
+ method: 'POST',
1576
+ endpoint: '/api/now/v2/table/sys_script_include',
1577
+ data: scriptData
1578
+ });
1579
+ if (response.data?.result) {
1580
+ return {
1581
+ success: true,
1582
+ sys_id: response.data.result.sys_id,
1583
+ name: response.data.result.name
1584
+ };
1585
+ }
1586
+ return { success: false, error: 'No result returned from script creation' };
1587
+ }
1588
+ catch (error) {
1589
+ return {
1590
+ success: false,
1591
+ error: error instanceof Error ? error.message : String(error)
1592
+ };
1593
+ }
1594
+ }
1595
+ /**
1596
+ * Deploy business rule in global scope
1597
+ */
1598
+ async deployBusinessRuleInGlobalScope(context) {
1599
+ try {
1600
+ const ruleData = {
1601
+ ...context.deployment_config,
1602
+ name: context.artifact_name,
1603
+ sys_scope: 'global' // Force global scope
1604
+ };
1605
+ const response = await this.client.makeRequest({
1606
+ method: 'POST',
1607
+ endpoint: '/api/now/v2/table/sys_script',
1608
+ data: ruleData
1609
+ });
1610
+ if (response.data?.result) {
1611
+ return {
1612
+ success: true,
1613
+ sys_id: response.data.result.sys_id,
1614
+ name: response.data.result.name
1615
+ };
1616
+ }
1617
+ return { success: false, error: 'No result returned from business rule creation' };
1618
+ }
1619
+ catch (error) {
1620
+ return {
1621
+ success: false,
1622
+ error: error instanceof Error ? error.message : String(error)
1623
+ };
1624
+ }
1625
+ }
1626
+ /**
1627
+ * Generic global scope deployment for unknown artifact types
1628
+ */
1629
+ async deployGenericArtifactInGlobalScope(context) {
1630
+ try {
1631
+ // Attempt deployment based on common table patterns
1632
+ const possibleTables = [
1633
+ 'sys_script_include',
1634
+ 'sys_script',
1635
+ 'sys_ui_script',
1636
+ 'sys_ui_page'
1637
+ ];
1638
+ for (const table of possibleTables) {
1639
+ try {
1640
+ const data = {
1641
+ ...context.deployment_config,
1642
+ name: context.artifact_name,
1643
+ sys_scope: 'global'
1644
+ };
1645
+ const response = await this.client.makeRequest({
1646
+ method: 'POST',
1647
+ endpoint: `/api/now/v2/table/${table}`,
1648
+ data
1649
+ });
1650
+ if (response.data?.result) {
1651
+ return {
1652
+ success: true,
1653
+ sys_id: response.data.result.sys_id,
1654
+ name: response.data.result.name,
1655
+ table_used: table
1656
+ };
1657
+ }
1658
+ }
1659
+ catch (tableError) {
1660
+ // Continue to next table
1661
+ this.logger.debug(`Failed to deploy to ${table}`, { error: tableError });
1662
+ }
1663
+ }
1664
+ return { success: false, error: 'No suitable table found for deployment' };
1665
+ }
1666
+ catch (error) {
1667
+ return {
1668
+ success: false,
1669
+ error: error instanceof Error ? error.message : String(error)
1670
+ };
1671
+ }
1672
+ }
1673
+ /**
1674
+ * Update context with global deployment information
1675
+ */
1676
+ async updateContextWithGlobalDeployment(context, deploymentResult) {
1677
+ try {
1678
+ // Store deployment information in memory for coordination
1679
+ await this.memory.updateSharedContext({
1680
+ session_id: context.session_id,
1681
+ context_key: 'global_deployment_fallback',
1682
+ context_value: JSON.stringify({
1683
+ original_context: context,
1684
+ global_deployment: deploymentResult,
1685
+ timestamp: new Date().toISOString()
1686
+ }),
1687
+ created_by_agent: context.agent_id
1688
+ });
1689
+ }
1690
+ catch (error) {
1691
+ this.logger.warn('Failed to update context with global deployment', { error });
1692
+ }
1693
+ }
1694
+ /**
1695
+ * Enhanced context update with deployment tracking
1696
+ */
1697
+ async updateContextWithEnhancedGlobalDeployment(context, deploymentResult) {
1698
+ try {
1699
+ await this.memory.updateSharedContext({
1700
+ session_id: context.session_id,
1701
+ context_key: 'enhanced_global_deployment',
1702
+ context_value: JSON.stringify({
1703
+ deployment_result: deploymentResult,
1704
+ context: context,
1705
+ timestamp: new Date().toISOString()
1706
+ }),
1707
+ created_by_agent: context.agent_id
1708
+ });
1709
+ }
1710
+ catch (error) {
1711
+ this.logger.warn('Failed to update enhanced global deployment context', { error });
1712
+ }
1713
+ }
1714
+ /**
1715
+ * Enhanced widget deployment in global scope
1716
+ */
1717
+ async deployWidgetInGlobalScopeEnhanced(context, strategy) {
1718
+ try {
1719
+ const startTime = Date.now();
1720
+ const result = await this.deployWidgetInGlobalScope(context);
1721
+ return {
1722
+ ...result,
1723
+ deployment_time_ms: Date.now() - startTime,
1724
+ strategy_applied: strategy.name
1725
+ };
1726
+ }
1727
+ catch (error) {
1728
+ return {
1729
+ success: false,
1730
+ error: error instanceof Error ? error.message : String(error),
1731
+ deployment_time_ms: 0
1732
+ };
1733
+ }
1734
+ }
1735
+ /**
1736
+ * Enhanced flow deployment in global scope
1737
+ */
1738
+ async deployFlowInGlobalScopeEnhanced(context, strategy) {
1739
+ try {
1740
+ const startTime = Date.now();
1741
+ const result = await this.deployFlowInGlobalScope(context);
1742
+ return {
1743
+ ...result,
1744
+ deployment_time_ms: Date.now() - startTime,
1745
+ strategy_applied: strategy.name
1746
+ };
1747
+ }
1748
+ catch (error) {
1749
+ return {
1750
+ success: false,
1751
+ error: error instanceof Error ? error.message : String(error),
1752
+ deployment_time_ms: 0
1753
+ };
1754
+ }
1755
+ }
1756
+ /**
1757
+ * Enhanced script deployment in global scope
1758
+ */
1759
+ async deployScriptInGlobalScopeEnhanced(context, strategy) {
1760
+ try {
1761
+ const startTime = Date.now();
1762
+ const result = await this.deployScriptInGlobalScope(context);
1763
+ return {
1764
+ ...result,
1765
+ deployment_time_ms: Date.now() - startTime,
1766
+ strategy_applied: strategy.name
1767
+ };
1768
+ }
1769
+ catch (error) {
1770
+ return {
1771
+ success: false,
1772
+ error: error instanceof Error ? error.message : String(error),
1773
+ deployment_time_ms: 0
1774
+ };
1775
+ }
1776
+ }
1777
+ /**
1778
+ * Enhanced business rule deployment in global scope
1779
+ */
1780
+ async deployBusinessRuleInGlobalScopeEnhanced(context, strategy) {
1781
+ try {
1782
+ const startTime = Date.now();
1783
+ const result = await this.deployBusinessRuleInGlobalScope(context);
1784
+ return {
1785
+ ...result,
1786
+ deployment_time_ms: Date.now() - startTime,
1787
+ strategy_applied: strategy.name
1788
+ };
1789
+ }
1790
+ catch (error) {
1791
+ return {
1792
+ success: false,
1793
+ error: error instanceof Error ? error.message : String(error),
1794
+ deployment_time_ms: 0
1795
+ };
1796
+ }
1797
+ }
1798
+ /**
1799
+ * Enhanced table deployment in global scope
1800
+ */
1801
+ async deployTableInGlobalScopeEnhanced(context, strategy) {
1802
+ try {
1803
+ const startTime = Date.now();
1804
+ const tableData = {
1805
+ ...context.deployment_config,
1806
+ name: context.artifact_name,
1807
+ sys_scope: 'global'
1808
+ };
1809
+ const response = await this.client.makeRequest({
1810
+ method: 'POST',
1811
+ endpoint: '/api/now/v2/table/sys_db_object',
1812
+ data: tableData
1813
+ });
1814
+ if (response.data?.result) {
1815
+ return {
1816
+ success: true,
1817
+ sys_id: response.data.result.sys_id,
1818
+ name: response.data.result.name,
1819
+ deployment_time_ms: Date.now() - startTime,
1820
+ strategy_applied: strategy.name
1821
+ };
1822
+ }
1823
+ return {
1824
+ success: false,
1825
+ error: 'No result returned from table creation',
1826
+ deployment_time_ms: Date.now() - startTime
1827
+ };
1828
+ }
1829
+ catch (error) {
1830
+ return {
1831
+ success: false,
1832
+ error: error instanceof Error ? error.message : String(error),
1833
+ deployment_time_ms: 0
1834
+ };
1835
+ }
1836
+ }
1837
+ /**
1838
+ * Enhanced generic artifact deployment in global scope
1839
+ */
1840
+ async deployGenericArtifactInGlobalScopeEnhanced(context, strategy) {
1841
+ try {
1842
+ const startTime = Date.now();
1843
+ const result = await this.deployGenericArtifactInGlobalScope(context);
1844
+ return {
1845
+ ...result,
1846
+ deployment_time_ms: Date.now() - startTime,
1847
+ strategy_applied: strategy.name
1848
+ };
1849
+ }
1850
+ catch (error) {
1851
+ return {
1852
+ success: false,
1853
+ error: error instanceof Error ? error.message : String(error),
1854
+ deployment_time_ms: 0
1855
+ };
1856
+ }
1857
+ }
1858
+ /**
1859
+ * Handle application scope fallback
1860
+ */
1861
+ async handleApplicationScopeFallback(deploymentContext, context) {
1862
+ try {
1863
+ this.logger.info('🏢 Handling application scope fallback...');
1864
+ return {
1865
+ success: false,
1866
+ reason: 'Applications require special scope handling - cannot deploy in global scope',
1867
+ alternative_strategies: [
1868
+ '1. Create scoped application with broader permissions',
1869
+ '2. Deploy individual components separately in global scope',
1870
+ '3. Request administrator to configure application scope',
1871
+ '4. Use ServiceNow Studio for application development'
1872
+ ],
1873
+ manual_steps: [
1874
+ 'Navigate to System Applications > Studio',
1875
+ 'Create new scoped application',
1876
+ 'Configure appropriate scope permissions',
1877
+ 'Deploy components within application scope'
1878
+ ],
1879
+ estimated_time: '15-30 minutes with proper permissions'
1880
+ };
1881
+ }
1882
+ catch (error) {
1883
+ return {
1884
+ success: false,
1885
+ error: error instanceof Error ? error.message : String(error),
1886
+ reason: 'Failed to analyze application scope requirements'
1887
+ };
1888
+ }
1889
+ }
1890
+ /**
1891
+ * Attempt generic global scope deployment
1892
+ */
1893
+ async attemptGenericGlobalScopeDeployment(operation, context) {
1894
+ try {
1895
+ this.logger.info('🌐 Attempting generic global scope deployment...');
1896
+ return {
1897
+ success: false,
1898
+ reason: 'Generic global scope deployment requires more specific context',
1899
+ recommended_actions: [
1900
+ 'Provide more specific deployment context',
1901
+ 'Use artifact-specific deployment methods',
1902
+ 'Check deployment configuration',
1903
+ 'Contact administrator for manual deployment'
1904
+ ]
1905
+ };
1906
+ }
1907
+ catch (error) {
1908
+ return {
1909
+ success: false,
1910
+ error: error instanceof Error ? error.message : String(error)
1911
+ };
1912
+ }
1913
+ }
1914
+ /**
1915
+ * Validate global deployment
1916
+ */
1917
+ async validateGlobalDeployment(sysId, artifactType) {
1918
+ try {
1919
+ const table = this.getTableForType(artifactType);
1920
+ const validationResponse = await this.client.makeRequest({
1921
+ method: 'GET',
1922
+ endpoint: `/api/now/v2/table/${table}/${sysId}`,
1923
+ params: {
1924
+ sysparm_fields: 'sys_id,name,active,sys_scope'
1925
+ }
1926
+ });
1927
+ if (validationResponse.data?.result) {
1928
+ const artifact = validationResponse.data.result;
1929
+ return {
1930
+ status: 'validated',
1931
+ functional_tests: [
1932
+ `Artifact exists: ${artifact.name}`,
1933
+ `Scope: ${artifact.sys_scope || 'global'}`,
1934
+ `Active: ${artifact.active || 'unknown'}`
1935
+ ],
1936
+ warnings: artifact.sys_scope !== 'global' ? ['Artifact may not be in global scope'] : []
1937
+ };
1938
+ }
1939
+ return {
1940
+ status: 'validation_failed',
1941
+ functional_tests: [],
1942
+ warnings: ['Could not validate artifact deployment']
1943
+ };
1944
+ }
1945
+ catch (error) {
1946
+ return {
1947
+ status: 'validation_error',
1948
+ functional_tests: [],
1949
+ warnings: [`Validation error: ${error instanceof Error ? error.message : String(error)}`]
1950
+ };
1951
+ }
1952
+ }
1953
+ /**
1954
+ * Generate global scope recommendations
1955
+ */
1956
+ generateGlobalScopeRecommendations(deploymentContext, deploymentResult) {
1957
+ const recommendations = [
1958
+ '✅ Document this global scope deployment for future reference',
1959
+ '🔍 Review ACL permissions to ensure proper access control',
1960
+ '📋 Consider creating Update Set for deployment tracking'
1961
+ ];
1962
+ if (deploymentContext.artifact_type === 'widget') {
1963
+ recommendations.push('🎨 Test widget rendering in Service Portal');
1964
+ }
1965
+ if (deploymentContext.artifact_type === 'flow') {
1966
+ recommendations.push('⚡ Activate flow and test trigger conditions');
1967
+ }
1968
+ return recommendations;
1969
+ }
1970
+ /**
1971
+ * Analyze global scope failure
1972
+ */
1973
+ async analyzeGlobalScopeFailure(deploymentResult, deploymentContext, strategy) {
1974
+ const errorMessage = deploymentResult.error || 'Unknown error';
1975
+ const errorType = this.categorizeError(errorMessage);
1976
+ return {
1977
+ error_category: errorType,
1978
+ strategy_used: strategy.name,
1979
+ requires_admin_intervention: errorType === 'permissions' || errorType === 'authentication',
1980
+ estimated_manual_time: '10-30 minutes',
1981
+ manual_steps: [
1982
+ '1. Review ServiceNow system logs for detailed error information',
1983
+ '2. Check user permissions and roles',
1984
+ '3. Verify artifact configuration meets ServiceNow requirements',
1985
+ '4. Consider alternative deployment approaches',
1986
+ '5. Contact ServiceNow administrator if permission issues persist'
1987
+ ],
1988
+ technical_details: {
1989
+ original_error: deploymentContext.original_error,
1990
+ global_deployment_error: errorMessage,
1991
+ artifact_type: deploymentContext.artifact_type,
1992
+ deployment_strategy: strategy.name
1993
+ }
1994
+ };
701
1995
  }
702
1996
  async delay(ms) {
703
1997
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -710,6 +2004,60 @@ ${errorText}
710
2004
  throw new Error(`Mock mode is not supported for ${operation}. All operations must use real ServiceNow instance.`);
711
2005
  }
712
2006
  }
2007
+ /**
2008
+ * List available MCP resources
2009
+ */
2010
+ async listMCPResources() {
2011
+ try {
2012
+ const resources = await this.resourceManager.listResources();
2013
+ this.logger.debug(`Listed ${resources.length} MCP resources`);
2014
+ return {
2015
+ resources: resources.map(resource => ({
2016
+ uri: resource.uri,
2017
+ name: resource.name,
2018
+ description: resource.description,
2019
+ mimeType: resource.mimeType
2020
+ }))
2021
+ };
2022
+ }
2023
+ catch (error) {
2024
+ this.logger.error('Failed to list MCP resources:', error);
2025
+ return { resources: [] };
2026
+ }
2027
+ }
2028
+ /**
2029
+ * Read a specific MCP resource by URI
2030
+ */
2031
+ async readMCPResource(uri) {
2032
+ try {
2033
+ const resource = await this.resourceManager.readResource(uri);
2034
+ this.logger.debug(`Read MCP resource: ${uri}`);
2035
+ return {
2036
+ contents: [{
2037
+ uri: resource.uri,
2038
+ mimeType: resource.mimeType,
2039
+ text: resource.text
2040
+ }]
2041
+ };
2042
+ }
2043
+ catch (error) {
2044
+ this.logger.error(`Failed to read MCP resource ${uri}:`, error);
2045
+ throw new Error(`Resource not found or inaccessible: ${uri}`);
2046
+ }
2047
+ }
2048
+ /**
2049
+ * Get resource manager statistics
2050
+ */
2051
+ getMCPResourceStats() {
2052
+ return this.resourceManager.getResourceStats();
2053
+ }
2054
+ /**
2055
+ * Clear resource cache (useful for development)
2056
+ */
2057
+ clearMCPResourceCache() {
2058
+ this.resourceManager.clearCache();
2059
+ this.logger.debug('MCP resource cache cleared');
2060
+ }
713
2061
  /**
714
2062
  * Start the MCP server
715
2063
  */