snow-flow 1.1.35 → 1.1.36

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.
@@ -72,12 +72,14 @@ class ServiceNowDeploymentMCP {
72
72
  properties: {
73
73
  name: { type: 'string', description: 'Flow name' },
74
74
  description: { type: 'string', description: 'Flow description' },
75
+ flow_type: { type: 'string', enum: ['flow', 'subflow', 'action'], description: 'Type of flow to create (default: flow)', default: 'flow' },
75
76
  table: { type: 'string', description: 'Target table (e.g., sc_request, incident)' },
76
77
  trigger_type: { type: 'string', enum: ['record_created', 'record_updated', 'scheduled', 'manual'], description: 'Flow trigger type' },
77
78
  condition: { type: 'string', description: 'Trigger condition (encoded query)' },
78
79
  active: { type: 'boolean', description: 'Activate flow on deployment' },
79
80
  flow_definition: { type: 'string', description: 'Flow Designer definition JSON' },
80
81
  category: { type: 'string', description: 'Flow category (e.g., approval, automation)' },
82
+ validate_before_deploy: { type: 'boolean', description: 'Validate flow definition before deployment', default: true },
81
83
  },
82
84
  required: ['name', 'description', 'flow_definition', 'trigger_type'],
83
85
  },
@@ -287,6 +289,74 @@ class ServiceNowDeploymentMCP {
287
289
  required: ['sys_id'],
288
290
  },
289
291
  },
292
+ {
293
+ name: 'snow_smart_update_set',
294
+ description: 'Smart update set creation with context detection - automatically creates new update sets for new tasks',
295
+ inputSchema: {
296
+ type: 'object',
297
+ properties: {
298
+ detect_context: { type: 'boolean', description: 'Auto-detect task context change', default: true },
299
+ name_prefix: { type: 'string', description: 'Update set name prefix', default: 'AUTO' },
300
+ separate_by_task: { type: 'boolean', description: 'Create new update set for each task', default: true },
301
+ close_previous: { type: 'boolean', description: 'Close previous update set', default: true },
302
+ description: { type: 'string', description: 'Update set description' },
303
+ },
304
+ },
305
+ },
306
+ {
307
+ name: 'snow_validate_flow_definition',
308
+ description: 'Validate flow definition before deployment with preview and test mode',
309
+ inputSchema: {
310
+ type: 'object',
311
+ properties: {
312
+ definition: { type: 'string', description: 'Flow definition JSON to validate' },
313
+ flow_type: { type: 'string', enum: ['flow', 'subflow', 'action'], default: 'flow' },
314
+ show_preview: { type: 'boolean', description: 'Show visual preview', default: true },
315
+ test_mode: { type: 'boolean', description: 'Run in test mode', default: false },
316
+ check_dependencies: { type: 'boolean', description: 'Check for missing dependencies', default: true },
317
+ },
318
+ required: ['definition'],
319
+ },
320
+ },
321
+ {
322
+ name: 'snow_create_solution_package',
323
+ description: 'Create a solution package grouping related artifacts with a new update set',
324
+ inputSchema: {
325
+ type: 'object',
326
+ properties: {
327
+ name: { type: 'string', description: 'Solution package name' },
328
+ description: { type: 'string', description: 'Package description' },
329
+ artifacts: {
330
+ type: 'array',
331
+ description: 'Artifacts to include in the package',
332
+ items: {
333
+ type: 'object',
334
+ properties: {
335
+ type: { type: 'string', enum: ['flow', 'widget', 'script_include', 'business_rule', 'table'] },
336
+ create: { type: 'object', description: 'Artifact creation configuration' },
337
+ },
338
+ },
339
+ },
340
+ new_update_set: { type: 'boolean', description: 'Force new update set', default: true },
341
+ },
342
+ required: ['name', 'artifacts'],
343
+ },
344
+ },
345
+ {
346
+ name: 'snow_flow_wizard',
347
+ description: 'Interactive flow creation wizard with step-by-step guidance',
348
+ inputSchema: {
349
+ type: 'object',
350
+ properties: {
351
+ name: { type: 'string', description: 'Flow name' },
352
+ interactive: { type: 'boolean', description: 'Enable interactive mode', default: true },
353
+ preview_each_step: { type: 'boolean', description: 'Preview after each step', default: true },
354
+ test_as_you_build: { type: 'boolean', description: 'Test flow during creation', default: true },
355
+ flow_type: { type: 'string', enum: ['flow', 'subflow', 'action'], default: 'flow' },
356
+ },
357
+ required: ['name'],
358
+ },
359
+ },
290
360
  ],
