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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|