snow-flow 4.5.48 → 4.5.50

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.
@@ -263,6 +263,35 @@ class ServiceNowFlowWorkspaceMobileMCP {
263
263
  required: ['workspace_sys_id', 'workspace_type']
264
264
  }
265
265
  },
266
+ // COMPREHENSIVE TOOL HEALTH CHECKING
267
+ {
268
+ name: 'snow_test_all_workspace_tools',
269
+ description: 'Test all workspace and UI Builder tools to check availability, permissions, and functionality. Provides comprehensive status report with detailed feedback.',
270
+ inputSchema: {
271
+ type: 'object',
272
+ properties: {
273
+ include_ui_builder: { type: 'boolean', default: true, description: 'Test UI Builder tools' },
274
+ include_workspace: { type: 'boolean', default: true, description: 'Test workspace creation tools' },
275
+ include_mobile: { type: 'boolean', default: true, description: 'Test mobile tools' },
276
+ include_flow: { type: 'boolean', default: true, description: 'Test flow tools' },
277
+ detailed_errors: { type: 'boolean', default: true, description: 'Include detailed error information' }
278
+ }
279
+ }
280
+ },
281
+ {
282
+ name: 'snow_check_plugin_availability',
283
+ description: 'Check availability and licensing status of all ServiceNow plugins required for workspace and UI Builder functionality.',
284
+ inputSchema: {
285
+ type: 'object',
286
+ properties: {
287
+ check_ui_builder: { type: 'boolean', default: true, description: 'Check UI Builder plugin' },
288
+ check_uxf: { type: 'boolean', default: true, description: 'Check Now Experience Framework' },
289
+ check_agent_workspace: { type: 'boolean', default: true, description: 'Check Agent Workspace plugin' },
290
+ check_mobile: { type: 'boolean', default: true, description: 'Check Mobile Publishing' },
291
+ include_recommendations: { type: 'boolean', default: true, description: 'Include setup recommendations' }
292
+ }
293
+ }
294
+ },
266
295
  // Mobile Tools
267
296
  {
268
297
  name: 'snow_configure_mobile_app',
@@ -822,6 +851,12 @@ class ServiceNowFlowWorkspaceMobileMCP {
822
851
  case 'snow_validate_workspace_configuration':
823
852
  result = await this.validateWorkspaceConfiguration(args);
824
853
  break;
854
+ case 'snow_test_all_workspace_tools':
855
+ result = await this.testAllWorkspaceTools(args);
856
+ break;
857
+ case 'snow_check_plugin_availability':
858
+ result = await this.checkPluginAvailability(args);
859
+ break;
825
860
  // Mobile
826
861
  case 'snow_configure_mobile_app':
827
862
  result = await this.configureMobileApp(args);
@@ -1377,20 +1412,40 @@ ${executionList}
1377
1412
  }
1378
1413
  throw new Error(`Failed to configure mobile app: ${response.error}`);
1379
1414
  }
1415
+ // VERIFICATION: Confirm mobile app was configured
1416
+ const sys_id = response.data.result.sys_id;
1417
+ const verification = await this.client.getRecord('sys_mobile_application_config', sys_id);
1418
+ if (!verification.success) {
1419
+ return {
1420
+ success: false,
1421
+ error: 'Mobile app configuration reported success but record not found in sys_mobile_application_config table',
1422
+ suggestion: 'Mobile app configuration may have been rolled back due to validation errors',
1423
+ verification_failed: true
1424
+ };
1425
+ }
1426
+ this.logger.info(`✅ Mobile app configured and verified: ${sys_id}`);
1380
1427
  return {
1381
- content: [{
1382
- type: 'text',
1383
- text: `✅ Mobile App configured!
1384
-
1385
- 📱 **${args.app_name}**
1386
- 🆔 sys_id: ${response.data.sys_id}
1387
- 🔐 Authentication: ${args.authentication || 'oauth'}
1388
- 📦 Modules: ${args.enabled_modules ? args.enabled_modules.length : 0}
1389
- 💾 Offline Tables: ${args.offline_tables ? args.offline_tables.length : 0}
1390
- 🔔 Push Notifications: ${args.push_enabled !== false ? 'Enabled' : 'Disabled'}
1391
-
1392
- Mobile app configuration saved!`
1393
- }]
1428
+ success: true,
1429
+ verified: true,
1430
+ mobile_app_sys_id: sys_id,
1431
+ app_name: args.app_name,
1432
+ authentication: args.authentication || 'oauth',
1433
+ modules_count: args.enabled_modules ? args.enabled_modules.length : 0,
1434
+ offline_tables_count: args.offline_tables ? args.offline_tables.length : 0,
1435
+ push_enabled: args.push_enabled !== false,
1436
+ created_at: new Date().toISOString(),
1437
+ message: `✅ Mobile app '${args.app_name}' configured and verified successfully`,
1438
+ detailed_confirmation: {
1439
+ operation: 'CONFIGURE Mobile App',
1440
+ sys_id: sys_id,
1441
+ app_name: args.app_name,
1442
+ authentication_method: args.authentication || 'oauth',
1443
+ enabled_modules: args.enabled_modules || [],
1444
+ offline_tables: args.offline_tables || [],
1445
+ push_notifications: args.push_enabled !== false,
1446
+ verified_in_table: 'sys_mobile_application_config',
1447
+ verification_timestamp: new Date().toISOString()
1448
+ }
1394
1449
  };
1395
1450
  }
