snow-flow 3.6.4 → 3.6.6

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.
@@ -199,7 +199,7 @@
199
199
  "args": [
200
200
  "{{PROJECT_ROOT}}/dist/mcp/servicenow-local-development-mcp.js"
201
201
  ],
202
- "description": "Local development bridge for Claude Code - pull any ServiceNow artifact to local files with native tool integration (snow_pull_artifact, snow_push_artifact, snow_validate_artifact_coherence), smart field chunking for large artifacts, ES5 validation, coherence checking, 12+ artifact types support",
202
+ "description": "UNIVERSAL ARTIFACT DETECTION v3.6.6 - finds ANY ServiceNow record by sys_id using sys_metadata! Pull any artifact (even custom tables) to local files with Claude Code native tools. Supports all tables, generic artifact creation for unknown types, smart chunking, ES5 validation, coherence checking. Tools: snow_pull_artifact, snow_push_artifact, snow_validate_artifact_coherence",
203
203
  "env": {
204
204
  "SNOW_INSTANCE": "{{SNOW_INSTANCE}}",
205
205
  "SNOW_CLIENT_ID": "{{SNOW_CLIENT_ID}}",
package/dist/cli.js CHANGED
@@ -2646,6 +2646,125 @@ async function createMCPConfig(targetDir, force = false) {
2646
2646
  const claudeSettingsPath = (0, path_1.join)(targetDir, '.claude/settings.json');
2647
2647
  await fs_1.promises.writeFile(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
2648
2648
  }
2649
+ // Setup MCP configuration function
2650
+ async function setupMCPConfig(targetDir, instanceUrl, clientId, clientSecret, force = false) {
2651
+ // Find the Snow-Flow installation root
2652
+ let snowFlowRoot = '';
2653
+ // Try different locations to find the Snow-Flow root
2654
+ const possiblePaths = [
2655
+ (0, path_1.join)(targetDir, 'node_modules/snow-flow'),
2656
+ (0, path_1.join)(targetDir, '../snow-flow-dev/snow-flow'),
2657
+ (0, path_1.join)(process.env.HOME || '', 'Projects/snow-flow-dev/snow-flow'),
2658
+ __dirname.includes('dist') ? (0, path_1.resolve)(__dirname, '..') : __dirname
2659
+ ];
2660
+ for (const testPath of possiblePaths) {
2661
+ try {
2662
+ await fs_1.promises.access((0, path_1.join)(testPath, '.mcp.json.template'));
2663
+ snowFlowRoot = testPath;
2664
+ break;
2665
+ }
2666
+ catch {
2667
+ // Keep trying
2668
+ }
2669
+ }
2670
+ if (!snowFlowRoot) {
2671
+ // Last resort: assume we're running from the installed package
2672
+ snowFlowRoot = (0, path_1.resolve)(__dirname, '..');
2673
+ // Verify we can find the template
2674
+ try {
2675
+ await fs_1.promises.access((0, path_1.join)(snowFlowRoot, '.mcp.json.template'));
2676
+ }
2677
+ catch {
2678
+ throw new Error('Could not find snow-flow project root');
2679
+ }
2680
+ }
2681
+ // Read the template file
2682
+ const templatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
2683
+ let templateContent;
2684
+ try {
2685
+ templateContent = await fs_1.promises.readFile(templatePath, 'utf-8');
2686
+ }
2687
+ catch (error) {
2688
+ console.error('❌ Could not find .mcp.json.template file');
2689
+ throw error;
2690
+ }
2691
+ // Replace placeholders in template
2692
+ const mcpConfigContent = templateContent
2693
+ .replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
2694
+ .replace(/{{SNOW_INSTANCE}}/g, '${SNOW_INSTANCE}')
2695
+ .replace(/{{SNOW_CLIENT_ID}}/g, '${SNOW_CLIENT_ID}')
2696
+ .replace(/{{SNOW_CLIENT_SECRET}}/g, '${SNOW_CLIENT_SECRET}')
2697
+ .replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, '${SNOW_DEPLOYMENT_TIMEOUT}')
2698
+ .replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, '${MCP_DEPLOYMENT_TIMEOUT}')
2699
+ .replace(/{{NEO4J_URI}}/g, '${NEO4J_URI}')
2700
+ .replace(/{{NEO4J_USER}}/g, '${NEO4J_USER}')
2701
+ .replace(/{{NEO4J_PASSWORD}}/g, '${NEO4J_PASSWORD}')
2702
+ .replace(/{{SNOW_FLOW_ENV}}/g, '${SNOW_FLOW_ENV}');
2703
+ // Parse to ensure it's valid JSON
2704
+ const mcpConfig = JSON.parse(mcpConfigContent);
2705
+ // Keep the standard MCP structure that Claude Code expects
2706
+ const finalConfig = {
2707
+ "mcpServers": mcpConfig.servers
2708
+ };
2709
+ // Create .mcp.json in project root for Claude Code discovery
2710
+ const mcpConfigPath = (0, path_1.join)(targetDir, '.mcp.json');
2711
+ try {
2712
+ await fs_1.promises.access(mcpConfigPath);
2713
+ if (force) {
2714
+ console.log('⚠️ .mcp.json already exists, overwriting with --force flag');
2715
+ await fs_1.promises.writeFile(mcpConfigPath, JSON.stringify(finalConfig, null, 2));
2716
+ }
2717
+ else {
2718
+ console.log('⚠️ .mcp.json already exists, skipping (use --force to overwrite)');
2719
+ }
2720
+ }
2721
+ catch {
2722
+ await fs_1.promises.writeFile(mcpConfigPath, JSON.stringify(finalConfig, null, 2));
2723
+ }
2724
+ // Also create legacy config in .claude for backward compatibility
2725
+ const legacyConfigPath = (0, path_1.join)(targetDir, '.claude/mcp-config.json');
2726
+ await fs_1.promises.writeFile(legacyConfigPath, JSON.stringify(finalConfig, null, 2));
2727
+ }
2728
+ // Refresh MCP configuration command
2729
+ program
2730
+ .command('refresh-mcp')
2731
+ .description('Refresh MCP server configuration to latest version')
2732
+ .option('--force', 'Force overwrite existing configuration')
2733
+ .action(async (options) => {
2734
+ console.log(chalk_1.default.blue.bold(`\n🔄 Refreshing MCP Configuration to v${version_js_1.VERSION}...`));
2735
+ console.log('='.repeat(60));
2736
+ try {
2737
+ // Check if project is initialized
2738
+ const envPath = (0, path_1.join)(process.cwd(), '.env');
2739
+ if (!(0, fs_2.existsSync)(envPath)) {
2740
+ console.error(chalk_1.default.red('\n❌ No .env file found. Please run "snow-flow init" first.'));
2741
+ process.exit(1);
2742
+ }
2743
+ // Load env vars
2744
+ dotenv_1.default.config({ path: envPath });
2745
+ const instanceUrl = process.env.SNOW_INSTANCE;
2746
+ const clientId = process.env.SNOW_CLIENT_ID;
2747
+ const clientSecret = process.env.SNOW_CLIENT_SECRET;
2748
+ if (!instanceUrl || !clientId || !clientSecret) {
2749
+ console.error(chalk_1.default.red('\n❌ Missing ServiceNow credentials in .env file.'));
2750
+ process.exit(1);
2751
+ }
2752
+ console.log('\n📝 Updating MCP configuration...');
2753
+ await setupMCPConfig(process.cwd(), instanceUrl, clientId, clientSecret, options.force || false);
2754
+ console.log(chalk_1.default.green('\n✅ MCP configuration refreshed successfully!'));
2755
+ console.log('\n📢 IMPORTANT: Restart Claude Code to use the new configuration:');
2756
+ console.log(chalk_1.default.cyan(' claude --mcp-config .mcp.json'));
2757
+ console.log('\n💡 The Local Development server now includes:');
2758
+ console.log(' • Universal artifact detection via sys_metadata');
2759
+ console.log(' • Support for ANY ServiceNow table (even custom)');
2760
+ console.log(' • Generic artifact handling for unknown types');
2761
+ console.log(' • Automatic file structure creation');
2762
+ }
2763
+ catch (error) {
2764
+ console.error(chalk_1.default.red('\n❌ Failed to refresh MCP configuration:'), error);
2765
+ process.exit(1);
2766
+ }
2767
+ });
2649
2768
  // Direct widget creation command
