snow-flow 3.0.19 → 3.0.21

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.
@@ -487,6 +487,8 @@ class ServiceNowDeploymentMCP {
487
487
  const refreshResult = await this.deploymentAuthManager.forceTokenRefresh();
488
488
  if (!refreshResult.success) {
489
489
  return {
490
+ success: false,
491
+ error: authResult.error || 'Unable to authenticate',
490
492
  content: [
491
493
  {
492
494
  type: 'text',
@@ -500,7 +502,77 @@ class ServiceNowDeploymentMCP {
500
502
  if (!authResult.hasWriteScope) {
501
503
  this.logger.warn('⚠️ Token may lack write permissions, deployment might fail with 403');
502
504
  }
503
- this.logger.info('Deploying widget to ServiceNow', { name: args.name });
505
+ this.logger.info('Deploying widget to ServiceNow', { name: args.name, sys_id: args.sys_id });
506
+ // CHECK: If sys_id is provided, this is an UPDATE not a CREATE
507
+ if (args.sys_id) {
508
+ this.logger.info('🔄 UPDATE mode detected - updating existing widget', { sys_id: args.sys_id });
509
+ try {
510
+ // Update the existing widget
511
+ const updateResult = await this.client.updateRecord('sp_widget', args.sys_id, {
512
+ name: args.name || undefined,
513
+ title: args.title || undefined,
514
+ template: args.template || undefined,
515
+ css: args.css || undefined,
516
+ client_script: args.client_script || undefined,
517
+ server_script: args.server_script || undefined,
518
+ option_schema: args.option_schema || undefined,
519
+ demo_data: args.demo_data || undefined,
520
+ data: args.data || undefined,
521
+ description: args.description || undefined
522
+ });
523
+ if (updateResult.success) {
524
+ const credentials = await this.oauth.loadCredentials();
525
+ const widgetUrl = credentials?.instance ?
526
+ `https://${credentials.instance}/sp_config?id=widget_editor&sys_id=${args.sys_id}` :
527
+ 'ServiceNow instance URL not available';
528
+ return {
529
+ success: true,
530
+ sys_id: args.sys_id,
531
+ name: args.name,
532
+ content: [
533
+ {
534
+ type: 'text',
535
+ text: `✅ Widget updated successfully!
536
+
537
+ 🎯 Widget Details:
538
+ - Sys ID: ${args.sys_id}
539
+ - Name: ${args.name || 'Unchanged'}
540
+ - Deployment Context: ${args.config?.deployment_context || args.deployment_context || 'Widget update'}
541
+ - Method: Direct update via API
542
+
543
+ 🔗 Direct Links:
544
+ - Widget Editor: ${widgetUrl}
545
+ - Service Portal Designer: https://${credentials?.instance}/sp_config?id=designer
546
+
547
+ ⚡ **Widget Updated**
548
+ Your changes have been applied to the existing widget.`
549
+ }
550
+ ]
551
+ };
552
+ }
553
+ else {
554
+ return {
555
+ success: false,
556
+ error: updateResult.error || 'Failed to update widget',
557
+ content: [{
558
+ type: 'text',
559
+ text: `❌ Failed to update widget: ${updateResult.error || 'Unknown error'}`
560
+ }]
561
+ };
562
+ }
563
+ }
564
+ catch (updateError) {
565
+ this.logger.error('Widget update failed', updateError);
566
+ return {
567
+ success: false,
568
+ error: updateError.message || 'Update failed',
569
+ content: [{
570
+ type: 'text',
571
+ text: `❌ Widget update failed: ${updateError.message || 'Unknown error'}`
572
+ }]
573
+ };
574
+ }
575
+ }
504
576
  // ENHANCED: Mandatory Update Set management with auto-activation
505
577
  try {
506
578
  // Force Update Set creation/activation for all deployments
@@ -554,6 +626,9 @@ class ServiceNowDeploymentMCP {
554
626
  `https://${credentials.instance}/sp_config?id=widget_editor&sys_id=${existenceCheck.artifact.sys_id}` :
555
627
  'ServiceNow instance URL not available';
556
628
  return {
629
+ success: true,
630
+ sys_id: existenceCheck.artifact.sys_id,
631
+ name: args.name,
557
632
  content: [
558
633
  {
559
634
  type: 'text',
@@ -579,7 +654,14 @@ Your widget is deployed and ready for testing in Service Portal.`
579
654
  }
580
655
  // Validate widget structure
581
656
  if (!args.template || !args.name || !args.title) {
582
- throw new Error('Widget must have name, title, and template');
657
+ return {
658
+ success: false,
659
+ error: 'Widget must have name, title, and template',
660
+ content: [{
661
+ type: 'text',
662
+ text: '❌ Widget validation failed: Widget must have name, title, and template'
663
+ }]
664
+ };
583
665
  }
584
666
  // IMPROVED: Softer Service Portal permissions check with graceful fallback
585
667
  let hasServicePortalAccess = false;
@@ -860,6 +942,8 @@ Your widget is deployed and ready for testing in Service Portal.`
860
942
  `;
861
943
  }
862
944
  return {
945
+ success: false,
946
+ error: directError?.message || tableError?.message || 'Deployment failed',
863
947
  content: [
864
948
  {
865
949
  type: 'text',
@@ -998,7 +1082,11 @@ Use \`snow_deployment_debug\` for more information about this session.`,
998
1082
  const inconsistencyWarning = inconsistencies.length > 0
999
1083
  ? `\n\n⚠️ Sys_ID Inconsistencies Detected:\n${inconsistencies.map(inc => `- ${inc.issue}`).join('\n')}`
1000
1084
  : '';
1085
+ // Return both MCP response format AND success properties for attemptDirectDeployment
1001
1086
  return {
1087
+ success: true,
1088
+ sys_id: result.data.sys_id,
1089
+ name: args.name,
1002
1090
  content: [
1003
1091
  {
1004
1092
  type: 'text',
@@ -1056,7 +1144,14 @@ Use \`snow_deployment_debug\` for more information about this session.`,
1056
1144
  • Check dependencies with check_dependencies: true
1057
1145
 
1058
1146
  📚 Documentation: See CLAUDE.md for Widget Deployment Guidelines`;
1059
- throw new Error(enhancedError);
1147
+ return {
1148
+ success: false,
1149
+ error: result.error || 'Unknown deployment error',
1150
+ content: [{
1151
+ type: 'text',
1152
+ text: enhancedError
1153
+ }]
1154
+ };
1060
1155
  }
1061
1156
  }
1062
1157
  catch (error) {
@@ -1082,6 +1177,9 @@ Use \`snow_deployment_debug\` for more information about this session.`,
1082
1177
  `https://${credentials.instance}/sp_config?id=widget_editor&sys_id=${createdWidget.sys_id}` :
1083
1178
  'ServiceNow instance URL not available';
1084
1179
  return {
1180
+ success: true,
1181
+ sys_id: createdWidget.sys_id,
1182
+ name: args.name,
1085
1183
  content: [{
1086
1184
  type: 'text',
1087
1185
  text: `✅ Widget deployed successfully! (Error Recovery)
@@ -1130,7 +1228,14 @@ ${is403Error ? '\n⚠️ **Possible False Negative**: Widget may have been crea
1130
1228
  • Use snow_widget_test() for validation
1131
1229
 
1132
1230
  📚 **Important**: If you see "403" or "Forbidden" errors, the widget may still have been created successfully. Check ServiceNow directly.`;
1133
- throw new Error(enhancedError);
1231
+ return {
1232
+ success: false,
1233
+ error: error instanceof Error ? error.message : String(error),
1234
+ content: [{
1235
+ type: 'text',
1236
+ text: enhancedError
1237
+ }]
1238
+ };
1134
1239
  }
1135
1240
  }
1136
1241
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.0.19",
3
+ "version": "3.0.21",
4
4
  "description": "Snow-Flow v3.0.18: DIRECT API VERIFICATION! 🚀 Replaced unreliable searchRecords with direct API calls (snow_query_table style) for widget verification. All null/403 error recovery now uses GET /api/now/table/sp_widget with precise queries. NO MORE FALSE NEGATIVES - verification works consistently every time!",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",