291
361
  }));
292
362
  this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
@@ -324,6 +394,14 @@ class ServiceNowDeploymentMCP {
324
394
  return await this.previewWidget(args);
325
395
  case 'snow_widget_test':
326
396
  return await this.testWidget(args);
397
+ case 'snow_smart_update_set':
398
+ return await this.smartUpdateSet(args);
399
+ case 'snow_validate_flow_definition':
400
+ return await this.validateFlowDefinition(args);
401
+ case 'snow_create_solution_package':
402
+ return await this.createSolutionPackage(args);
403
+ case 'snow_flow_wizard':
404
+ return await this.flowWizard(args);
327
405
  default:
328
406
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
329
407
  }
@@ -764,7 +842,30 @@ Use \`snow_deployment_debug\` for more information about this session.`,
764
842
  ],
765
843
  };
766
844
  }
767
- this.logger.info('Deploying Flow Designer flow to ServiceNow', { name: args.name });
845
+ const flowType = args.flow_type || 'flow';
846
+ this.logger.info(`Deploying ${flowType} to ServiceNow`, { name: args.name, type: flowType });
847
+ // Validate flow definition first if requested
848
+ if (args.validate_before_deploy !== false) {
849
+ const validationResult = await this.validateFlowDefinition({
850
+ definition: args.flow_definition,
851
+ flow_type: flowType,
852
+ show_preview: false,
853
+ test_mode: false,
854
+ check_dependencies: true
855
+ });
856
+ // Check if validation failed
857
+ const validationText = validationResult.content?.[0]?.text || '';
858
+ if (validationText.includes('āŒ') || validationText.includes('ERROR')) {
859
+ return {
860
+ content: [
861
+ {
862
+ type: 'text',
863
+ text: `āŒ Flow validation failed. Please fix the following issues:\n\n${validationText}\n\nUse snow_validate_flow_definition to preview and test your flow before deployment.`
864
+ }
865
+ ]
866
+ };
867
+ }
868
+ }
768
869
  // Ensure Update Set is active
769
870
  const { updateSetId, updateSetName } = await this.ensureUpdateSet('Flow', args.name);
770
871
  // Check if this is a master flow with linked artifacts
@@ -804,14 +905,11 @@ Use \`snow_deployment_debug\` for more information about this session.`,
804
905
  return activity;
805
906
  });
806
907
  }
807
- // Create Flow Designer flow in ServiceNow with enhanced structure
908
+ // Create flow data based on flow type
808
909
  const flowData = {
809
910
  name: args.name,
810
911
  description: args.description,
811
912
  active: args.active !== false,
812
- table: args.table || '',
813
- trigger_type: args.trigger_type,
814
- condition: args.condition || '',
815
913
  flow_definition: JSON.stringify(flowDefinition),
816
914
  category: args.category || 'automation',
817
915
  // Additional fields for composed flows
@@ -819,8 +917,43 @@ Use \`snow_deployment_debug\` for more information about this session.`,
819
917
  linked_artifact_count: linkedArtifacts.length,
820
918
  artifact_references: deployedArtifacts.map(a => a.sys_id).join(',')
821
919
  };
