fraim-framework 2.0.77 ā 2.0.80
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/README.md +77 -1
- package/bin/fraim-mcp.js +1 -1
- package/bin/fraim.js +1 -1
- package/dist/src/cli/commands/add-ide.js +36 -20
- package/dist/src/cli/commands/init-project.js +17 -6
- package/dist/src/cli/commands/setup.js +407 -21
- package/dist/src/cli/commands/test-mcp.js +2 -2
- package/dist/src/cli/setup/auto-mcp-setup.js +27 -10
- package/dist/src/cli/setup/codex-local-config.js +3 -3
- package/dist/src/cli/setup/first-run.js +2 -1
- package/dist/src/cli/setup/ide-detector.js +1 -1
- package/dist/src/cli/setup/mcp-config-generator.js +206 -49
- package/dist/src/cli/setup/token-validator.js +8 -0
- package/dist/src/cli/utils/platform-detection.js +45 -0
- package/dist/src/core/config-loader.js +1 -1
- package/dist/src/core/utils/provider-utils.js +5 -1
- package/dist/src/local-mcp-server/stdio-server.js +84 -15
- package/index.js +1 -1
- package/package.json +116 -116
- package/dist/src/cli/commands/init.js +0 -148
- package/dist/src/cli/commands/mcp.js +0 -65
- package/dist/src/cli/commands/wizard.js +0 -35
|
@@ -422,46 +422,69 @@ class FraimLocalMCPServer {
|
|
|
422
422
|
catch (error) {
|
|
423
423
|
// If git command fails, construct URL from config if available.
|
|
424
424
|
const repositoryConfig = this.config?.repository;
|
|
425
|
-
if (repositoryConfig?.
|
|
425
|
+
if (repositoryConfig?.url) {
|
|
426
|
+
repoUrl = repositoryConfig.url;
|
|
427
|
+
this.log(`Constructed repo URL from config: ${repoUrl}`);
|
|
428
|
+
}
|
|
429
|
+
else if (repositoryConfig?.provider === 'github' && repositoryConfig.owner && repositoryConfig.name) {
|
|
426
430
|
repoUrl = `https://github.com/${repositoryConfig.owner}/${repositoryConfig.name}.git`;
|
|
427
|
-
this.log(
|
|
431
|
+
this.log(`Constructed repo URL from config: ${repoUrl}`);
|
|
428
432
|
}
|
|
429
433
|
else if (repositoryConfig?.provider === 'ado' &&
|
|
430
434
|
repositoryConfig.organization &&
|
|
431
435
|
repositoryConfig.project &&
|
|
432
436
|
repositoryConfig.name) {
|
|
433
437
|
repoUrl = `https://dev.azure.com/${repositoryConfig.organization}/${repositoryConfig.project}/_git/${repositoryConfig.name}`;
|
|
434
|
-
this.log(
|
|
438
|
+
this.log(`Constructed repo URL from config: ${repoUrl}`);
|
|
439
|
+
}
|
|
440
|
+
else if (repositoryConfig?.provider === 'gitlab') {
|
|
441
|
+
const projectPath = repositoryConfig.projectPath
|
|
442
|
+
|| (repositoryConfig.namespace && repositoryConfig.name
|
|
443
|
+
? `${repositoryConfig.namespace}/${repositoryConfig.name}`
|
|
444
|
+
: null);
|
|
445
|
+
if (projectPath) {
|
|
446
|
+
repoUrl = `https://gitlab.com/${projectPath}.git`;
|
|
447
|
+
this.log(`Constructed repo URL from config: ${repoUrl}`);
|
|
448
|
+
}
|
|
435
449
|
}
|
|
436
450
|
}
|
|
437
451
|
if (!repoUrl) {
|
|
438
|
-
this.log('
|
|
452
|
+
this.log('No git repository found and no config available');
|
|
439
453
|
return null;
|
|
440
454
|
}
|
|
441
|
-
// Parse
|
|
455
|
+
// Parse repository identity from URL
|
|
442
456
|
let name = '';
|
|
457
|
+
let owner = '';
|
|
443
458
|
let organization = '';
|
|
444
459
|
let project = '';
|
|
445
|
-
let
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
const adoMatch = repoUrl.match(/dev\.azure\.com\/([^\/]+)\/([^\/]+)\/_git\/([^\/]+)/);
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
460
|
+
let namespace = '';
|
|
461
|
+
let projectPath = '';
|
|
462
|
+
const githubMatch = repoUrl.match(/github\.com[\/:]([^\/]+)\/([^\/\.]+)/i);
|
|
463
|
+
const adoMatch = repoUrl.match(/dev\.azure\.com\/([^\/]+)\/([^\/]+)\/_git\/([^\/]+)/i);
|
|
464
|
+
const gitlabMatch = repoUrl.match(/gitlab[^\/:]*[\/:]([^?\s#]+?)(?:\.git)?$/i);
|
|
465
|
+
if (githubMatch) {
|
|
466
|
+
owner = githubMatch[1];
|
|
467
|
+
name = githubMatch[2];
|
|
452
468
|
}
|
|
453
469
|
else if (adoMatch) {
|
|
454
|
-
// Azure DevOps: organization and project are separate fields
|
|
455
470
|
organization = adoMatch[1];
|
|
456
471
|
project = adoMatch[2];
|
|
457
472
|
name = adoMatch[3];
|
|
458
473
|
}
|
|
474
|
+
else if (gitlabMatch) {
|
|
475
|
+
projectPath = gitlabMatch[1].replace(/^\/+/, '');
|
|
476
|
+
const segments = projectPath.split('/').filter(Boolean);
|
|
477
|
+
name = segments[segments.length - 1] || '';
|
|
478
|
+
namespace = segments.slice(0, -1).join('/');
|
|
479
|
+
}
|
|
459
480
|
else if (this.config?.repository) {
|
|
460
481
|
// Fall back to config if URL parsing fails
|
|
461
482
|
owner = this.config.repository.owner || '';
|
|
462
483
|
name = this.config.repository.name || '';
|
|
463
484
|
organization = this.config.repository.organization || '';
|
|
464
485
|
project = this.config.repository.project || '';
|
|
486
|
+
namespace = this.config.repository.namespace || '';
|
|
487
|
+
projectPath = this.config.repository.projectPath || (namespace && name ? `${namespace}/${name}` : '');
|
|
465
488
|
}
|
|
466
489
|
// Get current branch
|
|
467
490
|
let branch = '';
|
|
@@ -483,6 +506,8 @@ class FraimLocalMCPServer {
|
|
|
483
506
|
name: name || 'unknown',
|
|
484
507
|
...(organization && { organization }),
|
|
485
508
|
...(project && { project }),
|
|
509
|
+
...(namespace && { namespace }),
|
|
510
|
+
...(projectPath && { projectPath }),
|
|
486
511
|
...(branch && { branch })
|
|
487
512
|
};
|
|
488
513
|
if (owner) {
|
|
@@ -491,8 +516,8 @@ class FraimLocalMCPServer {
|
|
|
491
516
|
this.repoInfo = repoInfo;
|
|
492
517
|
const repoLabel = this.repoInfo.owner
|
|
493
518
|
? `${this.repoInfo.owner}/${this.repoInfo.name}`
|
|
494
|
-
: this.repoInfo.name;
|
|
495
|
-
this.log(
|
|
519
|
+
: this.repoInfo.projectPath || this.repoInfo.name;
|
|
520
|
+
this.log(`Detected repo info: ${repoLabel}`);
|
|
496
521
|
return this.repoInfo;
|
|
497
522
|
}
|
|
498
523
|
catch (error) {
|
|
@@ -1055,6 +1080,44 @@ class FraimLocalMCPServer {
|
|
|
1055
1080
|
request.params.arguments.sessionId = requestSessionId;
|
|
1056
1081
|
}
|
|
1057
1082
|
}
|
|
1083
|
+
normalizeRepoContext(repo) {
|
|
1084
|
+
if (!repo || typeof repo !== 'object')
|
|
1085
|
+
return repo;
|
|
1086
|
+
const normalized = { ...repo };
|
|
1087
|
+
const detectedProvider = (0, provider_utils_1.detectProvider)(normalized.url);
|
|
1088
|
+
if (typeof detectedProvider === 'string' && detectedProvider.length > 0) {
|
|
1089
|
+
normalized.provider = detectedProvider;
|
|
1090
|
+
}
|
|
1091
|
+
if (normalized.provider !== 'gitlab')
|
|
1092
|
+
return normalized;
|
|
1093
|
+
if (!normalized.projectPath && typeof normalized.url === 'string') {
|
|
1094
|
+
const gitlabMatch = normalized.url.match(/gitlab[^\/:]*[\/:]([^?\s#]+?)(?:\.git)?$/i);
|
|
1095
|
+
if (gitlabMatch) {
|
|
1096
|
+
normalized.projectPath = gitlabMatch[1].replace(/^\/+/, '');
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
if (!normalized.name && typeof normalized.projectPath === 'string') {
|
|
1100
|
+
const segments = normalized.projectPath.split('/').filter(Boolean);
|
|
1101
|
+
normalized.name = segments[segments.length - 1] || normalized.name;
|
|
1102
|
+
normalized.namespace = normalized.namespace || segments.slice(0, -1).join('/');
|
|
1103
|
+
}
|
|
1104
|
+
if (normalized.projectPath || !normalized.namespace || !normalized.name)
|
|
1105
|
+
return normalized;
|
|
1106
|
+
normalized.projectPath = `${normalized.namespace}/${normalized.name}`;
|
|
1107
|
+
return normalized;
|
|
1108
|
+
}
|
|
1109
|
+
normalizeIssueTrackingContext(issueTracking) {
|
|
1110
|
+
if (!issueTracking || typeof issueTracking !== 'object')
|
|
1111
|
+
return issueTracking;
|
|
1112
|
+
if (issueTracking.provider !== 'gitlab')
|
|
1113
|
+
return issueTracking;
|
|
1114
|
+
if (issueTracking.projectPath || !issueTracking.namespace || !issueTracking.name)
|
|
1115
|
+
return issueTracking;
|
|
1116
|
+
return {
|
|
1117
|
+
...issueTracking,
|
|
1118
|
+
projectPath: `${issueTracking.namespace}/${issueTracking.name}`
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1058
1121
|
/**
|
|
1059
1122
|
* Proxy request to remote FRAIM server
|
|
1060
1123
|
*/
|
|
@@ -1083,6 +1146,7 @@ class FraimLocalMCPServer {
|
|
|
1083
1146
|
...args.repo, // Agent values as fallback
|
|
1084
1147
|
...detectedRepo // Detected values override (always win)
|
|
1085
1148
|
};
|
|
1149
|
+
args.repo = this.normalizeRepoContext(args.repo);
|
|
1086
1150
|
const repoLabel = args.repo.owner ? `${args.repo.owner}/${args.repo.name}` : args.repo.name;
|
|
1087
1151
|
this.log(`[req:${requestId}] Auto-detected and injected repo info: ${repoLabel}`);
|
|
1088
1152
|
}
|
|
@@ -1100,6 +1164,7 @@ class FraimLocalMCPServer {
|
|
|
1100
1164
|
}
|
|
1101
1165
|
};
|
|
1102
1166
|
}
|
|
1167
|
+
args.repo = this.normalizeRepoContext(args.repo);
|
|
1103
1168
|
const repoLabel = args.repo.owner ? `${args.repo.owner}/${args.repo.name}` : args.repo.name;
|
|
1104
1169
|
this.log(`[req:${requestId}] Using agent-provided repo info: ${repoLabel}`);
|
|
1105
1170
|
}
|
|
@@ -1109,8 +1174,12 @@ class FraimLocalMCPServer {
|
|
|
1109
1174
|
...(args.issueTracking || {}),
|
|
1110
1175
|
...configuredIssueTracking
|
|
1111
1176
|
};
|
|
1177
|
+
args.issueTracking = this.normalizeIssueTrackingContext(args.issueTracking);
|
|
1112
1178
|
this.log(`[req:${requestId}] Applied issueTracking context: ${args.issueTracking.provider || 'unknown'}`);
|
|
1113
1179
|
}
|
|
1180
|
+
else if (args.issueTracking) {
|
|
1181
|
+
args.issueTracking = this.normalizeIssueTrackingContext(args.issueTracking);
|
|
1182
|
+
}
|
|
1114
1183
|
const runtimeRepoContext = {
|
|
1115
1184
|
...args.repo,
|
|
1116
1185
|
...(args.issueTracking ? { issueTracking: args.issueTracking } : {})
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
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
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"fraim": "./index.js",
|
|
8
|
-
"fraim-framework": "./index.js",
|
|
9
|
-
"fraim-mcp": "./bin/fraim-mcp.js"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"dev": "tsx --watch src/fraim-mcp-server.ts > server.log 2>&1",
|
|
13
|
-
"dev:prod": "npm run build && node dist/src/fraim-mcp-server.js > server.log 2>&1",
|
|
14
|
-
"build": "tsc && npm run build:stubs && node scripts/copy-ai-manager-rules.js && npm run validate:registry && tsx scripts/validate-purity.ts",
|
|
15
|
-
"build:stubs": "tsx scripts/build-stub-registry.ts",
|
|
16
|
-
"test-all": "npm run test && npm run test:ui",
|
|
17
|
-
"test": "node scripts/test-with-server.js",
|
|
18
|
-
"test:ui": "playwright test",
|
|
19
|
-
"test:ui:headed": "playwright test --headed",
|
|
20
|
-
"start:fraim": "tsx src/fraim-mcp-server.ts",
|
|
21
|
-
"dev:fraim": "tsx --watch src/fraim-mcp-server.ts",
|
|
22
|
-
"serve:website": "node fraim-pro/serve.js",
|
|
23
|
-
"watch:fraimlogs": "tsx scripts/watch-fraim-logs.ts > prodlogs.log 2>&1",
|
|
24
|
-
"manage-keys": "tsx scripts/fraim/manage-keys.ts",
|
|
25
|
-
"view-signups": "tsx scripts/view-signups.ts",
|
|
26
|
-
"fraim:init": "npm run build && node index.js init",
|
|
27
|
-
"fraim:sync": "node index.js sync --local",
|
|
28
|
-
"postinstall": "fraim sync --skip-updates || echo 'FRAIM setup skipped.'",
|
|
29
|
-
"prepublishOnly": "npm run build",
|
|
30
|
-
"release": "npm version patch && npm publish",
|
|
31
|
-
"validate:registry": "tsx scripts/verify-registry-paths.ts && npm run validate:workflows && npm run validate:skills && npm run validate:platform-agnostic && npm run validate:template-namespaces && npm run validate:config-fallbacks && npm run validate:bootstrap-config-coverage && npm run validate:provider-action-mappings",
|
|
32
|
-
"validate:workflows": "tsx scripts/validate-workflows.ts",
|
|
33
|
-
"validate:platform-agnostic": "tsx scripts/validate-platform-agnostic.ts",
|
|
34
|
-
"validate:skills": "tsx scripts/validate-skills.ts",
|
|
35
|
-
"validate:template-namespaces": "tsx scripts/validate-template-namespaces.ts",
|
|
36
|
-
"validate:config-fallbacks": "tsx scripts/validate-config-fallbacks.ts",
|
|
37
|
-
"validate:bootstrap-config-coverage": "tsx scripts/validate-bootstrap-config-coverage.ts",
|
|
38
|
-
"validate:provider-action-mappings": "tsx scripts/validate-provider-action-mappings.ts"
|
|
39
|
-
},
|
|
40
|
-
"repository": {
|
|
41
|
-
"type": "git",
|
|
42
|
-
"url": "git+https://github.com/mathursrus/FRAIM.git"
|
|
43
|
-
},
|
|
44
|
-
"keywords": [
|
|
45
|
-
"fraim",
|
|
46
|
-
"ai-management",
|
|
47
|
-
"ai-coordination",
|
|
48
|
-
"ai-agents",
|
|
49
|
-
"multi-agent",
|
|
50
|
-
"github",
|
|
51
|
-
"workflow",
|
|
52
|
-
"automation",
|
|
53
|
-
"gitops",
|
|
54
|
-
"cursor",
|
|
55
|
-
"claude",
|
|
56
|
-
"windsurf",
|
|
57
|
-
"rigor",
|
|
58
|
-
"enterprise",
|
|
59
|
-
"framework",
|
|
60
|
-
"ai-managers"
|
|
61
|
-
],
|
|
62
|
-
"author": "Sid Mathur <sid.mathur@gmail.com>",
|
|
63
|
-
"license": "MIT",
|
|
64
|
-
"bugs": {
|
|
65
|
-
"url": "https://github.com/mathursrus/FRAIM/issues"
|
|
66
|
-
},
|
|
67
|
-
"homepage": "https://github.com/mathursrus/FRAIM#readme",
|
|
68
|
-
"engines": {
|
|
69
|
-
"node": ">=16.0.0"
|
|
70
|
-
},
|
|
71
|
-
"devDependencies": {
|
|
72
|
-
"@playwright/test": "^1.58.2",
|
|
73
|
-
"@types/cors": "^2.8.19",
|
|
74
|
-
"@types/express": "^5.0.6",
|
|
75
|
-
"@types/node": "^20.0.0",
|
|
76
|
-
"@types/prompts": "^2.4.9",
|
|
77
|
-
"fast-glob": "^3.3.3",
|
|
78
|
-
"html-to-docx": "^1.8.0",
|
|
79
|
-
"markdown-it": "^14.1.0",
|
|
80
|
-
"markdown-it-highlightjs": "^4.2.0",
|
|
81
|
-
"playwright": "^1.58.2",
|
|
82
|
-
"pptxgenjs": "^4.0.1",
|
|
83
|
-
"puppeteer": "^24.36.1",
|
|
84
|
-
"qrcode": "^1.5.4",
|
|
85
|
-
"sharp": "^0.34.5",
|
|
86
|
-
"tsx": "^4.0.0",
|
|
87
|
-
"typescript": "^5.0.0"
|
|
88
|
-
},
|
|
89
|
-
"files": [
|
|
90
|
-
"dist/src/local-mcp-server/",
|
|
91
|
-
"dist/src/cli/",
|
|
92
|
-
"dist/src/core/",
|
|
93
|
-
"bin/fraim.js",
|
|
94
|
-
"bin/fraim-mcp.js",
|
|
95
|
-
"index.js",
|
|
96
|
-
"README.md",
|
|
97
|
-
"CHANGELOG.md",
|
|
98
|
-
"LICENSE",
|
|
99
|
-
"package.json"
|
|
100
|
-
],
|
|
101
|
-
"publishConfig": {
|
|
102
|
-
"access": "public"
|
|
103
|
-
},
|
|
104
|
-
"dependencies": {
|
|
105
|
-
"axios": "^1.7.0",
|
|
106
|
-
"chalk": "4.1.2",
|
|
107
|
-
"commander": "^14.0.2",
|
|
108
|
-
"cors": "^2.8.5",
|
|
109
|
-
"dotenv": "^16.4.7",
|
|
110
|
-
"express": "^5.2.1",
|
|
111
|
-
"mongodb": "^7.0.0",
|
|
112
|
-
"prompts": "^2.4.2",
|
|
113
|
-
"stripe": "^20.3.1",
|
|
114
|
-
"tree-kill": "^1.2.2"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "fraim-framework",
|
|
3
|
+
"version": "2.0.80",
|
|
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
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"fraim": "./index.js",
|
|
8
|
+
"fraim-framework": "./index.js",
|
|
9
|
+
"fraim-mcp": "./bin/fraim-mcp.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "tsx --watch src/fraim-mcp-server.ts > server.log 2>&1",
|
|
13
|
+
"dev:prod": "npm run build && node dist/src/fraim-mcp-server.js > server.log 2>&1",
|
|
14
|
+
"build": "tsc && npm run build:stubs && node scripts/copy-ai-manager-rules.js && npm run validate:registry && tsx scripts/validate-purity.ts",
|
|
15
|
+
"build:stubs": "tsx scripts/build-stub-registry.ts",
|
|
16
|
+
"test-all": "npm run test && npm run test:ui",
|
|
17
|
+
"test": "node scripts/test-with-server.js",
|
|
18
|
+
"test:ui": "playwright test",
|
|
19
|
+
"test:ui:headed": "playwright test --headed",
|
|
20
|
+
"start:fraim": "tsx src/fraim-mcp-server.ts",
|
|
21
|
+
"dev:fraim": "tsx --watch src/fraim-mcp-server.ts",
|
|
22
|
+
"serve:website": "node fraim-pro/serve.js",
|
|
23
|
+
"watch:fraimlogs": "tsx scripts/watch-fraim-logs.ts > prodlogs.log 2>&1",
|
|
24
|
+
"manage-keys": "tsx scripts/fraim/manage-keys.ts",
|
|
25
|
+
"view-signups": "tsx scripts/view-signups.ts",
|
|
26
|
+
"fraim:init": "npm run build && node index.js init",
|
|
27
|
+
"fraim:sync": "node index.js sync --local",
|
|
28
|
+
"postinstall": "fraim sync --skip-updates || echo 'FRAIM setup skipped.'",
|
|
29
|
+
"prepublishOnly": "npm run build",
|
|
30
|
+
"release": "npm version patch && npm publish",
|
|
31
|
+
"validate:registry": "tsx scripts/verify-registry-paths.ts && npm run validate:workflows && npm run validate:skills && npm run validate:platform-agnostic && npm run validate:template-namespaces && npm run validate:config-fallbacks && npm run validate:bootstrap-config-coverage && npm run validate:provider-action-mappings",
|
|
32
|
+
"validate:workflows": "tsx scripts/validate-workflows.ts",
|
|
33
|
+
"validate:platform-agnostic": "tsx scripts/validate-platform-agnostic.ts",
|
|
34
|
+
"validate:skills": "tsx scripts/validate-skills.ts",
|
|
35
|
+
"validate:template-namespaces": "tsx scripts/validate-template-namespaces.ts",
|
|
36
|
+
"validate:config-fallbacks": "tsx scripts/validate-config-fallbacks.ts",
|
|
37
|
+
"validate:bootstrap-config-coverage": "tsx scripts/validate-bootstrap-config-coverage.ts",
|
|
38
|
+
"validate:provider-action-mappings": "tsx scripts/validate-provider-action-mappings.ts"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/mathursrus/FRAIM.git"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"fraim",
|
|
46
|
+
"ai-management",
|
|
47
|
+
"ai-coordination",
|
|
48
|
+
"ai-agents",
|
|
49
|
+
"multi-agent",
|
|
50
|
+
"github",
|
|
51
|
+
"workflow",
|
|
52
|
+
"automation",
|
|
53
|
+
"gitops",
|
|
54
|
+
"cursor",
|
|
55
|
+
"claude",
|
|
56
|
+
"windsurf",
|
|
57
|
+
"rigor",
|
|
58
|
+
"enterprise",
|
|
59
|
+
"framework",
|
|
60
|
+
"ai-managers"
|
|
61
|
+
],
|
|
62
|
+
"author": "Sid Mathur <sid.mathur@gmail.com>",
|
|
63
|
+
"license": "MIT",
|
|
64
|
+
"bugs": {
|
|
65
|
+
"url": "https://github.com/mathursrus/FRAIM/issues"
|
|
66
|
+
},
|
|
67
|
+
"homepage": "https://github.com/mathursrus/FRAIM#readme",
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=16.0.0"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@playwright/test": "^1.58.2",
|
|
73
|
+
"@types/cors": "^2.8.19",
|
|
74
|
+
"@types/express": "^5.0.6",
|
|
75
|
+
"@types/node": "^20.0.0",
|
|
76
|
+
"@types/prompts": "^2.4.9",
|
|
77
|
+
"fast-glob": "^3.3.3",
|
|
78
|
+
"html-to-docx": "^1.8.0",
|
|
79
|
+
"markdown-it": "^14.1.0",
|
|
80
|
+
"markdown-it-highlightjs": "^4.2.0",
|
|
81
|
+
"playwright": "^1.58.2",
|
|
82
|
+
"pptxgenjs": "^4.0.1",
|
|
83
|
+
"puppeteer": "^24.36.1",
|
|
84
|
+
"qrcode": "^1.5.4",
|
|
85
|
+
"sharp": "^0.34.5",
|
|
86
|
+
"tsx": "^4.0.0",
|
|
87
|
+
"typescript": "^5.0.0"
|
|
88
|
+
},
|
|
89
|
+
"files": [
|
|
90
|
+
"dist/src/local-mcp-server/",
|
|
91
|
+
"dist/src/cli/",
|
|
92
|
+
"dist/src/core/",
|
|
93
|
+
"bin/fraim.js",
|
|
94
|
+
"bin/fraim-mcp.js",
|
|
95
|
+
"index.js",
|
|
96
|
+
"README.md",
|
|
97
|
+
"CHANGELOG.md",
|
|
98
|
+
"LICENSE",
|
|
99
|
+
"package.json"
|
|
100
|
+
],
|
|
101
|
+
"publishConfig": {
|
|
102
|
+
"access": "public"
|
|
103
|
+
},
|
|
104
|
+
"dependencies": {
|
|
105
|
+
"axios": "^1.7.0",
|
|
106
|
+
"chalk": "4.1.2",
|
|
107
|
+
"commander": "^14.0.2",
|
|
108
|
+
"cors": "^2.8.5",
|
|
109
|
+
"dotenv": "^16.4.7",
|
|
110
|
+
"express": "^5.2.1",
|
|
111
|
+
"mongodb": "^7.0.0",
|
|
112
|
+
"prompts": "^2.4.2",
|
|
113
|
+
"stripe": "^20.3.1",
|
|
114
|
+
"tree-kill": "^1.2.2"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -1,148 +0,0 @@
|
|
|
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));
|
|
@@ -1,65 +0,0 @@
|
|
|
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
|
-
});
|