snow-flow 1.3.10 → 1.3.12
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.
- package/dist/cli.js +178 -120
- package/dist/mcp/servicenow-xml-flow-mcp.js +935 -23
- package/dist/utils/improved-flow-xml-generator.js +762 -0
- package/dist/version.js +17 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -61,6 +61,118 @@ program
|
|
|
61
61
|
.name('snow-flow')
|
|
62
62
|
.description('ServiceNow Multi-Agent Development Framework')
|
|
63
63
|
.version(version_js_1.VERSION);
|
|
64
|
+
// Helper function to deploy XML to ServiceNow
|
|
65
|
+
async function deployXMLToServiceNow(xmlFile, options = {}) {
|
|
66
|
+
const oauth = new snow_oauth_js_1.ServiceNowOAuth();
|
|
67
|
+
const isAuthenticated = await oauth.getStoredTokens() !== null;
|
|
68
|
+
if (!isAuthenticated) {
|
|
69
|
+
cliLogger.error('❌ Not authenticated. Please run: snow-flow auth login');
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
// Initialize ServiceNow client
|
|
74
|
+
const client = new servicenow_client_js_1.ServiceNowClient();
|
|
75
|
+
// Read XML file
|
|
76
|
+
if (!(0, fs_2.existsSync)(xmlFile)) {
|
|
77
|
+
cliLogger.error(`❌ XML file not found: ${xmlFile}`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
cliLogger.info('📄 Reading XML file...');
|
|
81
|
+
const xmlContent = await fs_1.promises.readFile(xmlFile, 'utf-8');
|
|
82
|
+
// Import XML as remote update set
|
|
83
|
+
cliLogger.info('📤 Importing XML to ServiceNow...');
|
|
84
|
+
const importResponse = await client.makeRequest({
|
|
85
|
+
method: 'POST',
|
|
86
|
+
url: '/api/now/table/sys_remote_update_set',
|
|
87
|
+
headers: {
|
|
88
|
+
'Content-Type': 'application/xml',
|
|
89
|
+
'Accept': 'application/json'
|
|
90
|
+
},
|
|
91
|
+
data: xmlContent
|
|
92
|
+
});
|
|
93
|
+
if (!importResponse.result || !importResponse.result.sys_id) {
|
|
94
|
+
throw new Error('Failed to import XML update set');
|
|
95
|
+
}
|
|
96
|
+
const remoteUpdateSetId = importResponse.result.sys_id;
|
|
97
|
+
cliLogger.info(`✅ XML imported successfully (sys_id: ${remoteUpdateSetId})`);
|
|
98
|
+
// Load the update set
|
|
99
|
+
cliLogger.info('🔄 Loading update set...');
|
|
100
|
+
await client.makeRequest({
|
|
101
|
+
method: 'PUT',
|
|
102
|
+
url: `/api/now/table/sys_remote_update_set/${remoteUpdateSetId}`,
|
|
103
|
+
data: {
|
|
104
|
+
state: 'loaded'
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
// Find the loaded update set
|
|
108
|
+
const loadedResponse = await client.makeRequest({
|
|
109
|
+
method: 'GET',
|
|
110
|
+
url: '/api/now/table/sys_update_set',
|
|
111
|
+
params: {
|
|
112
|
+
sysparm_query: `remote_sys_id=${remoteUpdateSetId}`,
|
|
113
|
+
sysparm_limit: 1
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
if (!loadedResponse.result || loadedResponse.result.length === 0) {
|
|
117
|
+
throw new Error('Failed to find loaded update set');
|
|
118
|
+
}
|
|
119
|
+
const updateSetId = loadedResponse.result[0].sys_id;
|
|
120
|
+
const updateSetName = loadedResponse.result[0].name;
|
|
121
|
+
cliLogger.info(`✅ Update set loaded: ${updateSetName}`);
|
|
122
|
+
// Preview if requested
|
|
123
|
+
if (options.preview !== false) {
|
|
124
|
+
cliLogger.info('🔍 Previewing update set...');
|
|
125
|
+
await client.makeRequest({
|
|
126
|
+
method: 'POST',
|
|
127
|
+
url: `/api/now/table/sys_update_set/${updateSetId}/preview`
|
|
128
|
+
});
|
|
129
|
+
// Check preview results
|
|
130
|
+
const previewProblems = await client.makeRequest({
|
|
131
|
+
method: 'GET',
|
|
132
|
+
url: '/api/now/table/sys_update_preview_problem',
|
|
133
|
+
params: {
|
|
134
|
+
sysparm_query: `update_set=${updateSetId}`,
|
|
135
|
+
sysparm_limit: 100
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
if (previewProblems.result && previewProblems.result.length > 0) {
|
|
139
|
+
cliLogger.warn('\n⚠️ Preview found problems:');
|
|
140
|
+
previewProblems.result.forEach((p) => {
|
|
141
|
+
cliLogger.warn(` - ${p.type}: ${p.description}`);
|
|
142
|
+
});
|
|
143
|
+
if (options.commit !== false) {
|
|
144
|
+
cliLogger.warn('\n⚠️ Skipping auto-commit due to preview problems');
|
|
145
|
+
cliLogger.info('📋 Review and resolve problems in ServiceNow, then commit manually');
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
cliLogger.info('✅ Preview successful - no problems found');
|
|
151
|
+
}
|
|
152
|
+
// Commit if clean and requested
|
|
153
|
+
if (options.commit !== false && (!previewProblems.result || previewProblems.result.length === 0)) {
|
|
154
|
+
cliLogger.info('🚀 Committing update set...');
|
|
155
|
+
await client.makeRequest({
|
|
156
|
+
method: 'POST',
|
|
157
|
+
url: `/api/now/table/sys_update_set/${updateSetId}/commit`
|
|
158
|
+
});
|
|
159
|
+
cliLogger.info('\n✅ Update Set committed successfully!');
|
|
160
|
+
cliLogger.info('📍 Navigate to Flow Designer > Designer to see your flow');
|
|
161
|
+
cliLogger.info('\n🎉 Deployment complete!');
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
cliLogger.error('\n❌ Deployment failed:', error instanceof Error ? error.message : String(error));
|
|
169
|
+
cliLogger.info('\n💡 Troubleshooting tips:');
|
|
170
|
+
cliLogger.info(' 1. Check your authentication: snow-flow auth status');
|
|
171
|
+
cliLogger.info(' 2. Verify XML file format is correct');
|
|
172
|
+
cliLogger.info(' 3. Ensure you have required permissions in ServiceNow');
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
64
176
|
// Swarm command - the main orchestration command with EVERYTHING
|
|
65
177
|
program
|
|
66
178
|
.command('swarm <objective>')
|
|
@@ -159,8 +271,8 @@ program
|
|
|
159
271
|
cliLogger.info('📋 Creating production-ready ServiceNow flow XML...');
|
|
160
272
|
cliLogger.info('💡 Reason: Flow Designer flows are most reliable with XML-first approach\n');
|
|
161
273
|
try {
|
|
162
|
-
// Import XML flow generator
|
|
163
|
-
const {
|
|
274
|
+
// Import IMPROVED XML flow generator (fixes "too small to work" issue!)
|
|
275
|
+
const { generateImprovedFlowXML } = await Promise.resolve().then(() => __importStar(require('./utils/improved-flow-xml-generator.js')));
|
|
164
276
|
// Parse instruction to determine activities
|
|
165
277
|
const activities = [];
|
|
166
278
|
const objectiveLower = objective.toLowerCase();
|
|
@@ -236,12 +348,25 @@ program
|
|
|
236
348
|
outputs: { started: 'boolean' }
|
|
237
349
|
}]
|
|
238
350
|
};
|
|
239
|
-
// Generate XML
|
|
240
|
-
cliLogger.info('🏗️ Generating production XML...');
|
|
241
|
-
|
|
351
|
+
// Generate IMPROVED XML with enhanced structure
|
|
352
|
+
cliLogger.info('🏗️ Generating IMPROVED production XML...');
|
|
353
|
+
// Convert to improved flow definition
|
|
354
|
+
const improvedFlowDef = {
|
|
355
|
+
...flowDef,
|
|
356
|
+
run_as: 'user',
|
|
357
|
+
accessible_from: 'package_private',
|
|
358
|
+
category: 'custom',
|
|
359
|
+
tags: ['auto-generated'],
|
|
360
|
+
activities: flowDef.activities.map((act) => ({
|
|
361
|
+
...act,
|
|
362
|
+
description: act.description || act.name
|
|
363
|
+
}))
|
|
364
|
+
};
|
|
365
|
+
const result = generateImprovedFlowXML(improvedFlowDef);
|
|
242
366
|
xmlFlowResult = { ...result, flowDefinition: flowDef };
|
|
243
|
-
cliLogger.info(`\n✅ XML Generated Successfully!`);
|
|
367
|
+
cliLogger.info(`\n✅ IMPROVED XML Generated Successfully!`);
|
|
244
368
|
cliLogger.info(`📁 File saved to: ${result.filePath}`);
|
|
369
|
+
cliLogger.info(`🔥 IMPROVEMENTS: Uses v2 tables, Base64+gzip encoding, complete label_cache!`);
|
|
245
370
|
cliLogger.info(`📊 Flow structure:`);
|
|
246
371
|
cliLogger.info(` - Name: ${flowDef.name}`);
|
|
247
372
|
cliLogger.info(` - Table: ${flowDef.table}`);
|
|
@@ -262,9 +387,27 @@ program
|
|
|
262
387
|
// Check if auto-deploy is enabled
|
|
263
388
|
if (options.autoDeploy !== false) { // Default is true from swarm command
|
|
264
389
|
cliLogger.info('\n🚀 Auto-Deploy enabled - importing XML to ServiceNow...');
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
390
|
+
// Automatically deploy the XML file
|
|
391
|
+
const deploySuccess = await deployXMLToServiceNow(result.filePath, {
|
|
392
|
+
preview: true,
|
|
393
|
+
commit: true
|
|
394
|
+
});
|
|
395
|
+
if (deploySuccess) {
|
|
396
|
+
cliLogger.info('\n✅ Flow automatically deployed to ServiceNow!');
|
|
397
|
+
cliLogger.info('🎯 The flow is now available in Flow Designer');
|
|
398
|
+
// Store deployment success in memory
|
|
399
|
+
memorySystem.storeLearning(`deployment_${sessionId}`, {
|
|
400
|
+
success: true,
|
|
401
|
+
xml_file: result.filePath,
|
|
402
|
+
deployed_at: new Date().toISOString(),
|
|
403
|
+
flow_name: flowDef.name
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
cliLogger.warn('\n⚠️ Automatic deployment encountered issues');
|
|
408
|
+
cliLogger.info('💡 You can manually deploy later with:');
|
|
409
|
+
cliLogger.info(` snow-flow deploy-xml "${result.filePath}"`);
|
|
410
|
+
}
|
|
268
411
|
}
|
|
269
412
|
else {
|
|
270
413
|
cliLogger.info('📋 Use the import instructions above to deploy to ServiceNow');
|
|
@@ -1712,111 +1855,13 @@ program
|
|
|
1712
1855
|
.action(async (xmlFile, options) => {
|
|
1713
1856
|
console.log(`\n📦 Deploying XML Update Set: ${xmlFile}`);
|
|
1714
1857
|
console.log('='.repeat(60));
|
|
1715
|
-
|
|
1716
|
-
const
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
// Initialize ServiceNow client
|
|
1723
|
-
const client = new servicenow_client_js_1.ServiceNowClient();
|
|
1724
|
-
// Read XML file
|
|
1725
|
-
if (!(0, fs_2.existsSync)(xmlFile)) {
|
|
1726
|
-
console.error(`❌ XML file not found: ${xmlFile}`);
|
|
1727
|
-
return;
|
|
1728
|
-
}
|
|
1729
|
-
console.log('📄 Reading XML file...');
|
|
1730
|
-
const xmlContent = await fs_1.promises.readFile(xmlFile, 'utf-8');
|
|
1731
|
-
// Import XML as remote update set
|
|
1732
|
-
console.log('📤 Importing XML to ServiceNow...');
|
|
1733
|
-
const importResponse = await client.makeRequest({
|
|
1734
|
-
method: 'POST',
|
|
1735
|
-
url: '/api/now/table/sys_remote_update_set',
|
|
1736
|
-
headers: {
|
|
1737
|
-
'Content-Type': 'application/xml',
|
|
1738
|
-
'Accept': 'application/json'
|
|
1739
|
-
},
|
|
1740
|
-
data: xmlContent
|
|
1741
|
-
});
|
|
1742
|
-
if (!importResponse.result || !importResponse.result.sys_id) {
|
|
1743
|
-
throw new Error('Failed to import XML update set');
|
|
1744
|
-
}
|
|
1745
|
-
const remoteUpdateSetId = importResponse.result.sys_id;
|
|
1746
|
-
console.log(`✅ XML imported successfully (sys_id: ${remoteUpdateSetId})`);
|
|
1747
|
-
// Load the update set
|
|
1748
|
-
console.log('🔄 Loading update set...');
|
|
1749
|
-
await client.makeRequest({
|
|
1750
|
-
method: 'PUT',
|
|
1751
|
-
url: `/api/now/table/sys_remote_update_set/${remoteUpdateSetId}`,
|
|
1752
|
-
data: {
|
|
1753
|
-
state: 'loaded'
|
|
1754
|
-
}
|
|
1755
|
-
});
|
|
1756
|
-
// Find the loaded update set
|
|
1757
|
-
const loadedResponse = await client.makeRequest({
|
|
1758
|
-
method: 'GET',
|
|
1759
|
-
url: '/api/now/table/sys_update_set',
|
|
1760
|
-
params: {
|
|
1761
|
-
sysparm_query: `remote_sys_id=${remoteUpdateSetId}`,
|
|
1762
|
-
sysparm_limit: 1
|
|
1763
|
-
}
|
|
1764
|
-
});
|
|
1765
|
-
if (!loadedResponse.result || loadedResponse.result.length === 0) {
|
|
1766
|
-
throw new Error('Failed to find loaded update set');
|
|
1767
|
-
}
|
|
1768
|
-
const updateSetId = loadedResponse.result[0].sys_id;
|
|
1769
|
-
const updateSetName = loadedResponse.result[0].name;
|
|
1770
|
-
console.log(`✅ Update set loaded: ${updateSetName}`);
|
|
1771
|
-
// Preview if requested
|
|
1772
|
-
if (options.preview !== false) {
|
|
1773
|
-
console.log('🔍 Previewing update set...');
|
|
1774
|
-
await client.makeRequest({
|
|
1775
|
-
method: 'POST',
|
|
1776
|
-
url: `/api/now/table/sys_update_set/${updateSetId}/preview`
|
|
1777
|
-
});
|
|
1778
|
-
// Check preview results
|
|
1779
|
-
const previewProblems = await client.makeRequest({
|
|
1780
|
-
method: 'GET',
|
|
1781
|
-
url: '/api/now/table/sys_update_preview_problem',
|
|
1782
|
-
params: {
|
|
1783
|
-
sysparm_query: `update_set=${updateSetId}`,
|
|
1784
|
-
sysparm_limit: 100
|
|
1785
|
-
}
|
|
1786
|
-
});
|
|
1787
|
-
if (previewProblems.result && previewProblems.result.length > 0) {
|
|
1788
|
-
console.log('\n⚠️ Preview found problems:');
|
|
1789
|
-
previewProblems.result.forEach((p) => {
|
|
1790
|
-
console.log(` - ${p.type}: ${p.description}`);
|
|
1791
|
-
});
|
|
1792
|
-
if (options.commit !== false) {
|
|
1793
|
-
console.log('\n⚠️ Skipping auto-commit due to preview problems');
|
|
1794
|
-
console.log('📋 Review and resolve problems in ServiceNow, then commit manually');
|
|
1795
|
-
return;
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
|
-
else {
|
|
1799
|
-
console.log('✅ Preview successful - no problems found');
|
|
1800
|
-
}
|
|
1801
|
-
// Commit if clean and requested
|
|
1802
|
-
if (options.commit !== false && (!previewProblems.result || previewProblems.result.length === 0)) {
|
|
1803
|
-
console.log('🚀 Committing update set...');
|
|
1804
|
-
await client.makeRequest({
|
|
1805
|
-
method: 'POST',
|
|
1806
|
-
url: `/api/now/table/sys_update_set/${updateSetId}/commit`
|
|
1807
|
-
});
|
|
1808
|
-
console.log('\n✅ Update Set committed successfully!');
|
|
1809
|
-
console.log('📍 Navigate to Flow Designer > Designer to see your flow');
|
|
1810
|
-
console.log('\n🎉 Deployment complete!');
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
catch (error) {
|
|
1815
|
-
console.error('\n❌ Deployment failed:', error instanceof Error ? error.message : String(error));
|
|
1816
|
-
console.log('\n💡 Troubleshooting tips:');
|
|
1817
|
-
console.log(' 1. Check your authentication: snow-flow auth status');
|
|
1818
|
-
console.log(' 2. Verify XML file format is correct');
|
|
1819
|
-
console.log(' 3. Ensure you have required permissions in ServiceNow');
|
|
1858
|
+
// Use the shared deploy function
|
|
1859
|
+
const success = await deployXMLToServiceNow(xmlFile, {
|
|
1860
|
+
preview: options.preview,
|
|
1861
|
+
commit: options.commit
|
|
1862
|
+
});
|
|
1863
|
+
if (!success) {
|
|
1864
|
+
process.exit(1);
|
|
1820
1865
|
}
|
|
1821
1866
|
});
|
|
1822
1867
|
// Help command
|
|
@@ -4324,8 +4369,8 @@ program
|
|
|
4324
4369
|
console.log(`\n🔧 XML-First Flow Generator v${version_js_1.VERSION}`);
|
|
4325
4370
|
console.log('📋 Creating production-ready ServiceNow flow XML...\n');
|
|
4326
4371
|
try {
|
|
4327
|
-
// Import XML flow generator
|
|
4328
|
-
const {
|
|
4372
|
+
// Import IMPROVED XML flow generator (fixes "too small to work" issue!)
|
|
4373
|
+
const { generateImprovedFlowXML } = await Promise.resolve().then(() => __importStar(require('./utils/improved-flow-xml-generator.js')));
|
|
4329
4374
|
// Parse instruction to determine activities
|
|
4330
4375
|
const activities = [];
|
|
4331
4376
|
// Check for common patterns in instruction
|
|
@@ -4403,11 +4448,24 @@ return { started: true };`
|
|
|
4403
4448
|
}
|
|
4404
4449
|
];
|
|
4405
4450
|
}
|
|
4406
|
-
// Generate XML
|
|
4407
|
-
console.log('\n🏗️ Generating production XML...');
|
|
4408
|
-
|
|
4409
|
-
|
|
4451
|
+
// Generate IMPROVED XML with enhanced structure
|
|
4452
|
+
console.log('\n🏗️ Generating IMPROVED production XML...');
|
|
4453
|
+
// Convert to improved flow definition
|
|
4454
|
+
const improvedFlowDef = {
|
|
4455
|
+
...flowDef,
|
|
4456
|
+
run_as: 'user',
|
|
4457
|
+
accessible_from: 'package_private',
|
|
4458
|
+
category: 'custom',
|
|
4459
|
+
tags: ['cli-generated'],
|
|
4460
|
+
activities: flowDef.activities.map((act) => ({
|
|
4461
|
+
...act,
|
|
4462
|
+
description: act.description || act.name
|
|
4463
|
+
}))
|
|
4464
|
+
};
|
|
4465
|
+
const result = generateImprovedFlowXML(improvedFlowDef);
|
|
4466
|
+
console.log(`\n✅ IMPROVED XML Generated Successfully!`);
|
|
4410
4467
|
console.log(`📁 File saved to: ${result.filePath}`);
|
|
4468
|
+
console.log(`🔥 IMPROVEMENTS: Uses v2 tables, Base64+gzip encoding, complete label_cache!`);
|
|
4411
4469
|
console.log(`📊 Flow structure:`);
|
|
4412
4470
|
console.log(` - Name: ${flowDef.name}`);
|
|
4413
4471
|
console.log(` - Table: ${flowDef.table}`);
|