822
- // Deploy to ServiceNow using Flow Designer API
823
- const result = await this.client.createFlow(flowData);
920
+ // Configure based on flow type
921
+ switch (flowType) {
922
+ case 'flow':
923
+ flowData.table = args.table || '';
924
+ flowData.trigger_type = args.trigger_type;
925
+ flowData.condition = args.condition || '';
926
+ flowData.type = 'flow';
927
+ break;
928
+ case 'subflow':
929
+ // Subflows don't have triggers, they're called by other flows
930
+ flowData.type = 'subflow';
931
+ flowData.inputs = flowDefinition.inputs || [];
932
+ flowData.outputs = flowDefinition.outputs || [];
933
+ break;
934
+ case 'action':
935
+ // Actions are reusable components
936
+ flowData.type = 'action';
937
+ flowData.action_type = args.action_type || 'custom';
938
+ flowData.inputs = flowDefinition.inputs || [];
939
+ flowData.outputs = flowDefinition.outputs || [];
940
+ break;
941
+ }
942
+ // Deploy to ServiceNow using appropriate API based on flow type
943
+ let result;
944
+ switch (flowType) {
945
+ case 'flow':
946
+ result = await this.client.createFlow(flowData);
947
+ break;
948
+ case 'subflow':
949
+ result = await this.client.createSubflow(flowData);
950
+ break;
951
+ case 'action':
952
+ result = await this.client.createFlowAction(flowData);
953
+ break;
954
+ default:
955
+ throw new Error(`Unknown flow type: ${flowType}`);
956
+ }
824
957
  const credentials = await this.oauth.loadCredentials();
825
958
  const flowUrl = result.success && result.data
826
959
  ? `https://${credentials?.instance}/$flow-designer.do#/flow/${result.data.sys_id}`
@@ -837,11 +970,14 @@ Use \`snow_deployment_debug\` for more information about this session.`,
837
970
  type: 'text',
838
971
  text: `āœ… Flow Designer flow deployed successfully!
839
972
 
840
- šŸ”„ **Flow Details:**
973
+ šŸ”„ **${flowType.charAt(0).toUpperCase() + flowType.slice(1)} Details:**
841
974
  - Name: ${args.name}
842
- - Type: ${isComposedFlow ? '🧠 Intelligent Composed Flow' : 'šŸ“‹ Standard Flow'}
843
- - Trigger Type: ${args.trigger_type}
844
- - Table: ${args.table || 'N/A'}
975
+ - Flow Type: ${flowType === 'flow' ? 'šŸ“‹ Flow' : flowType === 'subflow' ? 'šŸ”„ Subflow' : '⚔ Action'}
976
+ - Composed: ${isComposedFlow ? '🧠 Yes - Intelligent Composed Flow' : 'āŒ No - Standard'}
977
+ ${flowType === 'flow' ? `- Trigger Type: ${args.trigger_type}
978
+ - Table: ${args.table || 'N/A'}` : ''}
979
+ ${flowType !== 'flow' ? `- Inputs: ${flowDefinition.inputs?.length || 0}
980
+ - Outputs: ${flowDefinition.outputs?.length || 0}` : ''}
845
981
  - Category: ${args.category || 'automation'}
846
982
  - Active: ${args.active !== false ? 'Yes' : 'No'}
847
983
 
@@ -2053,6 +2189,363 @@ Use \`snow_preview_widget\` to see a detailed preview of the widget rendering.`,
2053
2189
  }
2054
2190
  return recommendations.length > 0 ? recommendations.join('\n') : 'Widget structure looks good!';
2055
2191
  }
