fraim-framework 2.0.70 ā 2.0.71
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/bin/fraim.js +1 -1
- package/dist/src/cli/commands/init.js +148 -0
- package/dist/src/cli/commands/mcp.js +65 -0
- package/dist/src/cli/commands/wizard.js +35 -0
- package/index.js +1 -1
- package/package.json +5 -5
package/bin/fraim.js
CHANGED
|
@@ -0,0 +1,148 @@
|
|
|
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.initCommand = exports.runInit = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const first_run_1 = require("../setup/first-run");
|
|
12
|
+
const sync_1 = require("./sync");
|
|
13
|
+
const platform_detection_1 = require("../../utils/platform-detection");
|
|
14
|
+
const version_utils_1 = require("../../utils/version-utils");
|
|
15
|
+
const script_sync_utils_1 = require("../../utils/script-sync-utils");
|
|
16
|
+
const runInit = async (options = {}) => {
|
|
17
|
+
const projectRoot = process.cwd();
|
|
18
|
+
const fraimDir = path_1.default.join(projectRoot, '.fraim');
|
|
19
|
+
const configPath = path_1.default.join(fraimDir, 'config.json');
|
|
20
|
+
console.log(chalk_1.default.blue('š Initializing FRAIM...'));
|
|
21
|
+
if (!fs_1.default.existsSync(fraimDir)) {
|
|
22
|
+
fs_1.default.mkdirSync(fraimDir, { recursive: true });
|
|
23
|
+
console.log(chalk_1.default.green('ā
Created .fraim directory'));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.log(chalk_1.default.yellow('ā¹ļø .fraim directory already exists'));
|
|
27
|
+
}
|
|
28
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
29
|
+
let config;
|
|
30
|
+
// Try to detect platform from git remote
|
|
31
|
+
const detection = (0, platform_detection_1.detectPlatformFromGit)();
|
|
32
|
+
if (options.skipPlatform || detection.provider === 'unknown' || !detection.repository) {
|
|
33
|
+
// Conversational mode - no platform integration
|
|
34
|
+
if (!options.skipPlatform && (detection.provider === 'unknown' || !detection.repository)) {
|
|
35
|
+
console.log(chalk_1.default.yellow('\nā¹ļø No git remote found or unsupported platform.'));
|
|
36
|
+
console.log(chalk_1.default.blue(' Initializing in conversational mode (no platform integration).'));
|
|
37
|
+
console.log(chalk_1.default.gray(' You can still use FRAIM workflows and AI features.'));
|
|
38
|
+
console.log(chalk_1.default.gray(' Platform features (issues, PRs) will be unavailable.\n'));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
console.log(chalk_1.default.blue('\n Initializing in conversational mode (platform integration skipped).\n'));
|
|
42
|
+
}
|
|
43
|
+
// Get project name from directory or git
|
|
44
|
+
let projectName = path_1.default.basename(projectRoot);
|
|
45
|
+
try {
|
|
46
|
+
const { execSync } = require('child_process');
|
|
47
|
+
const gitName = execSync('git config --get remote.origin.url', {
|
|
48
|
+
stdio: 'pipe',
|
|
49
|
+
timeout: 2000
|
|
50
|
+
}).toString().trim();
|
|
51
|
+
const match = gitName.match(/\/([^\/]+?)(\.git)?$/);
|
|
52
|
+
if (match) {
|
|
53
|
+
projectName = match[1];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
// Use directory name as fallback
|
|
58
|
+
}
|
|
59
|
+
config = {
|
|
60
|
+
version: (0, version_utils_1.getFraimVersion)(),
|
|
61
|
+
project: {
|
|
62
|
+
name: projectName
|
|
63
|
+
},
|
|
64
|
+
customizations: {
|
|
65
|
+
workflowsPath: '.fraim/workflows'
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
console.log(chalk_1.default.gray(` Project: ${projectName}`));
|
|
69
|
+
console.log(chalk_1.default.gray(` Mode: Conversational (no platform integration)`));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Integrated mode - use platform
|
|
73
|
+
if (!detection.repository) {
|
|
74
|
+
console.log(chalk_1.default.red('ā Error: Repository information not available'));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
// Validate the detected repository config
|
|
78
|
+
const validation = (0, platform_detection_1.validateRepositoryConfig)(detection.repository);
|
|
79
|
+
if (!validation.valid) {
|
|
80
|
+
console.log(chalk_1.default.red('ā Error: Invalid repository configuration:'));
|
|
81
|
+
validation.errors.forEach(err => console.log(chalk_1.default.red(` - ${err}`)));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
console.log(chalk_1.default.blue('\n Initializing in integrated mode (platform integration enabled).'));
|
|
85
|
+
console.log(chalk_1.default.gray(` Platform: ${detection.provider.toUpperCase()}`));
|
|
86
|
+
if (detection.provider === 'github') {
|
|
87
|
+
console.log(chalk_1.default.gray(` Repository: ${detection.repository.owner}/${detection.repository.name}`));
|
|
88
|
+
}
|
|
89
|
+
else if (detection.provider === 'ado') {
|
|
90
|
+
console.log(chalk_1.default.gray(` Organization: ${detection.repository.organization}`));
|
|
91
|
+
console.log(chalk_1.default.gray(` Project: ${detection.repository.project}`));
|
|
92
|
+
console.log(chalk_1.default.gray(` Repository: ${detection.repository.name}`));
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
config = {
|
|
96
|
+
version: (0, version_utils_1.getFraimVersion)(),
|
|
97
|
+
project: {
|
|
98
|
+
name: detection.repository.name
|
|
99
|
+
},
|
|
100
|
+
repository: detection.repository,
|
|
101
|
+
customizations: {
|
|
102
|
+
workflowsPath: '.fraim/workflows'
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
107
|
+
console.log(chalk_1.default.green('ā
Created .fraim/config.json'));
|
|
108
|
+
}
|
|
109
|
+
// Create subdirectories
|
|
110
|
+
['workflows'].forEach(dir => {
|
|
111
|
+
const dirPath = path_1.default.join(fraimDir, dir);
|
|
112
|
+
if (!fs_1.default.existsSync(dirPath)) {
|
|
113
|
+
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
114
|
+
console.log(chalk_1.default.green(`ā
Created .fraim/${dir}`));
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
console.log(chalk_1.default.blue('\nš FRAIM initialized successfully!'));
|
|
118
|
+
// Sync workflows from registry
|
|
119
|
+
await (0, sync_1.runSync)({});
|
|
120
|
+
// Sync scripts to user directory
|
|
121
|
+
console.log(chalk_1.default.blue('š Syncing FRAIM scripts to user directory...'));
|
|
122
|
+
// Find registry path (same logic as sync command)
|
|
123
|
+
let registryPath = path_1.default.join(__dirname, '../../../../registry');
|
|
124
|
+
if (!fs_1.default.existsSync(registryPath)) {
|
|
125
|
+
registryPath = path_1.default.join(__dirname, '../../../registry');
|
|
126
|
+
}
|
|
127
|
+
if (!fs_1.default.existsSync(registryPath)) {
|
|
128
|
+
registryPath = path_1.default.join(projectRoot, 'registry');
|
|
129
|
+
}
|
|
130
|
+
if (fs_1.default.existsSync(registryPath)) {
|
|
131
|
+
const syncResult = (0, script_sync_utils_1.syncScriptsToUserDirectory)(registryPath);
|
|
132
|
+
console.log(chalk_1.default.green(`ā
Synced ${syncResult.synced} self-contained scripts to user directory.`));
|
|
133
|
+
if (syncResult.ephemeral > 0) {
|
|
134
|
+
console.log(chalk_1.default.gray(` ${syncResult.ephemeral} dependent scripts will use ephemeral execution.`));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
console.log(chalk_1.default.yellow('ā ļø Registry not found, skipping script sync.'));
|
|
139
|
+
}
|
|
140
|
+
// Trigger First Run Experience
|
|
141
|
+
await (0, first_run_1.runFirstRunExperience)();
|
|
142
|
+
process.exit(0);
|
|
143
|
+
};
|
|
144
|
+
exports.runInit = runInit;
|
|
145
|
+
exports.initCommand = new commander_1.Command('init')
|
|
146
|
+
.description('Initialize FRAIM in the current project')
|
|
147
|
+
.option('--skip-platform', 'Skip platform integration (conversational mode only)')
|
|
148
|
+
.action((options) => (0, exports.runInit)(options));
|
|
@@ -0,0 +1,65 @@
|
|
|
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.mcpCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const server_1 = require("../../local-mcp-server/server");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
exports.mcpCommand = new commander_1.Command('mcp')
|
|
11
|
+
.description('Start the local FRAIM MCP server')
|
|
12
|
+
.option('-p, --port <port>', 'Port to run the server on', '3003')
|
|
13
|
+
.option('--remote-only', 'Use remote server only (skip local proxy)', false)
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
try {
|
|
16
|
+
if (options.remoteOnly) {
|
|
17
|
+
console.log(chalk_1.default.yellow('ā ļø Remote-only mode not yet implemented'));
|
|
18
|
+
console.log(chalk_1.default.blue('ā¹ļø Starting local MCP server instead...'));
|
|
19
|
+
}
|
|
20
|
+
const port = parseInt(options.port);
|
|
21
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
22
|
+
console.error(chalk_1.default.red('ā Invalid port number. Must be between 1 and 65535.'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk_1.default.blue('š Starting FRAIM Local MCP Server...'));
|
|
26
|
+
console.log(chalk_1.default.gray(`š” Port: ${port}`));
|
|
27
|
+
console.log(chalk_1.default.gray(`š Auto-updates: Every 5 minutes`));
|
|
28
|
+
console.log(chalk_1.default.gray(`š Cache: ~/.fraim/cache`));
|
|
29
|
+
console.log('');
|
|
30
|
+
// Set the port in environment
|
|
31
|
+
process.env.FRAIM_LOCAL_MCP_PORT = port.toString();
|
|
32
|
+
// Start the server
|
|
33
|
+
await (0, server_1.startLocalMCPServer)();
|
|
34
|
+
// Server is now running, show configuration instructions
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(chalk_1.default.green('ā
FRAIM Local MCP Server is running!'));
|
|
37
|
+
console.log('');
|
|
38
|
+
console.log(chalk_1.default.bold('š Agent Configuration:'));
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log(chalk_1.default.gray('Add this to your agent\'s MCP configuration:'));
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log(chalk_1.default.cyan(JSON.stringify({
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"fraim": {
|
|
45
|
+
"command": "fraim",
|
|
46
|
+
"args": ["mcp"],
|
|
47
|
+
"env": {}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, null, 2)));
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(chalk_1.default.bold('š Endpoints:'));
|
|
53
|
+
console.log(chalk_1.default.gray(` MCP: http://localhost:${port}/mcp`));
|
|
54
|
+
console.log(chalk_1.default.gray(` Health: http://localhost:${port}/health`));
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(chalk_1.default.bold('š To stop the server:'));
|
|
57
|
+
console.log(chalk_1.default.gray(' Press Ctrl+C'));
|
|
58
|
+
console.log('');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(chalk_1.default.red('ā Failed to start Local MCP Server:'));
|
|
62
|
+
console.error(chalk_1.default.red(error instanceof Error ? error.message : String(error)));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
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.wizardCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const init_js_1 = require("./init.js");
|
|
10
|
+
const sync_js_1 = require("./sync.js");
|
|
11
|
+
exports.wizardCommand = new commander_1.Command('wizard')
|
|
12
|
+
.description('Run the interactive setup wizard')
|
|
13
|
+
.action(async () => {
|
|
14
|
+
console.log(chalk_1.default.cyan('š® FRAIM Interactive Setup Wizard\n'));
|
|
15
|
+
console.log('Running V2 setup (Init + Sync)...\n');
|
|
16
|
+
try {
|
|
17
|
+
// Run initialization
|
|
18
|
+
try {
|
|
19
|
+
await (0, init_js_1.runInit)();
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
console.log(chalk_1.default.yellow('ā ļø Init notice:'), err.message);
|
|
23
|
+
}
|
|
24
|
+
console.log(''); // newline
|
|
25
|
+
// Run sync (Force not strictly required if init is fresh, but safe)
|
|
26
|
+
// But if user runs wizard on existing project, maybe they want to resync
|
|
27
|
+
await (0, sync_js_1.runSync)({ force: false });
|
|
28
|
+
console.log(chalk_1.default.blue('\n⨠Wizard completed successfully!'));
|
|
29
|
+
console.log(chalk_1.default.gray('Tip: In the future, you can run `fraim sync` to update workflows.'));
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error(chalk_1.default.red('ā Wizard failed:'), error);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
});
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.71",
|
|
4
4
|
"description": "FRAIM v2: Framework for Rigor-based AI Management - Transform from solo developer to AI manager orchestrating production-ready code with enterprise-grade discipline",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -66,13 +66,10 @@
|
|
|
66
66
|
"@types/express": "^5.0.6",
|
|
67
67
|
"@types/node": "^20.0.0",
|
|
68
68
|
"@types/prompts": "^2.4.9",
|
|
69
|
-
"cors": "^2.8.5",
|
|
70
|
-
"express": "^5.2.1",
|
|
71
69
|
"fast-glob": "^3.3.3",
|
|
72
70
|
"html-to-docx": "^1.8.0",
|
|
73
71
|
"markdown-it": "^14.1.0",
|
|
74
72
|
"markdown-it-highlightjs": "^4.2.0",
|
|
75
|
-
"mongodb": "^7.0.0",
|
|
76
73
|
"pptxgenjs": "^4.0.1",
|
|
77
74
|
"puppeteer": "^24.36.1",
|
|
78
75
|
"qrcode": "^1.5.4",
|
|
@@ -101,6 +98,9 @@
|
|
|
101
98
|
"commander": "^14.0.2",
|
|
102
99
|
"dotenv": "^16.4.7",
|
|
103
100
|
"prompts": "^2.4.2",
|
|
104
|
-
"tree-kill": "^1.2.2"
|
|
101
|
+
"tree-kill": "^1.2.2",
|
|
102
|
+
"express": "^5.2.1",
|
|
103
|
+
"cors": "^2.8.5",
|
|
104
|
+
"mongodb": "^7.0.0"
|
|
105
105
|
}
|
|
106
106
|
}
|