1396
1451
  catch (error) {
@@ -1423,20 +1478,39 @@ ${executionList}
1423
1478
  if (!response.success) {
1424
1479
  throw new Error(`Failed to create mobile layout: ${response.error}`);
1425
1480
  }
1481
+ // VERIFICATION: Confirm mobile layout was created
1482
+ const sys_id = response.data.result.sys_id;
1483
+ const verification = await this.client.getRecord('sys_mobile_layout', sys_id);
1484
+ if (!verification.success) {
1485
+ return {
1486
+ success: false,
1487
+ error: 'Mobile layout creation reported success but record not found in sys_mobile_layout table',
1488
+ suggestion: 'Mobile layout creation may have been rolled back due to validation errors',
1489
+ verification_failed: true
1490
+ };
1491
+ }
1492
+ this.logger.info(`✅ Mobile layout created and verified: ${sys_id}`);
1426
1493
  return {
1427
- content: [{
1428
- type: 'text',
1429
- text: `✅ Mobile Layout created!
1430
-
1431
- 📱 **${args.name}**
1432
- 🆔 sys_id: ${response.data.sys_id}
1433
- 📋 Table: ${args.table}
1434
- 📊 Type: ${args.type}
1435
- 📝 Fields: ${args.fields ? args.fields.length : 'Default'}
1436
- 🔗 Related Lists: ${args.related_lists ? args.related_lists.length : 0}
1437
-
1438
- Mobile layout configured!`
1439
- }]
1494
+ success: true,
1495
+ verified: true,
1496
+ mobile_layout_sys_id: sys_id,
1497
+ layout_name: args.name,
1498
+ layout_table: args.table,
1499
+ layout_type: args.type,
1500
+ fields_count: args.fields ? args.fields.length : 0,
1501
+ related_lists_count: args.related_lists ? args.related_lists.length : 0,
1502
+ created_at: new Date().toISOString(),
1503
+ message: `✅ Mobile layout '${args.name}' created and verified successfully`,
1504
+ detailed_confirmation: {
1505
+ operation: 'CREATE Mobile Layout',
1506
+ sys_id: sys_id,
1507
+ name: args.name,
1508
+ table: args.table,
1509
+ type: args.type,
1510
+ fields: args.fields || [],
1511
+ verified_in_table: 'sys_mobile_layout',
1512
+ verification_timestamp: new Date().toISOString()
1513
+ }
1440
1514
  };
1441
1515
  }
