fraim 2.0.164 → 2.0.166
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/ai-hub/word-sideload.js +95 -0
- package/dist/src/cli/commands/first-run.js +37 -2
- package/dist/src/cli/commands/hub.js +41 -5
- package/dist/src/cli/commands/org.js +40 -0
- package/dist/src/cli/commands/test-mcp.js +171 -0
- package/dist/src/cli/fraim.js +2 -0
- package/dist/src/cli/setup/first-run.js +242 -0
- package/dist/src/cli/utils/org-publish.js +98 -0
- package/dist/src/core/config-writer.js +75 -0
- package/dist/src/core/utils/job-aliases.js +47 -0
- package/dist/src/core/utils/workflow-parser.js +174 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/public/ai-hub/powerpoint-taskpane/index.html +236 -236
- package/public/ai-hub/powerpoint-taskpane/manifest.xml +29 -29
- package/public/first-run/styles.css +73 -73
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sideloads the Word add-in manifest so it appears in Word's Developer Add-ins
|
|
4
|
+
* list without admin rights or AppSource publishing.
|
|
5
|
+
*
|
|
6
|
+
* Windows: writes a registry value under HKCU\SOFTWARE\Microsoft\Office\16.0\WEF\Developer
|
|
7
|
+
* macOS: writes an entry to ~/Library/Containers/com.microsoft.Word/Data/Documents/wef/
|
|
8
|
+
*
|
|
9
|
+
* Both paths are non-admin and survive app updates (keyed by manifest GUID).
|
|
10
|
+
* Safe to call multiple times — checks before writing.
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.isSideloaded = isSideloaded;
|
|
17
|
+
exports.sideloadManifest = sideloadManifest;
|
|
18
|
+
exports.removeSideload = removeSideload;
|
|
19
|
+
const fs_1 = __importDefault(require("fs"));
|
|
20
|
+
const path_1 = __importDefault(require("path"));
|
|
21
|
+
const os_1 = __importDefault(require("os"));
|
|
22
|
+
const child_process_1 = require("child_process");
|
|
23
|
+
const MANIFEST_GUID = 'd1090951-50cf-4cf2-9d12-b0f8541d265c';
|
|
24
|
+
function resolveManifestPath(projectPath) {
|
|
25
|
+
const candidates = [
|
|
26
|
+
path_1.default.resolve(projectPath, 'extensions/office-word/manifest.xml'),
|
|
27
|
+
path_1.default.resolve(__dirname, '..', '..', 'extensions/office-word/manifest.xml'),
|
|
28
|
+
path_1.default.resolve(__dirname, '..', '..', '..', 'extensions/office-word/manifest.xml'),
|
|
29
|
+
];
|
|
30
|
+
return candidates.find(c => fs_1.default.existsSync(c)) ?? null;
|
|
31
|
+
}
|
|
32
|
+
function isSideloaded() {
|
|
33
|
+
if (process.platform === 'win32') {
|
|
34
|
+
const result = (0, child_process_1.spawnSync)('reg', [
|
|
35
|
+
'query',
|
|
36
|
+
`HKCU\\SOFTWARE\\Microsoft\\Office\\16.0\\WEF\\Developer`,
|
|
37
|
+
'/v', MANIFEST_GUID,
|
|
38
|
+
], { encoding: 'utf8' });
|
|
39
|
+
return result.status === 0 && result.stdout.includes(MANIFEST_GUID);
|
|
40
|
+
}
|
|
41
|
+
if (process.platform === 'darwin') {
|
|
42
|
+
const wefDir = path_1.default.join(os_1.default.homedir(), 'Library', 'Containers', 'com.microsoft.Word', 'Data', 'Documents', 'wef');
|
|
43
|
+
return fs_1.default.existsSync(path_1.default.join(wefDir, `${MANIFEST_GUID}.xml`));
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function sideloadManifest(projectPath) {
|
|
48
|
+
const manifestPath = resolveManifestPath(projectPath);
|
|
49
|
+
if (!manifestPath) {
|
|
50
|
+
return { ok: false, reason: 'Manifest file not found — is extensions/office-word/ present?' };
|
|
51
|
+
}
|
|
52
|
+
if (process.platform === 'win32') {
|
|
53
|
+
const result = (0, child_process_1.spawnSync)('reg', [
|
|
54
|
+
'add',
|
|
55
|
+
`HKCU\\SOFTWARE\\Microsoft\\Office\\16.0\\WEF\\Developer`,
|
|
56
|
+
'/v', MANIFEST_GUID,
|
|
57
|
+
'/t', 'REG_SZ',
|
|
58
|
+
'/d', manifestPath,
|
|
59
|
+
'/f',
|
|
60
|
+
], { encoding: 'utf8' });
|
|
61
|
+
if (result.status !== 0) {
|
|
62
|
+
return { ok: false, reason: result.stderr || 'reg add failed' };
|
|
63
|
+
}
|
|
64
|
+
return { ok: true };
|
|
65
|
+
}
|
|
66
|
+
if (process.platform === 'darwin') {
|
|
67
|
+
const wefDir = path_1.default.join(os_1.default.homedir(), 'Library', 'Containers', 'com.microsoft.Word', 'Data', 'Documents', 'wef');
|
|
68
|
+
try {
|
|
69
|
+
fs_1.default.mkdirSync(wefDir, { recursive: true });
|
|
70
|
+
fs_1.default.copyFileSync(manifestPath, path_1.default.join(wefDir, `${MANIFEST_GUID}.xml`));
|
|
71
|
+
return { ok: true };
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return { ok: false, reason: String(err) };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { ok: false, reason: `Unsupported platform: ${process.platform}` };
|
|
78
|
+
}
|
|
79
|
+
function removeSideload() {
|
|
80
|
+
if (process.platform === 'win32') {
|
|
81
|
+
(0, child_process_1.spawnSync)('reg', [
|
|
82
|
+
'delete',
|
|
83
|
+
`HKCU\\SOFTWARE\\Microsoft\\Office\\16.0\\WEF\\Developer`,
|
|
84
|
+
'/v', MANIFEST_GUID,
|
|
85
|
+
'/f',
|
|
86
|
+
], { encoding: 'utf8' });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (process.platform === 'darwin') {
|
|
90
|
+
const wefDir = path_1.default.join(os_1.default.homedir(), 'Library', 'Containers', 'com.microsoft.Word', 'Data', 'Documents', 'wef');
|
|
91
|
+
const target = path_1.default.join(wefDir, `${MANIFEST_GUID}.xml`);
|
|
92
|
+
if (fs_1.default.existsSync(target))
|
|
93
|
+
fs_1.default.unlinkSync(target);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -9,7 +42,6 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
9
42
|
const child_process_1 = require("child_process");
|
|
10
43
|
const server_1 = require("../../first-run/server");
|
|
11
44
|
const session_service_1 = require("../../first-run/session-service");
|
|
12
|
-
const server_2 = require("../../ai-hub/server");
|
|
13
45
|
function openBrowser(url) {
|
|
14
46
|
try {
|
|
15
47
|
if (process.platform === 'win32') {
|
|
@@ -45,7 +77,10 @@ const runFirstRun = async (options) => {
|
|
|
45
77
|
projectRoot: options.projectRoot,
|
|
46
78
|
});
|
|
47
79
|
const server = new server_1.FirstRunServer({ sessionService });
|
|
48
|
-
|
|
80
|
+
// Lazy import: ai-hub/server pulls server-only code not shipped in the client
|
|
81
|
+
// package; keep it out of the CLI startup graph so the packed client loads (#422).
|
|
82
|
+
const { findAvailablePort } = await Promise.resolve().then(() => __importStar(require('../../ai-hub/server')));
|
|
83
|
+
const port = await findAvailablePort(43120);
|
|
49
84
|
const url = `http://127.0.0.1:${port}/first-run/`;
|
|
50
85
|
await server.start(port);
|
|
51
86
|
console.log(chalk_1.default.blue('Starting FRAIM first-run...'));
|
|
@@ -1,11 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.hubCommand = void 0;
|
|
7
40
|
const commander_1 = require("commander");
|
|
8
|
-
|
|
41
|
+
// ai-hub/server pulls in server-only code (persona-hiring etc.) that is not
|
|
42
|
+
// shipped in the client package; it is imported lazily inside the action below
|
|
43
|
+
// to keep it out of the CLI startup graph so the packed client loads (issue #422).
|
|
9
44
|
const git_utils_1 = require("../../core/utils/git-utils");
|
|
10
45
|
const path_1 = __importDefault(require("path"));
|
|
11
46
|
const child_process_1 = require("child_process");
|
|
@@ -69,13 +104,14 @@ exports.hubCommand = new commander_1.Command('hub')
|
|
|
69
104
|
.option('--no-open', 'Do not open the hub after startup')
|
|
70
105
|
.option('--browser', 'Open in the default browser instead of the desktop shell')
|
|
71
106
|
.action(async (options) => {
|
|
107
|
+
const { AiHubServer, findAvailablePort } = await Promise.resolve().then(() => __importStar(require('../../ai-hub/server')));
|
|
72
108
|
const preferredPort = options.port || (0, git_utils_1.getPort)() + 100;
|
|
73
109
|
const projectPath = path_1.default.resolve(options.projectPath || process.cwd());
|
|
74
110
|
if (options.open) {
|
|
75
111
|
const openedDesktop = !options.browser && openDesktopWindow(projectPath, preferredPort);
|
|
76
112
|
if (!openedDesktop) {
|
|
77
|
-
const port = await
|
|
78
|
-
const server = new
|
|
113
|
+
const port = await findAvailablePort(preferredPort);
|
|
114
|
+
const server = new AiHubServer({ projectPath });
|
|
79
115
|
await server.start(port);
|
|
80
116
|
const url = `http://127.0.0.1:${port}/ai-hub/`;
|
|
81
117
|
console.log(`AI Hub running at ${url}`);
|
|
@@ -87,8 +123,8 @@ exports.hubCommand = new commander_1.Command('hub')
|
|
|
87
123
|
console.log(`Project path: ${projectPath}`);
|
|
88
124
|
return;
|
|
89
125
|
}
|
|
90
|
-
const port = await
|
|
91
|
-
const server = new
|
|
126
|
+
const port = await findAvailablePort(preferredPort);
|
|
127
|
+
const server = new AiHubServer({ projectPath });
|
|
92
128
|
await server.start(port);
|
|
93
129
|
const url = `http://127.0.0.1:${port}/ai-hub/`;
|
|
94
130
|
console.log(`AI Hub running at ${url}`);
|
|
@@ -0,0 +1,40 @@
|
|
|
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.orgCommand = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const org_publish_1 = require("../utils/org-publish");
|
|
11
|
+
exports.orgCommand = new commander_1.Command('org')
|
|
12
|
+
.description('Manage your shared organization context');
|
|
13
|
+
exports.orgCommand
|
|
14
|
+
.command('publish')
|
|
15
|
+
.description('Publish org context/rules/learnings files to the configured org backend')
|
|
16
|
+
.argument('<files...>', 'Local files to publish: org_context.md, org_rules.md, and/or org-*.md learnings')
|
|
17
|
+
.action(async (files) => {
|
|
18
|
+
try {
|
|
19
|
+
const artifacts = files.map((f) => {
|
|
20
|
+
if (!fs_1.default.existsSync(f))
|
|
21
|
+
throw new Error(`File not found: ${f}`);
|
|
22
|
+
return { relativePath: (0, org_publish_1.packRelativePathFor)(f), content: fs_1.default.readFileSync(f, 'utf8') };
|
|
23
|
+
});
|
|
24
|
+
const result = await (0, org_publish_1.publishOrgArtifacts)(artifacts);
|
|
25
|
+
if (result.backend === 'fraim-cloud') {
|
|
26
|
+
console.log(chalk_1.default.green(`Published ${artifacts.length} org artifact(s) to your FRAIM organization (version ${result.version}).`));
|
|
27
|
+
console.log(chalk_1.default.gray('Run "fraim sync" on each machine to pull the update.'));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
console.log(chalk_1.default.green(`Pushed ${artifacts.length} org artifact(s) to branch "${result.branch}" in your organization repo.`));
|
|
31
|
+
if (result.prUrl)
|
|
32
|
+
console.log(chalk_1.default.cyan(`Open the pull request: ${result.prUrl}`));
|
|
33
|
+
console.log(chalk_1.default.gray('After it merges, run "fraim sync" to pull the update.'));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(chalk_1.default.red(`org publish failed: ${error.message}`));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.testMCPCommand = exports.runTestMCP = void 0;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
42
|
+
const fs_1 = __importDefault(require("fs"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const ide_detector_1 = require("../setup/ide-detector");
|
|
45
|
+
const script_sync_utils_1 = require("../utils/script-sync-utils");
|
|
46
|
+
const testIDEConfig = async (ide) => {
|
|
47
|
+
const result = {
|
|
48
|
+
ide: ide.name,
|
|
49
|
+
configExists: false,
|
|
50
|
+
configValid: false,
|
|
51
|
+
mcpServers: [],
|
|
52
|
+
errors: []
|
|
53
|
+
};
|
|
54
|
+
const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
|
|
55
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
56
|
+
result.errors.push('Config file does not exist');
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
result.configExists = true;
|
|
60
|
+
try {
|
|
61
|
+
if (ide.configFormat === 'json') {
|
|
62
|
+
const configContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
63
|
+
const config = JSON.parse(configContent);
|
|
64
|
+
const servers = ide.configType === 'vscode' ? config.servers : config.mcpServers;
|
|
65
|
+
if (servers) {
|
|
66
|
+
result.configValid = true;
|
|
67
|
+
result.mcpServers = Object.keys(servers);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const expectedKey = ide.configType === 'vscode' ? 'servers' : 'mcpServers';
|
|
71
|
+
result.errors.push(`No ${expectedKey} section found`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (ide.configFormat === 'toml') {
|
|
75
|
+
const configContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
76
|
+
// Simple TOML parsing for MCP servers
|
|
77
|
+
const serverMatches = configContent.match(/\[mcp_servers\.(\w+)\]/g);
|
|
78
|
+
if (serverMatches) {
|
|
79
|
+
result.configValid = true;
|
|
80
|
+
result.mcpServers = serverMatches.map(match => match.replace(/\[mcp_servers\.(\w+)\]/, '$1'));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
result.errors.push('No mcp_servers sections found');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
result.errors.push(`Failed to parse config: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
};
|
|
92
|
+
const checkGlobalSetup = () => {
|
|
93
|
+
const globalConfigPath = path_1.default.join((0, script_sync_utils_1.getUserFraimDir)(), 'config.json');
|
|
94
|
+
return fs_1.default.existsSync(globalConfigPath);
|
|
95
|
+
};
|
|
96
|
+
const runTestMCP = async () => {
|
|
97
|
+
console.log(chalk_1.default.blue('🔍 Testing MCP configuration...\n'));
|
|
98
|
+
// Check global setup
|
|
99
|
+
if (!checkGlobalSetup()) {
|
|
100
|
+
console.log(chalk_1.default.red('❌ Global FRAIM setup not found.'));
|
|
101
|
+
console.log(chalk_1.default.yellow('Please run: fraim setup --key=<your-fraim-key>'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
console.log(chalk_1.default.green('✅ Global FRAIM setup found'));
|
|
105
|
+
// Detect IDEs
|
|
106
|
+
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
107
|
+
if (detectedIDEs.length === 0) {
|
|
108
|
+
console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
console.log(chalk_1.default.blue(`\n🔍 Testing ${detectedIDEs.length} detected IDEs...\n`));
|
|
112
|
+
const results = await Promise.all(detectedIDEs.map(ide => testIDEConfig(ide)));
|
|
113
|
+
let totalConfigured = 0;
|
|
114
|
+
let totalWithFRAIM = 0;
|
|
115
|
+
for (const result of results) {
|
|
116
|
+
console.log(chalk_1.default.white(`📱 ${result.ide}`));
|
|
117
|
+
if (!result.configExists) {
|
|
118
|
+
console.log(chalk_1.default.red(' ❌ No MCP config found'));
|
|
119
|
+
console.log(chalk_1.default.gray(` 💡 Run: fraim setup --ide=${result.ide.toLowerCase()}`));
|
|
120
|
+
}
|
|
121
|
+
else if (!result.configValid) {
|
|
122
|
+
console.log(chalk_1.default.yellow(' ⚠️ Config exists but invalid'));
|
|
123
|
+
result.errors.forEach(error => {
|
|
124
|
+
console.log(chalk_1.default.red(` ❌ ${error}`));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
totalConfigured++;
|
|
129
|
+
console.log(chalk_1.default.green(` ✅ MCP config valid (${result.mcpServers.length} servers)`));
|
|
130
|
+
// Check for essential servers
|
|
131
|
+
const { BASE_MCP_SERVERS } = await Promise.resolve().then(() => __importStar(require('../mcp/mcp-server-registry')));
|
|
132
|
+
const essentialServers = BASE_MCP_SERVERS.map(s => s.id); // fraim, git, playwright
|
|
133
|
+
const hasEssential = essentialServers.filter(server => result.mcpServers.includes(server));
|
|
134
|
+
if (hasEssential.includes('fraim')) {
|
|
135
|
+
totalWithFRAIM++;
|
|
136
|
+
console.log(chalk_1.default.green(' ✅ FRAIM server configured'));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log(chalk_1.default.yellow(' ⚠️ FRAIM server missing'));
|
|
140
|
+
}
|
|
141
|
+
if (hasEssential.length > 1) {
|
|
142
|
+
console.log(chalk_1.default.green(` ✅ ${hasEssential.length - 1} additional servers: ${hasEssential.filter(s => s !== 'fraim').join(', ')}`));
|
|
143
|
+
}
|
|
144
|
+
const missingEssential = essentialServers.filter(server => !result.mcpServers.includes(server));
|
|
145
|
+
if (missingEssential.length > 0) {
|
|
146
|
+
console.log(chalk_1.default.yellow(` ⚠️ Missing servers: ${missingEssential.join(', ')}`));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
console.log(); // Empty line
|
|
150
|
+
}
|
|
151
|
+
// Summary
|
|
152
|
+
console.log(chalk_1.default.blue('📊 Summary:'));
|
|
153
|
+
console.log(chalk_1.default.green(` ✅ ${totalConfigured}/${detectedIDEs.length} IDEs have valid MCP configs`));
|
|
154
|
+
console.log(chalk_1.default.green(` ✅ ${totalWithFRAIM}/${detectedIDEs.length} IDEs have FRAIM configured`));
|
|
155
|
+
if (totalWithFRAIM === 0) {
|
|
156
|
+
console.log(chalk_1.default.red('\n❌ No IDEs have FRAIM configured!'));
|
|
157
|
+
console.log(chalk_1.default.yellow('💡 Run: fraim setup --key=<your-fraim-key>'));
|
|
158
|
+
}
|
|
159
|
+
else if (totalWithFRAIM < detectedIDEs.length) {
|
|
160
|
+
console.log(chalk_1.default.yellow(`\n⚠️ ${detectedIDEs.length - totalWithFRAIM} IDEs missing FRAIM configuration`));
|
|
161
|
+
console.log(chalk_1.default.yellow('💡 Run: fraim setup to configure remaining IDEs'));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.log(chalk_1.default.green('\n🎉 All detected IDEs have FRAIM configured!'));
|
|
165
|
+
console.log(chalk_1.default.blue('💡 Try running: fraim init-project in any project'));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
exports.runTestMCP = runTestMCP;
|
|
169
|
+
exports.testMCPCommand = new commander_1.Command('test-mcp')
|
|
170
|
+
.description('Test MCP server configurations for all detected IDEs')
|
|
171
|
+
.action(exports.runTestMCP);
|
package/dist/src/cli/fraim.js
CHANGED
|
@@ -53,6 +53,7 @@ const migrate_project_fraim_1 = require("./commands/migrate-project-fraim");
|
|
|
53
53
|
const hub_1 = require("./commands/hub");
|
|
54
54
|
const first_run_1 = require("./commands/first-run");
|
|
55
55
|
const workspace_config_1 = require("./commands/workspace-config");
|
|
56
|
+
const org_1 = require("./commands/org");
|
|
56
57
|
const fs_1 = __importDefault(require("fs"));
|
|
57
58
|
const path_1 = __importDefault(require("path"));
|
|
58
59
|
const program = new commander_1.Command();
|
|
@@ -95,6 +96,7 @@ program.addCommand(migrate_project_fraim_1.migrateProjectFraimCommand);
|
|
|
95
96
|
program.addCommand(hub_1.hubCommand);
|
|
96
97
|
program.addCommand(first_run_1.firstRunCommand);
|
|
97
98
|
program.addCommand(workspace_config_1.workspaceConfigCommand);
|
|
99
|
+
program.addCommand(org_1.orgCommand);
|
|
98
100
|
// Wait for async command initialization before parsing
|
|
99
101
|
(async () => {
|
|
100
102
|
// Import the initialization promise from setup command
|