fraim-framework 2.0.37 ā 2.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/init-project.js +74 -0
- package/dist/src/cli/commands/setup.js +176 -0
- package/dist/src/cli/commands/test-mcp.js +135 -0
- package/dist/src/cli/fraim.js +6 -0
- package/dist/src/cli/setup/auto-mcp-setup.js +367 -0
- package/dist/src/cli/setup/ide-detector.js +163 -0
- package/dist/src/cli/setup/mcp-config-generator.js +115 -0
- package/dist/src/cli/setup/token-validator.js +49 -0
- package/dist/tests/debug-tools.js +2 -2
- package/dist/tests/shared-server-utils.js +57 -0
- package/dist/tests/test-client-scripts-validation.js +27 -5
- package/dist/tests/test-complete-setup-flow.js +110 -0
- package/dist/tests/test-ide-detector.js +46 -0
- package/dist/tests/test-improved-setup.js +121 -0
- package/dist/tests/test-mcp-config-generator.js +70 -0
- package/dist/tests/test-mcp-connection.js +58 -117
- package/dist/tests/test-mcp-issue-integration.js +2 -2
- package/dist/tests/test-mcp-lifecycle-methods.js +34 -100
- package/dist/tests/test-mcp-shared-server.js +308 -0
- package/dist/tests/test-package-size.js +21 -8
- package/dist/tests/test-script-location-independence.js +39 -62
- package/dist/tests/test-server-utils.js +32 -0
- package/dist/tests/test-session-rehydration.js +2 -2
- package/dist/tests/test-setup-integration.js +98 -0
- package/dist/tests/test-standalone.js +2 -2
- package/dist/tests/test-stub-registry.js +23 -7
- package/dist/tests/test-telemetry.js +2 -2
- package/dist/tests/test-token-validator.js +30 -0
- package/dist/tests/test-user-journey.js +2 -1
- package/package.json +2 -2
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.initProjectCommand = exports.runInitProject = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const sync_1 = require("./sync");
|
|
13
|
+
const types_1 = require("../../fraim/types");
|
|
14
|
+
const git_utils_1 = require("../../utils/git-utils");
|
|
15
|
+
const version_utils_1 = require("../../utils/version-utils");
|
|
16
|
+
const checkGlobalSetup = () => {
|
|
17
|
+
const globalConfigPath = path_1.default.join(os_1.default.homedir(), '.fraim', 'config.json');
|
|
18
|
+
return fs_1.default.existsSync(globalConfigPath);
|
|
19
|
+
};
|
|
20
|
+
const runInitProject = async () => {
|
|
21
|
+
console.log(chalk_1.default.blue('š Initializing FRAIM project...'));
|
|
22
|
+
// Check if global setup exists
|
|
23
|
+
if (!checkGlobalSetup()) {
|
|
24
|
+
console.log(chalk_1.default.red('ā Global FRAIM setup not found.'));
|
|
25
|
+
console.log(chalk_1.default.yellow('Please run global setup first:'));
|
|
26
|
+
console.log(chalk_1.default.cyan(' fraim setup --key=<your-fraim-key>'));
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const projectRoot = process.cwd();
|
|
30
|
+
const fraimDir = path_1.default.join(projectRoot, '.fraim');
|
|
31
|
+
const configPath = path_1.default.join(fraimDir, 'config.json');
|
|
32
|
+
if (!fs_1.default.existsSync(fraimDir)) {
|
|
33
|
+
fs_1.default.mkdirSync(fraimDir, { recursive: true });
|
|
34
|
+
console.log(chalk_1.default.green('ā
Created .fraim directory'));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.log(chalk_1.default.yellow('ā¹ļø .fraim directory already exists'));
|
|
38
|
+
}
|
|
39
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
40
|
+
const remoteInfo = (0, git_utils_1.getGitRemoteInfo)();
|
|
41
|
+
// Git remote is optional for project init
|
|
42
|
+
const config = {
|
|
43
|
+
...types_1.DEFAULT_FRAIM_CONFIG,
|
|
44
|
+
version: (0, version_utils_1.getFraimVersion)(),
|
|
45
|
+
project: {
|
|
46
|
+
...types_1.DEFAULT_FRAIM_CONFIG.project,
|
|
47
|
+
name: remoteInfo.repo || path_1.default.basename(projectRoot)
|
|
48
|
+
},
|
|
49
|
+
git: {
|
|
50
|
+
...types_1.DEFAULT_FRAIM_CONFIG.git,
|
|
51
|
+
repoOwner: remoteInfo.owner || types_1.DEFAULT_FRAIM_CONFIG.git.repoOwner,
|
|
52
|
+
repoName: remoteInfo.repo || path_1.default.basename(projectRoot)
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
56
|
+
console.log(chalk_1.default.green('ā
Created .fraim/config.json'));
|
|
57
|
+
}
|
|
58
|
+
// Create subdirectories
|
|
59
|
+
['workflows'].forEach(dir => {
|
|
60
|
+
const dirPath = path_1.default.join(fraimDir, dir);
|
|
61
|
+
if (!fs_1.default.existsSync(dirPath)) {
|
|
62
|
+
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
63
|
+
console.log(chalk_1.default.green(`ā
Created .fraim/${dir}`));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Sync workflows from registry
|
|
67
|
+
await (0, sync_1.runSync)({});
|
|
68
|
+
console.log(chalk_1.default.green('\nā
FRAIM project initialized!'));
|
|
69
|
+
console.log(chalk_1.default.cyan('Try: Ask your AI agent "list fraim workflows"'));
|
|
70
|
+
};
|
|
71
|
+
exports.runInitProject = runInitProject;
|
|
72
|
+
exports.initProjectCommand = new commander_1.Command('init-project')
|
|
73
|
+
.description('Initialize FRAIM in the current project (requires global setup)')
|
|
74
|
+
.action(exports.runInitProject);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.setupCommand = exports.runSetup = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
13
|
+
const token_validator_1 = require("../setup/token-validator");
|
|
14
|
+
const auto_mcp_setup_1 = require("../setup/auto-mcp-setup");
|
|
15
|
+
const script_sync_utils_1 = require("../../utils/script-sync-utils");
|
|
16
|
+
const version_utils_1 = require("../../utils/version-utils");
|
|
17
|
+
const promptForFraimKey = async () => {
|
|
18
|
+
console.log(chalk_1.default.blue('š FRAIM Key Setup'));
|
|
19
|
+
console.log('FRAIM requires a valid API key to access workflows and features.\n');
|
|
20
|
+
let key = null;
|
|
21
|
+
let attempts = 0;
|
|
22
|
+
const maxAttempts = 3;
|
|
23
|
+
while (!key && attempts < maxAttempts) {
|
|
24
|
+
const keyResponse = await (0, prompts_1.default)({
|
|
25
|
+
type: 'password',
|
|
26
|
+
name: 'key',
|
|
27
|
+
message: attempts === 0
|
|
28
|
+
? 'Enter your FRAIM key (required)'
|
|
29
|
+
: `Enter your FRAIM key (attempt ${attempts + 1}/${maxAttempts})`,
|
|
30
|
+
validate: (value) => {
|
|
31
|
+
if (!value)
|
|
32
|
+
return 'FRAIM key is required';
|
|
33
|
+
if ((0, token_validator_1.isValidTokenFormat)(value, 'fraim'))
|
|
34
|
+
return true;
|
|
35
|
+
return 'Please enter a valid FRAIM key (starts with fraim_)';
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (!keyResponse.key) {
|
|
39
|
+
console.log(chalk_1.default.red('\nā FRAIM key is required to proceed.'));
|
|
40
|
+
console.log(chalk_1.default.gray('If you need a key, please email sid.mathur@gmail.com to request one.\n'));
|
|
41
|
+
const retry = await (0, prompts_1.default)({
|
|
42
|
+
type: 'confirm',
|
|
43
|
+
name: 'retry',
|
|
44
|
+
message: 'Would you like to try entering the FRAIM key again?',
|
|
45
|
+
initial: true
|
|
46
|
+
});
|
|
47
|
+
if (!retry.retry) {
|
|
48
|
+
console.log(chalk_1.default.red('Setup cancelled. Please obtain a FRAIM key and try again.'));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
attempts++;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
// Validate key
|
|
55
|
+
const isValid = await (0, token_validator_1.validateFraimKey)(keyResponse.key);
|
|
56
|
+
if (isValid) {
|
|
57
|
+
console.log(chalk_1.default.green('ā
FRAIM key validated\n'));
|
|
58
|
+
return keyResponse.key;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log(chalk_1.default.red('ā Invalid FRAIM key\n'));
|
|
62
|
+
attempts++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
console.log(chalk_1.default.red('\nā Maximum attempts reached. Setup cancelled.'));
|
|
66
|
+
console.log(chalk_1.default.gray('Please ensure you have a valid FRAIM key and try again.'));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
};
|
|
69
|
+
const saveGlobalConfig = (fraimKey) => {
|
|
70
|
+
const globalConfigDir = path_1.default.join(os_1.default.homedir(), '.fraim');
|
|
71
|
+
const globalConfigPath = path_1.default.join(globalConfigDir, 'config.json');
|
|
72
|
+
if (!fs_1.default.existsSync(globalConfigDir)) {
|
|
73
|
+
fs_1.default.mkdirSync(globalConfigDir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
const config = {
|
|
76
|
+
version: (0, version_utils_1.getFraimVersion)(),
|
|
77
|
+
apiKey: fraimKey,
|
|
78
|
+
configuredAt: new Date().toISOString(),
|
|
79
|
+
userPreferences: {
|
|
80
|
+
autoSync: true,
|
|
81
|
+
backupConfigs: true
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
fs_1.default.writeFileSync(globalConfigPath, JSON.stringify(config, null, 2));
|
|
85
|
+
console.log(chalk_1.default.green('ā
Global FRAIM configuration saved'));
|
|
86
|
+
};
|
|
87
|
+
const syncGlobalScripts = () => {
|
|
88
|
+
console.log(chalk_1.default.blue('š Syncing FRAIM scripts to user directory...'));
|
|
89
|
+
// Find registry path
|
|
90
|
+
let registryPath = path_1.default.join(__dirname, '../../../../registry');
|
|
91
|
+
if (!fs_1.default.existsSync(registryPath)) {
|
|
92
|
+
registryPath = path_1.default.join(__dirname, '../../../registry');
|
|
93
|
+
}
|
|
94
|
+
if (fs_1.default.existsSync(registryPath)) {
|
|
95
|
+
const syncResult = (0, script_sync_utils_1.syncScriptsToUserDirectory)(registryPath);
|
|
96
|
+
console.log(chalk_1.default.green(`ā
Synced ${syncResult.synced} scripts to user directory.`));
|
|
97
|
+
if (syncResult.ephemeral > 0) {
|
|
98
|
+
console.log(chalk_1.default.gray(` ${syncResult.ephemeral} dependent scripts will use ephemeral execution.`));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log(chalk_1.default.yellow('ā ļø Registry not found, skipping script sync.'));
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const runSetup = async (options) => {
|
|
106
|
+
console.log(chalk_1.default.blue('š Welcome to FRAIM! Let\'s get you set up.\n'));
|
|
107
|
+
// Show what we're about to do
|
|
108
|
+
console.log(chalk_1.default.yellow('š This setup will:'));
|
|
109
|
+
console.log(chalk_1.default.gray(' ⢠Validate your FRAIM and GitHub tokens'));
|
|
110
|
+
console.log(chalk_1.default.gray(' ⢠Create global FRAIM configuration'));
|
|
111
|
+
console.log(chalk_1.default.gray(' ⢠Detect and configure supported IDEs'));
|
|
112
|
+
console.log(chalk_1.default.gray(' ⢠Sync FRAIM scripts to your system'));
|
|
113
|
+
console.log(chalk_1.default.gray(' ⢠Set up MCP servers for AI integration\n'));
|
|
114
|
+
// Get FRAIM key
|
|
115
|
+
let fraimKey = options.key;
|
|
116
|
+
if (!fraimKey) {
|
|
117
|
+
fraimKey = await promptForFraimKey();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
if (!(0, token_validator_1.isValidTokenFormat)(fraimKey, 'fraim')) {
|
|
121
|
+
console.log(chalk_1.default.red('ā Invalid FRAIM key format. Key must start with fraim_'));
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
console.log(chalk_1.default.blue('š Validating FRAIM key...'));
|
|
125
|
+
const isValid = await (0, token_validator_1.validateFraimKey)(fraimKey);
|
|
126
|
+
if (!isValid) {
|
|
127
|
+
console.log(chalk_1.default.red('ā Invalid FRAIM key'));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
console.log(chalk_1.default.green('ā
FRAIM key validated\n'));
|
|
131
|
+
}
|
|
132
|
+
// Get GitHub token
|
|
133
|
+
let githubToken = options.githubToken;
|
|
134
|
+
if (!githubToken) {
|
|
135
|
+
githubToken = await (0, auto_mcp_setup_1.promptForGitHubToken)();
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (!(0, token_validator_1.isValidTokenFormat)(githubToken, 'github')) {
|
|
139
|
+
console.log(chalk_1.default.red('ā Invalid GitHub token format. Token must start with ghp_ or github_pat_'));
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
console.log(chalk_1.default.blue('š Validating GitHub token...'));
|
|
143
|
+
const isValid = await (0, token_validator_1.validateGitHubToken)(githubToken);
|
|
144
|
+
if (!isValid) {
|
|
145
|
+
console.log(chalk_1.default.red('ā Invalid GitHub token'));
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
console.log(chalk_1.default.green('ā
GitHub token validated\n'));
|
|
149
|
+
}
|
|
150
|
+
// Save global configuration
|
|
151
|
+
console.log(chalk_1.default.blue('š¾ Saving global configuration...'));
|
|
152
|
+
saveGlobalConfig(fraimKey);
|
|
153
|
+
// Sync global scripts
|
|
154
|
+
syncGlobalScripts();
|
|
155
|
+
// Configure IDEs
|
|
156
|
+
const selectedIDEs = options.ide ? options.ide.split(',') : undefined;
|
|
157
|
+
const autoAll = options.all;
|
|
158
|
+
if (autoAll && selectedIDEs) {
|
|
159
|
+
console.log(chalk_1.default.yellow('ā ļø Both --all and --ide specified. Using --ide selection.'));
|
|
160
|
+
}
|
|
161
|
+
await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, githubToken, selectedIDEs);
|
|
162
|
+
console.log(chalk_1.default.green('\nšÆ Setup complete! Next steps:'));
|
|
163
|
+
console.log(chalk_1.default.cyan(' 1. Restart your configured IDEs'));
|
|
164
|
+
console.log(chalk_1.default.cyan(' 2. Go to any project directory'));
|
|
165
|
+
console.log(chalk_1.default.cyan(' 3. Run: fraim init-project'));
|
|
166
|
+
console.log(chalk_1.default.cyan(' 4. Ask your AI agent: "list fraim workflows"'));
|
|
167
|
+
console.log(chalk_1.default.blue('\nš” Use "fraim test-mcp" to verify your setup anytime.'));
|
|
168
|
+
};
|
|
169
|
+
exports.runSetup = runSetup;
|
|
170
|
+
exports.setupCommand = new commander_1.Command('setup')
|
|
171
|
+
.description('Complete global FRAIM setup with IDE configuration')
|
|
172
|
+
.option('--key <key>', 'FRAIM API key')
|
|
173
|
+
.option('--github-token <token>', 'GitHub Personal Access Token')
|
|
174
|
+
.option('--all', 'Auto-configure all detected IDEs')
|
|
175
|
+
.option('--ide <ides>', 'Configure specific IDEs (comma-separated: claude,cursor,kiro)')
|
|
176
|
+
.action(exports.runSetup);
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.testMCPCommand = exports.runTestMCP = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const os_1 = __importDefault(require("os"));
|
|
12
|
+
const ide_detector_1 = require("../setup/ide-detector");
|
|
13
|
+
const testIDEConfig = async (ide) => {
|
|
14
|
+
const result = {
|
|
15
|
+
ide: ide.name,
|
|
16
|
+
configExists: false,
|
|
17
|
+
configValid: false,
|
|
18
|
+
mcpServers: [],
|
|
19
|
+
errors: []
|
|
20
|
+
};
|
|
21
|
+
const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
|
|
22
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
23
|
+
result.errors.push('Config file does not exist');
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
result.configExists = true;
|
|
27
|
+
try {
|
|
28
|
+
if (ide.configFormat === 'json') {
|
|
29
|
+
const configContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
30
|
+
const config = JSON.parse(configContent);
|
|
31
|
+
if (config.mcpServers) {
|
|
32
|
+
result.configValid = true;
|
|
33
|
+
result.mcpServers = Object.keys(config.mcpServers);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
result.errors.push('No mcpServers section found');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else if (ide.configFormat === 'toml') {
|
|
40
|
+
const configContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
41
|
+
// Simple TOML parsing for MCP servers
|
|
42
|
+
const serverMatches = configContent.match(/\[mcp_servers\.(\w+)\]/g);
|
|
43
|
+
if (serverMatches) {
|
|
44
|
+
result.configValid = true;
|
|
45
|
+
result.mcpServers = serverMatches.map(match => match.replace(/\[mcp_servers\.(\w+)\]/, '$1'));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
result.errors.push('No mcp_servers sections found');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
result.errors.push(`Failed to parse config: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
const checkGlobalSetup = () => {
|
|
58
|
+
const globalConfigPath = path_1.default.join(os_1.default.homedir(), '.fraim', 'config.json');
|
|
59
|
+
return fs_1.default.existsSync(globalConfigPath);
|
|
60
|
+
};
|
|
61
|
+
const runTestMCP = async () => {
|
|
62
|
+
console.log(chalk_1.default.blue('š Testing MCP configuration...\n'));
|
|
63
|
+
// Check global setup
|
|
64
|
+
if (!checkGlobalSetup()) {
|
|
65
|
+
console.log(chalk_1.default.red('ā Global FRAIM setup not found.'));
|
|
66
|
+
console.log(chalk_1.default.yellow('Please run: fraim setup --key=<your-fraim-key>'));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
console.log(chalk_1.default.green('ā
Global FRAIM setup found'));
|
|
70
|
+
// Detect IDEs
|
|
71
|
+
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
72
|
+
if (detectedIDEs.length === 0) {
|
|
73
|
+
console.log(chalk_1.default.yellow('ā ļø No supported IDEs detected.'));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
console.log(chalk_1.default.blue(`\nš Testing ${detectedIDEs.length} detected IDEs...\n`));
|
|
77
|
+
const results = await Promise.all(detectedIDEs.map(ide => testIDEConfig(ide)));
|
|
78
|
+
let totalConfigured = 0;
|
|
79
|
+
let totalWithFRAIM = 0;
|
|
80
|
+
for (const result of results) {
|
|
81
|
+
console.log(chalk_1.default.white(`š± ${result.ide}`));
|
|
82
|
+
if (!result.configExists) {
|
|
83
|
+
console.log(chalk_1.default.red(' ā No MCP config found'));
|
|
84
|
+
console.log(chalk_1.default.gray(` š” Run: fraim setup --ide=${result.ide.toLowerCase()}`));
|
|
85
|
+
}
|
|
86
|
+
else if (!result.configValid) {
|
|
87
|
+
console.log(chalk_1.default.yellow(' ā ļø Config exists but invalid'));
|
|
88
|
+
result.errors.forEach(error => {
|
|
89
|
+
console.log(chalk_1.default.red(` ā ${error}`));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
totalConfigured++;
|
|
94
|
+
console.log(chalk_1.default.green(` ā
MCP config valid (${result.mcpServers.length} servers)`));
|
|
95
|
+
// Check for essential servers
|
|
96
|
+
const essentialServers = ['fraim', 'git', 'github', 'playwright'];
|
|
97
|
+
const hasEssential = essentialServers.filter(server => result.mcpServers.includes(server));
|
|
98
|
+
if (hasEssential.includes('fraim')) {
|
|
99
|
+
totalWithFRAIM++;
|
|
100
|
+
console.log(chalk_1.default.green(' ā
FRAIM server configured'));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.log(chalk_1.default.yellow(' ā ļø FRAIM server missing'));
|
|
104
|
+
}
|
|
105
|
+
if (hasEssential.length > 1) {
|
|
106
|
+
console.log(chalk_1.default.green(` ā
${hasEssential.length - 1} additional servers: ${hasEssential.filter(s => s !== 'fraim').join(', ')}`));
|
|
107
|
+
}
|
|
108
|
+
const missingEssential = essentialServers.filter(server => !result.mcpServers.includes(server));
|
|
109
|
+
if (missingEssential.length > 0) {
|
|
110
|
+
console.log(chalk_1.default.yellow(` ā ļø Missing servers: ${missingEssential.join(', ')}`));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
console.log(); // Empty line
|
|
114
|
+
}
|
|
115
|
+
// Summary
|
|
116
|
+
console.log(chalk_1.default.blue('š Summary:'));
|
|
117
|
+
console.log(chalk_1.default.green(` ā
${totalConfigured}/${detectedIDEs.length} IDEs have valid MCP configs`));
|
|
118
|
+
console.log(chalk_1.default.green(` ā
${totalWithFRAIM}/${detectedIDEs.length} IDEs have FRAIM configured`));
|
|
119
|
+
if (totalWithFRAIM === 0) {
|
|
120
|
+
console.log(chalk_1.default.red('\nā No IDEs have FRAIM configured!'));
|
|
121
|
+
console.log(chalk_1.default.yellow('š” Run: fraim setup --key=<your-fraim-key>'));
|
|
122
|
+
}
|
|
123
|
+
else if (totalWithFRAIM < detectedIDEs.length) {
|
|
124
|
+
console.log(chalk_1.default.yellow(`\nā ļø ${detectedIDEs.length - totalWithFRAIM} IDEs missing FRAIM configuration`));
|
|
125
|
+
console.log(chalk_1.default.yellow('š” Run: fraim setup to configure remaining IDEs'));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.log(chalk_1.default.green('\nš All detected IDEs have FRAIM configured!'));
|
|
129
|
+
console.log(chalk_1.default.blue('š” Try running: fraim init-project in any project'));
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
exports.runTestMCP = runTestMCP;
|
|
133
|
+
exports.testMCPCommand = new commander_1.Command('test-mcp')
|
|
134
|
+
.description('Test MCP server configurations for all detected IDEs')
|
|
135
|
+
.action(exports.runTestMCP);
|
package/dist/src/cli/fraim.js
CHANGED
|
@@ -10,6 +10,9 @@ const sync_1 = require("./commands/sync");
|
|
|
10
10
|
const doctor_1 = require("./commands/doctor");
|
|
11
11
|
const list_1 = require("./commands/list");
|
|
12
12
|
const wizard_1 = require("./commands/wizard");
|
|
13
|
+
const setup_1 = require("./commands/setup");
|
|
14
|
+
const init_project_1 = require("./commands/init-project");
|
|
15
|
+
const test_mcp_1 = require("./commands/test-mcp");
|
|
13
16
|
const fs_1 = __importDefault(require("fs"));
|
|
14
17
|
const path_1 = __importDefault(require("path"));
|
|
15
18
|
const program = new commander_1.Command();
|
|
@@ -42,4 +45,7 @@ program.addCommand(sync_1.syncCommand);
|
|
|
42
45
|
program.addCommand(doctor_1.doctorCommand);
|
|
43
46
|
program.addCommand(list_1.listCommand);
|
|
44
47
|
program.addCommand(wizard_1.wizardCommand);
|
|
48
|
+
program.addCommand(setup_1.setupCommand);
|
|
49
|
+
program.addCommand(init_project_1.initProjectCommand);
|
|
50
|
+
program.addCommand(test_mcp_1.testMCPCommand);
|
|
45
51
|
program.parse(process.argv);
|