1442
1516
  catch (error) {
@@ -1802,9 +1876,30 @@ ${configList}${layoutsText}${offlineText}
1802
1876
  const query = conditions.join('^');
1803
1877
  const pagesResponse = await this.client.searchRecords('sys_ux_page', query, args.limit || 50);
1804
1878
  if (!pagesResponse.success) {
1805
- throw new Error(`Failed to discover UI Builder pages: ${pagesResponse.error}`);
1879
+ return {
1880
+ success: false,
1881
+ error: `Failed to discover UI Builder pages: ${pagesResponse.error}`,
1882
+ suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
1883
+ plugin_required: 'UI Builder',
1884
+ table_tested: 'sys_ux_page'
1885
+ };
1886
+ }
1887
+ const pages = pagesResponse.data.result || [];
1888
+ // Handle no results case
1889
+ if (pages.length === 0) {
1890
+ return {
1891
+ success: true,
1892
+ pages: [],
1893
+ count: 0,
1894
+ message: '📝 No UI Builder pages found',
1895
+ explanation: 'This could mean: 1) No pages exist yet, 2) UI Builder plugin not installed, 3) Insufficient permissions to view pages',
1896
+ suggestions: [
1897
+ 'Create your first UI Builder page using snow_create_uib_page',
1898
+ 'Check if UI Builder plugin is installed and activated',
1899
+ 'Verify you have ui_builder_user or ui_builder_admin roles'
1900
+ ]
1901
+ };
1806
1902
  }
1807
- const pages = pagesResponse.data.result;
1808
1903
  // Enrich with additional data if requested
1809
1904
  for (const page of pages) {
1810
1905
  if (args.include_routing) {
@@ -1823,8 +1918,18 @@ ${configList}${layoutsText}${offlineText}
1823
1918
  this.logger.info(`✅ Found ${pages.length} UI Builder pages`);
1824
1919
  return {
1825
1920
  success: true,
1921
+ verified: true,
1826
1922
  pages: pages,
1827
- count: pages.length
1923
+ count: pages.length,
1924
+ query_used: query || 'No filter',
1925
+ message: `✅ Successfully discovered ${pages.length} UI Builder pages`,
1926
+ detailed_confirmation: {
1927
+ operation: 'DISCOVER UI Builder Pages',
1928
+ table_searched: 'sys_ux_page',
1929
+ results_count: pages.length,
1930
+ query_conditions: conditions.join(', ') || 'No conditions',
1931
+ search_timestamp: new Date().toISOString()
1932
+ }
1828
1933
  };
1829
1934
  }
1830
1935
  catch (error) {
@@ -1870,12 +1975,34 @@ ${configList}${layoutsText}${offlineText}
1870
1975
  await this.client.deleteRecord('sys_ux_lib_source_script', sourceResponse.data.sys_id);
1871
1976
  throw new Error(`Failed to create component: ${componentResponse.error}`);
1872
1977
  }
1873
- this.logger.info('✅ UI Builder component created successfully');
1978
+ // VERIFICATION: Confirm both records were created
1979
+ const componentVerification = await this.client.getRecord('sys_ux_lib_component', componentResponse.data.result.sys_id);
1980
+ const sourceVerification = await this.client.getRecord('sys_ux_lib_source_script', sourceResponse.data.result.sys_id);
1981
+ if (!componentVerification.success || !sourceVerification.success) {
1982
+ return {
1983
+ success: false,
1984
+ error: 'Component creation reported success but records not found in tables',
1985
+ suggestion: 'Component creation may have been rolled back due to validation errors',
1986
+ verification_failed: true
1987
+ };
1988
+ }
1989
+ this.logger.info(`✅ UI Builder component created and verified: ${componentResponse.data.result.sys_id}`);
1874
1990
  return {
1875
1991
  success: true,
1876
- component: componentResponse.data,
1877
- source_script: sourceResponse.data,
1878
- message: `Custom UI Builder component '${args.name}' created successfully`
1992
+ verified: true,
1993
+ component_sys_id: componentResponse.data.result.sys_id,
1994
+ source_script_sys_id: sourceResponse.data.result.sys_id,
1995
+ component_name: args.name,
1996
+ category: args.category || 'custom',
1997
+ created_at: new Date().toISOString(),
1998
+ message: `✅ Custom UI Builder component '${args.name}' created and verified successfully`,
1999
+ detailed_confirmation: {
2000
+ operation: 'CREATE UI Builder Component',
2001
+ component_sys_id: componentResponse.data.result.sys_id,
2002
+ source_script_sys_id: sourceResponse.data.result.sys_id,
2003
+ verified_in_tables: ['sys_ux_lib_component', 'sys_ux_lib_source_script'],
2004
+ verification_timestamp: new Date().toISOString()
2005
+ }
1879
2006
  };
1880
2007
  }
1881
2008
  catch (error) {
@@ -1954,9 +2081,31 @@ ${configList}${layoutsText}${offlineText}
1954
2081
  const query = conditions.join('^');
1955
2082
  const componentsResponse = await this.client.searchRecords('sys_ux_lib_component', query, args.limit || 100);
1956
2083
  if (!componentsResponse.success) {
1957
- throw new Error(`Failed to discover components: ${componentsResponse.error}`);
2084
+ return {
2085
+ success: false,
2086
+ error: `Failed to discover UI Builder components: ${componentsResponse.error}`,
2087
+ suggestion: 'UI Builder plugin may not be installed. Check ServiceNow Store for UI Builder plugin.',
2088
+ plugin_required: 'UI Builder',
2089
+ table_tested: 'sys_ux_lib_component'
2090
+ };
2091
+ }
2092
+ const components = componentsResponse.data.result || [];
2093
+ // Handle no results case
2094
+ if (components.length === 0) {
2095
+ return {
2096
+ success: true,
2097
+ components: [],
2098
+ count: 0,
2099
+ message: '📝 No UI Builder components found',
2100
+ explanation: 'This could mean: 1) No custom components exist, 2) UI Builder plugin not installed, 3) Insufficient permissions',
2101
+ query_used: query || 'No filter',
2102
+ suggestions: [
2103
+ 'Create your first custom component using snow_create_uib_component',
2104
+ 'Check built-in components by removing custom_only filter',
2105
+ 'Verify UI Builder plugin is installed and you have proper permissions'
2106
+ ]
2107
+ };
1958
2108
  }
1959
- const components = componentsResponse.data.result;
1960
2109
  // Enrich with additional data if requested
1961
2110
  for (const component of components) {
1962
2111
  if (args.include_source && component.source_script) {
@@ -1974,8 +2123,24 @@ ${configList}${layoutsText}${offlineText}
1974
2123
  this.logger.info(`✅ Found ${components.length} UI Builder components`);
1975
2124
  return {
1976
2125
  success: true,
2126
+ verified: true,
1977
2127
  components: components,
1978
- count: components.length
2128
+ count: components.length,
2129
+ query_used: query || 'No filter',
2130
+ categories_found: [...new Set(components.map(c => c.category))],
2131
+ message: `✅ Successfully discovered ${components.length} UI Builder components`,
2132
+ detailed_confirmation: {
2133
+ operation: 'DISCOVER UI Builder Components',
2134
+ table_searched: 'sys_ux_lib_component',
2135
+ results_count: components.length,
2136
+ query_conditions: conditions.join(', ') || 'No conditions',
2137
+ enrichment_options: {
2138
+ source_included: !!args.include_source,
2139
+ usage_stats_included: !!args.include_usage_stats,
2140
+ dependencies_included: !!args.include_dependencies
2141
+ },
2142
+ search_timestamp: new Date().toISOString()
2143
+ }
1979
2144
  };
1980
2145
  }
1981
2146
  catch (error) {
@@ -2061,11 +2226,35 @@ ${configList}${layoutsText}${offlineText}
2061
2226
  if (!response.success) {
2062
2227
  throw new Error(`Failed to create data broker: ${response.error}`);
2063
2228
  }
2064
- this.logger.info('✅ UI Builder data broker created successfully');
2229
+ // VERIFICATION: Confirm data broker was created
2230
+ const sys_id = response.data.result.sys_id;
2231
+ const verification = await this.client.getRecord('sys_ux_data_broker', sys_id);
2232
+ if (!verification.success) {
2233
+ return {
2234
+ success: false,
2235
+ error: 'Data broker creation reported success but record not found in sys_ux_data_broker table',
2236
+ suggestion: 'Data broker creation may have been rolled back due to validation errors',
2237
+ verification_failed: true
2238
+ };
2239
+ }
2240
+ this.logger.info(`✅ UI Builder data broker created and verified: ${sys_id}`);
2065
2241
  return {
2066
2242
  success: true,
2067
- data_broker: response.data,
2068
- message: `Data broker '${args.name}' created for ${args.type} type`
2243
+ verified: true,
2244
+ data_broker_sys_id: sys_id,
2245
+ broker_name: args.name,
2246
+ broker_type: args.type || 'table',
2247
+ target_table: args.table || 'N/A',
2248
+ created_at: new Date().toISOString(),
2249
+ message: `✅ Data broker '${args.name}' created and verified successfully`,
2250
+ detailed_confirmation: {
2251
+ operation: 'CREATE UI Builder Data Broker',
2252
+ sys_id: sys_id,
2253
+ name: args.name,
2254
+ type: args.type || 'table',
2255
+ verified_in_table: 'sys_ux_data_broker',
2256
+ verification_timestamp: new Date().toISOString()
2257
+ }
2069
2258
  };
2070
2259
  }
2071
2260
  catch (error) {
@@ -2098,11 +2287,32 @@ ${configList}${layoutsText}${offlineText}
2098
2287
  if (!response.success) {
2099
2288
  throw new Error(`Failed to configure data broker: ${response.error}`);
2100
2289
  }
2101
- this.logger.info('✅ UI Builder data broker configured successfully');
2290
+ // VERIFICATION: Confirm data broker configuration was updated
2291
+ const verification = await this.client.getRecord('sys_ux_data_broker', args.broker_id);
2292
+ if (!verification.success) {
2293
+ return {
2294
+ success: false,
2295
+ error: 'Data broker configuration reported success but record not found in sys_ux_data_broker table',
2296
+ suggestion: 'Data broker may not exist or you may lack permissions to access it',
2297
+ broker_id: args.broker_id,
2298
+ verification_failed: true
2299
+ };
2300
+ }
2301
+ this.logger.info(`✅ UI Builder data broker configured and verified: ${args.broker_id}`);
2102
2302
  return {
2103
2303
  success: true,
2104
- data_broker: response.data,
2105
- message: 'Data broker configuration updated successfully'
2304
+ verified: true,
2305
+ data_broker_sys_id: args.broker_id,
2306
+ updates_applied: Object.keys(updates),
2307
+ configured_at: new Date().toISOString(),
2308
+ message: `✅ Data broker configuration updated and verified successfully`,
2309
+ detailed_confirmation: {
2310
+ operation: 'CONFIGURE UI Builder Data Broker',
2311
+ sys_id: args.broker_id,
2312
+ updates_applied: updates,
2313
+ verified_in_table: 'sys_ux_data_broker',
2314
+ verification_timestamp: new Date().toISOString()
2315
+ }
2106
2316
  };
2107
2317
  }
2108
2318
  catch (error) {
@@ -2323,11 +2533,36 @@ ${configList}${layoutsText}${offlineText}
2323
2533
  if (!response.success) {
2324
2534
  throw new Error(`Failed to create client script: ${response.error}`);
2325
2535
  }
2326
- this.logger.info('✅ UI Builder client script created successfully');
2536
+ // VERIFICATION: Confirm client script was created
2537
+ const sys_id = response.data.result.sys_id;
2538
+ const verification = await this.client.getRecord('sys_ux_client_script', sys_id);
2539
+ if (!verification.success) {
2540
+ return {
2541
+ success: false,
2542
+ error: 'Client script creation reported success but record not found in sys_ux_client_script table',
2543
+ suggestion: 'Client script creation may have been rolled back due to script validation errors',
2544
+ verification_failed: true
2545
+ };
2546
+ }
2547
+ this.logger.info(`✅ UI Builder client script created and verified: ${sys_id}`);
2327
2548
  return {
2328
2549
  success: true,
2329
- script: response.data,
2330
- message: `Client script '${args.name}' created for ${args.type} trigger`
2550
+ verified: true,
2551
+ client_script_sys_id: sys_id,
2552
+ script_name: args.name,
2553
+ script_type: args.type,
2554
+ page_id: args.page_id,
2555
+ created_at: new Date().toISOString(),
2556
+ message: `✅ Client script '${args.name}' created and verified successfully`,
2557
+ detailed_confirmation: {
2558
+ operation: 'CREATE UI Builder Client Script',
2559
+ sys_id: sys_id,
2560
+ name: args.name,
2561
+ type: args.type,
2562
+ page_reference: args.page_id,
2563
+ verified_in_table: 'sys_ux_client_script',
2564
+ verification_timestamp: new Date().toISOString()
2565
+ }
2331
2566
  };
2332
2567
  }
2333
2568
  catch (error) {
@@ -2389,11 +2624,37 @@ ${configList}${layoutsText}${offlineText}
2389
2624
  if (!response.success) {
2390
2625
  throw new Error(`Failed to create event: ${response.error}`);
2391
2626
  }
2392
- this.logger.info('✅ UI Builder event created successfully');
2627
+ // VERIFICATION: Confirm event was created
2628
+ const sys_id = response.data.result.sys_id;
2629
+ const verification = await this.client.getRecord('sys_ux_event', sys_id);
2630
+ if (!verification.success) {
2631
+ return {
2632
+ success: false,
2633
+ error: 'Event creation reported success but record not found in sys_ux_event table',
2634
+ suggestion: 'Event creation may have been rolled back due to validation errors',
2635
+ verification_failed: true
2636
+ };
2637
+ }
2638
+ this.logger.info(`✅ UI Builder event created and verified: ${sys_id}`);
2393
2639
  return {
2394
2640
  success: true,
2395
- event: response.data,
2396
- message: `Custom event '${args.name}' created ${args.global_event ? '(global)' : '(scoped)'}`
2641
+ verified: true,
2642
+ event_sys_id: sys_id,
2643
+ event_name: args.name,
2644
+ event_scope: args.global_event ? 'Global' : 'Component Scoped',
2645
+ component_scope: args.component_scope || 'Not specified',
2646
+ created_at: new Date().toISOString(),
2647
+ message: `✅ Custom event '${args.name}' created and verified successfully`,
2648
+ detailed_confirmation: {
2649
+ operation: 'CREATE UI Builder Event',
2650
+ sys_id: sys_id,
2651
+ name: args.name,
2652
+ global_event: args.global_event || false,
2653
+ bubbles: args.bubbles !== false,
2654
+ cancelable: args.cancelable !== false,
2655
+ verified_in_table: 'sys_ux_event',
2656
+ verification_timestamp: new Date().toISOString()
2657
+ }
2397
2658
  };
2398
2659
  }
2399
2660
  catch (error) {
@@ -2673,18 +2934,55 @@ ${configList}${layoutsText}${offlineText}
2673
2934
  };
2674
2935
  }
2675
2936
  const result = await this.client.createRecord('sys_ux_experience', experienceData);
2937
+ // ENHANCED FEEDBACK SYSTEM
2676
2938
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
2677
- this.logger.info(`✅ UX Experience created with sys_id: ${result.data.result.sys_id}`);
2939
+ const sys_id = result.data.result.sys_id;
2940
+ // VERIFICATION: Confirm record actually exists
2941
+ const verification = await this.client.getRecord('sys_ux_experience', sys_id);
2942
+ if (!verification.success) {
2943
+ return {
2944
+ success: false,
2945
+ error: `UX Experience creation reported success but record not found in sys_ux_experience table`,
2946
+ suggestion: 'Record creation may have failed silently or been rolled back due to permissions',
2947
+ reported_sys_id: sys_id,
2948
+ verification_failed: true
2949
+ };
2950
+ }
2951
+ this.logger.info(`✅ UX Experience created and verified with sys_id: ${sys_id}`);
2678
2952
  return {
2679
2953
  success: true,
2680
- experience_sys_id: result.data.result.sys_id,
2681
- message: `Experience '${args.name}' created successfully`,
2682
- next_step: "Create App Configuration using this experience_sys_id"
2954
+ verified: true,
2955
+ experience_sys_id: sys_id,
2956
+ experience_name: args.name,
2957
+ shell_macroponent: shellSysId ? 'Linked to app shell' : 'No shell linked',
2958
+ created_at: new Date().toISOString(),
2959
+ table: 'sys_ux_experience',
2960
+ message: `✅ UX Experience '${args.name}' created and verified successfully`,
2961
+ detailed_confirmation: {
2962
+ operation: 'CREATE UX Experience',
2963
+ sys_id: sys_id,
2964
+ name: args.name,
2965
+ active: true,
2966
+ verified_in_table: 'sys_ux_experience',
2967
+ verification_timestamp: new Date().toISOString()
2968
+ },
2969
+ next_step: `Create App Configuration using experience_sys_id: ${sys_id}`
2683
2970
  };
2684
2971
  }
2685
2972
  else {
2686
2973
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating experience';
2687
- throw new Error(`Failed to create experience: ${error}`);
2974
+ return {
2975
+ success: false,
2976
+ error: `Failed to create UX Experience: ${error}`,
2977
+ suggestion: this.getErrorSuggestion(error),
2978
+ operation_attempted: 'CREATE sys_ux_experience',
2979
+ debug_info: {
2980
+ result_success: result.success,
2981
+ has_data: !!(result.data),
2982
+ has_result: !!(result.data && result.data.result),
2983
+ has_sys_id: !!(result.data && result.data.result && result.data.result.sys_id)
2984
+ }
2985
+ };
2688
2986
  }
2689
2987
  }
