snow-flow 1.3.17 → 1.3.19

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.
@@ -41,6 +41,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.ServiceNowXMLFlowMCP = void 0;
42
42
  const base_mcp_server_1 = require("./base-mcp-server");
43
43
  const improved_flow_xml_generator_1 = __importStar(require("../utils/improved-flow-xml-generator"));
44
+ const xml_first_flow_generator_1 = require("../utils/xml-first-flow-generator"); // Keep for backward compatibility
44
45
  const natural_language_mapper_1 = require("../api/natural-language-mapper");
45
46
  const servicenow_id_generator_js_1 = require("../utils/servicenow-id-generator.js");
46
47
  const fs = __importStar(require("fs"));
@@ -118,7 +119,7 @@ class ServiceNowXMLFlowMCP extends base_mcp_server_1.BaseMCPServer {
118
119
  // Generate flow XML from natural language
119
120
  this.registerTool({
120
121
  name: 'snow_xml_flow_from_instruction',
121
- description: 'Generate flow Update Set XML from natural language instruction',
122
+ description: '⚠️ DEPRECATED - Use snow_create_flow instead. This tool is kept for backwards compatibility only.',
122
123
  inputSchema: {
123
124
  type: 'object',
124
125
  properties: {
@@ -130,6 +131,11 @@ class ServiceNowXMLFlowMCP extends base_mcp_server_1.BaseMCPServer {
130
131
  type: 'boolean',
131
132
  default: true,
132
133
  description: 'Save XML to file'
134
+ },
135
+ auto_deploy: {
136
+ type: 'boolean',
137
+ default: true,
138
+ description: 'Automatically deploy XML to ServiceNow after generation (RECOMMENDED)'
133
139
  }
134
140
  },
135
141
  required: ['instruction']
@@ -219,7 +225,7 @@ class ServiceNowXMLFlowMCP extends base_mcp_server_1.BaseMCPServer {
219
225
  */
220
226
  async generateFlowFromInstruction(args) {
221
227
  try {
222
- const { instruction } = args;
228
+ const { instruction, auto_deploy = true } = args;
223
229
  // Parse natural language to flow components
224
230
  const flowRequirements = await this.nlMapper.parseFlowRequirements(instruction);
225
231
  // Convert to IMPROVED flow definition
@@ -235,21 +241,128 @@ class ServiceNowXMLFlowMCP extends base_mcp_server_1.BaseMCPServer {
235
241
  tags: ['auto-generated'],
236
242
  activities: this.convertToImprovedActivities(flowRequirements)
237
243
  };
238
- // Use IMPROVED generator
239
- const result = (0, improved_flow_xml_generator_1.generateImprovedFlowXML)(flowDef);
244
+ // Use PRODUCTION-READY generator with proper Update Set structure
245
+ const result = (0, xml_first_flow_generator_1.generateProductionFlowXML)(flowDef);
246
+ let deploymentResult = null;
247
+ // 🚀 AUTO-DEPLOYMENT: Deploy immediately if requested
248
+ if (auto_deploy) {
249
+ try {
250
+ this.logger.info('🚀 AUTO-DEPLOYING XML to ServiceNow...');
251
+ // Check authentication
252
+ const isAuth = await this.oauth.isAuthenticated();
253
+ if (!isAuth) {
254
+ throw new Error('Not authenticated with ServiceNow. Please run: snow-flow auth login');
255
+ }
256
+ // Initialize ServiceNow client
257
+ const client = new ServiceNowClient();
258
+ // Read the XML file
259
+ const fs = require('fs').promises;
260
+ const xmlContent = await fs.readFile(result.filePath, 'utf-8');
261
+ // Import XML as remote update set
262
+ const importResponse = await client.makeRequest({
263
+ method: 'POST',
264
+ url: '/api/now/table/sys_remote_update_set',
265
+ headers: {
266
+ 'Content-Type': 'application/xml',
267
+ 'Accept': 'application/json'
268
+ },
269
+ data: xmlContent
270
+ });
271
+ if (!importResponse.result || !importResponse.result.sys_id) {
272
+ throw new Error('Failed to import XML update set');
273
+ }
274
+ const remoteUpdateSetId = importResponse.result.sys_id;
275
+ this.logger.info(`✅ XML imported successfully (sys_id: ${remoteUpdateSetId})`);
276
+ // Load the update set
277
+ await client.makeRequest({
278
+ method: 'PUT',
279
+ url: `/api/now/table/sys_remote_update_set/${remoteUpdateSetId}`,
280
+ data: {
281
+ state: 'loaded'
282
+ }
283
+ });
284
+ // Find the loaded update set
285
+ const loadedResponse = await client.makeRequest({
286
+ method: 'GET',
287
+ url: '/api/now/table/sys_update_set',
288
+ params: {
289
+ sysparm_query: `remote_sys_id=${remoteUpdateSetId}`,
290
+ sysparm_limit: 1
291
+ }
292
+ });
293
+ if (!loadedResponse.result || loadedResponse.result.length === 0) {
294
+ throw new Error('Failed to find loaded update set');
295
+ }
296
+ const updateSetId = loadedResponse.result[0].sys_id;
297
+ const updateSetName = loadedResponse.result[0].name;
298
+ // Preview the update set
299
+ await client.makeRequest({
300
+ method: 'POST',
301
+ url: `/api/now/table/sys_update_set/${updateSetId}/preview`
302
+ });
303
+ // Check for preview problems
304
+ const previewProblems = await client.makeRequest({
305
+ method: 'GET',
306
+ url: '/api/now/table/sys_update_preview_problem',
307
+ params: {
308
+ sysparm_query: `update_set=${updateSetId}`,
309
+ sysparm_limit: 100
310
+ }
311
+ });
312
+ if (previewProblems.result && previewProblems.result.length > 0) {
313
+ const problemsList = previewProblems.result.map((p) => `- ${p.type}: ${p.description}`).join('\n');
314
+ throw new Error(`Preview found problems:\n${problemsList}\n\nPlease review and resolve in ServiceNow UI`);
315
+ }
316
+ // Commit the update set
317
+ await client.makeRequest({
318
+ method: 'POST',
319
+ url: `/api/now/table/sys_update_set/${updateSetId}/commit`
320
+ });
321
+ deploymentResult = {
322
+ success: true,
323
+ message: '✅ XML automatically deployed to ServiceNow!',
324
+ update_set_id: updateSetId,
325
+ update_set_name: updateSetName,
326
+ steps_completed: [
327
+ '✅ XML imported as remote update set',
328
+ '✅ Update set loaded successfully',
329
+ '✅ Preview completed with no problems',
330
+ '✅ Update set committed successfully'
331
+ ]
332
+ };
333
+ this.logger.info('✅ Auto-deployment successful', deploymentResult);
334
+ }
335
+ catch (deployError) {
336
+ this.logger.warn('⚠️ Auto-deployment failed, providing manual instructions', deployError);
337
+ deploymentResult = {
338
+ success: false,
339
+ error: deployError instanceof Error ? deployError.message : String(deployError),
340
+ manual_command: `snow-flow deploy-xml ${result.filePath}`,
341
+ troubleshooting: [
342
+ '1. Check ServiceNow authentication: snow-flow auth status',
343
+ '2. Verify admin permissions in ServiceNow',
344
+ '3. Review XML file for format issues',
345
+ '4. Try manual deployment command above'
346
+ ]
347
+ };
348
+ }
349
+ }
240
350
  return {
241
351
  success: true,
242
352
  xml: args.save_to_file === false ? result.xml : undefined,
243
353
  file_path: result.filePath,
244
354
  flow_definition: flowDef,
245
- message: `✅ Generated IMPROVED flow XML from instruction: ${instruction}`,
355
+ deployment: deploymentResult,
356
+ message: `✅ Generated IMPROVED flow XML from instruction: ${instruction}${deploymentResult?.success ? ' + DEPLOYED!' : ''}`,
246
357
  improvements: [
247
358
  '✅ Production-ready Flow Designer format',
248
359
  '✅ Complete XML structure with all required fields',
249
360
  '✅ Base64+gzip encoded action values',
250
- '✅ Proper v2 table usage'
361
+ '✅ Proper v2 table usage',
362
+ ...(deploymentResult?.success ? ['✅ Automatically deployed to ServiceNow!'] : [])
251
363
  ],
252
- import_instructions: result.instructions
364
+ import_instructions: deploymentResult?.success ? 'Flow is already deployed and ready to use!' : result.instructions,
365
+ auto_deploy_command: deploymentResult?.manual_command || `snow-flow deploy-xml ${result.filePath}`
253
366
  };
254
367
  }
255
368
  catch (error) {
@@ -17,4 +17,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  // Re-export coordination framework types
19
19
  __exportStar(require("./snow-flow.types"), exports);
20
- __exportStar(require("../coordination/types"), exports);
@@ -12,6 +12,7 @@ const fs_1 = require("fs");
12
12
  const path_1 = require("path");
13
13
  const events_1 = require("events");
14
14
  const os_1 = __importDefault(require("os"));
15
+ const unified_auth_store_js_1 = require("./unified-auth-store.js");
15
16
  class MCPServerManager extends events_1.EventEmitter {
16
17
  constructor(configPath) {
17
18
  super();
@@ -172,15 +173,33 @@ class MCPServerManager extends events_1.EventEmitter {
172
173
  }
173
174
  // Check if script exists
174
175
  await fs_1.promises.access(scriptPath);
175
- // Start the process
176
+ // Bridge OAuth tokens to MCP servers
177
+ await unified_auth_store_js_1.unifiedAuthStore.bridgeToMCP();
178
+ // Get current tokens for the MCP server
179
+ const tokens = await unified_auth_store_js_1.unifiedAuthStore.getTokens();
180
+ const authEnv = {};
181
+ if (tokens) {
182
+ authEnv.SNOW_OAUTH_TOKENS = JSON.stringify(tokens);
183
+ authEnv.SNOW_INSTANCE = tokens.instance;
184
+ authEnv.SNOW_CLIENT_ID = tokens.clientId;
185
+ authEnv.SNOW_CLIENT_SECRET = tokens.clientSecret;
186
+ if (tokens.accessToken) {
187
+ authEnv.SNOW_ACCESS_TOKEN = tokens.accessToken;
188
+ }
189
+ if (tokens.refreshToken) {
190
+ authEnv.SNOW_REFRESH_TOKEN = tokens.refreshToken;
191
+ }
192
+ if (tokens.expiresAt) {
193
+ authEnv.SNOW_TOKEN_EXPIRES_AT = tokens.expiresAt;
194
+ }
195
+ }
196
+ // Start the process with OAuth tokens
176
197
  const childProcess = (0, child_process_1.spawn)('node', [scriptPath], {
177
198
  stdio: ['ignore', 'pipe', 'pipe'],
178
199
  detached: true,
179
200
  env: {
180
201
  ...process.env,
181
- SNOW_INSTANCE: process.env.SNOW_INSTANCE,
182
- SNOW_CLIENT_ID: process.env.SNOW_CLIENT_ID,
183
- SNOW_CLIENT_SECRET: process.env.SNOW_CLIENT_SECRET
202
+ ...authEnv
184
203
  }
185
204
  });
186
205
  // Set up logging
@@ -15,6 +15,7 @@ const action_type_cache_1 = require("./action-type-cache");
15
15
  const snow_flow_config_js_1 = require("../config/snow-flow-config.js");
16
16
  const widget_template_generator_js_1 = require("./widget-template-generator.js");
17
17
  const logger_1 = require("./logger");
18
+ const unified_auth_store_js_1 = require("./unified-auth-store.js");
18
19
  const flow_structure_builder_1 = require("./flow-structure-builder");
19
20
  class ServiceNowClient {
20
21
  constructor() {
@@ -115,7 +116,22 @@ class ServiceNowClient {
115
116
  */
116
117
  async ensureAuthenticated() {
117
118
  if (!this.credentials) {
118
- this.credentials = await this.oauth.loadCredentials();
119
+ // Try unified auth store first (most reliable)
120
+ const tokens = await unified_auth_store_js_1.unifiedAuthStore.getTokens();
121
+ if (tokens) {
122
+ this.credentials = {
123
+ instance: tokens.instance,
124
+ clientId: tokens.clientId,
125
+ clientSecret: tokens.clientSecret,
126
+ accessToken: tokens.accessToken,
127
+ refreshToken: tokens.refreshToken,
128
+ expiresAt: tokens.expiresAt
129
+ };
130
+ }
131
+ else {
132
+ // Fallback to OAuth loadCredentials
133
+ this.credentials = await this.oauth.loadCredentials();
134
+ }
119
135
  }
120
136
  if (!this.credentials) {
121
137
  console.error('❌ No ServiceNow credentials found');
@@ -18,6 +18,7 @@ const axios_1 = __importDefault(require("axios"));
18
18
  const net_1 = __importDefault(require("net"));
19
19
  const crypto_1 = __importDefault(require("crypto"));
20
20
  const snow_flow_config_js_1 = require("../config/snow-flow-config.js");
21
+ const unified_auth_store_js_1 = require("./unified-auth-store.js");
21
22
  class ServiceNowOAuth {
22
23
  constructor() {
23
24
  // Store tokens in user's home directory
@@ -348,15 +349,16 @@ class ServiceNowOAuth {
348
349
  */
349
350
  async saveTokens(tokenData) {
350
351
  try {
351
- const configDir = process.env.SNOW_FLOW_HOME || (0, path_1.join)(os_1.default.homedir(), '.snow-flow');
352
- await fs_1.promises.mkdir(configDir, { recursive: true });
353
352
  const expiresAt = new Date();
354
353
  expiresAt.setSeconds(expiresAt.getSeconds() + tokenData.expiresIn);
355
354
  const authData = {
356
355
  ...tokenData,
357
356
  expiresAt: expiresAt.toISOString()
358
357
  };
359
- await fs_1.promises.writeFile(this.tokenPath, JSON.stringify(authData, null, 2), 'utf8');
358
+ // Use unified auth store
359
+ await unified_auth_store_js_1.unifiedAuthStore.saveTokens(authData);
360
+ // Bridge to MCP servers immediately
361
+ await unified_auth_store_js_1.unifiedAuthStore.bridgeToMCP();
360
362
  }
361
363
  catch (error) {
362
364
  console.error('Failed to save tokens:', error);
@@ -368,8 +370,7 @@ class ServiceNowOAuth {
368
370
  */
369
371
  async loadTokens() {
370
372
  try {
371
- const data = await fs_1.promises.readFile(this.tokenPath, 'utf8');
372
- return JSON.parse(data);
373
+ return await unified_auth_store_js_1.unifiedAuthStore.getTokens();
373
374
  }
374
375
  catch (error) {
375
376
  return null;
@@ -495,6 +496,12 @@ class ServiceNowOAuth {
495
496
  console.log('No active session to logout from');
496
497
  }
497
498
  }
499
+ /**
500
+ * Get stored OAuth tokens for use in other contexts (MCP servers)
501
+ */
502
+ async getStoredTokens() {
503
+ return await this.loadTokens();
504
+ }
498
505
  /**
499
506
  * Load credentials (including tokens) with .env fallback
500
507
  */
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ /**
3
+ * Unified Authentication Store for ServiceNow
4
+ *
5
+ * Provides shared token storage accessible from both CLI and MCP contexts.
6
+ * Solves the token isolation problem between different execution contexts.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.unifiedAuthStore = exports.UnifiedAuthStore = void 0;
13
+ const fs_1 = require("fs");
14
+ const path_1 = require("path");
15
+ const os_1 = __importDefault(require("os"));
16
+ const dotenv_1 = __importDefault(require("dotenv"));
17
+ // Load environment variables
18
+ dotenv_1.default.config();
19
+ class UnifiedAuthStore {
20
+ constructor() {
21
+ this.memoryStore = null;
22
+ // Use consistent path across all contexts
23
+ const configDir = process.env.SNOW_FLOW_HOME || (0, path_1.join)(os_1.default.homedir(), '.snow-flow');
24
+ this.tokenPath = (0, path_1.join)(configDir, 'auth.json');
25
+ // Also check environment for shared tokens (from MCP bridge)
26
+ if (process.env.SNOW_OAUTH_TOKENS) {
27
+ try {
28
+ this.memoryStore = JSON.parse(process.env.SNOW_OAUTH_TOKENS);
29
+ }
30
+ catch (e) {
31
+ console.error('Failed to parse SNOW_OAUTH_TOKENS from environment');
32
+ }
33
+ }
34
+ }
35
+ static getInstance() {
36
+ if (!UnifiedAuthStore.instance) {
37
+ UnifiedAuthStore.instance = new UnifiedAuthStore();
38
+ }
39
+ return UnifiedAuthStore.instance;
40
+ }
41
+ /**
42
+ * Get tokens from file or memory
43
+ */
44
+ async getTokens() {
45
+ try {
46
+ // First check memory store (fastest)
47
+ if (this.memoryStore) {
48
+ return this.memoryStore;
49
+ }
50
+ // Then check file system
51
+ const data = await fs_1.promises.readFile(this.tokenPath, 'utf8');
52
+ const tokens = JSON.parse(data);
53
+ // Cache in memory for performance
54
+ this.memoryStore = tokens;
55
+ return tokens;
56
+ }
57
+ catch (error) {
58
+ // Fallback to environment variables
59
+ return this.getTokensFromEnv();
60
+ }
61
+ }
62
+ /**
63
+ * Save tokens to file and memory
64
+ */
65
+ async saveTokens(tokens) {
66
+ try {
67
+ const configDir = (0, path_1.join)(os_1.default.homedir(), '.snow-flow');
68
+ await fs_1.promises.mkdir(configDir, { recursive: true });
69
+ await fs_1.promises.writeFile(this.tokenPath, JSON.stringify(tokens, null, 2));
70
+ // Update memory store
71
+ this.memoryStore = tokens;
72
+ // Update environment for child processes
73
+ process.env.SNOW_OAUTH_TOKENS = JSON.stringify(tokens);
74
+ }
75
+ catch (error) {
76
+ console.error('Failed to save tokens:', error);
77
+ throw error;
78
+ }
79
+ }
80
+ /**
81
+ * Get tokens from environment variables (fallback)
82
+ */
83
+ getTokensFromEnv() {
84
+ const instance = process.env.SNOW_INSTANCE;
85
+ const clientId = process.env.SNOW_CLIENT_ID;
86
+ const clientSecret = process.env.SNOW_CLIENT_SECRET;
87
+ if (!instance || !clientId || !clientSecret) {
88
+ return null;
89
+ }
90
+ return {
91
+ instance: instance.replace(/\/$/, ''),
92
+ clientId,
93
+ clientSecret,
94
+ accessToken: process.env.SNOW_ACCESS_TOKEN,
95
+ refreshToken: process.env.SNOW_REFRESH_TOKEN,
96
+ expiresAt: process.env.SNOW_TOKEN_EXPIRES_AT
97
+ };
98
+ }
99
+ /**
100
+ * Check if tokens are valid and not expired
101
+ */
102
+ async isAuthenticated() {
103
+ try {
104
+ const tokens = await this.getTokens();
105
+ if (!tokens || !tokens.accessToken) {
106
+ return false;
107
+ }
108
+ // Check expiration
109
+ if (tokens.expiresAt) {
110
+ const expiresAt = new Date(tokens.expiresAt);
111
+ const now = new Date();
112
+ return now < expiresAt;
113
+ }
114
+ // If no expiration, assume valid
115
+ return true;
116
+ }
117
+ catch (error) {
118
+ return false;
119
+ }
120
+ }
121
+ /**
122
+ * Clear all stored tokens
123
+ */
124
+ async clearTokens() {
125
+ try {
126
+ await fs_1.promises.unlink(this.tokenPath);
127
+ }
128
+ catch (error) {
129
+ // Ignore if file doesn't exist
130
+ }
131
+ // Clear memory and environment
132
+ this.memoryStore = null;
133
+ delete process.env.SNOW_OAUTH_TOKENS;
134
+ delete process.env.SNOW_ACCESS_TOKEN;
135
+ delete process.env.SNOW_REFRESH_TOKEN;
136
+ delete process.env.SNOW_TOKEN_EXPIRES_AT;
137
+ }
138
+ /**
139
+ * Get ServiceNow instance URL
140
+ */
141
+ async getInstanceUrl() {
142
+ const tokens = await this.getTokens();
143
+ if (!tokens) {
144
+ return null;
145
+ }
146
+ let instance = tokens.instance;
147
+ if (!instance.startsWith('http')) {
148
+ instance = `https://${instance}`;
149
+ }
150
+ if (!instance.endsWith('.service-now.com')) {
151
+ instance = `${instance}.service-now.com`;
152
+ }
153
+ return instance;
154
+ }
155
+ /**
156
+ * Get headers for API requests
157
+ */
158
+ async getAuthHeaders() {
159
+ const tokens = await this.getTokens();
160
+ if (!tokens || !tokens.accessToken) {
161
+ return null;
162
+ }
163
+ return {
164
+ 'Authorization': `Bearer ${tokens.accessToken}`,
165
+ 'Content-Type': 'application/json',
166
+ 'Accept': 'application/json'
167
+ };
168
+ }
169
+ /**
170
+ * Bridge tokens to MCP servers via environment
171
+ */
172
+ async bridgeToMCP() {
173
+ const tokens = await this.getTokens();
174
+ if (tokens) {
175
+ process.env.SNOW_OAUTH_TOKENS = JSON.stringify(tokens);
176
+ process.env.SNOW_INSTANCE = tokens.instance;
177
+ process.env.SNOW_CLIENT_ID = tokens.clientId;
178
+ process.env.SNOW_CLIENT_SECRET = tokens.clientSecret;
179
+ if (tokens.accessToken) {
180
+ process.env.SNOW_ACCESS_TOKEN = tokens.accessToken;
181
+ }
182
+ if (tokens.refreshToken) {
183
+ process.env.SNOW_REFRESH_TOKEN = tokens.refreshToken;
184
+ }
185
+ if (tokens.expiresAt) {
186
+ process.env.SNOW_TOKEN_EXPIRES_AT = tokens.expiresAt;
187
+ }
188
+ }
189
+ }
190
+ }
191
+ exports.UnifiedAuthStore = UnifiedAuthStore;
192
+ // Export singleton instance
193
+ exports.unifiedAuthStore = UnifiedAuthStore.getInstance();
@@ -425,47 +425,38 @@ class XMLFirstFlowGenerator {
425
425
  }
426
426
  exports.XMLFirstFlowGenerator = XMLFirstFlowGenerator;
427
427
  /**
428
- * Generate PRODUCTION-READY flow XML (NO placeholders!)
428
+ * Generate PRODUCTION-READY flow XML with BOTH formats
429
429
  */
430
430
  function generateProductionFlowXML(flowDef) {
431
431
  const generator = new XMLFirstFlowGenerator(flowDef.name.replace(/[^a-zA-Z0-9]+/g, '_') + '_Import');
432
+ // Generate Update Set XML (better for automatic deployment)
432
433
  const xml = generator.generateFlowUpdateSetXML(flowDef);
433
434
  const filePath = generator.saveToFile(xml, flowDef.name.toLowerCase().replace(/[^a-z0-9]+/g, '_') + '_flow.xml');
434
435
  const instructions = `
435
- === ServiceNow Flow Import Instructions ===
436
+ === ServiceNow Flow Deployment Options ===
436
437
 
437
- 1. Log into your ServiceNow instance as an admin user
438
+ 🚀 OPTION 1: Automatic Deployment (RECOMMENDED)
439
+ Use the snow-flow deploy-xml command for complete automation:
440
+
441
+ snow-flow deploy-xml ${filePath}
442
+
443
+ This automatically:
444
+ ✅ Imports the Update Set
445
+ ✅ Previews for conflicts
446
+ ✅ Commits if clean
447
+ ✅ Reports any issues
438
448
 
439
- 2. Navigate to:
440
- System Update Sets > Retrieved Update Sets
449
+ 🔧 OPTION 2: Manual Import (if automatic fails)
450
+
451
+ 1. Log into ServiceNow as admin
452
+ 2. Navigate to: System Update Sets > Local Update Sets
453
+ 3. Click "Import Update Set from XML"
454
+ 4. Choose file: ${filePath}
455
+ 5. Click "Upload" and follow prompts
456
+ 6. Preview and commit the Update Set
457
+ 7. Find your flow in Flow Designer
441
458
 
442
- 3. Click the "Import Update Set from XML" link at the bottom of the list
443
- (NOT the "Import from XML" in the context menu!)
444
-
445
- 4. Choose file: ${filePath}
446
-
447
- 5. Click "Upload"
448
-
449
- 6. Find your imported Update Set in the list
450
-
451
- 7. Click on the Update Set name to open it
452
-
453
- 8. Click "Preview Update Set"
454
- - Review any errors or warnings
455
- - Resolve any missing dependencies
456
-
457
- 9. Once preview is clean, click "Commit Update Set"
458
-
459
- 10. Navigate to Flow Designer:
460
- - All > Flow Designer > Designer
461
- - Your flow "${flowDef.name}" should appear in the list
462
-
463
- 11. Open the flow to verify all components are present
464
-
465
- TROUBLESHOOTING:
466
- - If flow appears empty: Check that all sys_update_xml records were imported
467
- - If import fails: Verify you're using "Import Update Set from XML" link
468
- - For dependency errors: Import required plugins/applications first
459
+ The flow "${flowDef.name}" will appear in Flow Designer > Designer
469
460
  `.trim();
470
461
  return { xml, filePath, instructions };
471
462
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "1.3.17",
3
+ "version": "1.3.19",
4
4
  "description": "ServiceNow Queen Agent - Hive-Mind Intelligence for ServiceNow Development inspired by claude-flow. Transform complex workflows into elegant one-command orchestration.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",