2192
+ /**
2193
+ * Smart Update Set Management with context detection
2194
+ */
2195
+ async smartUpdateSet(args) {
2196
+ try {
2197
+ // Check authentication
2198
+ const isAuth = await this.oauth.isAuthenticated();
2199
+ if (!isAuth) {
2200
+ return {
2201
+ content: [
2202
+ {
2203
+ type: 'text',
2204
+ text: 'āŒ Not authenticated with ServiceNow.\n\nPlease run: snow-flow auth login',
2205
+ },
2206
+ ],
2207
+ };
2208
+ }
2209
+ // Get current context (task identifier)
2210
+ const taskContext = args.description || 'Current Task';
2211
+ const contextKey = `task_context_${taskContext.replace(/\s+/g, '_').toLowerCase()}`;
2212
+ // Check if we need a new update set
2213
+ const currentUpdateSet = await this.client.getCurrentUpdateSet();
2214
+ let needNewUpdateSet = true;
2215
+ if (currentUpdateSet.success && currentUpdateSet.data) {
2216
+ // Check if current update set is for the same task
2217
+ if (!args.separate_by_task || currentUpdateSet.data.description?.includes(taskContext)) {
2218
+ needNewUpdateSet = false;
2219
+ }
2220
+ }
2221
+ if (!needNewUpdateSet && currentUpdateSet.data) {
2222
+ return {
2223
+ content: [
2224
+ {
2225
+ type: 'text',
2226
+ text: `āœ… Using existing Update Set for this task:\n\nšŸ“¦ **Current Update Set:**\n- Name: ${currentUpdateSet.data.name}\n- ID: ${currentUpdateSet.data.sys_id}\n- Description: ${currentUpdateSet.data.description}\n\nšŸ’” Same task context detected - no new Update Set needed.`
2227
+ }
2228
+ ]
2229
+ };
2230
+ }
2231
+ // Close previous update set if requested
2232
+ if (args.close_previous && currentUpdateSet.data) {
2233
+ await this.client.completeUpdateSet(currentUpdateSet.data.sys_id);
2234
+ this.logger.info('Closed previous Update Set', { id: currentUpdateSet.data.sys_id });
2235
+ }
2236
+ // Create new update set
2237
+ const updateSetNumber = Date.now().toString().slice(-6);
2238
+ const updateSetName = `${args.name_prefix}-${updateSetNumber}: ${taskContext}`;
2239
+ const result = await this.client.createUpdateSet({
2240
+ name: updateSetName,
2241
+ description: `Auto-created for task: ${taskContext}\n\nContext Detection: ${args.detect_context ? 'Enabled' : 'Disabled'}\nSeparate by Task: ${args.separate_by_task ? 'Yes' : 'No'}`,
2242
+ state: 'in_progress'
2243
+ });
2244
+ if (!result.success) {
2245
+ throw new Error(`Failed to create Update Set: ${result.error}`);
2246
+ }
2247
+ // Set as current update set
2248
+ await this.client.setCurrentUpdateSet(result.data.sys_id);
2249
+ const credentials = await this.oauth.loadCredentials();
2250
+ const updateSetUrl = `https://${credentials?.instance}/sys_update_set.do?sys_id=${result.data.sys_id}`;
2251
+ return {
2252
+ content: [
2253
+ {
2254
+ type: 'text',
2255
+ text: `āœ… Smart Update Set created successfully!\n\nšŸ“¦ **New Update Set:**\n- Name: ${updateSetName}\n- ID: ${result.data.sys_id}\n- Task Context: ${taskContext}\n\nšŸ”§ **Smart Features:**\n- Context Detection: ${args.detect_context ? 'āœ… Enabled' : 'āŒ Disabled'}\n- Separate by Task: ${args.separate_by_task ? 'āœ… Yes' : 'āŒ No'}\n- Auto-close Previous: ${args.close_previous ? 'āœ… Yes' : 'āŒ No'}\n${currentUpdateSet.data && args.close_previous ? `- Previous Set Closed: āœ… ${currentUpdateSet.data.name}` : ''}\n\nšŸ”— **Direct Link:**\n${updateSetUrl}\n\nšŸ’” **Next Steps:**\n1. All new changes will be tracked in this Update Set\n2. Deploy your artifacts - they'll be automatically included\n3. Complete the Update Set when your task is done\n4. Next task will get its own Update Set automatically`
2256
+ }
2257
+ ]
2258
+ };
2259
+ }
2260
+ catch (error) {
2261
+ throw new Error(`Smart Update Set creation failed: ${error instanceof Error ? error.message : String(error)}`);
2262
+ }
2263
+ }
2264
+ /**
2265
+ * Validate Flow Definition before deployment
2266
+ */
2267
+ async validateFlowDefinition(args) {
2268
+ try {
2269
+ const flowType = args.flow_type || 'flow';
2270
+ let definition;
2271
+ try {
2272
+ definition = typeof args.definition === 'string' ? JSON.parse(args.definition) : args.definition;
2273
+ }
2274
+ catch (error) {
2275
+ return {
2276
+ content: [
2277
+ {
2278
+ type: 'text',
2279
+ text: `āŒ Invalid JSON format in flow definition:\n\n${error instanceof Error ? error.message : String(error)}\n\nšŸ’” Please check your JSON syntax.`
2280
+ }
2281
+ ]
2282
+ };
2283
+ }
2284
+ const issues = [];
2285
+ const warnings = [];
2286
+ const info = [];
2287
+ // Basic structure validation
2288
+ if (!definition.activities || !Array.isArray(definition.activities)) {
2289
+ issues.push('āŒ Missing or invalid "activities" array');
2290
+ }
2291
+ // Flow type specific validation
2292
+ switch (flowType) {
2293
+ case 'flow':
2294
+ if (!definition.trigger && !args.trigger_type) {
2295
+ issues.push('āŒ Flow must have a trigger defined');
2296
+ }
2297
+ break;
2298
+ case 'subflow':
2299
+ if (!definition.inputs) {
2300
+ warnings.push('āš ļø Subflow has no inputs defined');
2301
+ }
2302
+ if (!definition.outputs) {
2303
+ warnings.push('āš ļø Subflow has no outputs defined');
2304
+ }
2305
+ break;
2306
+ case 'action':
2307
+ if (!definition.action_type) {
2308
+ warnings.push('āš ļø Action type not specified');
2309
+ }
2310
+ break;
2311
+ }
2312
+ // Activity validation
2313
+ if (definition.activities) {
2314
+ definition.activities.forEach((activity, index) => {
2315
+ if (!activity.name) {
2316
+ issues.push(`āŒ Activity ${index + 1} missing required "name" field`);
2317
+ }
2318
+ if (!activity.type) {
2319
+ issues.push(`āŒ Activity ${index + 1} missing required "type" field`);
2320
+ }
2321
+ // Check for common activity types
2322
+ const validTypes = ['rest', 'script', 'approval', 'condition', 'subflow', 'notification', 'wait', 'lookup'];
2323
+ if (activity.type && !validTypes.includes(activity.type)) {
2324
+ warnings.push(`āš ļø Activity "${activity.name}" uses non-standard type: ${activity.type}`);
2325
+ }
2326
+ });
2327
+ }
2328
+ // Dependency checking
2329
+ if (args.check_dependencies) {
2330
+ const dependencies = this.extractDependencies(definition);
2331
+ if (dependencies.length > 0) {
2332
+ info.push(`šŸ“¦ Dependencies found: ${dependencies.join(', ')}`);
2333
+ }
2334
+ }
2335
+ // Generate preview if requested
2336
+ let preview = '';
2337
+ if (args.show_preview) {
2338
+ preview = this.generateFlowPreview(definition, flowType);
2339
+ }
2340
+ const hasErrors = issues.length > 0;
2341
+ const status = hasErrors ? 'āŒ VALIDATION FAILED' : 'āœ… VALIDATION PASSED';
2342
+ return {
2343
+ content: [
2344
+ {
2345
+ type: 'text',
2346
+ text: `${status}\n\nšŸ“‹ **Flow Validation Report:**\n- Flow Type: ${flowType}\n- Activities: ${definition.activities?.length || 0}\n- Status: ${hasErrors ? 'Failed' : 'Passed'}\n\n${issues.length > 0 ? `🚨 **Critical Issues:**\n${issues.join('\n')}\n\n` : ''}${warnings.length > 0 ? `āš ļø **Warnings:**\n${warnings.join('\n')}\n\n` : ''}${info.length > 0 ? `ā„¹ļø **Information:**\n${info.join('\n')}\n\n` : ''}${preview ? `\nšŸ“Š **Flow Preview:**\n${preview}\n` : ''}${!hasErrors && args.test_mode ? '\n🧪 **Test Mode:** Flow structure is valid for testing\n' : ''}${!hasErrors ? '\nāœ… Flow definition is valid and ready for deployment!' : '\nāŒ Please fix the issues before deploying.'}`
2347
+ }
2348
+ ]
2349
+ };
2350
+ }
2351
+ catch (error) {
2352
+ throw new Error(`Flow validation failed: ${error instanceof Error ? error.message : String(error)}`);
2353
+ }
2354
+ }
2355
+ /**
2356
+ * Create Solution Package grouping multiple artifacts
2357
+ */
2358
+ async createSolutionPackage(args) {
2359
+ try {
2360
+ // Check authentication
2361
+ const isAuth = await this.oauth.isAuthenticated();
2362
+ if (!isAuth) {
2363
+ return {
2364
+ content: [
2365
+ {
2366
+ type: 'text',
2367
+ text: 'āŒ Not authenticated with ServiceNow.\n\nPlease run: snow-flow auth login',
2368
+ },
2369
+ ],
2370
+ };
2371
+ }
2372
+ // Create new update set for the solution
2373
+ if (args.new_update_set) {
2374
+ const updateSetResult = await this.smartUpdateSet({
2375
+ detect_context: true,
2376
+ name_prefix: 'SOLUTION',
2377
+ description: args.description || `Solution Package: ${args.name}`,
2378
+ separate_by_task: false,
2379
+ close_previous: true
2380
+ });
2381
+ }
2382
+ const deployedArtifacts = [];
2383
+ const failedArtifacts = [];
2384
+ // Deploy each artifact in the package
2385
+ for (const artifact of args.artifacts) {
2386
+ try {
2387
+ let result;
2388
+ switch (artifact.type) {
2389
+ case 'flow':
2390
+ result = await this.deployFlow(artifact.create);
2391
+ break;
2392
+ case 'widget':
2393
+ result = await this.deployWidget(artifact.create);
2394
+ break;
2395
+ case 'script_include':
2396
+ result = await this.deployScriptInclude(artifact.create);
2397
+ break;
2398
+ case 'business_rule':
2399
+ result = await this.deployBusinessRule(artifact.create);
2400
+ break;
2401
+ case 'table':
2402
+ result = await this.deployTable(artifact.create);
2403
+ break;
2404
+ default:
2405
+ throw new Error(`Unknown artifact type: ${artifact.type}`);
2406
+ }
2407
+ deployedArtifacts.push({
2408
+ type: artifact.type,
2409
+ name: artifact.create.name,
2410
+ result: 'Success'
2411
+ });
2412
+ }
2413
+ catch (error) {
2414
+ failedArtifacts.push({
2415
+ type: artifact.type,
2416
+ name: artifact.create.name,
2417
+ error: error instanceof Error ? error.message : String(error)
2418
+ });
2419
+ }
2420
+ }
2421
+ const successCount = deployedArtifacts.length;
2422
+ const failureCount = failedArtifacts.length;
2423
+ const totalCount = successCount + failureCount;
2424
+ return {
2425
+ content: [
2426
+ {
2427
+ type: 'text',
2428
+ text: `šŸ“¦ **Solution Package Deployment Complete!**\n\nšŸŽÆ **Package Details:**\n- Name: ${args.name}\n- Description: ${args.description || 'N/A'}\n- Total Artifacts: ${totalCount}\n- Successful: ${successCount} āœ…\n- Failed: ${failureCount} ${failureCount > 0 ? 'āŒ' : ''}\n\n${deployedArtifacts.length > 0 ? `āœ… **Successfully Deployed:**\n${deployedArtifacts.map((a, i) => `${i + 1}. ${a.type}: ${a.name}`).join('\n')}\n` : ''}${failedArtifacts.length > 0 ? `\nāŒ **Failed Deployments:**\n${failedArtifacts.map((a, i) => `${i + 1}. ${a.type}: ${a.name}\n Error: ${a.error}`).join('\n')}\n` : ''}\nšŸ’” **Solution Benefits:**\n- All artifacts grouped in one Update Set\n- Dependencies automatically resolved\n- Consistent deployment across artifacts\n- Easy rollback if needed\n\n${successCount === totalCount ? 'šŸŽ‰ All artifacts deployed successfully!' : 'āš ļø Some artifacts failed. Please review the errors above.'}`
2429
+ }
2430
+ ]
2431
+ };
2432
+ }
2433
+ catch (error) {
2434
+ throw new Error(`Solution package creation failed: ${error instanceof Error ? error.message : String(error)}`);
2435
+ }
2436
+ }
2437
+ /**
2438
+ * Interactive Flow Creation Wizard
2439
+ */
2440
+ async flowWizard(args) {
2441
+ try {
2442
+ const flowType = args.flow_type || 'flow';
2443
+ const steps = [];
2444
+ // Step 1: Basic Information
2445
+ steps.push({
2446
+ step: 1,
2447
+ name: 'Basic Information',
2448
+ status: 'āœ…',
2449
+ details: `Name: ${args.name}\nType: ${flowType}\nDescription: Configure your flow step by step`
2450
+ });
2451
+ // Step 2: Trigger Configuration (for flows only)
2452
+ if (flowType === 'flow') {
2453
+ steps.push({
2454
+ step: 2,
2455
+ name: 'Trigger Configuration',
2456
+ status: 'šŸ“',
2457
+ details: 'Choose trigger type: record_created, record_updated, scheduled, or manual'
2458
+ });
2459
+ }
2460
+ // Step 3: Activities
2461
+ steps.push({
2462
+ step: 3,
2463
+ name: 'Add Activities',
2464
+ status: 'šŸ“',
2465
+ details: 'Add activities: scripts, approvals, notifications, conditions'
2466
+ });
2467
+ // Step 4: Variables and Data
2468
+ steps.push({
2469
+ step: 4,
2470
+ name: 'Variables & Data',
2471
+ status: 'šŸ“',
2472
+ details: 'Define flow variables and data transformations'
2473
+ });
2474
+ // Step 5: Error Handling
2475
+ steps.push({
2476
+ step: 5,
2477
+ name: 'Error Handling',
2478
+ status: 'šŸ“',
2479
+ details: 'Configure error handlers and retry logic'
2480
+ });
2481
+ // Step 6: Testing
2482
+ steps.push({
2483
+ step: 6,
2484
+ name: 'Test Flow',
2485
+ status: 'šŸ“',
2486
+ details: 'Test with sample data before deployment'
2487
+ });
2488
+ // Generate wizard interface
2489
+ const wizardText = `šŸ§™ā€ā™‚ļø **Flow Creation Wizard**\n\nšŸ“‹ **Flow Details:**\n- Name: ${args.name}\n- Type: ${flowType}\n- Interactive: ${args.interactive ? 'āœ…' : 'āŒ'}\n- Preview Each Step: ${args.preview_each_step ? 'āœ…' : 'āŒ'}\n- Test As You Build: ${args.test_as_you_build ? 'āœ…' : 'āŒ'}\n\nšŸ“Š **Wizard Steps:**\n${steps.map(s => `${s.step}. ${s.status} ${s.name}\n ${s.details}`).join('\n\n')}\n\nšŸ’” **Interactive Features:**\n- āœ… Step-by-step guidance\n- āœ… Preview after each step\n- āœ… Validation at each stage\n- āœ… Test before deployment\n- āœ… Rollback capability\n\nšŸŽÆ **Next Actions:**\n1. Use snow_deploy_flow with your configuration\n2. Or continue building with individual artifact tools\n3. Test with snow_validate_flow_definition\n\n⚔ **Quick Start Example:**\n\`\`\`json\n{\n "name": "${args.name}",\n "flow_type": "${flowType}",\n "trigger_type": "record_created",\n "table": "incident",\n "flow_definition": {\n "activities": [\n {\n "name": "Check Priority",\n "type": "condition",\n "condition": "current.priority == 1"\n },\n {\n "name": "Send Alert",\n "type": "notification",\n "recipients": "incident.assigned_to"\n }\n ]\n }\n}\n\`\`\``;
2490
+ return {
2491
+ content: [
2492
+ {
2493
+ type: 'text',
2494
+ text: wizardText
2495
+ }
2496
+ ]
2497
+ };
2498
+ }
2499
+ catch (error) {
2500
+ throw new Error(`Flow wizard failed: ${error instanceof Error ? error.message : String(error)}`);
2501
+ }
2502
+ }
2503
+ /**
2504
+ * Extract dependencies from flow definition
2505
+ */
2506
+ extractDependencies(definition) {
2507
+ const dependencies = new Set();
2508
+ if (definition.activities) {
2509
+ definition.activities.forEach((activity) => {
2510
+ if (activity.type === 'rest' && activity.rest_message) {
2511
+ dependencies.add(`REST Message: ${activity.rest_message}`);
2512
+ }
2513
+ if (activity.type === 'script' && activity.script_include) {
2514
+ dependencies.add(`Script Include: ${activity.script_include}`);
2515
+ }
2516
+ if (activity.type === 'subflow' && activity.subflow_name) {
2517
+ dependencies.add(`Subflow: ${activity.subflow_name}`);
2518
+ }
2519
+ if (activity.artifact_reference) {
2520
+ dependencies.add(`${activity.artifact_reference.type}: ${activity.artifact_reference.name}`);
2521
+ }
2522
+ });
2523
+ }
2524
+ return Array.from(dependencies);
2525
+ }
2526
+ /**
2527
+ * Generate visual preview of flow
2528
+ */
2529
+ generateFlowPreview(definition, flowType) {
2530
+ let preview = `\n${flowType.toUpperCase()} STRUCTURE:\n`;
2531
+ preview += '═'.repeat(40) + '\n';
2532
+ if (flowType === 'flow' && definition.trigger) {
2533
+ preview += `\n[TRIGGER: ${definition.trigger.type || 'Unknown'}]\n ↓\n`;
2534
+ }
2535
+ if (definition.activities) {
2536
+ definition.activities.forEach((activity, index) => {
2537
+ const isLast = index === definition.activities.length - 1;
2538
+ preview += `[${activity.type?.toUpperCase() || 'UNKNOWN'}: ${activity.name || `Activity ${index + 1}`}]\n`;
2539
+ if (!isLast) {
2540
+ preview += ' ↓\n';
2541
+ }
2542
+ });
2543
+ }
2544
+ if (flowType !== 'flow' && definition.outputs) {
2545
+ preview += `\n[OUTPUTS: ${definition.outputs.length} defined]\n`;
2546
+ }
2547
+ return preview;
2548
+ }
2056
2549
  async start() {
2057
2550
  const transport = new stdio_js_1.StdioServerTransport();
2058
2551
  await this.server.connect(transport);