2650
2769
  program
2651
2770
  .command('create-widget [type]')
@@ -21,6 +21,7 @@ export interface LocalArtifact {
21
21
  createdAt: Date;
22
22
  lastSyncedAt: Date;
23
23
  artifactConfig?: ArtifactTypeConfig;
24
+ isGeneric?: boolean;
24
25
  }
25
26
  export interface LocalFile {
26
27
  filename: string;
@@ -55,6 +56,11 @@ export declare class ArtifactLocalSync {
55
56
  * DYNAMIC push local changes back to ServiceNow using artifact registry
56
57
  */
57
58
  pushArtifact(sys_id: string): Promise<boolean>;
59
+ /**
60
+ * Push generic artifact changes back to ServiceNow
61
+ * Only updates known script fields to avoid data corruption
62
+ */
63
+ pushGenericArtifact(artifact: LocalArtifact): Promise<boolean>;
58
64
  /**
59
65
  * Push local changes back to ServiceNow
60
66
  * (Wrapper for backward compatibility)
@@ -109,9 +115,14 @@ export declare class ArtifactLocalSync {
109
115
  getSyncStatus(sys_id: string): string;
110
116
  /**
111
117
  * Pull any supported artifact type by detecting table from sys_id
112
- * ENHANCED: Better error logging and more robust detection
118
+ * ENHANCED: Now uses sys_metadata to find ANY table, not just registered ones!
113
119
  */
114
120
  pullArtifactBySysId(sys_id: string): Promise<LocalArtifact>;
121
+ /**
122
+ * Pull a generic artifact from an unknown/custom table
123
+ * Creates a basic file structure for any ServiceNow record
124
+ */
125
+ pullGenericArtifact(tableName: string, sys_id: string): Promise<LocalArtifact>;
115
126
  /**
116
127
  * Get supported artifact types
117
128
  */
@@ -254,6 +254,10 @@ class ArtifactLocalSync {
254
254
  if (!artifact) {
255
255
  throw new Error(`No local artifact found for ${sys_id}. Run pullArtifact first.`);
256
256
  }
257
+ // Handle generic artifacts differently
258
+ if (artifact.isGeneric) {
259
+ return this.pushGenericArtifact(artifact);
260
+ }
257
261
  const config = artifact.artifactConfig;
258
262
  if (!config) {
259
263
  throw new Error(`No configuration found for artifact ${sys_id}`);
@@ -354,6 +358,56 @@ class ArtifactLocalSync {
354
358
  return false;
355
359
  }
356
360
  }
361
+ /**
362
+ * Push generic artifact changes back to ServiceNow
363
+ * Only updates known script fields to avoid data corruption
364
+ */
365
+ async pushGenericArtifact(artifact) {
366
+ console.log(`\n🔄 Pushing generic artifact changes to ${artifact.tableName}...`);
367
+ const updates = {};
368
+ let hasChanges = false;
369
+ // Only update known script fields for safety
370
+ const scriptFields = ['script', 'condition', 'script_plain', 'advanced',
371
+ 'client_script', 'server_script', 'template', 'body'];
372
+ for (const file of artifact.files) {
373
+ if (file.field && scriptFields.includes(file.field)) {
374
+ if (fs.existsSync(file.path)) {
375
+ const currentContent = fs.readFileSync(file.path, 'utf8');
376
+ if (currentContent !== file.originalContent) {
377
+ hasChanges = true;
378
+ updates[file.field] = currentContent;
379
+ console.log(` 📝 Changed: ${file.filename} (${file.field})`);
380
+ }
381
+ }
382
+ }
383
+ }
384
+ if (!hasChanges) {
385
+ console.log(`✅ No changes detected. Generic artifact is up to date.`);
386
+ return true;
387
+ }
388
+ try {
389
+ console.log(`\n📤 Updating generic artifact in ServiceNow...`);
390
+ const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
391
+ const updateResult = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.updateRecord(artifact.tableName, artifact.sys_id, updates), timeoutConfig.pushToolTimeout, `Update generic artifact ${artifact.sys_id}`);
392
+ if (!updateResult || !updateResult.success) {
393
+ const errorMsg = updateResult?.error || 'Unknown API error';
394
+ console.error(`❌ ServiceNow API returned failure: ${errorMsg}`);
395
+ artifact.syncStatus = 'pending_upload';
396
+ return false;
397
+ }
398
+ artifact.syncStatus = 'synced';
399
+ artifact.lastSyncedAt = new Date();
400
+ console.log(`✅ Generic artifact successfully updated in ServiceNow!`);
401
+ console.log(`🔗 Table: ${artifact.tableName}`);
402
+ console.log(`🔗 sys_id: ${artifact.sys_id}`);
403
+ return true;
404
+ }
405
+ catch (error) {
406
+ console.error(`❌ Failed to update generic artifact:`, error);
407
+ artifact.syncStatus = 'pending_upload';
408
+ return false;
409
+ }
410
+ }
357
411
  /**
358
412
  * Push local changes back to ServiceNow
359
413
  * (Wrapper for backward compatibility)
@@ -703,20 +757,43 @@ snow-flow sync status ${widget.sys_id}
703
757
  }
704
758
  /**
705
759
  * Pull any supported artifact type by detecting table from sys_id
706
- * ENHANCED: Better error logging and more robust detection
760
+ * ENHANCED: Now uses sys_metadata to find ANY table, not just registered ones!
707
761
  */
708
762
  async pullArtifactBySysId(sys_id) {
709
763
  console.log(`\n🔍 Auto-detecting artifact type for sys_id: ${sys_id}`);
710
- console.log(`📋 Checking ${Object.keys(artifact_registry_1.ARTIFACT_REGISTRY).length} supported tables...`);
711
764
  // CRITICAL: Add MAXIMUM operation timeout to prevent infinite hanging
712
765
  const MAX_OPERATION_TIME = 30000; // 30 seconds max for entire operation
713
766
  const operationStart = Date.now();
714
- // SMART ORDER: Check most common tables first for better performance
767
+ const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
768
+ // STEP 1: Try to find the table name using sys_metadata (works for ANY table!)
769
+ console.log(`🔮 Querying sys_metadata to find table name...`);
770
+ try {
771
+ const metadataResponse = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords('sys_metadata', `sys_id=${sys_id}`, 1), 5000, `Query sys_metadata for ${sys_id}`);
772
+ if (metadataResponse.result?.[0]?.sys_class_name) {
773
+ const tableName = metadataResponse.result[0].sys_class_name;
774
+ console.log(` ✅ Found in sys_metadata! Table: ${tableName}`);
775
+ // Check if this table is in our registry
776
+ if (artifact_registry_1.ARTIFACT_REGISTRY[tableName]) {
777
+ console.log(` ✅ Table is supported! Proceeding with pull...`);
778
+ return this.pullArtifact(tableName, sys_id);
779
+ }
780
+ else {
781
+ console.log(` ⚠️ Table '${tableName}' is not in artifact registry`);
782
+ console.log(` 🔧 Attempting generic pull for custom table...`);
783
+ return this.pullGenericArtifact(tableName, sys_id);
784
+ }
785
+ }
786
+ }
787
+ catch (error) {
788
+ console.log(` ⚠️ sys_metadata query failed: ${error instanceof Error ? error.message : error}`);
789
+ console.log(` 📋 Falling back to registered table search...`);
790
+ }
791
+ // STEP 2: If sys_metadata fails, try common tables first
792
+ console.log(`\n📋 Checking ${Object.keys(artifact_registry_1.ARTIFACT_REGISTRY).length} registered tables...`);
715
793
  const allTables = Object.keys(artifact_registry_1.ARTIFACT_REGISTRY);
716
794
  const commonTables = ['sp_widget', 'sys_script_include', 'sys_script', 'sys_ui_page'];
717
795
  const otherTables = allTables.filter(t => !commonTables.includes(t));
718
796
  const tables = [...commonTables, ...otherTables]; // Common tables first
719
- const timeoutConfig = (0, mcp_timeout_config_js_1.getMCPTimeoutConfig)();
720
797
  const errors = [];
721
798
  for (const table of tables) {
722
799
  // Check if we've exceeded maximum operation time
@@ -727,7 +804,7 @@ snow-flow sync status ${widget.sys_id}
727
804
  try {
728
805
  console.log(` 🔎 Checking table: ${table}...`);
729
806
  // Reduced timeout per table for faster failure
730
- const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(table, `sys_id=${sys_id}`, 1), 3000, // 3 second timeout per table (reduced from 8s)
807
+ const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(table, `sys_id=${sys_id}`, 1), 3000, // 3 second timeout per table
731
808
  `Detect table for ${sys_id}`);
732
809
  if (response.result?.[0]) {
733
810
  console.log(` ✅ Found in table: ${table}`);
@@ -742,12 +819,29 @@ snow-flow sync status ${widget.sys_id}
742
819
  const errorMsg = error instanceof Error ? error.message : String(error);
743
820
  console.log(` ⚠️ Error checking ${table}: ${errorMsg}`);
744
821
  errors.push({ table, error: errorMsg });
745
- // Don't fail on permission errors, timeouts, etc. - keep trying other tables
822
+ }
823
+ }
824
+ // STEP 3: Try a few common custom tables as last resort
825
+ const customTables = ['sys_ui_script', 'sys_processor', 'sys_ws_operation', 'sys_portal_page'];
826
+ console.log(`\n🔍 Checking additional custom tables...`);
827
+ for (const table of customTables) {
828
+ if (Date.now() - operationStart > MAX_OPERATION_TIME)
829
+ break;
830
+ try {
831
+ console.log(` 🔎 Checking custom table: ${table}...`);
832
+ const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(table, `sys_id=${sys_id}`, 1), 3000, `Check custom table ${table}`);
833
+ if (response.result?.[0]) {
834
+ console.log(` ✅ Found in custom table: ${table}`);
835
+ return this.pullGenericArtifact(table, sys_id);
836
+ }
837
+ }
838
+ catch (error) {
839
+ // Silent fail for custom tables
746
840
  }
747
841
  }
748
842
  // Generate detailed error message
749
843
  console.log(`\n❌ Artifact detection failed!`);
750
- console.log(`🔍 Searched ${tables.length} tables for sys_id: ${sys_id}`);
844
+ console.log(`🔍 Searched sys_metadata + ${tables.length} registered tables + ${customTables.length} custom tables`);
751
845
  if (errors.length > 0) {
752
846
  console.log(`\n⚠️ Errors encountered:`);
753
847
  errors.forEach(({ table, error }) => {
@@ -757,9 +851,92 @@ snow-flow sync status ${widget.sys_id}
757
851
  console.log(`\n💡 Troubleshooting tips:`);
758
852
  console.log(` 1. Verify the sys_id exists in ServiceNow`);
759
853
  console.log(` 2. Check your permissions for the target table`);
760
- console.log(` 3. Try specifying the table explicitly: snow_pull_artifact({sys_id, table: 'sp_widget'})`);
761
- console.log(` 4. Supported tables: ${tables.join(', ')}`);
762
- throw new Error(`Could not find artifact with sys_id ${sys_id} in any supported table. See details above.`);
854
+ console.log(` 3. Try specifying the table explicitly: snow_pull_artifact({sys_id, table: 'table_name'})`);
855
+ console.log(` 4. The artifact might be in a custom or scoped application table`);
856
+ throw new Error(`Could not find artifact with sys_id ${sys_id}. It may be in a custom table or you may lack permissions.`);
857
+ }
858
+ /**
859
+ * Pull a generic artifact from an unknown/custom table
860
+ * Creates a basic file structure for any ServiceNow record
861
+ */
862
+ async pullGenericArtifact(tableName, sys_id) {
863
+ console.log(`\n🔧 Pulling generic artifact from custom table: ${tableName}`);
864
+ try {
865
+ // Fetch the record with all fields
866
+ const response = await (0, mcp_timeout_config_js_1.withMCPTimeout)(this.client.searchRecords(tableName, `sys_id=${sys_id}`, 1), 10000, `Fetch generic artifact from ${tableName}`);
867
+ const record = response.result?.[0];
868
+ if (!record) {
869
+ throw new Error(`Record not found in ${tableName}`);
870
+ }
871
+ // Create a generic folder structure
872
+ const name = record.name || record.short_description || record.sys_name || sys_id;
873
+ const sanitizedName = this.sanitizeFilename(name);
874
+ const artifactPath = path.join(this.baseDir, 'custom', tableName, sanitizedName);
875
+ // Clean up existing files
876
+ if (fs.existsSync(artifactPath)) {
877
+ fs.rmSync(artifactPath, { recursive: true });
878
+ }
879
+ fs.mkdirSync(artifactPath, { recursive: true });
880
+ const files = [];
881
+ // Create JSON file with all fields
882
+ const jsonFile = this.createLocalFile(artifactPath, `${sanitizedName}.json`, JSON.stringify(record, null, 2), 'all_fields', 'json');
883
+ files.push(jsonFile);
884
+ // Extract common script fields if they exist
885
+ const scriptFields = ['script', 'condition', 'script_plain', 'advanced',
886
+ 'client_script', 'server_script', 'template', 'body'];
887
+ for (const field of scriptFields) {
888
+ if (record[field] && typeof record[field] === 'string' && record[field].trim()) {
889
+ const ext = field.includes('template') || field === 'body' ? 'html' : 'js';
890
+ const scriptFile = this.createLocalFile(artifactPath, `${sanitizedName}.${field}.${ext}`, record[field], field, ext);
891
+ files.push(scriptFile);
892
+ }
893
+ }
894
+ // Create README
895
+ const readmeContent = `# Generic Artifact: ${name}\n\n` +
896
+ `**Table:** ${tableName}\n` +
897
+ `**Sys ID:** ${sys_id}\n` +
898
+ `**Created:** ${record.sys_created_on || 'Unknown'}\n` +
899
+ `**Updated:** ${record.sys_updated_on || 'Unknown'}\n\n` +
900
+ `## Notice\n\n` +
901
+ `This is a generic artifact from a custom/unknown table.\n` +
902
+ `Snow-Flow has created a basic file structure to allow editing.\n\n` +
903
+ `## Files\n\n` +
904
+ `- **${sanitizedName}.json** - Complete record data\n` +
905
+ (files.length > 1 ? files.slice(1).map(f => `- **${f.filename}** - ${f.field} field content\n`).join('') : '') +
906
+ `\n## Push Support\n\n` +
907
+ `Generic artifacts have limited push support. ` +
908
+ `Only script fields will be updated when pushing back.\n`;
909
+ const readmeFile = this.createLocalFile(artifactPath, 'README.md', readmeContent, 'documentation', 'md');
910
+ files.push(readmeFile);
911
+ // Create artifact record
912
+ const artifact = {
913
+ sys_id: sys_id,
914
+ name: name,
915
+ type: `Custom (${tableName})`,
916
+ tableName: tableName,
917
+ localPath: artifactPath,
918
+ files: files,
919
+ metadata: record,
920
+ syncStatus: 'synced',
921
+ createdAt: new Date(),
922
+ lastSyncedAt: new Date(),
923
+ isGeneric: true // Mark as generic for special handling
924
+ };
925
+ this.artifacts.set(sys_id, artifact);
926
+ const relativePath = path.relative(process.cwd(), artifactPath);
927
+ const displayPath = relativePath.startsWith('..') ? artifactPath : relativePath;
928
+ console.log(`✅ Generic artifact pulled successfully!`);
929
+ console.log(`📁 Location: ${displayPath}`);
930
+ console.log(`📄 Files created:`);
931
+ files.forEach(f => console.log(` - ${f.filename} (${f.type})`));
932
+ console.log(`\n⚠️ Note: This is a generic pull from a custom table.`);
933
+ console.log(` Full push support may be limited.`);
934
+ return artifact;
935
+ }
936
+ catch (error) {
937
+ console.error(`❌ Failed to pull generic artifact:`, error);
938
+ throw error;
939
+ }
763
940
  }
764
941
  /**
765
942
  * Get supported artifact types
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.6.4",
4
- "description": "EARLY AUTO-COMPACT at 65% context usage prevents mid-API failures. v3.6.4 triggers compact BEFORE context window issues, not after. Aggressive compact mode with MCP state preservation. Prevents 'too many tokens' errors during ServiceNow operations. Includes infinite hanging fix, consolidated CLAUDE.md with 18 MCP servers, NO MOCK DATA policy, audit logging, and ES5 enforcement.",
3
+ "version": "3.6.6",
4
+ "description": "MCP TEMPLATE FIX - v3.6.6 ensures snow-flow init generates correct .mcp.json with UNIVERSAL ARTIFACT DETECTION. Uses sys_metadata to find ANY ServiceNow record by sys_id alone. Generic artifact support for custom/unknown tables. Auto-creates editable file structure for ANY table type. Includes early auto-compact, audit logging, and consolidated CLAUDE.md.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {