snow-flow 3.5.13 → 3.5.15

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 CHANGED
@@ -2462,6 +2462,7 @@ async function createMCPConfig(targetDir, force = false) {
2462
2462
  "servicenow-system-properties",
2463
2463
  "servicenow-update-set",
2464
2464
  "servicenow-development-assistant",
2465
+ "servicenow-local-development",
2465
2466
  "servicenow-security-compliance",
2466
2467
  "servicenow-reporting-analytics",
2467
2468
  "servicenow-machine-learning",
@@ -2473,7 +2474,90 @@ async function createMCPConfig(targetDir, force = false) {
2473
2474
  ],
2474
2475
  "permissions": {
2475
2476
  "allow": [
2476
- "Bash(*)",
2477
+ // Snow-Flow Core Commands
2478
+ "Bash(npx snow-flow *)",
2479
+ "Bash(snow-flow *)",
2480
+ "Bash(./snow-flow *)",
2481
+ // Development Commands
2482
+ "Bash(npm run *)",
2483
+ "Bash(npm install *)",
2484
+ "Bash(npm update *)",
2485
+ "Bash(npm test *)",
2486
+ "Bash(npm run lint)",
2487
+ "Bash(npm run build)",
2488
+ "Bash(npm run dev)",
2489
+ "Bash(npm start)",
2490
+ "Bash(yarn *)",
2491
+ "Bash(pnpm *)",
2492
+ // Git Operations
2493
+ "Bash(git status)",
2494
+ "Bash(git diff *)",
2495
+ "Bash(git log *)",
2496
+ "Bash(git add *)",
2497
+ "Bash(git commit *)",
2498
+ "Bash(git push *)",
2499
+ "Bash(git pull *)",
2500
+ "Bash(git branch *)",
2501
+ "Bash(git checkout *)",
2502
+ "Bash(git merge *)",
2503
+ "Bash(git config *)",
2504
+ "Bash(git remote *)",
2505
+ // GitHub CLI
2506
+ "Bash(gh *)",
2507
+ // Node.js and System Commands
2508
+ "Bash(node *)",
2509
+ "Bash(npm *)",
2510
+ "Bash(npx *)",
2511
+ "Bash(which *)",
2512
+ "Bash(pwd)",
2513
+ "Bash(ls *)",
2514
+ "Bash(cd *)",
2515
+ "Bash(mkdir *)",
2516
+ "Bash(rm *)",
2517
+ "Bash(cp *)",
2518
+ "Bash(mv *)",
2519
+ "Bash(find *)",
2520
+ "Bash(grep *)",
2521
+ "Bash(cat *)",
2522
+ "Bash(head *)",
2523
+ "Bash(tail *)",
2524
+ "Bash(less *)",
2525
+ "Bash(more *)",
2526
+ // API Testing and Network
2527
+ "Bash(curl *)",
2528
+ "Bash(wget *)",
2529
+ "Bash(ping *)",
2530
+ "Bash(telnet *)",
2531
+ "Bash(nc *)",
2532
+ "Bash(netstat *)",
2533
+ // JSON and Data Processing
2534
+ "Bash(jq *)",
2535
+ "Bash(awk *)",
2536
+ "Bash(sed *)",
2537
+ "Bash(sort *)",
2538
+ "Bash(uniq *)",
2539
+ "Bash(wc *)",
2540
+ // Process and System Monitoring
2541
+ "Bash(ps *)",
2542
+ "Bash(top)",
2543
+ "Bash(htop)",
2544
+ "Bash(lsof *)",
2545
+ "Bash(df *)",
2546
+ "Bash(du *)",
2547
+ "Bash(free *)",
2548
+ "Bash(uptime)",
2549
+ // Environment
2550
+ "Bash(env)",
2551
+ "Bash(export *)",
2552
+ "Bash(echo *)",
2553
+ "Bash(printenv *)",
2554
+ // Docker (if used)
2555
+ "Bash(docker *)",
2556
+ "Bash(docker-compose *)",
2557
+ // ServiceNow CLI (if exists)
2558
+ "Bash(sn *)",
2559
+ "Bash(snc *)",
2560
+ // File Operations - Claude Code Tools
2477
2561
  "Read(*)",
2478
2562
  "Write(*)",
2479
2563
  "Edit(*)",
@@ -2490,10 +2574,37 @@ async function createMCPConfig(targetDir, force = false) {
2490
2574
  "Task(*)",
2491
2575
  "ListMcpResourcesTool",
2492
2576
  "ReadMcpResourceTool",
2577
+ // MCP Tools - All ServiceNow Servers
2493
2578
  "mcp__servicenow-*",
2494
2579
  "mcp__snow-flow__*"
2495
2580
  ],
2496
- "deny": []
2581
+ "deny": [
2582
+ "Bash(rm -rf /)",
2583
+ "Bash(sudo rm *)",
2584
+ "Bash(sudo *)"
2585
+ ]
2586
+ },
2587
+ "hooks": {
2588
+ "PreCompact": [
2589
+ {
2590
+ "matcher": "manual",
2591
+ "hooks": [
2592
+ {
2593
+ "type": "command",
2594
+ "command": "/bin/bash -c 'INPUT=$(cat); CUSTOM=$(echo \"$INPUT\" | jq -r \".custom_instructions // \\\"\\\"\"); echo \"🔄 PreCompact Guidance:\"; echo \"📋 IMPORTANT: Review CLAUDE.md in project root for:\"; echo \" • 18+ MCP servers and snow_pull_artifact for widget debugging\"; echo \" • Swarm coordination strategies (hierarchical, mesh, adaptive)\"; echo \" • SPARC methodology workflows with batchtools optimization\"; echo \" • Critical concurrent execution rules (GOLDEN RULE: 1 MESSAGE = ALL OPERATIONS)\"; if [ -n \"$CUSTOM\" ]; then echo \"🎯 Custom compact instructions: $CUSTOM\"; fi; echo \"✅ Ready for compact operation\"'"
2595
+ }
2596
+ ]
2597
+ },
2598
+ {
2599
+ "matcher": "auto",
2600
+ "hooks": [
2601
+ {
2602
+ "type": "command",
2603
+ "command": "/bin/bash -c 'echo \"🔄 Auto-Compact Guidance (Context Window Full):\"; echo \"📋 CRITICAL: Before compacting, ensure you understand:\"; echo \" • All 18+ MCP servers including servicenow-local-development\"; echo \" • Use snow_pull_artifact for widget debugging (NOT snow_query_table)\"; echo \" • Concurrent execution patterns from CLAUDE.md\"; echo \" • Batchtools optimization for 300% performance gains\"; echo \" • Swarm coordination strategies for complex tasks\"; echo \"⚡ Apply GOLDEN RULE: Always batch operations in single messages\"; echo \"✅ Auto-compact proceeding with full agent context\"'"
2604
+ }
2605
+ ]
2606
+ }
2607
+ ]
2497
2608
  },
2498
2609
  "env": {
2499
2610
  "BASH_DEFAULT_TIMEOUT_MS": "0",
@@ -2508,12 +2619,16 @@ async function createMCPConfig(targetDir, force = false) {
2508
2619
  "CLAUDE_CODE_MAX_OUTPUT_TOKENS": "32000",
2509
2620
  "CLAUDE_CODE_TIMEOUT": "0",
2510
2621
  "CLAUDE_CODE_SESSION_TIMEOUT": "0",
2511
- "CLAUDE_CODE_EXECUTION_TIMEOUT": "0"
2622
+ "CLAUDE_CODE_EXECUTION_TIMEOUT": "0",
2623
+ "SNOW_FLOW_DEBUG": "false",
2624
+ "SNOW_FLOW_LOG_LEVEL": "info",
2625
+ "MCP_DEBUG": "false",
2626
+ "NODE_ENV": "development"
2512
2627
  },
2513
2628
  "cleanupPeriodDays": 90,
2514
2629
  "includeCoAuthoredBy": true
2515
- // Removed invalid properties: automation, snowFlow, mcpServers
2516
- // These were causing "Property X is not allowed" errors in Claude Code
2630
+ // Snow-Flow v3.5.13+ optimized settings with servicenow-local-development
2631
+ // Comprehensive permissions for Snow-Flow development workflow
2517
2632
  };
2518
2633
  const claudeSettingsPath = (0, path_1.join)(targetDir, '.claude/settings.json');
2519
2634
  await fs_1.promises.writeFile(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
@@ -31,6 +31,8 @@ export interface LocalFile {
31
31
  currentContent?: string;
32
32
  isModified: boolean;
33
33
  fieldMapping?: FieldMapping;
34
+ existedBefore?: boolean;
35
+ previousContent?: string;
34
36
  }
35
37
  export declare class ArtifactLocalSync {
36
38
  private baseDir;
@@ -84,9 +86,21 @@ export declare class ArtifactLocalSync {
84
86
  */
85
87
  private validateES5;
86
88
  /**
87
- * Strip headers/footers we added - now uses field mapping for accuracy
89
+ * Strip headers/footers we added - FIXED to use actual fieldMapping wrappers
88
90
  */
89
91
  private stripAddedWrappers;
92
+ /**
93
+ * Create regex pattern from wrapper text, handling placeholders
94
+ */
95
+ private escapeRegexAndCreatePattern;
96
+ /**
97
+ * Fallback: Strip generic comments when no fieldMapping available
98
+ */
99
+ private stripGenericComments;
100
+ /**
101
+ * INTELLIGENT WRAPPER DETECTION: Check if content actually needs wrappers
102
+ */
103
+ private needsWrappers;
90
104
  /**
91
105
  * Sanitize filename for filesystem
92
106
  */
@@ -127,6 +127,7 @@ class ArtifactLocalSync {
127
127
  throw new Error(`Unsupported artifact type: ${tableName}. Supported types: ${Object.keys(artifact_registry_1.ARTIFACT_REGISTRY).join(', ')}`);
128
128
  }
129
129
  console.log(`\n🔄 Pulling ${config.displayName} (${sys_id}) to local files...`);
130
+ console.log(`📋 Snow-Flow v3.5.15 - Intelligent Wrapper System Active`);
130
131
  // Get timeout configuration
131
132
  const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
132
133
  // Use smart fetcher for known types, otherwise direct query
@@ -186,9 +187,17 @@ class ArtifactLocalSync {
186
187
  .replace('{name}', sanitizedName)
187
188
  .replace('{api_name}', artifactData.api_name || sanitizedName)
188
189
  .replace('{short_description}', artifactData.short_description || sanitizedName);
189
- // Generate header/footer with replacements
190
- const header = this.replacePlaceholders(mapping.wrapperHeader || '', artifactData);
191
- const footer = this.replacePlaceholders(mapping.wrapperFooter || '', artifactData);
190
+ // INTELLIGENT WRAPPER SYSTEM: Only add wrappers if actually needed
191
+ let header = '';
192
+ let footer = '';
193
+ if (mapping.wrapperHeader && mapping.wrapperFooter && this.needsWrappers(processedContent, mapping)) {
194
+ header = this.replacePlaceholders(mapping.wrapperHeader, artifactData);
195
+ footer = this.replacePlaceholders(mapping.wrapperFooter, artifactData);
196
+ console.log(` 🔧 Adding wrappers for ${filename} (content needs them)`);
197
+ }
198
+ else if (mapping.wrapperHeader && mapping.wrapperFooter) {
199
+ console.log(` ✅ Skipping wrappers for ${filename} (content is already wrapped)`);
200
+ }
192
201
  const file = this.createLocalFile(artifactPath, `${filename}.${mapping.fileExtension}`, processedContent, mapping.serviceNowField, mapping.fileExtension, header, footer);
193
202
  file.fieldMapping = mapping;
194
203
  files.push(file);
@@ -370,6 +379,31 @@ class ArtifactLocalSync {
370
379
  createLocalFile(dirPath, filename, content, field, type, header = '', footer = '') {
371
380
  const filePath = path.join(dirPath, filename);
372
381
  const fullContent = header + content + footer;
382
+ // CRITICAL FIX: Check if file exists and handle overwrites intelligently
383
+ let fileExists = false;
384
+ let existingContent = '';
385
+ if (fs.existsSync(filePath)) {
386
+ fileExists = true;
387
+ existingContent = fs.readFileSync(filePath, 'utf8');
388
+ // Check if existing content is the same (avoid unnecessary writes)
389
+ if (existingContent === fullContent) {
390
+ console.log(` 📄 Unchanged: ${filename} (identical content, skipping write)`);
391
+ return {
392
+ filename,
393
+ path: filePath,
394
+ field,
395
+ type: type,
396
+ originalContent: content,
397
+ isModified: false
398
+ };
399
+ }
400
+ console.log(` 🔄 Overwriting: ${filename}`);
401
+ console.log(` ℹ️ File size: ${existingContent.length} → ${fullContent.length} chars`);
402
+ }
403
+ else {
404
+ console.log(` 📝 Creating: ${filename}`);
405
+ }
406
+ // Write the file
373
407
  fs.writeFileSync(filePath, fullContent, 'utf8');
374
408
  return {
375
409
  filename,
@@ -377,7 +411,9 @@ class ArtifactLocalSync {
377
411
  field,
378
412
  type: type,
379
413
  originalContent: content,
380
- isModified: false
414
+ isModified: fileExists, // Mark as modified if we overwrote existing file
415
+ existedBefore: fileExists,
416
+ previousContent: existingContent
381
417
  };
382
418
  }
383
419
  /**
@@ -544,29 +580,105 @@ snow-flow sync status ${widget.sys_id}
544
580
  return issues;
545
581
  }
546
582
  /**
547
- * Strip headers/footers we added - now uses field mapping for accuracy
583
+ * Strip headers/footers we added - FIXED to use actual fieldMapping wrappers
548
584
  */
549
585
  stripAddedWrappers(content, type, fieldMapping) {
550
- // Remove our added comments and wrappers
586
+ if (!fieldMapping || !fieldMapping.wrapperHeader || !fieldMapping.wrapperFooter) {
587
+ // No wrappers defined, just remove generic comments
588
+ return this.stripGenericComments(content, type);
589
+ }
590
+ let cleaned = content;
591
+ // Get the actual wrappers that were added (without placeholders)
592
+ const header = fieldMapping.wrapperHeader;
593
+ const footer = fieldMapping.wrapperFooter;
594
+ // CRITICAL FIX: Use the EXACT wrappers from fieldMapping
595
+ if (header && footer) {
596
+ // Create regex patterns from the actual wrappers
597
+ const headerPattern = this.escapeRegexAndCreatePattern(header);
598
+ const footerPattern = this.escapeRegexAndCreatePattern(footer);
599
+ // Remove footer first (from end)
600
+ if (footerPattern) {
601
+ cleaned = cleaned.replace(new RegExp(footerPattern + '$'), '');
602
+ }
603
+ // Remove header (from start)
604
+ if (headerPattern) {
605
+ cleaned = cleaned.replace(new RegExp('^' + headerPattern), '');
606
+ }
607
+ }
608
+ return cleaned.trim();
609
+ }
610
+ /**
611
+ * Create regex pattern from wrapper text, handling placeholders
612
+ */
613
+ escapeRegexAndCreatePattern(wrapper) {
614
+ // Replace placeholders with generic patterns
615
+ let pattern = wrapper
616
+ .replace(/\{name\}/g, '[^}]*') // Replace {name} with pattern to match any name
617
+ .replace(/\{[^}]+\}/g, '[^}]*'); // Replace any other {placeholder}
618
+ // Escape special regex characters
619
+ pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
620
+ // Convert \n back to actual newlines in pattern
621
+ pattern = pattern.replace(/\\n/g, '\\s*\\n\\s*');
622
+ return pattern;
623
+ }
624
+ /**
625
+ * Fallback: Strip generic comments when no fieldMapping available
626
+ */
627
+ stripGenericComments(content, type) {
551
628
  let cleaned = content;
552
629
  if (type === 'js') {
553
- // Remove wrapper function if we added it
554
- cleaned = cleaned.replace(/^\(function\(\) \{\n/, '');
555
- cleaned = cleaned.replace(/\n\}\)\(\);$/, '');
556
- // Remove our header comments
557
- cleaned = cleaned.replace(/^\/\*\*[\s\S]*?\*\/\n\n/, '');
558
- cleaned = cleaned.replace(/^function\(/, 'function(');
630
+ // Remove generic comment blocks at start
631
+ cleaned = cleaned.replace(/^\/\*\*[\s\S]*?\*\/\s*\n?/, '');
632
+ // Remove simple function wrappers (conservative approach)
633
+ cleaned = cleaned.replace(/^\(function\(\) \{\s*\n?/, '');
634
+ cleaned = cleaned.replace(/\s*\n?\}\)\(\);\s*$/, '');
635
+ cleaned = cleaned.replace(/^function\(\s*/, 'function(');
559
636
  }
560
637
  else if (type === 'html') {
561
- // Remove our HTML comments
562
- cleaned = cleaned.replace(/^<!-- ServiceNow Widget Template -->[\s\S]*?-->\n\n/, '');
638
+ // Remove HTML comments
639
+ cleaned = cleaned.replace(/^<!--[\s\S]*?-->\s*\n?/, '');
563
640
  }
564
641
  else if (type === 'css') {
565
- // Remove our CSS comments
566
- cleaned = cleaned.replace(/^\/\* ServiceNow Widget Styles \*\/[\s\S]*?\*\/\n\n/, '');
642
+ // Remove CSS comments
643
+ cleaned = cleaned.replace(/^\/\*[\s\S]*?\*\/\s*\n?/, '');
567
644
  }
568
645
  return cleaned.trim();
569
646
  }
647
+ /**
648
+ * INTELLIGENT WRAPPER DETECTION: Check if content actually needs wrappers
649
+ */
650
+ needsWrappers(content, mapping) {
651
+ if (!content || !content.trim()) {
652
+ return false; // Empty content doesn't need wrappers
653
+ }
654
+ // Check for server script wrappers
655
+ if (mapping.wrapperHeader?.includes('(function()') && mapping.wrapperFooter?.includes('})()')) {
656
+ // Check if content already has function wrapper
657
+ const trimmed = content.trim();
658
+ if (trimmed.match(/^\(function\s*\([^)]*\)\s*\{[\s\S]*\}\s*\)\s*\([^)]*\)\s*;?$/)) {
659
+ return false; // Already has function wrapper
660
+ }
661
+ if (trimmed.match(/^\(function\(\)\s*\{[\s\S]*\}\)\(\)\s*;?$/)) {
662
+ return false; // Already has our specific wrapper
663
+ }
664
+ }
665
+ // Check for client script wrappers
666
+ if (mapping.wrapperHeader?.includes('function(') && mapping.wrapperFooter?.includes(')')) {
667
+ const trimmed = content.trim();
668
+ if (trimmed.match(/^function\s*\([^)]*\)\s*\{[\s\S]*\}$/)) {
669
+ return false; // Already is a function
670
+ }
671
+ }
672
+ // Check if content already has comments that look like ours
673
+ if (mapping.wrapperHeader?.includes('/**')) {
674
+ if (content.includes('* Server Script for Widget:') ||
675
+ content.includes('* Client Controller for Widget:') ||
676
+ content.includes('* ES5 ONLY -')) {
677
+ return false; // Already has our comments
678
+ }
679
+ }
680
+ return true; // Content needs wrappers
681
+ }
570
682
  /**
571
683
  * Sanitize filename for filesystem
572
684
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.5.13",
4
- "description": "ServiceNow development framework with MCP server integration and reliable push operations. Fixed false positive success reporting in artifact push - now properly validates API responses. Features intelligent timeout configuration for long operations while preventing Claude API timeouts. Debug logging cleaned up for production use. Executes background scripts using ES5 JavaScript only (ServiceNow Rhino engine requirement). Provides 18 MCP servers including local development sync for editing ServiceNow artifacts with Claude Code native tools, widget deployment with coherence validation, table operations, script execution, machine learning, advanced features, and comprehensive platform management.",
3
+ "version": "3.5.15",
4
+ "description": "ServiceNow development framework with FIXED local artifact sync system. CRITICAL BUG RESOLVED: Fixed cumulative wrapper problems in snow_pull_artifact where dynamic registry wrappers didn't match hardcoded strip patterns, causing dubbele function wrappers. Now features intelligent wrapper detection and proper content handling. Enhanced 'snow-flow init' creates optimized settings.json with 18 MCP servers, extensive development permissions, intelligent hooks, and ServiceNow-specific commands. Features intelligent timeout configuration and comprehensive ServiceNow development workflow.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {