fraim 2.0.281 → 2.0.283
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 +467 -467
- package/bin/fraim.js +12 -12
- package/dist/src/cli/mcp/fraim-mcp-latest-launcher.js +266 -182
- package/dist/src/cli/mcp/mcp-server-registry.js +11 -3
- package/dist/src/cli/setup/ide-invocation-surfaces.js +64 -64
- package/dist/src/cli/utils/agent-adapters.js +61 -61
- package/dist/src/core/handoff-contracts.js +39 -39
- package/dist/src/core/utils/stub-generator.js +53 -53
- package/dist/src/first-run/server.js +5 -1
- package/dist/src/first-run/session-service.js +48 -12
- package/dist/src/fraim/issues.js +4 -4
- package/dist/src/mcp/tool-schemas.js +40 -40
- package/dist/src/middleware/telemetry.js +21 -21
- package/dist/src/services/email-service.js +623 -623
- package/dist/src/services/installer-service.js +22 -22
- package/index.js +83 -83
- package/package.json +59 -59
- package/public/first-run/error-frame.js +100 -100
- package/public/first-run/index.html +35 -35
- package/public/first-run/script.js +747 -742
- package/public/first-run/styles.css +929 -929
- package/dist/src/cli/commands/learning-usage.js +0 -412
- package/dist/src/cli/commands/test-mcp.js +0 -171
- package/dist/src/cli/setup/first-run.js +0 -242
- package/dist/src/core/config-writer.js +0 -75
- package/dist/src/core/utils/job-aliases.js +0 -47
- package/dist/src/core/utils/workflow-parser.js +0 -174
- package/dist/src/services/email-service-clean.js +0 -782
package/bin/fraim.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
try {
|
|
4
|
-
require('../dist/src/cli/fraim.js');
|
|
5
|
-
} catch (error) {
|
|
6
|
-
if (error && error.code === 'MODULE_NOT_FOUND') {
|
|
7
|
-
console.error('Could not find FRAIM CLI implementation.');
|
|
8
|
-
console.error('If you are running from source, run "npm run build" first.');
|
|
9
|
-
console.error(`Error details: ${error.message}`);
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
throw error;
|
|
13
|
-
}
|
|
2
|
+
|
|
3
|
+
try {
|
|
4
|
+
require('../dist/src/cli/fraim.js');
|
|
5
|
+
} catch (error) {
|
|
6
|
+
if (error && error.code === 'MODULE_NOT_FOUND') {
|
|
7
|
+
console.error('Could not find FRAIM CLI implementation.');
|
|
8
|
+
console.error('If you are running from source, run "npm run build" first.');
|
|
9
|
+
console.error(`Error details: ${error.message}`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
@@ -6,111 +6,116 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.getFraimMcpLatestLauncherPath = getFraimMcpLatestLauncherPath;
|
|
7
7
|
exports.getFraimMcpShimPath = getFraimMcpShimPath;
|
|
8
8
|
exports.getFraimNpxShimPath = getFraimNpxShimPath;
|
|
9
|
+
exports.getFraimCliShimPath = getFraimCliShimPath;
|
|
10
|
+
exports.getPackagedFraimRuntimePath = getPackagedFraimRuntimePath;
|
|
11
|
+
exports.getPackagedFraimRuntime = getPackagedFraimRuntime;
|
|
12
|
+
exports.hasPackagedFraimRuntime = hasPackagedFraimRuntime;
|
|
9
13
|
exports.ensureFraimMcpLatestLauncher = ensureFraimMcpLatestLauncher;
|
|
10
14
|
const fs_1 = __importDefault(require("fs"));
|
|
11
15
|
const os_1 = __importDefault(require("os"));
|
|
12
16
|
const path_1 = __importDefault(require("path"));
|
|
13
17
|
const LAUNCHER_VERSION = 1;
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
18
|
+
const PACKAGED_RUNTIME_VERSION = 1;
|
|
19
|
+
const launcherSource = `#!/usr/bin/env node
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
const { spawnSync } = require('child_process');
|
|
24
|
+
|
|
25
|
+
const LAUNCHER_VERSION = ${LAUNCHER_VERSION};
|
|
26
|
+
const USER_DIR = process.env.FRAIM_USER_DIR || path.join(os.homedir(), '.fraim');
|
|
27
|
+
const STATE_DIR = path.join(USER_DIR, 'mcp-launcher');
|
|
28
|
+
const STATE_PATH = path.join(STATE_DIR, 'latest.json');
|
|
29
|
+
const CACHE_ROOT = path.join(USER_DIR, 'npm-cache', 'mcp');
|
|
30
|
+
|
|
31
|
+
const commandName = (name) => process.platform === 'win32' ? name + '.cmd' : name;
|
|
32
|
+
const npmCommand = commandName('npm');
|
|
33
|
+
const npxCommand = commandName('npx');
|
|
34
|
+
const cliArgs = process.argv.slice(2).length > 0 ? process.argv.slice(2) : ['mcp'];
|
|
35
|
+
|
|
36
|
+
function quoteCmdArg(arg) {
|
|
37
|
+
const value = String(arg);
|
|
38
|
+
return /[\\s"&|<>^]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function runCommand(command, args, options) {
|
|
42
|
+
if (process.platform !== 'win32') {
|
|
43
|
+
return spawnSync(command, args, options);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return spawnSync(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', [command, ...args.map(quoteCmdArg)].join(' ')], options);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function ensureDir(dir) {
|
|
50
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readState() {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse(fs.readFileSync(STATE_PATH, 'utf8'));
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function writeState(state) {
|
|
62
|
+
ensureDir(STATE_DIR);
|
|
63
|
+
fs.writeFileSync(STATE_PATH, JSON.stringify({ ...state, launcherVersion: LAUNCHER_VERSION, updatedAt: new Date().toISOString() }, null, 2));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveLatest(packageName) {
|
|
67
|
+
const result = runCommand(npmCommand, ['view', packageName, 'version', '--silent'], {
|
|
68
|
+
encoding: 'utf8',
|
|
69
|
+
env: process.env
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (result.status !== 0) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const version = String(result.stdout || '').trim();
|
|
77
|
+
return /^\\d+\\.\\d+\\.\\d+/.test(version) ? version : null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function resolvePackage() {
|
|
81
|
+
const fraimVersion = resolveLatest('fraim');
|
|
82
|
+
if (fraimVersion) {
|
|
83
|
+
const state = { packageName: 'fraim', binName: 'fraim', version: fraimVersion, fromCache: false };
|
|
84
|
+
writeState(state);
|
|
85
|
+
return state;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const cached = readState();
|
|
89
|
+
if (cached && cached.packageName === 'fraim' && cached.binName === 'fraim' && cached.version) {
|
|
90
|
+
console.error('[fraim-mcp-launcher] Could not resolve npm latest; using cached fraim@' + cached.version + '.');
|
|
91
|
+
return { packageName: 'fraim', binName: 'fraim', version: cached.version, fromCache: true };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.error('[fraim-mcp-launcher] Could not resolve fraim latest from npm and no cached fraim version exists.');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function runPackage(plan, cacheDir) {
|
|
99
|
+
ensureDir(cacheDir);
|
|
100
|
+
const env = { ...process.env, npm_config_cache: cacheDir };
|
|
101
|
+
const result = runCommand(npxCommand, ['--yes', '--package', plan.packageName + '@' + plan.version, plan.binName, ...cliArgs], {
|
|
102
|
+
stdio: 'inherit',
|
|
103
|
+
env
|
|
104
|
+
});
|
|
105
|
+
return typeof result.status === 'number' ? result.status : 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const plan = resolvePackage();
|
|
109
|
+
const versionCacheDir = path.join(CACHE_ROOT, plan.packageName + '-' + plan.version.replace(/[^a-zA-Z0-9._-]/g, '_'));
|
|
110
|
+
let status = runPackage(plan, versionCacheDir);
|
|
111
|
+
|
|
112
|
+
if (status !== 0 && process.platform === 'win32') {
|
|
113
|
+
const retryCache = path.join(CACHE_ROOT, 'retry-' + Date.now() + '-' + process.pid);
|
|
114
|
+
console.error('[fraim-mcp-launcher] Package execution failed; retrying once with a fresh npm cache.');
|
|
115
|
+
status = runPackage(plan, retryCache);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
process.exit(status);
|
|
114
119
|
`;
|
|
115
120
|
function getFraimMcpLatestLauncherPath() {
|
|
116
121
|
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', 'fraim-mcp-latest.js');
|
|
@@ -121,90 +126,155 @@ function getFraimMcpShimPath() {
|
|
|
121
126
|
function getFraimNpxShimPath() {
|
|
122
127
|
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', process.platform === 'win32' ? 'fraim-npx.cmd' : 'fraim-npx.sh');
|
|
123
128
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
129
|
+
function getFraimCliShimPath() {
|
|
130
|
+
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', process.platform === 'win32' ? 'fraim.cmd' : 'fraim');
|
|
131
|
+
}
|
|
132
|
+
function getPackagedFraimRuntimePath() {
|
|
133
|
+
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', 'packaged-fraim-runtime.json');
|
|
134
|
+
}
|
|
135
|
+
function runtimeFromEnv(env = process.env) {
|
|
136
|
+
return env.FRAIM_PACKAGED_CLI_EXECUTABLE && env.FRAIM_PACKAGED_CLI_SCRIPT
|
|
137
|
+
? { executable: env.FRAIM_PACKAGED_CLI_EXECUTABLE, script: env.FRAIM_PACKAGED_CLI_SCRIPT }
|
|
138
|
+
: null;
|
|
139
|
+
}
|
|
140
|
+
function getPackagedFraimRuntime(env = process.env) {
|
|
141
|
+
const envRuntime = runtimeFromEnv(env);
|
|
142
|
+
if (envRuntime)
|
|
143
|
+
return envRuntime;
|
|
144
|
+
try {
|
|
145
|
+
const raw = JSON.parse(fs_1.default.readFileSync(getPackagedFraimRuntimePath(), 'utf8'));
|
|
146
|
+
if (!raw.executable || !raw.script)
|
|
147
|
+
return null;
|
|
148
|
+
if (!fs_1.default.existsSync(raw.executable) || !fs_1.default.existsSync(raw.script))
|
|
149
|
+
return null;
|
|
150
|
+
return { executable: raw.executable, script: raw.script };
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function hasPackagedFraimRuntime(env = process.env) {
|
|
157
|
+
return getPackagedFraimRuntime(env) !== null;
|
|
158
|
+
}
|
|
159
|
+
function posixSingleQuote(value) {
|
|
160
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
161
|
+
}
|
|
162
|
+
function windowsBatchPath(value) {
|
|
163
|
+
return value.replace(/%/g, '%%').replace(/"/g, '""');
|
|
164
|
+
}
|
|
165
|
+
function writePackagedRuntimeMetadata(runtime) {
|
|
166
|
+
writeFileIfChanged(getPackagedFraimRuntimePath(), JSON.stringify({
|
|
167
|
+
version: PACKAGED_RUNTIME_VERSION,
|
|
168
|
+
executable: runtime.executable,
|
|
169
|
+
script: runtime.script,
|
|
170
|
+
updatedAt: new Date().toISOString(),
|
|
171
|
+
}, null, 2) + '\n');
|
|
172
|
+
}
|
|
173
|
+
function packagedFraimShimSource(command, runtime) {
|
|
174
|
+
const { executable, script } = runtime;
|
|
175
|
+
const commandArg = command === 'mcp' ? ' mcp' : '';
|
|
176
|
+
if (process.platform === 'win32') {
|
|
177
|
+
return [
|
|
178
|
+
'@echo off',
|
|
179
|
+
'setlocal',
|
|
180
|
+
'set "ELECTRON_RUN_AS_NODE=1"',
|
|
181
|
+
`"${windowsBatchPath(executable)}" "${windowsBatchPath(script)}"${commandArg} %*`,
|
|
182
|
+
'exit /b %ERRORLEVEL%',
|
|
183
|
+
'',
|
|
184
|
+
].join('\r\n');
|
|
185
|
+
}
|
|
186
|
+
return [
|
|
187
|
+
'#!/usr/bin/env sh',
|
|
188
|
+
'set -eu',
|
|
189
|
+
'export ELECTRON_RUN_AS_NODE=1',
|
|
190
|
+
`exec ${posixSingleQuote(executable)} ${posixSingleQuote(script)}${commandArg} "$@"`,
|
|
191
|
+
'',
|
|
192
|
+
].join('\n');
|
|
193
|
+
}
|
|
194
|
+
const windowsFraimMcpShimSource = `@echo off
|
|
195
|
+
setlocal
|
|
196
|
+
for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
|
|
197
|
+
where node >nul 2>nul
|
|
198
|
+
if not errorlevel 1 (
|
|
199
|
+
node "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
|
|
200
|
+
exit /b %ERRORLEVEL%
|
|
201
|
+
)
|
|
202
|
+
if exist "%FRAIM_USER_DIR_VALUE%\\node\\node.exe" (
|
|
203
|
+
set "PATH=%FRAIM_USER_DIR_VALUE%\\node;%PATH%"
|
|
204
|
+
"%FRAIM_USER_DIR_VALUE%\\node\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
|
|
205
|
+
exit /b %ERRORLEVEL%
|
|
206
|
+
)
|
|
207
|
+
for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
|
|
208
|
+
if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" (
|
|
209
|
+
set "PATH=%FRAIM_USER_DIR_VALUE%\\node\\%%D;%PATH%"
|
|
210
|
+
"%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
|
|
211
|
+
exit /b %ERRORLEVEL%
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
echo [fraim-mcp] Could not find node on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
|
|
215
|
+
exit /b 1
|
|
146
216
|
`;
|
|
147
|
-
const windowsFraimNpxShimSource = `@echo off
|
|
148
|
-
setlocal
|
|
149
|
-
for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
|
|
150
|
-
where npx >nul 2>nul
|
|
151
|
-
if not errorlevel 1 (
|
|
152
|
-
npx %*
|
|
153
|
-
exit /b %ERRORLEVEL%
|
|
154
|
-
)
|
|
155
|
-
if exist "%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" (
|
|
156
|
-
"%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" %*
|
|
157
|
-
exit /b %ERRORLEVEL%
|
|
158
|
-
)
|
|
159
|
-
for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
|
|
160
|
-
if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" (
|
|
161
|
-
"%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" %*
|
|
162
|
-
exit /b %ERRORLEVEL%
|
|
163
|
-
)
|
|
164
|
-
)
|
|
165
|
-
echo [fraim-npx] Could not find npx on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
|
|
166
|
-
exit /b 1
|
|
217
|
+
const windowsFraimNpxShimSource = `@echo off
|
|
218
|
+
setlocal
|
|
219
|
+
for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
|
|
220
|
+
where npx >nul 2>nul
|
|
221
|
+
if not errorlevel 1 (
|
|
222
|
+
npx %*
|
|
223
|
+
exit /b %ERRORLEVEL%
|
|
224
|
+
)
|
|
225
|
+
if exist "%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" (
|
|
226
|
+
"%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" %*
|
|
227
|
+
exit /b %ERRORLEVEL%
|
|
228
|
+
)
|
|
229
|
+
for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
|
|
230
|
+
if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" (
|
|
231
|
+
"%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" %*
|
|
232
|
+
exit /b %ERRORLEVEL%
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
echo [fraim-npx] Could not find npx on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
|
|
236
|
+
exit /b 1
|
|
167
237
|
`;
|
|
168
|
-
const posixFraimMcpShimSource = `#!/usr/bin/env sh
|
|
169
|
-
set -eu
|
|
170
|
-
SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
171
|
-
FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
|
|
172
|
-
LAUNCHER="$FRAIM_USER_DIR_VALUE/bin/fraim-mcp-latest.js"
|
|
173
|
-
|
|
174
|
-
if command -v node >/dev/null 2>&1; then
|
|
175
|
-
exec node "$LAUNCHER" "$@"
|
|
176
|
-
fi
|
|
177
|
-
if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/node" ]; then
|
|
178
|
-
PATH="$FRAIM_USER_DIR_VALUE/node/bin:$PATH"
|
|
179
|
-
export PATH
|
|
180
|
-
exec "$FRAIM_USER_DIR_VALUE/node/bin/node" "$LAUNCHER" "$@"
|
|
181
|
-
fi
|
|
182
|
-
if [ -x "$FRAIM_USER_DIR_VALUE/node/node" ]; then
|
|
183
|
-
PATH="$FRAIM_USER_DIR_VALUE/node:$PATH"
|
|
184
|
-
export PATH
|
|
185
|
-
exec "$FRAIM_USER_DIR_VALUE/node/node" "$LAUNCHER" "$@"
|
|
186
|
-
fi
|
|
187
|
-
|
|
188
|
-
echo "[fraim-mcp] Could not find node on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
|
|
189
|
-
exit 1
|
|
238
|
+
const posixFraimMcpShimSource = `#!/usr/bin/env sh
|
|
239
|
+
set -eu
|
|
240
|
+
SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
241
|
+
FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
|
|
242
|
+
LAUNCHER="$FRAIM_USER_DIR_VALUE/bin/fraim-mcp-latest.js"
|
|
243
|
+
|
|
244
|
+
if command -v node >/dev/null 2>&1; then
|
|
245
|
+
exec node "$LAUNCHER" "$@"
|
|
246
|
+
fi
|
|
247
|
+
if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/node" ]; then
|
|
248
|
+
PATH="$FRAIM_USER_DIR_VALUE/node/bin:$PATH"
|
|
249
|
+
export PATH
|
|
250
|
+
exec "$FRAIM_USER_DIR_VALUE/node/bin/node" "$LAUNCHER" "$@"
|
|
251
|
+
fi
|
|
252
|
+
if [ -x "$FRAIM_USER_DIR_VALUE/node/node" ]; then
|
|
253
|
+
PATH="$FRAIM_USER_DIR_VALUE/node:$PATH"
|
|
254
|
+
export PATH
|
|
255
|
+
exec "$FRAIM_USER_DIR_VALUE/node/node" "$LAUNCHER" "$@"
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
echo "[fraim-mcp] Could not find node on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
|
|
259
|
+
exit 1
|
|
190
260
|
`;
|
|
191
|
-
const posixFraimNpxShimSource = `#!/usr/bin/env sh
|
|
192
|
-
set -eu
|
|
193
|
-
SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
194
|
-
FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
|
|
195
|
-
|
|
196
|
-
if command -v npx >/dev/null 2>&1; then
|
|
197
|
-
exec npx "$@"
|
|
198
|
-
fi
|
|
199
|
-
if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/npx" ]; then
|
|
200
|
-
exec "$FRAIM_USER_DIR_VALUE/node/bin/npx" "$@"
|
|
201
|
-
fi
|
|
202
|
-
if [ -x "$FRAIM_USER_DIR_VALUE/node/npx" ]; then
|
|
203
|
-
exec "$FRAIM_USER_DIR_VALUE/node/npx" "$@"
|
|
204
|
-
fi
|
|
205
|
-
|
|
206
|
-
echo "[fraim-npx] Could not find npx on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
|
|
207
|
-
exit 1
|
|
261
|
+
const posixFraimNpxShimSource = `#!/usr/bin/env sh
|
|
262
|
+
set -eu
|
|
263
|
+
SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
264
|
+
FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
|
|
265
|
+
|
|
266
|
+
if command -v npx >/dev/null 2>&1; then
|
|
267
|
+
exec npx "$@"
|
|
268
|
+
fi
|
|
269
|
+
if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/npx" ]; then
|
|
270
|
+
exec "$FRAIM_USER_DIR_VALUE/node/bin/npx" "$@"
|
|
271
|
+
fi
|
|
272
|
+
if [ -x "$FRAIM_USER_DIR_VALUE/node/npx" ]; then
|
|
273
|
+
exec "$FRAIM_USER_DIR_VALUE/node/npx" "$@"
|
|
274
|
+
fi
|
|
275
|
+
|
|
276
|
+
echo "[fraim-npx] Could not find npx on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
|
|
277
|
+
exit 1
|
|
208
278
|
`;
|
|
209
279
|
const writeFileIfChanged = (filePath, content, mode) => {
|
|
210
280
|
if (!fs_1.default.existsSync(filePath) || fs_1.default.readFileSync(filePath, 'utf8') !== content) {
|
|
@@ -223,9 +293,23 @@ function ensureFraimMcpLatestLauncher() {
|
|
|
223
293
|
const launcherPath = getFraimMcpLatestLauncherPath();
|
|
224
294
|
const launcherDir = path_1.default.dirname(launcherPath);
|
|
225
295
|
fs_1.default.mkdirSync(launcherDir, { recursive: true });
|
|
226
|
-
writeFileIfChanged(launcherPath, launcherSource, process.platform === 'win32' ? undefined : 0o755);
|
|
227
296
|
const fraimMcpShimPath = getFraimMcpShimPath();
|
|
228
297
|
const fraimNpxShimPath = getFraimNpxShimPath();
|
|
298
|
+
const packagedRuntime = getPackagedFraimRuntime();
|
|
299
|
+
if (packagedRuntime) {
|
|
300
|
+
const fraimCliShimPath = getFraimCliShimPath();
|
|
301
|
+
if (runtimeFromEnv()) {
|
|
302
|
+
writePackagedRuntimeMetadata(packagedRuntime);
|
|
303
|
+
}
|
|
304
|
+
writeFileIfChanged(fraimMcpShimPath, packagedFraimShimSource('mcp', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
|
|
305
|
+
writeFileIfChanged(fraimCliShimPath, packagedFraimShimSource('cli', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
|
|
306
|
+
return {
|
|
307
|
+
command: fraimMcpShimPath,
|
|
308
|
+
args: [],
|
|
309
|
+
path: packagedRuntime.script,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
writeFileIfChanged(launcherPath, launcherSource, process.platform === 'win32' ? undefined : 0o755);
|
|
229
313
|
writeFileIfChanged(fraimMcpShimPath, process.platform === 'win32' ? windowsFraimMcpShimSource : posixFraimMcpShimSource, process.platform === 'win32' ? undefined : 0o755);
|
|
230
314
|
writeFileIfChanged(fraimNpxShimPath, process.platform === 'win32' ? windowsFraimNpxShimSource : posixFraimNpxShimSource, process.platform === 'win32' ? undefined : 0o755);
|
|
231
315
|
return {
|
|
@@ -55,6 +55,14 @@ exports.BASE_MCP_SERVERS = [
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
];
|
|
58
|
+
function activeBaseMCPServers() {
|
|
59
|
+
// The packaged desktop owns FRAIM's runtime but intentionally does not bundle
|
|
60
|
+
// npm. Keep third-party npx MCP servers out of fresh desktop-generated config;
|
|
61
|
+
// users can add them later through connect-mcp when a system npm is available.
|
|
62
|
+
return (0, fraim_mcp_latest_launcher_1.hasPackagedFraimRuntime)()
|
|
63
|
+
? exports.BASE_MCP_SERVERS.filter((server) => server.id === 'fraim')
|
|
64
|
+
: exports.BASE_MCP_SERVERS;
|
|
65
|
+
}
|
|
58
66
|
// ============================================================================
|
|
59
67
|
// PROVIDER MCP SERVER BUILDER (uses provider registry)
|
|
60
68
|
// ============================================================================
|
|
@@ -147,7 +155,7 @@ function buildStdioServer(mcpConfig, token, config) {
|
|
|
147
155
|
// REGISTRY LOOKUP FUNCTIONS
|
|
148
156
|
// ============================================================================
|
|
149
157
|
function getBaseMCPServer(id) {
|
|
150
|
-
return
|
|
158
|
+
return activeBaseMCPServers().find(server => server.id === id);
|
|
151
159
|
}
|
|
152
160
|
async function getProviderMCPServerIds() {
|
|
153
161
|
// This would need to fetch all providers and filter those with MCP servers
|
|
@@ -157,7 +165,7 @@ async function getProviderMCPServerIds() {
|
|
|
157
165
|
function getAllMCPServerIds() {
|
|
158
166
|
// Return only base server IDs
|
|
159
167
|
// Provider server IDs are dynamic and come from the registry
|
|
160
|
-
return
|
|
168
|
+
return activeBaseMCPServers().map(s => s.id);
|
|
161
169
|
}
|
|
162
170
|
async function isProviderServer(serverId) {
|
|
163
171
|
const provider = await (0, provider_registry_1.getProvider)(serverId);
|
|
@@ -172,7 +180,7 @@ async function isHTTPServer(serverId) {
|
|
|
172
180
|
// ============================================================================
|
|
173
181
|
function buildAllBaseServers(fraimKey) {
|
|
174
182
|
const servers = new Map();
|
|
175
|
-
for (const def of
|
|
183
|
+
for (const def of activeBaseMCPServers()) {
|
|
176
184
|
servers.set(def.id, def.buildServer(fraimKey));
|
|
177
185
|
}
|
|
178
186
|
return servers;
|