snow-flow 8.5.7 → 8.6.0
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/.mcp.json.template +8 -0
- package/CLAUDE.md +52 -4
- package/README.md +99 -30
- package/{OPENCODE-SETUP.md → SNOWCODE-SETUP.md} +47 -21
- package/{OPENCODE-TROUBLESHOOTING.md → SNOWCODE-TROUBLESHOOTING.md} +18 -18
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +526 -280
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/enterprise.d.ts +36 -0
- package/dist/cli/enterprise.d.ts.map +1 -0
- package/dist/cli/enterprise.js +231 -0
- package/dist/cli/enterprise.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +544 -250
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/clients/enterprise-remote-client.d.ts +78 -0
- package/dist/mcp/clients/enterprise-remote-client.d.ts.map +1 -0
- package/dist/mcp/clients/enterprise-remote-client.js +221 -0
- package/dist/mcp/clients/enterprise-remote-client.js.map +1 -0
- package/dist/mcp/servicenow-mcp-unified/tools/adapters/index.d.ts +0 -5
- package/dist/mcp/servicenow-mcp-unified/tools/adapters/index.d.ts.map +1 -1
- package/dist/mcp/servicenow-mcp-unified/tools/adapters/index.js +2 -18
- package/dist/mcp/servicenow-mcp-unified/tools/adapters/index.js.map +1 -1
- package/dist/templates/claude-md-template.d.ts +1 -1
- package/dist/templates/claude-md-template.js +1 -1
- package/dist/templates/readme-template.d.ts +1 -1
- package/dist/templates/readme-template.js +18 -18
- package/dist/utils/artifact-local-sync.d.ts +1 -1
- package/dist/utils/artifact-local-sync.js +4 -4
- package/dist/utils/snow-oauth.d.ts +11 -5
- package/dist/utils/snow-oauth.d.ts.map +1 -1
- package/dist/utils/snow-oauth.js +337 -90
- package/dist/utils/snow-oauth.js.map +1 -1
- package/dist/utils/{opencode-output-interceptor.d.ts → snowcode-output-interceptor.d.ts} +7 -7
- package/dist/utils/{opencode-output-interceptor.d.ts.map → snowcode-output-interceptor.d.ts.map} +1 -1
- package/dist/utils/{opencode-output-interceptor.js → snowcode-output-interceptor.js} +10 -10
- package/dist/utils/{opencode-output-interceptor.js.map → snowcode-output-interceptor.js.map} +1 -1
- package/package.json +20 -9
- package/scripts/{start-opencode.sh → start-snowcode.sh} +28 -28
- package/scripts/verify-snowcode-fork.sh +141 -0
- package/templates/snowcode-package.json +5 -0
- package/THEMES.md +0 -223
- package/bin/opencode +0 -17
- package/dist/mcp/servicenow-mcp-unified/config/tool-definitions.json +0 -3935
- package/dist/mcp/servicenow-mcp-unified/tools/automation/snow_automation_discover.js +0 -164
- package/dist/mcp/servicenow-mcp-unified/tools/deployment/snow_artifact_transfer.js +0 -282
- package/dist/mcp/servicenow-mcp-unified/tools/filters/snow_build_filter.js +0 -171
- package/dist/mcp/servicenow-mcp-unified/tools/formatters/snow_format_value.js +0 -164
- package/dist/mcp/servicenow-mcp-unified/tools/knowledge/index.js.bak +0 -45
- package/dist/mcp/servicenow-mcp-unified/tools/local-sync/snow_artifact_sync.js +0 -172
- package/dist/mcp/servicenow-mcp-unified/tools/system-properties/index.js +0 -36
- package/dist/mcp/servicenow-mcp-unified/tools/ui-builder/snow_discover_uib.js +0 -296
- package/dist/mcp/servicenow-mcp-unified/tools/workspace/snow_create_ux_component.js +0 -292
- package/dist/memory/session-memory.d.ts +0 -80
- package/dist/memory/session-memory.d.ts.map +0 -1
- package/dist/memory/session-memory.js +0 -468
- package/dist/memory/session-memory.js.map +0 -1
- package/dist/templates/opencode-agents-template.d.ts +0 -2
- package/dist/templates/opencode-agents-template.d.ts.map +0 -1
- package/dist/templates/opencode-agents-template.js +0 -469
- package/dist/templates/opencode-agents-template.js.map +0 -1
- package/scripts/bulk-optimize-tools.js +0 -486
- package/scripts/optimize-mcp-tools.ts +0 -410
- package/themes/README.md +0 -83
- package/themes/servicenow.json +0 -117
- /package/{opencode-config.example.json → snowcode-config.example.json} +0 -0
package/dist/cli.js
CHANGED
|
@@ -40,6 +40,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
40
40
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
41
|
};
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.setupMCPConfig = setupMCPConfig;
|
|
43
44
|
const commander_1 = require("commander");
|
|
44
45
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
45
46
|
const fs_1 = require("fs");
|
|
@@ -67,6 +68,7 @@ if (currentCommand && commandsNeedingMCP.includes(currentCommand) && !commandsNo
|
|
|
67
68
|
// Removed provider-agnostic imports - using Claude Code directly
|
|
68
69
|
const auth_js_1 = require("./cli/auth.js");
|
|
69
70
|
const session_js_1 = require("./cli/session.js");
|
|
71
|
+
const enterprise_js_1 = require("./cli/enterprise.js");
|
|
70
72
|
// Load environment variables
|
|
71
73
|
dotenv_1.default.config();
|
|
72
74
|
// Create CLI logger instance
|
|
@@ -80,6 +82,8 @@ program
|
|
|
80
82
|
(0, auth_js_1.registerAuthCommands)(program);
|
|
81
83
|
// Register session inspection commands
|
|
82
84
|
(0, session_js_1.registerSessionCommands)(program);
|
|
85
|
+
// Register enterprise commands (login, status, portal, logout)
|
|
86
|
+
(0, enterprise_js_1.registerEnterpriseCommands)(program);
|
|
83
87
|
// Flow deprecation handler - check for flow-related commands
|
|
84
88
|
function checkFlowDeprecation(command, objective) {
|
|
85
89
|
const flowKeywords = ['flow', 'create-flow', 'xml-flow', 'flow-designer'];
|
|
@@ -306,6 +310,19 @@ program
|
|
|
306
310
|
cliLogger.info('💡 Run "snow-flow auth login" to enable live ServiceNow integration');
|
|
307
311
|
}
|
|
308
312
|
}
|
|
313
|
+
// Check Enterprise features
|
|
314
|
+
const { hasEnterpriseFeatures, getEnterpriseInfo } = await Promise.resolve().then(() => __importStar(require('./cli/enterprise.js')));
|
|
315
|
+
const enterpriseEnabled = await hasEnterpriseFeatures();
|
|
316
|
+
const enterpriseInfo = enterpriseEnabled ? await getEnterpriseInfo() : null;
|
|
317
|
+
if (options.verbose && enterpriseEnabled && enterpriseInfo) {
|
|
318
|
+
cliLogger.info(`\n🌟 Snow-Flow Enterprise: ✅ Active (${enterpriseInfo.tier.toUpperCase()})`);
|
|
319
|
+
cliLogger.info(` Organization: ${enterpriseInfo.name}`);
|
|
320
|
+
cliLogger.info(` Features: ${enterpriseInfo.features.join(', ')}`);
|
|
321
|
+
}
|
|
322
|
+
else if (options.verbose) {
|
|
323
|
+
cliLogger.info('\n🌟 Snow-Flow Enterprise: ❌ Not active');
|
|
324
|
+
cliLogger.info('💡 Run "snow-flow login <license-key>" to enable enterprise features');
|
|
325
|
+
}
|
|
309
326
|
// Initialize Queen Agent memory system
|
|
310
327
|
if (options.verbose) {
|
|
311
328
|
cliLogger.info('\n💾 Initializing swarm memory system...');
|
|
@@ -326,13 +343,13 @@ program
|
|
|
326
343
|
started_at: new Date().toISOString(),
|
|
327
344
|
is_authenticated: isAuthenticated
|
|
328
345
|
});
|
|
329
|
-
// Start
|
|
346
|
+
// Start SnowCode multi-agent orchestration
|
|
330
347
|
try {
|
|
331
348
|
// Generate the orchestration prompt
|
|
332
349
|
const orchestrationPrompt = buildQueenAgentPrompt(objective, taskAnalysis, options, isAuthenticated, sessionId);
|
|
333
350
|
if (options.verbose) {
|
|
334
|
-
cliLogger.info('\n👑 Initializing multi-agent orchestration with
|
|
335
|
-
cliLogger.info('🎯
|
|
351
|
+
cliLogger.info('\n👑 Initializing multi-agent orchestration with SnowCode...');
|
|
352
|
+
cliLogger.info('🎯 SnowCode will coordinate the following:');
|
|
336
353
|
cliLogger.info(` - Analyze objective: "${objective}"`);
|
|
337
354
|
cliLogger.info(` - Spawn ${taskAnalysis.estimatedAgentCount} specialized agents via Task() system`);
|
|
338
355
|
cliLogger.info(` - Coordinate through shared memory (session: ${sessionId})`);
|
|
@@ -344,7 +361,7 @@ program
|
|
|
344
361
|
options.sharedMemory || options.progressMonitoring;
|
|
345
362
|
if (options.verbose && hasIntelligentFeatures && isAuthenticated) {
|
|
346
363
|
cliLogger.info('\n🧠 INTELLIGENT ORCHESTRATION MODE ENABLED!');
|
|
347
|
-
cliLogger.info('✨
|
|
364
|
+
cliLogger.info('✨ SnowCode will use advanced features:');
|
|
348
365
|
if (options.autoPermissions) {
|
|
349
366
|
cliLogger.info(' 🔐 Automatic permission escalation');
|
|
350
367
|
}
|
|
@@ -376,12 +393,12 @@ program
|
|
|
376
393
|
cliLogger.info('\n🔗 Live ServiceNow integration: ❌ Disabled');
|
|
377
394
|
}
|
|
378
395
|
}
|
|
379
|
-
// Try to execute
|
|
380
|
-
const success = await
|
|
396
|
+
// Try to execute SnowCode directly with the objective
|
|
397
|
+
const success = await executeSnowCode(objective);
|
|
381
398
|
if (success) {
|
|
382
399
|
if (options.verbose) {
|
|
383
|
-
cliLogger.info('✅
|
|
384
|
-
cliLogger.info('🤖
|
|
400
|
+
cliLogger.info('✅ SnowCode launched successfully!');
|
|
401
|
+
cliLogger.info('🤖 SnowCode is now executing your objective');
|
|
385
402
|
cliLogger.info(`💾 Monitor progress with session ID: ${sessionId}`);
|
|
386
403
|
if (isAuthenticated && options.autoDeploy) {
|
|
387
404
|
cliLogger.info('🚀 Real artifacts will be created in ServiceNow');
|
|
@@ -397,11 +414,11 @@ program
|
|
|
397
414
|
});
|
|
398
415
|
}
|
|
399
416
|
else {
|
|
400
|
-
cliLogger.warn('⚠️
|
|
401
|
-
cliLogger.info('\n📋 Please ensure
|
|
402
|
-
cliLogger.info(' npm install -g
|
|
403
|
-
cliLogger.info('\n💡 Or start
|
|
404
|
-
cliLogger.info(' 1. Run:
|
|
417
|
+
cliLogger.warn('⚠️ SnowCode CLI not found or failed to start');
|
|
418
|
+
cliLogger.info('\n📋 Please ensure SnowCode is installed:');
|
|
419
|
+
cliLogger.info(' npm install -g @groeimetai/snowcode');
|
|
420
|
+
cliLogger.info('\n💡 Or start SnowCode manually:');
|
|
421
|
+
cliLogger.info(' 1. Run: snowcode');
|
|
405
422
|
cliLogger.info(` 2. Enter objective: ${objective}`);
|
|
406
423
|
if (isAuthenticated && options.autoDeploy) {
|
|
407
424
|
cliLogger.info('\n🚀 Deployment Mode: Artifacts will be created in ServiceNow');
|
|
@@ -421,26 +438,26 @@ program
|
|
|
421
438
|
});
|
|
422
439
|
}
|
|
423
440
|
});
|
|
424
|
-
// Helper function to execute
|
|
425
|
-
async function
|
|
441
|
+
// Helper function to execute SnowCode directly with the objective
|
|
442
|
+
async function executeSnowCode(objective) {
|
|
426
443
|
try {
|
|
427
|
-
// Check if
|
|
444
|
+
// Check if SnowCode CLI is available
|
|
428
445
|
const { execSync } = require('child_process');
|
|
429
446
|
try {
|
|
430
|
-
execSync('which
|
|
447
|
+
execSync('which snowcode', { stdio: 'ignore' });
|
|
431
448
|
}
|
|
432
449
|
catch {
|
|
433
|
-
cliLogger.warn('⚠️
|
|
434
|
-
cliLogger.info('📋 Please install
|
|
450
|
+
cliLogger.warn('⚠️ SnowCode CLI not found in PATH');
|
|
451
|
+
cliLogger.info('📋 Please install SnowCode: npm install -g @groeimetai/snowcode');
|
|
435
452
|
return false;
|
|
436
453
|
}
|
|
437
|
-
// Check for
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
if (!
|
|
441
|
-
cliLogger.warn('⚠️
|
|
454
|
+
// Check for SnowCode config (.snowcode/snowcode.json created by init)
|
|
455
|
+
const snowcodeConfigPath = (0, path_1.join)(process.cwd(), '.snowcode', 'snowcode.json');
|
|
456
|
+
const hasSnowcodeConfig = (0, fs_2.existsSync)(snowcodeConfigPath);
|
|
457
|
+
if (!hasSnowcodeConfig) {
|
|
458
|
+
cliLogger.warn('⚠️ SnowCode configuration not found');
|
|
442
459
|
cliLogger.info('📋 Please run: snow-flow init');
|
|
443
|
-
cliLogger.info(' This will create .
|
|
460
|
+
cliLogger.info(' This will create .snowcode/snowcode.json with MCP servers configured');
|
|
444
461
|
return false;
|
|
445
462
|
}
|
|
446
463
|
// Check for .env file with required configuration
|
|
@@ -457,10 +474,10 @@ async function executeOpenCode(objective) {
|
|
|
457
474
|
// Debug output if enabled
|
|
458
475
|
if (process.env.SNOW_FLOW_DEBUG === 'true' || process.env.VERBOSE === 'true') {
|
|
459
476
|
cliLogger.info(`🔍 Working Directory: ${process.cwd()}`);
|
|
460
|
-
cliLogger.info(`🔍
|
|
477
|
+
cliLogger.info(`🔍 SnowCode Config: ${snowcodeConfigPath}`);
|
|
461
478
|
cliLogger.info(`🔍 Environment File: ${envPath}`);
|
|
462
479
|
}
|
|
463
|
-
// Write objective to temp file for
|
|
480
|
+
// Write objective to temp file for SnowCode to read
|
|
464
481
|
const { tmpdir } = await Promise.resolve().then(() => __importStar(require('os')));
|
|
465
482
|
const { writeFileSync, unlinkSync } = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
466
483
|
const tmpFile = (0, path_1.join)(tmpdir(), `snow-flow-objective-${Date.now()}.txt`);
|
|
@@ -468,29 +485,29 @@ async function executeOpenCode(objective) {
|
|
|
468
485
|
// Get default model from .env if available
|
|
469
486
|
const defaultModel = process.env.DEFAULT_MODEL;
|
|
470
487
|
const defaultProvider = process.env.DEFAULT_LLM_PROVIDER;
|
|
471
|
-
// Start
|
|
472
|
-
//
|
|
473
|
-
let
|
|
474
|
-
// If we have a default model, pass it to
|
|
488
|
+
// Start SnowCode with the objective and default model
|
|
489
|
+
// SnowCode will be started interactively with stdin redirect
|
|
490
|
+
let snowcodeCommand = `snowcode < "${tmpFile}"`;
|
|
491
|
+
// If we have a default model, pass it to SnowCode
|
|
475
492
|
if (defaultModel) {
|
|
476
|
-
|
|
493
|
+
snowcodeCommand = `snowcode --model "${defaultModel}" < "${tmpFile}"`;
|
|
477
494
|
}
|
|
478
|
-
// Spawn
|
|
479
|
-
//
|
|
480
|
-
// We pass the objective via stdin redirect (shell:
|
|
481
|
-
const
|
|
482
|
-
stdio: 'inherit', // All stdio inherited -
|
|
495
|
+
// Spawn SnowCode process - let it run fully interactively
|
|
496
|
+
// SnowCode is a TUI (Terminal User Interface) application that needs full terminal control
|
|
497
|
+
// We pass the objective via stdin redirect (shell: snowcode < tmpfile)
|
|
498
|
+
const snowcodeProcess = (0, child_process_1.spawn)('sh', ['-c', snowcodeCommand], {
|
|
499
|
+
stdio: 'inherit', // All stdio inherited - SnowCode can use TTY
|
|
483
500
|
cwd: process.cwd(),
|
|
484
501
|
env: {
|
|
485
502
|
...process.env,
|
|
486
|
-
// Ensure DEFAULT_MODEL is available to
|
|
503
|
+
// Ensure DEFAULT_MODEL is available to SnowCode
|
|
487
504
|
DEFAULT_MODEL: defaultModel || '',
|
|
488
505
|
DEFAULT_LLM_PROVIDER: defaultProvider || ''
|
|
489
506
|
}
|
|
490
507
|
});
|
|
491
508
|
// Set up process monitoring
|
|
492
509
|
return new Promise((resolve) => {
|
|
493
|
-
|
|
510
|
+
snowcodeProcess.on('close', async (code) => {
|
|
494
511
|
// Clean up temp file
|
|
495
512
|
try {
|
|
496
513
|
unlinkSync(tmpFile);
|
|
@@ -500,7 +517,7 @@ async function executeOpenCode(objective) {
|
|
|
500
517
|
}
|
|
501
518
|
resolve(code === 0);
|
|
502
519
|
});
|
|
503
|
-
|
|
520
|
+
snowcodeProcess.on('error', (error) => {
|
|
504
521
|
// Clean up temp file
|
|
505
522
|
try {
|
|
506
523
|
unlinkSync(tmpFile);
|
|
@@ -508,15 +525,15 @@ async function executeOpenCode(objective) {
|
|
|
508
525
|
catch (e) {
|
|
509
526
|
// Ignore cleanup errors
|
|
510
527
|
}
|
|
511
|
-
cliLogger.error(`❌ Failed to start
|
|
528
|
+
cliLogger.error(`❌ Failed to start SnowCode: ${error.message}`);
|
|
512
529
|
resolve(false);
|
|
513
530
|
});
|
|
514
531
|
// Set timeout (configurable via environment variable)
|
|
515
532
|
const timeoutMinutes = parseInt(process.env.SNOW_FLOW_TIMEOUT_MINUTES || '0');
|
|
516
533
|
if (timeoutMinutes > 0) {
|
|
517
534
|
setTimeout(() => {
|
|
518
|
-
cliLogger.warn(`⏱️
|
|
519
|
-
|
|
535
|
+
cliLogger.warn(`⏱️ SnowCode session timeout (${timeoutMinutes} minutes), terminating...`);
|
|
536
|
+
snowcodeProcess.kill('SIGTERM');
|
|
520
537
|
// Clean up temp file
|
|
521
538
|
try {
|
|
522
539
|
unlinkSync(tmpFile);
|
|
@@ -530,25 +547,25 @@ async function executeOpenCode(objective) {
|
|
|
530
547
|
});
|
|
531
548
|
}
|
|
532
549
|
catch (error) {
|
|
533
|
-
cliLogger.error('❌ Error launching
|
|
534
|
-
cliLogger.info('📋 Please start
|
|
550
|
+
cliLogger.error('❌ Error launching SnowCode:', error instanceof Error ? error.message : String(error));
|
|
551
|
+
cliLogger.info('📋 Please start SnowCode manually: snowcode');
|
|
535
552
|
return false;
|
|
536
553
|
}
|
|
537
554
|
}
|
|
538
|
-
// Real-time monitoring dashboard for
|
|
539
|
-
function startMonitoringDashboard(
|
|
555
|
+
// Real-time monitoring dashboard for SnowCode process
|
|
556
|
+
function startMonitoringDashboard(snowcodeProcess) {
|
|
540
557
|
let iterations = 0;
|
|
541
558
|
const startTime = Date.now();
|
|
542
559
|
// Show initial dashboard only once
|
|
543
560
|
cliLogger.info(`┌─────────────────────────────────────────────────────────────┐`);
|
|
544
561
|
cliLogger.info(`│ 🚀 Snow-Flow Dashboard v${version_js_1.VERSION} │`);
|
|
545
562
|
cliLogger.info(`├─────────────────────────────────────────────────────────────┤`);
|
|
546
|
-
cliLogger.info(`│ 🤖
|
|
547
|
-
cliLogger.info(`│ 📊 Process ID: ${
|
|
563
|
+
cliLogger.info(`│ 🤖 SnowCode Status: ✅ Starting │`);
|
|
564
|
+
cliLogger.info(`│ 📊 Process ID: ${snowcodeProcess.pid || 'N/A'} │`);
|
|
548
565
|
cliLogger.info(`│ ⏱️ Session Time: 00:00 │`);
|
|
549
566
|
cliLogger.info(`│ 🔄 Monitoring Cycles: 0 │`);
|
|
550
567
|
cliLogger.info('└─────────────────────────────────────────────────────────────┘');
|
|
551
|
-
// Silent monitoring - only log to file or memory, don't interfere with
|
|
568
|
+
// Silent monitoring - only log to file or memory, don't interfere with SnowCode UI
|
|
552
569
|
const monitoringInterval = setInterval(() => {
|
|
553
570
|
iterations++;
|
|
554
571
|
const uptime = Math.floor((Date.now() - startTime) / 1000);
|
|
@@ -1363,7 +1380,7 @@ program
|
|
|
1363
1380
|
cliLogger.info(` - Primary: ${sessionData.taskAnalysis.primaryAgent}`);
|
|
1364
1381
|
cliLogger.info(` - Supporting: ${sessionData.taskAnalysis.supportingAgents.join(', ')}`);
|
|
1365
1382
|
if (launchData && launchData.success) {
|
|
1366
|
-
cliLogger.info(`\n✅ Status:
|
|
1383
|
+
cliLogger.info(`\n✅ Status: SnowCode (or Claude Code) launched successfully`);
|
|
1367
1384
|
cliLogger.info(`🚀 Launched at: ${launchData.launched_at}`);
|
|
1368
1385
|
}
|
|
1369
1386
|
else if (errorData) {
|
|
@@ -1372,11 +1389,11 @@ program
|
|
|
1372
1389
|
cliLogger.error(`🕐 Failed at: ${errorData.failed_at}`);
|
|
1373
1390
|
}
|
|
1374
1391
|
else {
|
|
1375
|
-
cliLogger.info(`\n⏳ Status: Awaiting manual
|
|
1392
|
+
cliLogger.info(`\n⏳ Status: Awaiting manual SnowCode execution`);
|
|
1376
1393
|
}
|
|
1377
1394
|
cliLogger.info('\n💡 Tips:');
|
|
1378
|
-
cliLogger.info(' - Check
|
|
1379
|
-
cliLogger.info(' - Use Memory.get("swarm_session_' + sessionId + '") in
|
|
1395
|
+
cliLogger.info(' - Check SnowCode for real-time agent progress');
|
|
1396
|
+
cliLogger.info(' - Use Memory.get("swarm_session_' + sessionId + '") in SnowCode');
|
|
1380
1397
|
cliLogger.info(' - Monitor TodoRead for task completion status');
|
|
1381
1398
|
if (options.watch) {
|
|
1382
1399
|
cliLogger.info(`\n👀 Watching for updates every ${options.interval} seconds...`);
|
|
@@ -1387,7 +1404,7 @@ program
|
|
|
1387
1404
|
// Re-fetch session data to check for updates
|
|
1388
1405
|
const updatedSession = memorySystem.getLearning(`session_${sessionId}`);
|
|
1389
1406
|
if (updatedSession) {
|
|
1390
|
-
cliLogger.info(' Status: Active - Check
|
|
1407
|
+
cliLogger.info(' Status: Active - Check SnowCode for details');
|
|
1391
1408
|
}
|
|
1392
1409
|
}, parseInt(options.interval) * 1000);
|
|
1393
1410
|
// Handle graceful shutdown
|
|
@@ -1480,12 +1497,12 @@ program
|
|
|
1480
1497
|
console.log('│ 📋 Recent Activity: │');
|
|
1481
1498
|
console.log(`│ • ${new Date().toLocaleTimeString()} - System monitoring active │`);
|
|
1482
1499
|
cliLogger.info('└─────────────────────────────────────────────────────────────┘');
|
|
1483
|
-
// Check for active
|
|
1500
|
+
// Check for active SnowCode/Claude Code processes
|
|
1484
1501
|
try {
|
|
1485
1502
|
const { execSync } = require('child_process');
|
|
1486
|
-
const processes = execSync('ps aux | grep "claude\\|opencode" | grep -v grep', { encoding: 'utf8' }).toString();
|
|
1503
|
+
const processes = execSync('ps aux | grep "claude\\|opencode\\|snowcode" | grep -v grep', { encoding: 'utf8' }).toString();
|
|
1487
1504
|
if (processes.trim()) {
|
|
1488
|
-
cliLogger.info('\n🤖 Active
|
|
1505
|
+
cliLogger.info('\n🤖 Active SnowCode/Claude Code Processes:');
|
|
1489
1506
|
const lines = processes.trim().split('\n');
|
|
1490
1507
|
lines.forEach((line, index) => {
|
|
1491
1508
|
if (index < 3) { // Show max 3 processes
|
|
@@ -1576,43 +1593,92 @@ program
|
|
|
1576
1593
|
console.log('🔐 Creating environment configuration...');
|
|
1577
1594
|
await createEnvFile(targetDir, options.force);
|
|
1578
1595
|
// Create MCP configuration - always included now (SPARC is default)
|
|
1579
|
-
console.log('🔧 Setting up MCP servers for
|
|
1596
|
+
console.log('🔧 Setting up MCP servers for SnowCode (also works with Claude Code)...');
|
|
1580
1597
|
await createMCPConfig(targetDir, options.force);
|
|
1581
1598
|
// Copy CLAUDE.md file
|
|
1582
1599
|
console.log('📚 Creating documentation files...');
|
|
1583
1600
|
await copyCLAUDEmd(targetDir, options.force);
|
|
1584
1601
|
// Create README files
|
|
1585
1602
|
await createReadmeFiles(targetDir, options.force);
|
|
1586
|
-
// Copy
|
|
1587
|
-
await
|
|
1588
|
-
// Copy
|
|
1589
|
-
await
|
|
1603
|
+
// Copy snowcode-config.example.json
|
|
1604
|
+
await copySnowCodeConfig(targetDir, options.force);
|
|
1605
|
+
// Copy SnowCode themes
|
|
1606
|
+
await copySnowCodeThemes(targetDir, options.force);
|
|
1607
|
+
// Copy SnowCode package.json with snowcode-plugin
|
|
1608
|
+
console.log('📦 Configuring SnowCode plugin (snowcode fork)...');
|
|
1609
|
+
await copySnowCodePackageJson(targetDir, options.force);
|
|
1590
1610
|
// Copy MCP server management scripts
|
|
1591
1611
|
console.log('🔧 Setting up MCP server management scripts...');
|
|
1592
1612
|
await copyMCPServerScripts(targetDir, options.force);
|
|
1593
1613
|
console.log(chalk_1.default.green.bold('\n✅ Snow-Flow project initialized successfully!'));
|
|
1594
1614
|
console.log('\n📋 Created Snow-Flow configuration:');
|
|
1595
|
-
console.log(' ✓ .
|
|
1596
|
-
console.log(' ✓ .
|
|
1615
|
+
console.log(' ✓ .snowcode/ - SnowCode configuration with both MCP servers');
|
|
1616
|
+
console.log(' ✓ .snowcode/themes/ - ServiceNow custom theme for SnowCode');
|
|
1597
1617
|
console.log(' ✓ .claude/ - Claude Code MCP configuration (backward compatibility)');
|
|
1598
1618
|
console.log(' ✓ .mcp.json - 2 unified MCP servers (370 tools total)');
|
|
1599
|
-
console.log(' ✓ scripts/ - MCP server management and
|
|
1600
|
-
console.log(' ✓ AGENTS.md -
|
|
1619
|
+
console.log(' ✓ scripts/ - MCP server management and SnowCode launcher');
|
|
1620
|
+
console.log(' ✓ AGENTS.md - SnowCode primary instructions');
|
|
1601
1621
|
console.log(' ✓ CLAUDE.md - Claude Code compatibility');
|
|
1602
1622
|
console.log(' ✓ README.md - Complete capabilities documentation');
|
|
1603
|
-
console.log(' ✓
|
|
1623
|
+
console.log(' ✓ SNOWCODE-TROUBLESHOOTING.md - Troubleshooting guide');
|
|
1604
1624
|
console.log(' ✓ .snow-flow/ - Project workspace and memory');
|
|
1605
1625
|
if (!options.skipMcp) {
|
|
1606
|
-
// NOTE: MCP servers work with
|
|
1607
|
-
console.log(chalk_1.default.blue('\nℹ️ MCP servers configured for
|
|
1626
|
+
// NOTE: MCP servers work with SnowCode's native Task() system
|
|
1627
|
+
console.log(chalk_1.default.blue('\nℹ️ MCP servers configured for SnowCode (also compatible with Claude Code)'));
|
|
1608
1628
|
console.log(chalk_1.default.green('✅ 411 ServiceNow tools automatically available via 2 unified servers'));
|
|
1609
1629
|
console.log(chalk_1.default.blue('📋 SDK handles MCP server lifecycle automatically'));
|
|
1610
1630
|
// Verify MCP servers can actually start
|
|
1611
1631
|
console.log(chalk_1.default.dim('\n🔍 Verifying MCP server configuration...'));
|
|
1612
1632
|
await verifyMCPServers(targetDir);
|
|
1633
|
+
// Start MCP servers using the locally copied script
|
|
1634
|
+
console.log(chalk_1.default.blue('\n🚀 Starting MCP servers...'));
|
|
1635
|
+
try {
|
|
1636
|
+
const { execSync } = require('child_process');
|
|
1637
|
+
const path = require('path');
|
|
1638
|
+
const fs = require('fs');
|
|
1639
|
+
// Use the script that was copied to the project directory
|
|
1640
|
+
const localScriptPath = path.join(targetDir, 'scripts', 'mcp-server-manager.sh');
|
|
1641
|
+
// Check if the script exists locally
|
|
1642
|
+
if (!fs.existsSync(localScriptPath)) {
|
|
1643
|
+
throw new Error('MCP server manager script not found. Re-run snow-flow init if needed.');
|
|
1644
|
+
}
|
|
1645
|
+
// Make script executable
|
|
1646
|
+
try {
|
|
1647
|
+
fs.chmodSync(localScriptPath, '755');
|
|
1648
|
+
}
|
|
1649
|
+
catch (chmodError) {
|
|
1650
|
+
// Ignore chmod errors on Windows
|
|
1651
|
+
}
|
|
1652
|
+
// Execute and capture output
|
|
1653
|
+
const output = execSync(`bash "${localScriptPath}" start`, {
|
|
1654
|
+
cwd: targetDir,
|
|
1655
|
+
encoding: 'utf-8'
|
|
1656
|
+
});
|
|
1657
|
+
// Check if startup was successful
|
|
1658
|
+
if (output.includes('✓ MCP server started')) {
|
|
1659
|
+
console.log(chalk_1.default.green('✅ MCP servers started successfully'));
|
|
1660
|
+
const pidMatch = output.match(/PID: (\d+)/);
|
|
1661
|
+
if (pidMatch) {
|
|
1662
|
+
console.log(chalk_1.default.dim(` Server PID: ${pidMatch[1]}`));
|
|
1663
|
+
}
|
|
1664
|
+
console.log(chalk_1.default.dim(' Check status: ./scripts/mcp-server-manager.sh status'));
|
|
1665
|
+
console.log(chalk_1.default.dim(' View logs: ./scripts/mcp-server-manager.sh logs'));
|
|
1666
|
+
}
|
|
1667
|
+
else {
|
|
1668
|
+
console.log(chalk_1.default.yellow('⚠️ MCP server startup status unclear'));
|
|
1669
|
+
console.log(output);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
catch (error) {
|
|
1673
|
+
console.log(chalk_1.default.yellow('⚠️ MCP servers will start automatically when you launch SnowCode'));
|
|
1674
|
+
console.log(chalk_1.default.dim(' Or start manually: ./scripts/mcp-server-manager.sh start'));
|
|
1675
|
+
if (error.message.includes('No .env file found')) {
|
|
1676
|
+
console.log(chalk_1.default.dim(' 💡 Tip: Configure .env first, then run: ./scripts/mcp-server-manager.sh start'));
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1613
1679
|
}
|
|
1614
|
-
// Check and optionally install
|
|
1615
|
-
const configImported = await
|
|
1680
|
+
// Check and optionally install SnowCode
|
|
1681
|
+
const configImported = await checkAndInstallSnowCode();
|
|
1616
1682
|
console.log(chalk_1.default.blue.bold('\n🎯 Next steps:'));
|
|
1617
1683
|
console.log('1. Configure credentials: Edit ' + chalk_1.default.cyan('.env'));
|
|
1618
1684
|
console.log(' - Add your ServiceNow instance URL, username/password or OAuth credentials');
|
|
@@ -1620,10 +1686,10 @@ program
|
|
|
1620
1686
|
console.log(' - Authenticates with your LLM provider (Claude/OpenAI/Google/Ollama)');
|
|
1621
1687
|
console.log(' - Then authenticates with ServiceNow OAuth');
|
|
1622
1688
|
console.log(' - Your provider choice is automatically saved to .env');
|
|
1623
|
-
console.log('3. Start developing with
|
|
1689
|
+
console.log('3. Start developing with SnowCode: ' + chalk_1.default.cyan('./scripts/start-snowcode.sh'));
|
|
1624
1690
|
console.log(' - Smart launcher with pre-flight checks and MCP server management');
|
|
1625
1691
|
console.log(' - Or use swarm: ' + chalk_1.default.cyan('snow-flow swarm "create incident dashboard"'));
|
|
1626
|
-
console.log(' - Or launch
|
|
1692
|
+
console.log(' - Or launch SnowCode directly: ' + chalk_1.default.cyan('snowcode'));
|
|
1627
1693
|
console.log('\n📚 Documentation: ' + chalk_1.default.blue('https://github.com/groeimetai/snow-flow'));
|
|
1628
1694
|
console.log('💡 370+ ServiceNow tools • 2 MCP servers • Multi-LLM support');
|
|
1629
1695
|
// Force exit to prevent hanging
|
|
@@ -1654,7 +1720,7 @@ program
|
|
|
1654
1720
|
help Show this help
|
|
1655
1721
|
|
|
1656
1722
|
🎯 Example Usage:
|
|
1657
|
-
snow-flow init # Initialize project (auto-configures
|
|
1723
|
+
snow-flow init # Initialize project (auto-configures SnowCode)
|
|
1658
1724
|
snow-flow auth login # Authenticate (handles LLM + ServiceNow)
|
|
1659
1725
|
snow-flow auth status # Check authentication status
|
|
1660
1726
|
snow-flow swarm "create a widget for incident management"
|
|
@@ -1695,63 +1761,81 @@ program
|
|
|
1695
1761
|
`);
|
|
1696
1762
|
});
|
|
1697
1763
|
// Helper functions for init command
|
|
1698
|
-
// Check if
|
|
1699
|
-
async function
|
|
1764
|
+
// Check if SnowCode is installed, and offer to install it
|
|
1765
|
+
async function checkAndInstallSnowCode() {
|
|
1700
1766
|
const { execSync } = require('child_process');
|
|
1701
|
-
let
|
|
1767
|
+
let snowcodeInstalled = false;
|
|
1702
1768
|
try {
|
|
1703
|
-
// Check if
|
|
1704
|
-
execSync('which
|
|
1705
|
-
console.log(chalk_1.default.green('\n✅
|
|
1706
|
-
|
|
1769
|
+
// Check if snowcode is already installed
|
|
1770
|
+
execSync('which snowcode', { stdio: 'ignore' });
|
|
1771
|
+
console.log(chalk_1.default.green('\n✅ SnowCode is already installed!'));
|
|
1772
|
+
snowcodeInstalled = true;
|
|
1707
1773
|
}
|
|
1708
1774
|
catch {
|
|
1709
|
-
//
|
|
1710
|
-
console.log(chalk_1.default.yellow('\n⚠️
|
|
1711
|
-
console.log(chalk_1.default.blue('
|
|
1775
|
+
// SnowCode not installed
|
|
1776
|
+
console.log(chalk_1.default.yellow('\n⚠️ SnowCode is not installed'));
|
|
1777
|
+
console.log(chalk_1.default.blue('SnowCode is required to use Snow-Flow with any LLM provider'));
|
|
1712
1778
|
// Import inquirer dynamically
|
|
1713
1779
|
const inquirer = (await Promise.resolve().then(() => __importStar(require('inquirer')))).default;
|
|
1714
1780
|
const { shouldInstall } = await inquirer.prompt([
|
|
1715
1781
|
{
|
|
1716
1782
|
type: 'confirm',
|
|
1717
1783
|
name: 'shouldInstall',
|
|
1718
|
-
message: 'Would you like to install
|
|
1784
|
+
message: 'Would you like to install SnowCode now? (npm install -g @groeimetai/snowcode)',
|
|
1719
1785
|
default: true
|
|
1720
1786
|
}
|
|
1721
1787
|
]);
|
|
1722
1788
|
if (!shouldInstall) {
|
|
1723
|
-
console.log(chalk_1.default.yellow('\n⏭️ Skipping
|
|
1724
|
-
console.log(chalk_1.default.blue('You can install it later with: ') + chalk_1.default.cyan('npm install -g
|
|
1789
|
+
console.log(chalk_1.default.yellow('\n⏭️ Skipping SnowCode installation'));
|
|
1790
|
+
console.log(chalk_1.default.blue('You can install it later with: ') + chalk_1.default.cyan('npm install -g @groeimetai/snowcode'));
|
|
1725
1791
|
return false;
|
|
1726
1792
|
}
|
|
1727
|
-
// Install
|
|
1728
|
-
console.log(chalk_1.default.blue('\n📦 Installing
|
|
1793
|
+
// Install SnowCode
|
|
1794
|
+
console.log(chalk_1.default.blue('\n📦 Installing SnowCode globally...'));
|
|
1729
1795
|
console.log(chalk_1.default.dim('This may take a minute...'));
|
|
1730
1796
|
try {
|
|
1731
|
-
execSync('npm install -g
|
|
1732
|
-
console.log(chalk_1.default.green('\n✅
|
|
1733
|
-
|
|
1797
|
+
execSync('npm install -g @groeimetai/snowcode', { stdio: 'inherit' });
|
|
1798
|
+
console.log(chalk_1.default.green('\n✅ SnowCode installed successfully!'));
|
|
1799
|
+
snowcodeInstalled = true;
|
|
1734
1800
|
}
|
|
1735
1801
|
catch (error) {
|
|
1736
|
-
console.log(chalk_1.default.red('\n❌ Failed to install
|
|
1737
|
-
console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install -g
|
|
1802
|
+
console.log(chalk_1.default.red('\n❌ Failed to install SnowCode'));
|
|
1803
|
+
console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install -g @groeimetai/snowcode'));
|
|
1738
1804
|
return false;
|
|
1739
1805
|
}
|
|
1740
1806
|
}
|
|
1741
|
-
//
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
const
|
|
1807
|
+
// ALWAYS install SnowCode locally in the project directory with platform binaries
|
|
1808
|
+
console.log(chalk_1.default.blue('\n📦 Installing SnowCode locally (with platform binaries)...'));
|
|
1809
|
+
console.log(chalk_1.default.dim('Installing @groeimetai/snowcode@0.15.14-snow-flow-4...'));
|
|
1810
|
+
try {
|
|
1811
|
+
const projectDir = process.cwd();
|
|
1812
|
+
execSync('npm install @groeimetai/snowcode@0.15.14-snow-flow-4', {
|
|
1813
|
+
cwd: projectDir,
|
|
1814
|
+
stdio: 'inherit'
|
|
1815
|
+
});
|
|
1816
|
+
console.log(chalk_1.default.green('✅ SnowCode installed locally with platform binaries!'));
|
|
1817
|
+
console.log(chalk_1.default.dim(` Platform binary: opencode-${process.platform}-${process.arch}`));
|
|
1818
|
+
}
|
|
1819
|
+
catch (error) {
|
|
1820
|
+
console.log(chalk_1.default.red('\n❌ Failed to install SnowCode locally'));
|
|
1821
|
+
console.log(chalk_1.default.yellow('Please install it manually: ') + chalk_1.default.cyan('npm install @groeimetai/snowcode@0.15.14-snow-flow-4'));
|
|
1822
|
+
console.log(chalk_1.default.dim('This is required for the compiled binaries'));
|
|
1823
|
+
return false;
|
|
1824
|
+
}
|
|
1825
|
+
// If SnowCode is installed, copy config to .snowcode/ directory
|
|
1826
|
+
// SnowCode automatically detects config files in project root and .snowcode/ directory
|
|
1827
|
+
if (snowcodeInstalled) {
|
|
1828
|
+
const exampleConfigPath = (0, path_1.join)(process.cwd(), 'snowcode-config.example.json');
|
|
1829
|
+
const snowcodeConfigPath = (0, path_1.join)(process.cwd(), '.snowcode', 'config.json');
|
|
1746
1830
|
// Check if example config file exists
|
|
1747
1831
|
try {
|
|
1748
1832
|
await fs_1.promises.access(exampleConfigPath);
|
|
1749
|
-
console.log(chalk_1.default.blue('\n🔧 Setting up
|
|
1833
|
+
console.log(chalk_1.default.blue('\n🔧 Setting up SnowCode configuration...'));
|
|
1750
1834
|
try {
|
|
1751
|
-
// Copy example config to .
|
|
1835
|
+
// Copy example config to .snowcode/config.json for automatic detection
|
|
1752
1836
|
let configContent = await fs_1.promises.readFile(exampleConfigPath, 'utf-8');
|
|
1753
1837
|
// Ensure the config content has the correct cwd (in case it still has a placeholder)
|
|
1754
|
-
// This is a safety check - the placeholder should already be replaced by
|
|
1838
|
+
// This is a safety check - the placeholder should already be replaced by copySnowCodeConfig
|
|
1755
1839
|
if (configContent.includes('"/path/to/your/snow-flow/installation"')) {
|
|
1756
1840
|
console.log(chalk_1.default.yellow('⚠️ Config still contains placeholder, attempting to fix...'));
|
|
1757
1841
|
// Determine the snow-flow installation directory
|
|
@@ -1784,19 +1868,19 @@ async function checkAndInstallOpenCode() {
|
|
|
1784
1868
|
configContent = configContent.replace('"/path/to/your/snow-flow/installation"', `"${snowFlowRoot.replace(/\\/g, '/')}"`);
|
|
1785
1869
|
}
|
|
1786
1870
|
}
|
|
1787
|
-
await fs_1.promises.writeFile(
|
|
1788
|
-
console.log(chalk_1.default.green('✅
|
|
1789
|
-
console.log(chalk_1.default.blue('💡
|
|
1871
|
+
await fs_1.promises.writeFile(snowcodeConfigPath, configContent);
|
|
1872
|
+
console.log(chalk_1.default.green('✅ SnowCode configuration created at .snowcode/config.json'));
|
|
1873
|
+
console.log(chalk_1.default.blue('💡 SnowCode will automatically detect this configuration'));
|
|
1790
1874
|
return true; // Successfully configured
|
|
1791
1875
|
}
|
|
1792
1876
|
catch (error) {
|
|
1793
|
-
console.log(chalk_1.default.yellow('\n⚠️ Could not create
|
|
1794
|
-
console.log(chalk_1.default.blue('You can copy it manually: ') + chalk_1.default.cyan(`cp
|
|
1877
|
+
console.log(chalk_1.default.yellow('\n⚠️ Could not create SnowCode config'));
|
|
1878
|
+
console.log(chalk_1.default.blue('You can copy it manually: ') + chalk_1.default.cyan(`cp snowcode-config.example.json .snowcode/config.json`));
|
|
1795
1879
|
return false;
|
|
1796
1880
|
}
|
|
1797
1881
|
}
|
|
1798
1882
|
catch {
|
|
1799
|
-
console.log(chalk_1.default.yellow('\n⚠️
|
|
1883
|
+
console.log(chalk_1.default.yellow('\n⚠️ snowcode-config.example.json not found'));
|
|
1800
1884
|
console.log(chalk_1.default.blue('Config will be available after init completes'));
|
|
1801
1885
|
return false;
|
|
1802
1886
|
}
|
|
@@ -1857,7 +1941,7 @@ async function createReadmeFiles(targetDir, force = false) {
|
|
|
1857
1941
|
await fs_1.promises.writeFile((0, path_1.join)(targetDir, 'servicenow/README.md'), '# ServiceNow Artifacts\n\nThis directory contains generated ServiceNow development artifacts.');
|
|
1858
1942
|
}
|
|
1859
1943
|
// Helper functions
|
|
1860
|
-
async function
|
|
1944
|
+
async function copySnowCodeConfig(targetDir, force = false) {
|
|
1861
1945
|
try {
|
|
1862
1946
|
// Determine the snow-flow installation directory
|
|
1863
1947
|
let snowFlowRoot;
|
|
@@ -1892,14 +1976,14 @@ async function copyOpenCodeConfig(targetDir, force = false) {
|
|
|
1892
1976
|
throw new Error('Could not find snow-flow project root');
|
|
1893
1977
|
}
|
|
1894
1978
|
}
|
|
1895
|
-
// Try to find the
|
|
1979
|
+
// Try to find the snowcode-config.example.json
|
|
1896
1980
|
const sourceFiles = [
|
|
1897
|
-
(0, path_1.join)(snowFlowRoot, '
|
|
1898
|
-
(0, path_1.join)(__dirname, '..', '
|
|
1899
|
-
(0, path_1.join)(__dirname, '
|
|
1900
|
-
(0, path_1.join)(__dirname, '..', '..', '..', '
|
|
1901
|
-
(0, path_1.join)(__dirname, '..', '..', '..', '..', '
|
|
1902
|
-
(0, path_1.join)(process.cwd(), '
|
|
1981
|
+
(0, path_1.join)(snowFlowRoot, 'snowcode-config.example.json'),
|
|
1982
|
+
(0, path_1.join)(__dirname, '..', 'snowcode-config.example.json'),
|
|
1983
|
+
(0, path_1.join)(__dirname, 'snowcode-config.example.json'),
|
|
1984
|
+
(0, path_1.join)(__dirname, '..', '..', '..', 'snowcode-config.example.json'),
|
|
1985
|
+
(0, path_1.join)(__dirname, '..', '..', '..', '..', 'snowcode-config.example.json'),
|
|
1986
|
+
(0, path_1.join)(process.cwd(), 'snowcode-config.example.json')
|
|
1903
1987
|
];
|
|
1904
1988
|
let foundSource = false;
|
|
1905
1989
|
let configContent = '';
|
|
@@ -1907,7 +1991,7 @@ async function copyOpenCodeConfig(targetDir, force = false) {
|
|
|
1907
1991
|
try {
|
|
1908
1992
|
configContent = await fs_1.promises.readFile(sourcePath, 'utf8');
|
|
1909
1993
|
foundSource = true;
|
|
1910
|
-
console.log(`✅ Found
|
|
1994
|
+
console.log(`✅ Found snowcode-config.example.json at: ${sourcePath}`);
|
|
1911
1995
|
break;
|
|
1912
1996
|
}
|
|
1913
1997
|
catch {
|
|
@@ -1915,19 +1999,19 @@ async function copyOpenCodeConfig(targetDir, force = false) {
|
|
|
1915
1999
|
}
|
|
1916
2000
|
}
|
|
1917
2001
|
if (!foundSource) {
|
|
1918
|
-
console.log('⚠️ Could not find
|
|
2002
|
+
console.log('⚠️ Could not find snowcode-config.example.json source file');
|
|
1919
2003
|
return;
|
|
1920
2004
|
}
|
|
1921
2005
|
// Replace placeholders with actual snow-flow installation path
|
|
1922
2006
|
configContent = configContent.replace('"/path/to/your/snow-flow/installation"', `"${snowFlowRoot.replace(/\\/g, '/')}"`);
|
|
1923
|
-
const targetPath = (0, path_1.join)(targetDir, '
|
|
2007
|
+
const targetPath = (0, path_1.join)(targetDir, 'snowcode-config.example.json');
|
|
1924
2008
|
try {
|
|
1925
2009
|
await fs_1.promises.access(targetPath);
|
|
1926
2010
|
if (force) {
|
|
1927
|
-
console.log('⚠️
|
|
2011
|
+
console.log('⚠️ snowcode-config.example.json already exists, overwriting with --force flag');
|
|
1928
2012
|
}
|
|
1929
2013
|
else {
|
|
1930
|
-
console.log('✅
|
|
2014
|
+
console.log('✅ snowcode-config.example.json already exists');
|
|
1931
2015
|
return;
|
|
1932
2016
|
}
|
|
1933
2017
|
}
|
|
@@ -1935,15 +2019,15 @@ async function copyOpenCodeConfig(targetDir, force = false) {
|
|
|
1935
2019
|
// File doesn't exist, continue with creation
|
|
1936
2020
|
}
|
|
1937
2021
|
await fs_1.promises.writeFile(targetPath, configContent);
|
|
1938
|
-
console.log('✅ Created
|
|
2022
|
+
console.log('✅ Created snowcode-config.example.json with correct snow-flow path');
|
|
1939
2023
|
}
|
|
1940
2024
|
catch (error) {
|
|
1941
|
-
console.error('❌ Error copying
|
|
2025
|
+
console.error('❌ Error copying snowcode-config.example.json:', error);
|
|
1942
2026
|
}
|
|
1943
2027
|
}
|
|
1944
|
-
async function
|
|
2028
|
+
async function copySnowCodeThemes(targetDir, force = false) {
|
|
1945
2029
|
try {
|
|
1946
|
-
// Determine the snow-flow installation directory (same logic as
|
|
2030
|
+
// Determine the snow-flow installation directory (same logic as copySnowCodeConfig)
|
|
1947
2031
|
let snowFlowRoot;
|
|
1948
2032
|
const isGlobalInstall = __dirname.includes('node_modules/snow-flow') ||
|
|
1949
2033
|
__dirname.includes('node_modules/.pnpm') ||
|
|
@@ -1977,8 +2061,8 @@ async function copyOpenCodeThemes(targetDir, force = false) {
|
|
|
1977
2061
|
(0, path_1.join)(snowFlowRoot, 'themes'),
|
|
1978
2062
|
(0, path_1.join)(__dirname, '..', 'themes'),
|
|
1979
2063
|
(0, path_1.join)(__dirname, 'themes'),
|
|
1980
|
-
(0, path_1.join)(snowFlowRoot, '.
|
|
1981
|
-
(0, path_1.join)(__dirname, '..', '.
|
|
2064
|
+
(0, path_1.join)(snowFlowRoot, '.snowcode', 'themes'),
|
|
2065
|
+
(0, path_1.join)(__dirname, '..', '.snowcode', 'themes')
|
|
1982
2066
|
];
|
|
1983
2067
|
let themesSourceDir = null;
|
|
1984
2068
|
for (const sourcePath of themesSourcePaths) {
|
|
@@ -1996,8 +2080,8 @@ async function copyOpenCodeThemes(targetDir, force = false) {
|
|
|
1996
2080
|
console.log('⚠️ Could not find themes directory, skipping theme installation');
|
|
1997
2081
|
return;
|
|
1998
2082
|
}
|
|
1999
|
-
// Create target .
|
|
2000
|
-
const themesTargetDir = (0, path_1.join)(targetDir, '.
|
|
2083
|
+
// Create target .snowcode/themes directory
|
|
2084
|
+
const themesTargetDir = (0, path_1.join)(targetDir, '.snowcode', 'themes');
|
|
2001
2085
|
await fs_1.promises.mkdir(themesTargetDir, { recursive: true });
|
|
2002
2086
|
// Copy all theme files
|
|
2003
2087
|
const themeFiles = await fs_1.promises.readdir(themesSourceDir);
|
|
@@ -2029,11 +2113,86 @@ async function copyOpenCodeThemes(targetDir, force = false) {
|
|
|
2029
2113
|
}
|
|
2030
2114
|
}
|
|
2031
2115
|
if (copiedCount > 0) {
|
|
2032
|
-
console.log(`✅ Copied ${copiedCount}
|
|
2116
|
+
console.log(`✅ Copied ${copiedCount} SnowCode theme file(s) to .snowcode/themes/`);
|
|
2033
2117
|
}
|
|
2034
2118
|
}
|
|
2035
2119
|
catch (error) {
|
|
2036
|
-
console.error('❌ Error copying
|
|
2120
|
+
console.error('❌ Error copying SnowCode themes:', error);
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
async function copySnowCodePackageJson(targetDir, force = false) {
|
|
2124
|
+
try {
|
|
2125
|
+
// Determine the snow-flow installation directory
|
|
2126
|
+
let snowFlowRoot;
|
|
2127
|
+
const isGlobalInstall = __dirname.includes('node_modules/snow-flow') ||
|
|
2128
|
+
__dirname.includes('node_modules/.pnpm') ||
|
|
2129
|
+
__dirname.includes('npm/snow-flow');
|
|
2130
|
+
if (isGlobalInstall) {
|
|
2131
|
+
const parts = __dirname.split(/node_modules[\/\\]/);
|
|
2132
|
+
snowFlowRoot = parts[0] + 'node_modules/snow-flow';
|
|
2133
|
+
}
|
|
2134
|
+
else {
|
|
2135
|
+
let currentDir = __dirname;
|
|
2136
|
+
while (currentDir !== '/') {
|
|
2137
|
+
try {
|
|
2138
|
+
const packageJsonPath = (0, path_1.join)(currentDir, 'package.json');
|
|
2139
|
+
const packageJson = JSON.parse(await fs_1.promises.readFile(packageJsonPath, 'utf-8'));
|
|
2140
|
+
if (packageJson.name === 'snow-flow') {
|
|
2141
|
+
snowFlowRoot = currentDir;
|
|
2142
|
+
break;
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
catch {
|
|
2146
|
+
// Continue searching up
|
|
2147
|
+
}
|
|
2148
|
+
currentDir = (0, path_1.dirname)(currentDir);
|
|
2149
|
+
}
|
|
2150
|
+
if (!snowFlowRoot) {
|
|
2151
|
+
throw new Error('Could not find snow-flow project root');
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
// Find snowcode package.json template
|
|
2155
|
+
const templateSourcePaths = [
|
|
2156
|
+
(0, path_1.join)(snowFlowRoot, 'templates', 'snowcode-package.json'),
|
|
2157
|
+
(0, path_1.join)(__dirname, '..', 'templates', 'snowcode-package.json'),
|
|
2158
|
+
(0, path_1.join)(__dirname, 'templates', 'snowcode-package.json')
|
|
2159
|
+
];
|
|
2160
|
+
let templatePath = null;
|
|
2161
|
+
for (const sourcePath of templateSourcePaths) {
|
|
2162
|
+
try {
|
|
2163
|
+
await fs_1.promises.access(sourcePath);
|
|
2164
|
+
templatePath = sourcePath;
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
catch {
|
|
2168
|
+
// Continue to next path
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
if (!templatePath) {
|
|
2172
|
+
console.log('⚠️ SnowCode package.json template not found, SnowCode will use default plugin');
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
// Create .snowcode directory
|
|
2176
|
+
const snowcodeDir = (0, path_1.join)(targetDir, '.snowcode');
|
|
2177
|
+
await fs_1.promises.mkdir(snowcodeDir, { recursive: true });
|
|
2178
|
+
// Copy package.json template
|
|
2179
|
+
const targetPath = (0, path_1.join)(snowcodeDir, 'package.json');
|
|
2180
|
+
// Check if file already exists
|
|
2181
|
+
try {
|
|
2182
|
+
await fs_1.promises.access(targetPath);
|
|
2183
|
+
if (!force) {
|
|
2184
|
+
console.log('✅ .snowcode/package.json already exists (snowcode-plugin configured)');
|
|
2185
|
+
return;
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
catch {
|
|
2189
|
+
// File doesn't exist, we can create it
|
|
2190
|
+
}
|
|
2191
|
+
await fs_1.promises.copyFile(templatePath, targetPath);
|
|
2192
|
+
console.log('✅ Created .snowcode/package.json with @groeimetai/snowcode-plugin');
|
|
2193
|
+
}
|
|
2194
|
+
catch (error) {
|
|
2195
|
+
console.error('❌ Error copying SnowCode package.json:', error);
|
|
2037
2196
|
}
|
|
2038
2197
|
}
|
|
2039
2198
|
/**
|
|
@@ -2044,8 +2203,8 @@ async function verifyMCPServers(targetDir) {
|
|
|
2044
2203
|
const path = require('path');
|
|
2045
2204
|
const fs = require('fs').promises;
|
|
2046
2205
|
try {
|
|
2047
|
-
// Read
|
|
2048
|
-
const configPath = path.join(targetDir, '.
|
|
2206
|
+
// Read SnowCode configuration
|
|
2207
|
+
const configPath = path.join(targetDir, '.snowcode', 'snowcode.json');
|
|
2049
2208
|
const configContent = await fs.readFile(configPath, 'utf-8');
|
|
2050
2209
|
const config = JSON.parse(configContent);
|
|
2051
2210
|
if (!config.mcp) {
|
|
@@ -2064,7 +2223,11 @@ async function verifyMCPServers(targetDir) {
|
|
|
2064
2223
|
process.stdout.write(chalk_1.default.dim(` Testing ${serverName}... `));
|
|
2065
2224
|
try {
|
|
2066
2225
|
// Try to spawn the MCP server
|
|
2067
|
-
|
|
2226
|
+
// Handle both old format (command: string, args: array) and new format (command: array)
|
|
2227
|
+
const [cmd, ...args] = Array.isArray(serverConfig.command)
|
|
2228
|
+
? serverConfig.command
|
|
2229
|
+
: [serverConfig.command, ...(serverConfig.args || [])];
|
|
2230
|
+
const serverProcess = spawn(cmd, args, {
|
|
2068
2231
|
env: { ...process.env, ...serverConfig.env },
|
|
2069
2232
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
2070
2233
|
});
|
|
@@ -2099,7 +2262,8 @@ async function verifyMCPServers(targetDir) {
|
|
|
2099
2262
|
}
|
|
2100
2263
|
else if (error.includes('Cannot find module') || error.includes('ENOENT')) {
|
|
2101
2264
|
console.log(chalk_1.default.red('✗ (server file not found)'));
|
|
2102
|
-
|
|
2265
|
+
const serverPath = Array.isArray(serverConfig.command) ? serverConfig.command[1] : serverConfig.args?.[0];
|
|
2266
|
+
console.log(chalk_1.default.yellow(` Check: ${serverPath}`));
|
|
2103
2267
|
failCount++;
|
|
2104
2268
|
}
|
|
2105
2269
|
else if (error) {
|
|
@@ -2142,7 +2306,7 @@ async function verifyMCPServers(targetDir) {
|
|
|
2142
2306
|
}
|
|
2143
2307
|
catch (error) {
|
|
2144
2308
|
console.log(chalk_1.default.yellow(` ⚠️ Could not verify MCP servers: ${error.message}`));
|
|
2145
|
-
console.log(chalk_1.default.dim(' Servers will be tested when
|
|
2309
|
+
console.log(chalk_1.default.dim(' Servers will be tested when SnowCode starts'));
|
|
2146
2310
|
}
|
|
2147
2311
|
}
|
|
2148
2312
|
async function copyMCPServerScripts(targetDir, force = false) {
|
|
@@ -2204,7 +2368,7 @@ async function copyMCPServerScripts(targetDir, force = false) {
|
|
|
2204
2368
|
// Copy specific scripts
|
|
2205
2369
|
const scriptFiles = [
|
|
2206
2370
|
'mcp-server-manager.sh',
|
|
2207
|
-
'start-
|
|
2371
|
+
'start-snowcode.sh'
|
|
2208
2372
|
];
|
|
2209
2373
|
let copiedCount = 0;
|
|
2210
2374
|
for (const scriptFile of scriptFiles) {
|
|
@@ -2234,11 +2398,11 @@ async function copyMCPServerScripts(targetDir, force = false) {
|
|
|
2234
2398
|
console.log(`✅ Copied ${copiedCount} MCP server management script(s) to scripts/`);
|
|
2235
2399
|
console.log(`✅ Scripts are executable and ready to use`);
|
|
2236
2400
|
}
|
|
2237
|
-
// Also copy
|
|
2401
|
+
// Also copy SNOWCODE-TROUBLESHOOTING.md to project root
|
|
2238
2402
|
const troubleshootingSourcePaths = [
|
|
2239
|
-
(0, path_1.join)(snowFlowRoot, '
|
|
2240
|
-
(0, path_1.join)(__dirname, '..', '
|
|
2241
|
-
(0, path_1.join)(__dirname, '
|
|
2403
|
+
(0, path_1.join)(snowFlowRoot, 'SNOWCODE-TROUBLESHOOTING.md'),
|
|
2404
|
+
(0, path_1.join)(__dirname, '..', 'SNOWCODE-TROUBLESHOOTING.md'),
|
|
2405
|
+
(0, path_1.join)(__dirname, 'SNOWCODE-TROUBLESHOOTING.md')
|
|
2242
2406
|
];
|
|
2243
2407
|
let troubleshootingSourcePath = null;
|
|
2244
2408
|
for (const sourcePath of troubleshootingSourcePaths) {
|
|
@@ -2252,22 +2416,22 @@ async function copyMCPServerScripts(targetDir, force = false) {
|
|
|
2252
2416
|
}
|
|
2253
2417
|
}
|
|
2254
2418
|
if (troubleshootingSourcePath) {
|
|
2255
|
-
const targetPath = (0, path_1.join)(targetDir, '
|
|
2419
|
+
const targetPath = (0, path_1.join)(targetDir, 'SNOWCODE-TROUBLESHOOTING.md');
|
|
2256
2420
|
try {
|
|
2257
2421
|
await fs_1.promises.access(targetPath);
|
|
2258
2422
|
if (!force) {
|
|
2259
|
-
console.log(`✅
|
|
2423
|
+
console.log(`✅ SNOWCODE-TROUBLESHOOTING.md already exists`);
|
|
2260
2424
|
}
|
|
2261
2425
|
else {
|
|
2262
2426
|
const content = await fs_1.promises.readFile(troubleshootingSourcePath, 'utf8');
|
|
2263
2427
|
await fs_1.promises.writeFile(targetPath, content);
|
|
2264
|
-
console.log(`✅ Created
|
|
2428
|
+
console.log(`✅ Created SNOWCODE-TROUBLESHOOTING.md`);
|
|
2265
2429
|
}
|
|
2266
2430
|
}
|
|
2267
2431
|
catch {
|
|
2268
2432
|
const content = await fs_1.promises.readFile(troubleshootingSourcePath, 'utf8');
|
|
2269
2433
|
await fs_1.promises.writeFile(targetPath, content);
|
|
2270
|
-
console.log(`✅ Created
|
|
2434
|
+
console.log(`✅ Created SNOWCODE-TROUBLESHOOTING.md`);
|
|
2271
2435
|
}
|
|
2272
2436
|
}
|
|
2273
2437
|
}
|
|
@@ -2356,7 +2520,7 @@ async function copyCLAUDEmd(targetDir, force = false) {
|
|
|
2356
2520
|
await fs_1.promises.writeFile(claudeMdPath, claudeMdContent);
|
|
2357
2521
|
console.log('✅ Created CLAUDE.md (Primary instructions)');
|
|
2358
2522
|
}
|
|
2359
|
-
// Create AGENTS.md (identical copy for
|
|
2523
|
+
// Create AGENTS.md (identical copy for SnowCode compatibility)
|
|
2360
2524
|
const agentsMdPath = (0, path_1.join)(targetDir, 'AGENTS.md');
|
|
2361
2525
|
try {
|
|
2362
2526
|
await fs_1.promises.access(agentsMdPath);
|
|
@@ -2370,18 +2534,18 @@ async function copyCLAUDEmd(targetDir, force = false) {
|
|
|
2370
2534
|
}
|
|
2371
2535
|
catch {
|
|
2372
2536
|
await fs_1.promises.writeFile(agentsMdPath, agentsMdContent);
|
|
2373
|
-
console.log('✅ Created AGENTS.md (Identical copy for
|
|
2537
|
+
console.log('✅ Created AGENTS.md (Identical copy for SnowCode compatibility)');
|
|
2374
2538
|
}
|
|
2375
|
-
// Create .
|
|
2376
|
-
const
|
|
2377
|
-
const agentsDir = (0, path_1.join)(
|
|
2378
|
-
const modesDir = (0, path_1.join)(
|
|
2539
|
+
// Create .snowcode/ directory structure
|
|
2540
|
+
const snowcodeDir = (0, path_1.join)(targetDir, '.snowcode');
|
|
2541
|
+
const agentsDir = (0, path_1.join)(snowcodeDir, 'agent'); // Singular 'agent' as required by SnowCode
|
|
2542
|
+
const modesDir = (0, path_1.join)(snowcodeDir, 'modes');
|
|
2379
2543
|
try {
|
|
2380
|
-
await fs_1.promises.mkdir(
|
|
2544
|
+
await fs_1.promises.mkdir(snowcodeDir, { recursive: true });
|
|
2381
2545
|
await fs_1.promises.mkdir(agentsDir, { recursive: true });
|
|
2382
2546
|
await fs_1.promises.mkdir(modesDir, { recursive: true });
|
|
2383
|
-
console.log('✅ Created .
|
|
2384
|
-
// Copy agent files from .claude/ to .
|
|
2547
|
+
console.log('✅ Created .snowcode/ directory structure');
|
|
2548
|
+
// Copy agent files from .claude/ to .snowcode/agent/ (if they exist)
|
|
2385
2549
|
const sourceAgentsDir = (0, path_1.join)(__dirname, '..', '.claude', 'agents');
|
|
2386
2550
|
try {
|
|
2387
2551
|
const agentFiles = await fs_1.promises.readdir(sourceAgentsDir);
|
|
@@ -2393,68 +2557,85 @@ async function copyCLAUDEmd(targetDir, force = false) {
|
|
|
2393
2557
|
await fs_1.promises.writeFile(targetFile, content);
|
|
2394
2558
|
}
|
|
2395
2559
|
}
|
|
2396
|
-
console.log('✅ Copied agent configurations to .
|
|
2560
|
+
console.log('✅ Copied agent configurations to .snowcode/agent/');
|
|
2397
2561
|
}
|
|
2398
2562
|
catch (err) {
|
|
2399
|
-
// Silently continue - agent configs are in
|
|
2400
|
-
}
|
|
2401
|
-
// Create .
|
|
2402
|
-
//
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
},
|
|
2427
|
-
"snow-flow": {
|
|
2428
|
-
type: "local",
|
|
2429
|
-
command: "node",
|
|
2430
|
-
args: [(0, path_1.join)(distPath, "mcp/snow-flow-mcp.js")],
|
|
2431
|
-
env: {
|
|
2432
|
-
SNOW_FLOW_ENV: "production"
|
|
2433
|
-
},
|
|
2434
|
-
enabled: true,
|
|
2435
|
-
description: "Snow-Flow orchestration with 176+ tools: swarm coordination, agent spawning, memory, neural learning"
|
|
2563
|
+
// Silently continue - agent configs are in snowcode.json, not separate files
|
|
2564
|
+
}
|
|
2565
|
+
// Create .snowcode/snowcode.json by converting from .mcp.json.template
|
|
2566
|
+
// SINGLE SOURCE OF TRUTH: .mcp.json.template → both Claude and SnowCode formats
|
|
2567
|
+
// CRITICAL: SnowCode/OpenCode does NOT auto-expand ${...} variables
|
|
2568
|
+
// 🔧 Read actual environment values from .env file
|
|
2569
|
+
const envPath = (0, path_1.join)(targetDir, '.env');
|
|
2570
|
+
const envValues = {};
|
|
2571
|
+
try {
|
|
2572
|
+
const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
|
|
2573
|
+
// Parse .env file (simple parser - handles KEY=VALUE lines)
|
|
2574
|
+
const lines = envContent.split('\n');
|
|
2575
|
+
for (var line of lines) {
|
|
2576
|
+
line = line.trim();
|
|
2577
|
+
// Skip comments and empty lines
|
|
2578
|
+
if (!line || line.startsWith('#'))
|
|
2579
|
+
continue;
|
|
2580
|
+
var equalIndex = line.indexOf('=');
|
|
2581
|
+
if (equalIndex > 0) {
|
|
2582
|
+
var key = line.substring(0, equalIndex).trim();
|
|
2583
|
+
var value = line.substring(equalIndex + 1).trim();
|
|
2584
|
+
// Remove quotes if present
|
|
2585
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
2586
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
2587
|
+
value = value.substring(1, value.length - 1);
|
|
2588
|
+
}
|
|
2589
|
+
envValues[key] = value;
|
|
2436
2590
|
}
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
//
|
|
2452
|
-
const
|
|
2453
|
-
|
|
2454
|
-
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
catch (error) {
|
|
2594
|
+
console.log('⚠️ No .env file found - SnowCode config will use placeholder values');
|
|
2595
|
+
}
|
|
2596
|
+
// Helper function to get env value with proper URL formatting
|
|
2597
|
+
function getEnvValue(key, defaultValue = '') {
|
|
2598
|
+
var value = envValues[key] || process.env[key] || defaultValue;
|
|
2599
|
+
// Special handling for SNOW_INSTANCE - ensure it's a full URL
|
|
2600
|
+
if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
|
|
2601
|
+
value = 'https://' + value.replace(/^https?:\/\//, '');
|
|
2602
|
+
}
|
|
2603
|
+
return value;
|
|
2604
|
+
}
|
|
2605
|
+
// Read .mcp.json.template (single source of truth for MCP servers)
|
|
2606
|
+
const mcpTemplatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
|
|
2607
|
+
let mcpTemplateContent;
|
|
2608
|
+
try {
|
|
2609
|
+
mcpTemplateContent = await fs_1.promises.readFile(mcpTemplatePath, 'utf-8');
|
|
2610
|
+
}
|
|
2611
|
+
catch (error) {
|
|
2612
|
+
console.log('⚠️ Could not find .mcp.json.template');
|
|
2613
|
+
throw error;
|
|
2614
|
+
}
|
|
2615
|
+
// Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
|
|
2616
|
+
const mcpConfigContent = mcpTemplateContent
|
|
2617
|
+
.replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
|
|
2618
|
+
.replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
|
|
2619
|
+
.replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
|
|
2620
|
+
.replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
|
|
2621
|
+
.replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
|
|
2622
|
+
const claudeConfig = JSON.parse(mcpConfigContent);
|
|
2623
|
+
// Convert Claude Desktop format to SnowCode format
|
|
2624
|
+
const snowcodeConfig = convertToSnowCodeFormat(claudeConfig);
|
|
2625
|
+
// Write both snowcode.json AND config.json (Claude uses config.json)
|
|
2626
|
+
const snowcodeConfigPath = (0, path_1.join)(snowcodeDir, 'snowcode.json');
|
|
2627
|
+
const configJsonPath = (0, path_1.join)(snowcodeDir, 'config.json');
|
|
2628
|
+
await fs_1.promises.writeFile(snowcodeConfigPath, JSON.stringify(snowcodeConfig, null, 2));
|
|
2629
|
+
await fs_1.promises.writeFile(configJsonPath, JSON.stringify(snowcodeConfig, null, 2));
|
|
2630
|
+
console.log('✅ Created .snowcode/snowcode.json (converted from .mcp.json.template → SnowCode format)');
|
|
2631
|
+
console.log('✅ Created .snowcode/config.json (SnowCode format, Claude compatibility)');
|
|
2632
|
+
// Also create AGENTS.md in .snowcode/
|
|
2633
|
+
const snowcodeAgentsMdPath = (0, path_1.join)(snowcodeDir, 'AGENTS.md');
|
|
2634
|
+
await fs_1.promises.writeFile(snowcodeAgentsMdPath, agentsMdContent);
|
|
2635
|
+
console.log('✅ Created .snowcode/AGENTS.md');
|
|
2455
2636
|
}
|
|
2456
2637
|
catch (error) {
|
|
2457
|
-
console.log('⚠️ Error creating .
|
|
2638
|
+
console.log('⚠️ Error creating .snowcode/ directory:', error instanceof Error ? error.message : String(error));
|
|
2458
2639
|
}
|
|
2459
2640
|
}
|
|
2460
2641
|
catch (error) {
|
|
@@ -2578,6 +2759,40 @@ async function appendToEnvFile(targetDir, content) {
|
|
|
2578
2759
|
const envFilePath = (0, path_1.join)(targetDir, '.env');
|
|
2579
2760
|
await fs_1.promises.appendFile(envFilePath, content);
|
|
2580
2761
|
}
|
|
2762
|
+
/**
|
|
2763
|
+
* Converts Claude Desktop MCP config format to SnowCode/OpenCode format
|
|
2764
|
+
* Single source of truth: .mcp.json.template → both .mcp.json and .snowcode/snowcode.json
|
|
2765
|
+
*/
|
|
2766
|
+
function convertToSnowCodeFormat(claudeConfig) {
|
|
2767
|
+
const snowcodeConfig = {
|
|
2768
|
+
"$schema": "https://opencode.ai/config.json",
|
|
2769
|
+
"name": "snow-flow",
|
|
2770
|
+
"description": "ServiceNow development with SnowCode and multi-LLM support",
|
|
2771
|
+
"mcp": {},
|
|
2772
|
+
"tools": {
|
|
2773
|
+
"enabled": true,
|
|
2774
|
+
"requireApproval": false
|
|
2775
|
+
},
|
|
2776
|
+
"instructions": [
|
|
2777
|
+
"AGENTS.md",
|
|
2778
|
+
"../CLAUDE.md",
|
|
2779
|
+
"../AGENTS.md"
|
|
2780
|
+
]
|
|
2781
|
+
};
|
|
2782
|
+
// Convert each server from Claude Desktop format to SnowCode format
|
|
2783
|
+
const servers = claudeConfig.servers || claudeConfig.mcpServers || {};
|
|
2784
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
2785
|
+
const s = server;
|
|
2786
|
+
snowcodeConfig.mcp[name] = {
|
|
2787
|
+
type: "local",
|
|
2788
|
+
command: s.args ? [s.command, ...s.args] : (Array.isArray(s.command) ? s.command : [s.command]),
|
|
2789
|
+
environment: s.env || s.environment || {},
|
|
2790
|
+
enabled: true,
|
|
2791
|
+
description: s.description || ""
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
return snowcodeConfig;
|
|
2795
|
+
}
|
|
2581
2796
|
async function checkNeo4jAvailability() {
|
|
2582
2797
|
const { execSync } = require('child_process');
|
|
2583
2798
|
try {
|
|
@@ -2633,6 +2848,45 @@ async function createMCPConfig(targetDir, force = false) {
|
|
|
2633
2848
|
throw new Error('Could not find snow-flow project root');
|
|
2634
2849
|
}
|
|
2635
2850
|
}
|
|
2851
|
+
// 🔧 FIX: Read actual environment values from .env file
|
|
2852
|
+
// This solves the issue where SnowCode/Claude Code doesn't expand ${...} variables
|
|
2853
|
+
const envPath = (0, path_1.join)(targetDir, '.env');
|
|
2854
|
+
const envValues = {};
|
|
2855
|
+
try {
|
|
2856
|
+
const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
|
|
2857
|
+
// Parse .env file (simple parser - handles KEY=VALUE lines)
|
|
2858
|
+
const lines = envContent.split('\n');
|
|
2859
|
+
for (var line of lines) {
|
|
2860
|
+
line = line.trim();
|
|
2861
|
+
// Skip comments and empty lines
|
|
2862
|
+
if (!line || line.startsWith('#'))
|
|
2863
|
+
continue;
|
|
2864
|
+
var equalIndex = line.indexOf('=');
|
|
2865
|
+
if (equalIndex > 0) {
|
|
2866
|
+
var key = line.substring(0, equalIndex).trim();
|
|
2867
|
+
var value = line.substring(equalIndex + 1).trim();
|
|
2868
|
+
// Remove quotes if present
|
|
2869
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
2870
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
2871
|
+
value = value.substring(1, value.length - 1);
|
|
2872
|
+
}
|
|
2873
|
+
envValues[key] = value;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
catch (error) {
|
|
2878
|
+
console.log('⚠️ No .env file found - MCP config will use placeholder values');
|
|
2879
|
+
console.log(' Run "snow-flow auth login" after init to configure credentials');
|
|
2880
|
+
}
|
|
2881
|
+
// Helper function to get env value with proper URL formatting
|
|
2882
|
+
function getEnvValue(key, defaultValue = '') {
|
|
2883
|
+
var value = envValues[key] || process.env[key] || defaultValue;
|
|
2884
|
+
// Special handling for SNOW_INSTANCE - ensure it's a full URL
|
|
2885
|
+
if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
|
|
2886
|
+
value = 'https://' + value.replace(/^https?:\/\//, '');
|
|
2887
|
+
}
|
|
2888
|
+
return value;
|
|
2889
|
+
}
|
|
2636
2890
|
// Read the template file
|
|
2637
2891
|
const templatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
|
|
2638
2892
|
let templateContent;
|
|
@@ -2643,19 +2897,20 @@ async function createMCPConfig(targetDir, force = false) {
|
|
|
2643
2897
|
console.error('❌ Could not find .mcp.json.template file');
|
|
2644
2898
|
throw error;
|
|
2645
2899
|
}
|
|
2646
|
-
// Replace placeholders
|
|
2900
|
+
// Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
|
|
2901
|
+
// This ensures SnowCode/Claude Code can use the MCP servers immediately
|
|
2647
2902
|
const distPath = (0, path_1.join)(snowFlowRoot, 'dist');
|
|
2648
2903
|
const mcpConfigContent = templateContent
|
|
2649
2904
|
.replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
|
|
2650
|
-
.replace(/{{SNOW_INSTANCE}}/g, '
|
|
2651
|
-
.replace(/{{SNOW_CLIENT_ID}}/g, '
|
|
2652
|
-
.replace(/{{SNOW_CLIENT_SECRET}}/g, '
|
|
2653
|
-
.replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, '
|
|
2654
|
-
.replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, '
|
|
2655
|
-
.replace(/{{NEO4J_URI}}/g, '
|
|
2656
|
-
.replace(/{{NEO4J_USER}}/g, '
|
|
2657
|
-
.replace(/{{NEO4J_PASSWORD}}/g, '
|
|
2658
|
-
.replace(/{{SNOW_FLOW_ENV}}/g, '
|
|
2905
|
+
.replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
|
|
2906
|
+
.replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
|
|
2907
|
+
.replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
|
|
2908
|
+
.replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('SNOW_DEPLOYMENT_TIMEOUT', '180000'))
|
|
2909
|
+
.replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('MCP_DEPLOYMENT_TIMEOUT', '180000'))
|
|
2910
|
+
.replace(/{{NEO4J_URI}}/g, getEnvValue('NEO4J_URI', ''))
|
|
2911
|
+
.replace(/{{NEO4J_USER}}/g, getEnvValue('NEO4J_USER', ''))
|
|
2912
|
+
.replace(/{{NEO4J_PASSWORD}}/g, getEnvValue('NEO4J_PASSWORD', ''))
|
|
2913
|
+
.replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
|
|
2659
2914
|
// Parse to ensure it's valid JSON
|
|
2660
2915
|
const mcpConfig = JSON.parse(mcpConfigContent);
|
|
2661
2916
|
// Keep the standard MCP structure that Claude Code expects
|
|
@@ -2912,6 +3167,44 @@ async function setupMCPConfig(targetDir, instanceUrl, clientId, clientSecret, fo
|
|
|
2912
3167
|
throw new Error('Could not find snow-flow project root');
|
|
2913
3168
|
}
|
|
2914
3169
|
}
|
|
3170
|
+
// 🔧 FIX: Read actual environment values from .env file
|
|
3171
|
+
// This solves the issue where SnowCode/Claude Code doesn't expand ${...} variables
|
|
3172
|
+
const envPath = (0, path_1.join)(targetDir, '.env');
|
|
3173
|
+
const envValues = {};
|
|
3174
|
+
try {
|
|
3175
|
+
const envContent = await fs_1.promises.readFile(envPath, 'utf-8');
|
|
3176
|
+
// Parse .env file (simple parser - handles KEY=VALUE lines)
|
|
3177
|
+
const lines = envContent.split('\n');
|
|
3178
|
+
for (var line of lines) {
|
|
3179
|
+
line = line.trim();
|
|
3180
|
+
// Skip comments and empty lines
|
|
3181
|
+
if (!line || line.startsWith('#'))
|
|
3182
|
+
continue;
|
|
3183
|
+
var equalIndex = line.indexOf('=');
|
|
3184
|
+
if (equalIndex > 0) {
|
|
3185
|
+
var key = line.substring(0, equalIndex).trim();
|
|
3186
|
+
var value = line.substring(equalIndex + 1).trim();
|
|
3187
|
+
// Remove quotes if present
|
|
3188
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
3189
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
3190
|
+
value = value.substring(1, value.length - 1);
|
|
3191
|
+
}
|
|
3192
|
+
envValues[key] = value;
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
catch (error) {
|
|
3197
|
+
// .env file doesn't exist yet - that's okay
|
|
3198
|
+
}
|
|
3199
|
+
// Helper function to get env value with proper URL formatting
|
|
3200
|
+
function getEnvValue(key, defaultValue = '') {
|
|
3201
|
+
var value = envValues[key] || process.env[key] || defaultValue;
|
|
3202
|
+
// Special handling for SNOW_INSTANCE - ensure it's a full URL
|
|
3203
|
+
if (key === 'SNOW_INSTANCE' && value && !value.startsWith('http')) {
|
|
3204
|
+
value = 'https://' + value.replace(/^https?:\/\//, '');
|
|
3205
|
+
}
|
|
3206
|
+
return value;
|
|
3207
|
+
}
|
|
2915
3208
|
// Read the template file
|
|
2916
3209
|
const templatePath = (0, path_1.join)(snowFlowRoot, '.mcp.json.template');
|
|
2917
3210
|
let templateContent;
|
|
@@ -2922,18 +3215,19 @@ async function setupMCPConfig(targetDir, instanceUrl, clientId, clientSecret, fo
|
|
|
2922
3215
|
console.error('❌ Could not find .mcp.json.template file');
|
|
2923
3216
|
throw error;
|
|
2924
3217
|
}
|
|
2925
|
-
// Replace placeholders
|
|
3218
|
+
// Replace placeholders with ACTUAL values from .env (not ${...} syntax!)
|
|
3219
|
+
// This ensures SnowCode/Claude Code can use the MCP servers immediately
|
|
2926
3220
|
const mcpConfigContent = templateContent
|
|
2927
3221
|
.replace(/{{PROJECT_ROOT}}/g, snowFlowRoot)
|
|
2928
|
-
.replace(/{{SNOW_INSTANCE}}/g, '
|
|
2929
|
-
.replace(/{{SNOW_CLIENT_ID}}/g, '
|
|
2930
|
-
.replace(/{{SNOW_CLIENT_SECRET}}/g, '
|
|
2931
|
-
.replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, '
|
|
2932
|
-
.replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, '
|
|
2933
|
-
.replace(/{{NEO4J_URI}}/g, '
|
|
2934
|
-
.replace(/{{NEO4J_USER}}/g, '
|
|
2935
|
-
.replace(/{{NEO4J_PASSWORD}}/g, '
|
|
2936
|
-
.replace(/{{SNOW_FLOW_ENV}}/g, '
|
|
3222
|
+
.replace(/{{SNOW_INSTANCE}}/g, getEnvValue('SNOW_INSTANCE'))
|
|
3223
|
+
.replace(/{{SNOW_CLIENT_ID}}/g, getEnvValue('SNOW_CLIENT_ID'))
|
|
3224
|
+
.replace(/{{SNOW_CLIENT_SECRET}}/g, getEnvValue('SNOW_CLIENT_SECRET'))
|
|
3225
|
+
.replace(/{{SNOW_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('SNOW_DEPLOYMENT_TIMEOUT', '180000'))
|
|
3226
|
+
.replace(/{{MCP_DEPLOYMENT_TIMEOUT}}/g, getEnvValue('MCP_DEPLOYMENT_TIMEOUT', '180000'))
|
|
3227
|
+
.replace(/{{NEO4J_URI}}/g, getEnvValue('NEO4J_URI', ''))
|
|
3228
|
+
.replace(/{{NEO4J_USER}}/g, getEnvValue('NEO4J_USER', ''))
|
|
3229
|
+
.replace(/{{NEO4J_PASSWORD}}/g, getEnvValue('NEO4J_PASSWORD', ''))
|
|
3230
|
+
.replace(/{{SNOW_FLOW_ENV}}/g, getEnvValue('SNOW_FLOW_ENV', 'development'));
|
|
2937
3231
|
// Parse to ensure it's valid JSON
|
|
2938
3232
|
const mcpConfig = JSON.parse(mcpConfigContent);
|
|
2939
3233
|
// Keep the standard MCP structure that Claude Code expects
|
|
@@ -2986,8 +3280,8 @@ program
|
|
|
2986
3280
|
console.log('\n📝 Updating MCP configuration...');
|
|
2987
3281
|
await setupMCPConfig(process.cwd(), instanceUrl, clientId, clientSecret, options.force || false);
|
|
2988
3282
|
console.log(chalk_1.default.green('\n✅ MCP configuration refreshed successfully!'));
|
|
2989
|
-
console.log('\n📢 IMPORTANT: Restart
|
|
2990
|
-
console.log(chalk_1.default.cyan('
|
|
3283
|
+
console.log('\n📢 IMPORTANT: Restart SnowCode (or Claude Code) to use the new configuration:');
|
|
3284
|
+
console.log(chalk_1.default.cyan(' SnowCode: snowcode'));
|
|
2991
3285
|
console.log(chalk_1.default.cyan(' Claude Code: claude --mcp-config .mcp.json'));
|
|
2992
3286
|
console.log('\n💡 The Local Development server now includes:');
|
|
2993
3287
|
console.log(' • Universal artifact detection via sys_metadata');
|
|
@@ -3018,16 +3312,16 @@ program
|
|
|
3018
3312
|
// MCP Server command with subcommands
|
|
3019
3313
|
program
|
|
3020
3314
|
.command('mcp <action>')
|
|
3021
|
-
.description('Manage ServiceNow MCP servers for
|
|
3315
|
+
.description('Manage ServiceNow MCP servers for SnowCode integration')
|
|
3022
3316
|
.option('--server <name>', 'Specific server name to manage')
|
|
3023
3317
|
.option('--port <port>', 'Port for MCP server (default: auto)')
|
|
3024
3318
|
.option('--host <host>', 'Host for MCP server (default: localhost)')
|
|
3025
3319
|
.action(async (action, options) => {
|
|
3026
|
-
// NOTE: MCP servers work with
|
|
3027
|
-
console.log(chalk_1.default.blue('ℹ️ MCP servers configured for
|
|
3320
|
+
// NOTE: MCP servers work with SnowCode's native Task() system
|
|
3321
|
+
console.log(chalk_1.default.blue('ℹ️ MCP servers configured for SnowCode (also compatible with Claude Code)'));
|
|
3028
3322
|
console.log(chalk_1.default.yellow('⚠️ Manual MCP commands are no longer needed'));
|
|
3029
|
-
console.log(chalk_1.default.green('✅
|
|
3030
|
-
console.log(chalk_1.default.blue('\n💡 Simply run your swarm commands -
|
|
3323
|
+
console.log(chalk_1.default.green('✅ SnowCode automatically handles all MCP server lifecycle'));
|
|
3324
|
+
console.log(chalk_1.default.blue('\n💡 Simply run your swarm commands - SnowCode handles the rest!'));
|
|
3031
3325
|
return;
|
|
3032
3326
|
});
|
|
3033
3327
|
// MCP action handlers
|
|
@@ -3052,9 +3346,9 @@ async function handleMCPStart(manager, options) {
|
|
|
3052
3346
|
const total = status.length;
|
|
3053
3347
|
console.log(`\n✅ Started ${running}/${total} MCP servers`);
|
|
3054
3348
|
if (running === total) {
|
|
3055
|
-
console.log('🎉 All MCP servers are now running and available in
|
|
3349
|
+
console.log('🎉 All MCP servers are now running and available in SnowCode!');
|
|
3056
3350
|
console.log('\n📋 Next steps:');
|
|
3057
|
-
console.log(' 1. Open
|
|
3351
|
+
console.log(' 1. Open SnowCode (or Claude Code)');
|
|
3058
3352
|
console.log(' 2. MCP tools will be automatically available');
|
|
3059
3353
|
console.log(' 3. Use snow_deploy_widget, snow_deploy_flow, etc.');
|
|
3060
3354
|
}
|
|
@@ -3133,7 +3427,7 @@ async function handleMCPStatus(manager, options) {
|
|
|
3133
3427
|
const total = servers.length;
|
|
3134
3428
|
console.log(`📈 Summary: ${running}/${total} servers running`);
|
|
3135
3429
|
if (running === total) {
|
|
3136
|
-
console.log('🎉 All MCP servers are operational and available in
|
|
3430
|
+
console.log('🎉 All MCP servers are operational and available in SnowCode (or Claude Code)!');
|
|
3137
3431
|
}
|
|
3138
3432
|
else if (running > 0) {
|
|
3139
3433
|
console.log('⚠️ Some servers are not running. Use "snow-flow mcp start" to start them.');
|
|
@@ -3243,22 +3537,22 @@ async function handleMCPDebug(options) {
|
|
|
3243
3537
|
console.log(` SNOW_INSTANCE: ${process.env.SNOW_INSTANCE ? '✅ Set' : '❌ Not set'}`);
|
|
3244
3538
|
console.log(` SNOW_CLIENT_ID: ${process.env.SNOW_CLIENT_ID ? '✅ Set' : '❌ Not set'}`);
|
|
3245
3539
|
console.log(` SNOW_CLIENT_SECRET: ${process.env.SNOW_CLIENT_SECRET ? '✅ Set' : '❌ Not set'}`);
|
|
3246
|
-
// Check
|
|
3247
|
-
console.log('\n🤖
|
|
3540
|
+
// Check SnowCode
|
|
3541
|
+
console.log('\n🤖 SnowCode:');
|
|
3248
3542
|
const { execSync } = require('child_process');
|
|
3249
3543
|
try {
|
|
3250
|
-
execSync('which
|
|
3251
|
-
console.log(' ✅
|
|
3544
|
+
execSync('which snowcode', { stdio: 'ignore' });
|
|
3545
|
+
console.log(' ✅ SnowCode CLI found');
|
|
3252
3546
|
}
|
|
3253
3547
|
catch {
|
|
3254
|
-
console.log(' ❌
|
|
3255
|
-
console.log(' 💡 Install with: npm install -g
|
|
3548
|
+
console.log(' ❌ SnowCode CLI not found in PATH');
|
|
3549
|
+
console.log(' 💡 Install with: npm install -g @groeimetai/snowcode');
|
|
3256
3550
|
}
|
|
3257
3551
|
console.log('\n💡 Tips:');
|
|
3258
|
-
console.log(' 1. Ensure
|
|
3552
|
+
console.log(' 1. Ensure SnowCode is configured: snowcode config import snowcode-config.example.json');
|
|
3259
3553
|
console.log(' 2. Check .env file has valid ServiceNow credentials and LLM API keys');
|
|
3260
3554
|
console.log(' 3. Start developing: snow-flow swarm "your objective"');
|
|
3261
|
-
console.log(' 4.
|
|
3555
|
+
console.log(' 4. SnowCode will automatically connect to Snow-Flow\'s MCP servers');
|
|
3262
3556
|
}
|
|
3263
3557
|
// SPARC Detailed Help Command - DISABLED (sparc-help.js file missing)
|
|
3264
3558
|
// program
|