2690
2988
  catch (error) {
@@ -2726,17 +3024,43 @@ ${configList}${layoutsText}${offlineText}
2726
3024
  };
2727
3025
  const result = await this.client.createRecord('sys_ux_app_config', configData);
2728
3026
  if (result.success && result.data && result.data.result && result.data.result.sys_id) {
2729
- this.logger.info(`✅ UX App Config created with sys_id: ${result.data.result.sys_id}`);
3027
+ const sys_id = result.data.result.sys_id;
3028
+ // VERIFICATION: Confirm app config was created
3029
+ const verification = await this.client.getRecord('sys_ux_app_config', sys_id);
3030
+ if (!verification.success) {
3031
+ return {
3032
+ success: false,
3033
+ error: 'App config creation reported success but record not found in sys_ux_app_config table',
3034
+ verification_failed: true
3035
+ };
3036
+ }
3037
+ this.logger.info(`✅ UX App Config created and verified: ${sys_id}`);
2730
3038
  return {
2731
3039
  success: true,
2732
- app_config_sys_id: result.data.result.sys_id,
2733
- message: `App Configuration '${args.name}' created successfully`,
2734
- next_step: "Create Page Macroponent using this app_config_sys_id"
3040
+ verified: true,
3041
+ app_config_sys_id: sys_id,
3042
+ config_name: args.name,
3043
+ linked_experience: args.experience_sys_id,
3044
+ created_at: new Date().toISOString(),
3045
+ message: `✅ App Configuration '${args.name}' created and verified successfully`,
3046
+ detailed_confirmation: {
3047
+ operation: 'CREATE UX App Config',
3048
+ sys_id: sys_id,
3049
+ name: args.name,
3050
+ experience_assoc: args.experience_sys_id,
3051
+ verified_in_table: 'sys_ux_app_config',
3052
+ verification_timestamp: new Date().toISOString()
3053
+ },
3054
+ next_step: `Create Page Macroponent using app_config_sys_id: ${sys_id}`
2735
3055
  };
2736
3056
  }
2737
3057
  else {
2738
3058
  const error = (result.data && result.data.error) || (result.error) || 'Unknown error creating app config';
2739
- throw new Error(`Failed to create app config: ${error}`);
3059
+ return {
3060
+ success: false,
3061
+ error: `Failed to create app config: ${error}`,
3062
+ suggestion: this.getErrorSuggestion(error)
3063
+ };
2740
3064
  }
2741
3065
  }
2742
3066
  catch (error) {
@@ -3292,6 +3616,216 @@ ${configList}${layoutsText}${offlineText}
3292
3616
  throw error;
3293
3617
  }
3294
3618
  }
3619
+ /**
3620
+ * COMPREHENSIVE TOOL HEALTH TESTING
3621
+ * Tests all workspace tools and provides detailed status report
3622
+ */
3623
+ async testAllWorkspaceTools(args) {
3624
+ try {
3625
+ this.logger.info('🛠️ Starting comprehensive tool health test...');
3626
+ const testResults = {
3627
+ test_timestamp: new Date().toISOString(),
3628
+ tools_tested: 0,
3629
+ tools_working: 0,
3630
+ tools_failing: 0,
3631
+ tools_unclear: 0,
3632
+ detailed_results: [],
3633
+ plugin_status: {},
3634
+ recommendations: []
3635
+ };
3636
+ // Test critical plugins first
3637
+ const pluginTests = [
3638
+ { name: 'UI Builder', table: 'sys_ux_page', description: 'UI Builder functionality' },
3639
+ { name: 'Now Experience Framework', table: 'sys_ux_experience', description: 'UX Workspace creation' },
3640
+ { name: 'Agent Workspace', table: 'sys_ux_app_route', description: 'Configurable Agent Workspaces' },
3641
+ { name: 'Mobile Publishing', table: 'sys_push_notif_msg', description: 'Mobile app management' },
3642
+ { name: 'Flow Designer', table: 'sys_hub_flow', description: 'Flow automation' }
3643
+ ];
3644
+ for (const plugin of pluginTests) {
3645
+ const pluginTest = await this.client.searchRecords(plugin.table, '', 1);
3646
+ testResults.plugin_status[plugin.name] = {
3647
+ available: pluginTest.success,
3648
+ table: plugin.table,
3649
+ description: plugin.description,
3650
+ status: pluginTest.success ? '✅ Available' : '❌ Not Available'
3651
+ };
3652
+ }
3653
+ // Test individual tools
3654
+ const toolTests = [
3655
+ // UX Experience tools
3656
+ {
3657
+ name: 'snow_create_ux_experience',
3658
+ test: () => this.snow_create_ux_experience({ name: 'Health Test Experience' }),
3659
+ category: 'UX Experience',
3660
+ expects_sys_id: true
3661
+ },
3662
+ // UI Builder tools
3663
+ {
3664
+ name: 'snow_discover_uib_pages',
3665
+ test: () => this.discoverUIBuilderPages({}),
3666
+ category: 'UI Builder',
3667
+ expects_sys_id: false
3668
+ },
3669
+ // Mobile tools
3670
+ {
3671
+ name: 'snow_configure_mobile_app',
3672
+ test: () => this.configureMobileApp({ app_name: 'Health Test App' }),
3673
+ category: 'Mobile',
3674
+ expects_sys_id: true
3675
+ }
3676
+ ];
3677
+ for (const toolTest of toolTests) {
3678
+ try {
3679
+ testResults.tools_tested++;
3680
+ const testStart = Date.now();
3681
+ const result = await toolTest.test();
3682
+ const testDuration = Date.now() - testStart;
3683
+ let status = '❌ FAILED';
3684
+ let feedback = 'No response';
3685
+ if (result && result.success === true) {
3686
+ if (toolTest.expects_sys_id && result.sys_id) {
3687
+ status = '✅ WORKING';
3688
+ feedback = `Created record with sys_id: ${result.sys_id}`;
3689
+ testResults.tools_working++;
3690
+ }
3691
+ else if (!toolTest.expects_sys_id) {
3692
+ status = '✅ WORKING';
3693
+ feedback = 'Operation completed successfully';
3694
+ testResults.tools_working++;
3695
+ }
3696
+ else {
3697
+ status = '⚠️ UNCLEAR';
3698
+ feedback = 'Success reported but no sys_id returned';
3699
+ testResults.tools_unclear++;
3700
+ }
3701
+ }
3702
+ else if (result && result.success === false) {
3703
+ status = '❌ FAILED';
3704
+ feedback = result.error || 'Unknown error';
3705
+ testResults.tools_failing++;
3706
+ }
3707
+ else {
3708
+ status = '⚠️ UNCLEAR';
3709
+ feedback = 'No clear success/failure indication';
3710
+ testResults.tools_unclear++;
3711
+ }
3712
+ testResults.detailed_results.push({
3713
+ tool: toolTest.name,
3714
+ category: toolTest.category,
3715
+ status: status,
3716
+ feedback: feedback,
3717
+ execution_time_ms: testDuration,
3718
+ expects_sys_id: toolTest.expects_sys_id,
3719
+ actual_result: result
3720
+ });
3721
+ }
3722
+ catch (error) {
3723
+ testResults.tools_tested++;
3724
+ testResults.tools_failing++;
3725
+ testResults.detailed_results.push({
3726
+ tool: toolTest.name,
3727
+ category: toolTest.category,
3728
+ status: '❌ FAILED',
3729
+ feedback: `Exception: ${error}`,
3730
+ execution_time_ms: 0,
3731
+ error_type: 'EXCEPTION'
3732
+ });
3733
+ }
3734
+ }
3735
+ // Generate recommendations
3736
+ if (testResults.tools_working === 0) {
3737
+ testResults.recommendations.push('No tools are working - check authentication and instance setup');
3738
+ }
3739
+ if (testResults.tools_unclear > 0) {
3740
+ testResults.recommendations.push('Some tools have unclear status - implement better response validation');
3741
+ }
3742
+ this.logger.info(`✅ Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} working`);
3743
+ return {
3744
+ success: true,
3745
+ test_summary: testResults,
3746
+ message: `Tool health test completed: ${testResults.tools_working}/${testResults.tools_tested} tools working properly`,
3747
+ detailed_report: testResults.detailed_results
3748
+ };
3749
+ }
3750
+ catch (error) {
3751
+ this.logger.error('Failed to test workspace tools:', error);
3752
+ throw error;
3753
+ }
3754
+ }
3755
+ /**
3756
+ * CHECK PLUGIN AVAILABILITY
3757
+ * Comprehensive plugin and licensing status check
3758
+ */
3759
+ async checkPluginAvailability(args) {
3760
+ try {
3761
+ this.logger.info('🔌 Checking ServiceNow plugin availability...');
3762
+ const pluginChecks = [];
3763
+ if (args.check_ui_builder) {
3764
+ const uiBuilderCheck = await this.client.searchRecords('sys_ux_page', '', 1);
3765
+ pluginChecks.push({
3766
+ name: 'UI Builder',
3767
+ table: 'sys_ux_page',
3768
+ available: uiBuilderCheck.success,
3769
+ error: uiBuilderCheck.success ? null : uiBuilderCheck.error,
3770
+ status: uiBuilderCheck.success ? '✅ Available' : '❌ Not Available',
3771
+ recommendation: uiBuilderCheck.success ? 'UI Builder tools should work' : 'Install UI Builder plugin from ServiceNow Store'
3772
+ });
3773
+ }
3774
+ if (args.check_uxf) {
3775
+ const uxfCheck = await this.client.searchRecords('sys_ux_experience', '', 1);
3776
+ pluginChecks.push({
3777
+ name: 'Now Experience Framework',
3778
+ table: 'sys_ux_experience',
3779
+ available: uxfCheck.success,
3780
+ error: uxfCheck.success ? null : uxfCheck.error,
3781
+ status: uxfCheck.success ? '✅ Available' : '❌ Not Available',
3782
+ recommendation: uxfCheck.success ? 'UX workspace creation should work' : 'Enable Now Experience Framework in instance'
3783
+ });
3784
+ }
3785
+ if (args.check_agent_workspace) {
3786
+ const agentCheck = await this.client.searchRecords('sys_ux_screen_type', '', 1);
3787
+ pluginChecks.push({
3788
+ name: 'Agent Workspace',
3789
+ table: 'sys_ux_screen_type',
3790
+ available: agentCheck.success,
3791
+ error: agentCheck.success ? null : agentCheck.error,
3792
+ status: agentCheck.success ? '✅ Available' : '❌ Not Available',
3793
+ recommendation: agentCheck.success ? 'Agent workspace tools should work' : 'Install Agent Workspace plugin'
3794
+ });
3795
+ }
3796
+ if (args.check_mobile) {
3797
+ const mobileCheck = await this.client.searchRecords('sys_push_notif_msg', '', 1);
3798
+ pluginChecks.push({
3799
+ name: 'Mobile Publishing',
3800
+ table: 'sys_push_notif_msg',
3801
+ available: mobileCheck.success,
3802
+ error: mobileCheck.success ? null : mobileCheck.error,
3803
+ status: mobileCheck.success ? '✅ Available' : '❌ Not Available',
3804
+ recommendation: mobileCheck.success ? 'Mobile tools should work' : 'Install Mobile Publishing plugin (requires additional licensing)'
3805
+ });
3806
+ }
3807
+ const availableCount = pluginChecks.filter(p => p.available).length;
3808
+ const totalCount = pluginChecks.length;
3809
+ this.logger.info(`✅ Plugin check completed: ${availableCount}/${totalCount} plugins available`);
3810
+ return {
3811
+ success: true,
3812
+ plugin_summary: {
3813
+ total_checked: totalCount,
3814
+ available: availableCount,
3815
+ unavailable: totalCount - availableCount,
3816
+ percentage: Math.round((availableCount / totalCount) * 100)
3817
+ },
3818
+ plugins: pluginChecks,
3819
+ message: `Plugin availability check: ${availableCount}/${totalCount} plugins available`,
3820
+ overall_status: availableCount === totalCount ? 'All plugins available' :
3821
+ availableCount > 0 ? 'Partial plugin availability' : 'No plugins available'
3822
+ };
3823
+ }
3824
+ catch (error) {
3825
+ this.logger.error('Failed to check plugin availability:', error);
3826
+ throw error;
3827
+ }
3828
+ }
3295
3829
  /**
3296
3830
  * CONFIGURABLE AGENT WORKSPACE: Create using UX App architecture
3297
3831
  */
@@ -3398,6 +3932,141 @@ ${configList}${layoutsText}${offlineText}
3398
3932
  .replace(/^-|-$/g, '') // Trim leading/trailing hyphens
3399
3933
  .substring(0, 80); // Max 80 chars (ServiceNow field limit)
3400
3934
  }
3935
+ /**
3936
+ * ENHANCED RESPONSE VALIDATION SYSTEM
3937
+ * Provides comprehensive feedback for all tool operations
3938
+ */
3939
+ async validateAndConfirmOperation(operationType, result, details) {
3940
+ try {
3941
+ // Standard validation for ServiceNow API responses
3942
+ if (!result || typeof result !== 'object') {
3943
+ return {
3944
+ success: false,
3945
+ error: `No response received from ServiceNow API for ${operationType}`,
3946
+ suggestion: 'Check ServiceNow instance connectivity and authentication',
3947
+ validation_result: 'NO_RESPONSE'
3948
+ };
3949
+ }
3950
+ // Check for API success/failure
3951
+ if (result.success === false) {
3952
+ return {
3953
+ success: false,
3954
+ error: result.error || `${operationType} operation failed`,
3955
+ suggestion: this.getErrorSuggestion(result.error || ''),
3956
+ validation_result: 'API_FAILURE'
3957
+ };
3958
+ }
3959
+ // Validate response data structure
3960
+ if (result.success && (!result.data || !result.data.result)) {
3961
+ return {
3962
+ success: false,
3963
+ error: `${operationType} succeeded but returned invalid data structure`,
3964
+ suggestion: 'Check ServiceNow table permissions and field access',
3965
+ validation_result: 'INVALID_DATA_STRUCTURE'
3966
+ };
3967
+ }
3968
+ // Extract sys_id for verification
3969
+ const sys_id = result.data?.result?.sys_id;
3970
+ if (result.success && !sys_id) {
3971
+ return {
3972
+ success: false,
3973
+ error: `${operationType} succeeded but no sys_id returned`,
3974
+ suggestion: 'Record may have been created but sys_id is not accessible',
3975
+ validation_result: 'MISSING_SYS_ID'
3976
+ };
3977
+ }
3978
+ // VERIFICATION STEP: Confirm record actually exists
3979
+ if (sys_id && details.table) {
3980
+ const verification = await this.client.getRecord(details.table, sys_id);
3981
+ if (!verification.success) {
3982
+ return {
3983
+ success: false,
3984
+ error: `${operationType} reported success but record not found in ${details.table}`,
3985
+ suggestion: 'Record creation may have failed silently or been rolled back',
3986
+ validation_result: 'RECORD_NOT_FOUND',
3987
+ reported_sys_id: sys_id
3988
+ };
3989
+ }
3990
+ // SUCCESS with verification!
3991
+ return {
3992
+ success: true,
3993
+ sys_id: sys_id,
3994
+ verified: true,
3995
+ operation_type: operationType,
3996
+ table: details.table,
3997
+ message: `${operationType} completed successfully`,
3998
+ confirmation: `Record verified in ${details.table} with sys_id: ${sys_id}`,
3999
+ validation_result: 'VERIFIED_SUCCESS'
4000
+ };
4001
+ }
4002
+ // Success without verification (no sys_id or table)
4003
+ return {
4004
+ success: true,
4005
+ operation_type: operationType,
4006
+ message: `${operationType} completed`,
4007
+ validation_result: 'SUCCESS_NO_VERIFICATION'
4008
+ };
4009
+ }
4010
+ catch (error) {
4011
+ this.logger.error('Validation error:', error);
4012
+ return {
4013
+ success: false,
4014
+ error: `Validation failed for ${operationType}: ${error}`,
4015
+ suggestion: 'Check ServiceNow connectivity and permissions',
4016
+ validation_result: 'VALIDATION_ERROR'
4017
+ };
4018
+ }
4019
+ }
4020
+ /**
4021
+ * Get actionable suggestions based on error type
4022
+ */
4023
+ getErrorSuggestion(error) {
4024
+ const errorLower = error.toLowerCase();
4025
+ if (errorLower.includes('403') || errorLower.includes('forbidden')) {
4026
+ return 'Check user permissions. May need ui_builder_admin or workspace_admin roles.';
4027
+ }
4028
+ if (errorLower.includes('404') || errorLower.includes('not found')) {
4029
+ return 'Table/endpoint not available. Check if required plugin is installed and activated.';
4030
+ }
4031
+ if (errorLower.includes('400') || errorLower.includes('bad request')) {
4032
+ return 'Invalid parameters or missing required fields. Check API documentation.';
4033
+ }
4034
+ if (errorLower.includes('401') || errorLower.includes('unauthorized')) {
4035
+ return 'Authentication issue. Run snow-flow auth login to re-authenticate.';
4036
+ }
4037
+ if (errorLower.includes('plugin') || errorLower.includes('license')) {
4038
+ return 'Required plugin not installed. Check ServiceNow Store for required plugins.';
4039
+ }
4040
+ return 'Check ServiceNow system logs for detailed error information.';
4041
+ }
4042
+ /**
4043
+ * Enhanced tool execution wrapper with comprehensive feedback
4044
+ */
4045
+ async executeWithFeedback(operationType, operation, details) {
4046
+ try {
4047
+ this.logger.info(`🔄 Executing ${operationType}...`);
4048
+ const startTime = Date.now();
4049
+ const result = await operation();
4050
+ const executionTime = Date.now() - startTime;
4051
+ const validation = await this.validateAndConfirmOperation(operationType, result, details);
4052
+ return {
4053
+ ...validation,
4054
+ execution_time_ms: executionTime,
4055
+ timestamp: new Date().toISOString()
4056
+ };
4057
+ }
4058
+ catch (error) {
4059
+ this.logger.error(`❌ ${operationType} failed:`, error);
4060
+ return {
4061
+ success: false,
4062
+ operation_type: operationType,
4063
+ error: error instanceof Error ? error.message : String(error),
4064
+ suggestion: this.getErrorSuggestion(String(error)),
4065
+ validation_result: 'EXECUTION_ERROR',
4066
+ timestamp: new Date().toISOString()
4067
+ };
4068
+ }
4069
+ }
3401
4070
  /**
3402
4071
  * Validate workspace configuration (fix from user feedback)
3403
4072
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "4.5.48",
3
+ "version": "4.5.50",
4
4
  "description": "Conversational ServiceNow development platform using Claude Code. Multi-agent orchestration with 20+ MCP servers providing 245+ ServiceNow tools including complete UX + Agent Workspace creation with official APIs.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",