fraim 2.0.281 → 2.0.284

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 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,117 @@ 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"));
17
+ const windows_shim_path_search_1 = require("../../core/utils/windows-shim-path-search");
13
18
  const LAUNCHER_VERSION = 1;
14
- const launcherSource = `#!/usr/bin/env node
15
- const fs = require('fs');
16
- const os = require('os');
17
- const path = require('path');
18
- const { spawnSync } = require('child_process');
19
-
20
- const LAUNCHER_VERSION = ${LAUNCHER_VERSION};
21
- const USER_DIR = process.env.FRAIM_USER_DIR || path.join(os.homedir(), '.fraim');
22
- const STATE_DIR = path.join(USER_DIR, 'mcp-launcher');
23
- const STATE_PATH = path.join(STATE_DIR, 'latest.json');
24
- const CACHE_ROOT = path.join(USER_DIR, 'npm-cache', 'mcp');
25
-
26
- const commandName = (name) => process.platform === 'win32' ? name + '.cmd' : name;
27
- const npmCommand = commandName('npm');
28
- const npxCommand = commandName('npx');
29
- const cliArgs = process.argv.slice(2).length > 0 ? process.argv.slice(2) : ['mcp'];
30
-
31
- function quoteCmdArg(arg) {
32
- const value = String(arg);
33
- return /[\\s"&|<>^]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value;
34
- }
35
-
36
- function runCommand(command, args, options) {
37
- if (process.platform !== 'win32') {
38
- return spawnSync(command, args, options);
39
- }
40
-
41
- return spawnSync(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', [command, ...args.map(quoteCmdArg)].join(' ')], options);
42
- }
43
-
44
- function ensureDir(dir) {
45
- fs.mkdirSync(dir, { recursive: true });
46
- }
47
-
48
- function readState() {
49
- try {
50
- return JSON.parse(fs.readFileSync(STATE_PATH, 'utf8'));
51
- } catch {
52
- return null;
53
- }
54
- }
55
-
56
- function writeState(state) {
57
- ensureDir(STATE_DIR);
58
- fs.writeFileSync(STATE_PATH, JSON.stringify({ ...state, launcherVersion: LAUNCHER_VERSION, updatedAt: new Date().toISOString() }, null, 2));
59
- }
60
-
61
- function resolveLatest(packageName) {
62
- const result = runCommand(npmCommand, ['view', packageName, 'version', '--silent'], {
63
- encoding: 'utf8',
64
- env: process.env
65
- });
66
-
67
- if (result.status !== 0) {
68
- return null;
69
- }
70
-
71
- const version = String(result.stdout || '').trim();
72
- return /^\\d+\\.\\d+\\.\\d+/.test(version) ? version : null;
73
- }
74
-
75
- function resolvePackage() {
76
- const fraimVersion = resolveLatest('fraim');
77
- if (fraimVersion) {
78
- const state = { packageName: 'fraim', binName: 'fraim', version: fraimVersion, fromCache: false };
79
- writeState(state);
80
- return state;
81
- }
82
-
83
- const cached = readState();
84
- if (cached && cached.packageName === 'fraim' && cached.binName === 'fraim' && cached.version) {
85
- console.error('[fraim-mcp-launcher] Could not resolve npm latest; using cached fraim@' + cached.version + '.');
86
- return { packageName: 'fraim', binName: 'fraim', version: cached.version, fromCache: true };
87
- }
88
-
89
- console.error('[fraim-mcp-launcher] Could not resolve fraim latest from npm and no cached fraim version exists.');
90
- process.exit(1);
91
- }
92
-
93
- function runPackage(plan, cacheDir) {
94
- ensureDir(cacheDir);
95
- const env = { ...process.env, npm_config_cache: cacheDir };
96
- const result = runCommand(npxCommand, ['--yes', '--package', plan.packageName + '@' + plan.version, plan.binName, ...cliArgs], {
97
- stdio: 'inherit',
98
- env
99
- });
100
- return typeof result.status === 'number' ? result.status : 1;
101
- }
102
-
103
- const plan = resolvePackage();
104
- const versionCacheDir = path.join(CACHE_ROOT, plan.packageName + '-' + plan.version.replace(/[^a-zA-Z0-9._-]/g, '_'));
105
- let status = runPackage(plan, versionCacheDir);
106
-
107
- if (status !== 0 && process.platform === 'win32') {
108
- const retryCache = path.join(CACHE_ROOT, 'retry-' + Date.now() + '-' + process.pid);
109
- console.error('[fraim-mcp-launcher] Package execution failed; retrying once with a fresh npm cache.');
110
- status = runPackage(plan, retryCache);
111
- }
112
-
113
- process.exit(status);
19
+ const PACKAGED_RUNTIME_VERSION = 1;
20
+ const launcherSource = `#!/usr/bin/env node
21
+ const fs = require('fs');
22
+ const os = require('os');
23
+ const path = require('path');
24
+ const { spawnSync } = require('child_process');
25
+
26
+ const LAUNCHER_VERSION = ${LAUNCHER_VERSION};
27
+ const USER_DIR = process.env.FRAIM_USER_DIR || path.join(os.homedir(), '.fraim');
28
+ const STATE_DIR = path.join(USER_DIR, 'mcp-launcher');
29
+ const STATE_PATH = path.join(STATE_DIR, 'latest.json');
30
+ const CACHE_ROOT = path.join(USER_DIR, 'npm-cache', 'mcp');
31
+
32
+ const commandName = (name) => process.platform === 'win32' ? name + '.cmd' : name;
33
+ const npmCommand = commandName('npm');
34
+ const npxCommand = commandName('npx');
35
+ const cliArgs = process.argv.slice(2).length > 0 ? process.argv.slice(2) : ['mcp'];
36
+
37
+ function quoteCmdArg(arg) {
38
+ const value = String(arg);
39
+ return /[\\s"&|<>^]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value;
40
+ }
41
+
42
+ function runCommand(command, args, options) {
43
+ if (process.platform !== 'win32') {
44
+ return spawnSync(command, args, options);
45
+ }
46
+
47
+ return spawnSync(process.env.ComSpec || 'cmd.exe', ['/d', '/s', '/c', [command, ...args.map(quoteCmdArg)].join(' ')], options);
48
+ }
49
+
50
+ function ensureDir(dir) {
51
+ fs.mkdirSync(dir, { recursive: true });
52
+ }
53
+
54
+ function readState() {
55
+ try {
56
+ return JSON.parse(fs.readFileSync(STATE_PATH, 'utf8'));
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ function writeState(state) {
63
+ ensureDir(STATE_DIR);
64
+ fs.writeFileSync(STATE_PATH, JSON.stringify({ ...state, launcherVersion: LAUNCHER_VERSION, updatedAt: new Date().toISOString() }, null, 2));
65
+ }
66
+
67
+ function resolveLatest(packageName) {
68
+ const result = runCommand(npmCommand, ['view', packageName, 'version', '--silent'], {
69
+ encoding: 'utf8',
70
+ env: process.env
71
+ });
72
+
73
+ if (result.status !== 0) {
74
+ return null;
75
+ }
76
+
77
+ const version = String(result.stdout || '').trim();
78
+ return /^\\d+\\.\\d+\\.\\d+/.test(version) ? version : null;
79
+ }
80
+
81
+ function resolvePackage() {
82
+ const fraimVersion = resolveLatest('fraim');
83
+ if (fraimVersion) {
84
+ const state = { packageName: 'fraim', binName: 'fraim', version: fraimVersion, fromCache: false };
85
+ writeState(state);
86
+ return state;
87
+ }
88
+
89
+ const cached = readState();
90
+ if (cached && cached.packageName === 'fraim' && cached.binName === 'fraim' && cached.version) {
91
+ console.error('[fraim-mcp-launcher] Could not resolve npm latest; using cached fraim@' + cached.version + '.');
92
+ return { packageName: 'fraim', binName: 'fraim', version: cached.version, fromCache: true };
93
+ }
94
+
95
+ console.error('[fraim-mcp-launcher] Could not resolve fraim latest from npm and no cached fraim version exists.');
96
+ process.exit(1);
97
+ }
98
+
99
+ function runPackage(plan, cacheDir) {
100
+ ensureDir(cacheDir);
101
+ const env = { ...process.env, npm_config_cache: cacheDir };
102
+ const result = runCommand(npxCommand, ['--yes', '--package', plan.packageName + '@' + plan.version, plan.binName, ...cliArgs], {
103
+ stdio: 'inherit',
104
+ env
105
+ });
106
+ return typeof result.status === 'number' ? result.status : 1;
107
+ }
108
+
109
+ const plan = resolvePackage();
110
+ const versionCacheDir = path.join(CACHE_ROOT, plan.packageName + '-' + plan.version.replace(/[^a-zA-Z0-9._-]/g, '_'));
111
+ let status = runPackage(plan, versionCacheDir);
112
+
113
+ if (status !== 0 && process.platform === 'win32') {
114
+ const retryCache = path.join(CACHE_ROOT, 'retry-' + Date.now() + '-' + process.pid);
115
+ console.error('[fraim-mcp-launcher] Package execution failed; retrying once with a fresh npm cache.');
116
+ status = runPackage(plan, retryCache);
117
+ }
118
+
119
+ process.exit(status);
114
120
  `;
115
121
  function getFraimMcpLatestLauncherPath() {
116
122
  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 +127,155 @@ function getFraimMcpShimPath() {
121
127
  function getFraimNpxShimPath() {
122
128
  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
129
  }
124
- const windowsFraimMcpShimSource = `@echo off
125
- setlocal
126
- for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
127
- where node >nul 2>nul
128
- if not errorlevel 1 (
129
- node "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
130
- exit /b %ERRORLEVEL%
131
- )
132
- if exist "%FRAIM_USER_DIR_VALUE%\\node\\node.exe" (
133
- set "PATH=%FRAIM_USER_DIR_VALUE%\\node;%PATH%"
134
- "%FRAIM_USER_DIR_VALUE%\\node\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
135
- exit /b %ERRORLEVEL%
136
- )
137
- for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
138
- if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" (
139
- set "PATH=%FRAIM_USER_DIR_VALUE%\\node\\%%D;%PATH%"
140
- "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
141
- exit /b %ERRORLEVEL%
142
- )
143
- )
144
- echo [fraim-mcp] Could not find node on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
145
- exit /b 1
130
+ function getFraimCliShimPath() {
131
+ 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');
132
+ }
133
+ function getPackagedFraimRuntimePath() {
134
+ return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', 'packaged-fraim-runtime.json');
135
+ }
136
+ function runtimeFromEnv(env = process.env) {
137
+ return env.FRAIM_PACKAGED_CLI_EXECUTABLE && env.FRAIM_PACKAGED_CLI_SCRIPT
138
+ ? { executable: env.FRAIM_PACKAGED_CLI_EXECUTABLE, script: env.FRAIM_PACKAGED_CLI_SCRIPT }
139
+ : null;
140
+ }
141
+ function getPackagedFraimRuntime(env = process.env) {
142
+ const envRuntime = runtimeFromEnv(env);
143
+ if (envRuntime)
144
+ return envRuntime;
145
+ try {
146
+ const raw = JSON.parse(fs_1.default.readFileSync(getPackagedFraimRuntimePath(), 'utf8'));
147
+ if (!raw.executable || !raw.script)
148
+ return null;
149
+ if (!fs_1.default.existsSync(raw.executable) || !fs_1.default.existsSync(raw.script))
150
+ return null;
151
+ return { executable: raw.executable, script: raw.script };
152
+ }
153
+ catch {
154
+ return null;
155
+ }
156
+ }
157
+ function hasPackagedFraimRuntime(env = process.env) {
158
+ return getPackagedFraimRuntime(env) !== null;
159
+ }
160
+ function posixSingleQuote(value) {
161
+ return `'${value.replace(/'/g, `'\\''`)}'`;
162
+ }
163
+ function windowsBatchPath(value) {
164
+ return value.replace(/%/g, '%%').replace(/"/g, '""');
165
+ }
166
+ function writePackagedRuntimeMetadata(runtime) {
167
+ writeFileIfChanged(getPackagedFraimRuntimePath(), JSON.stringify({
168
+ version: PACKAGED_RUNTIME_VERSION,
169
+ executable: runtime.executable,
170
+ script: runtime.script,
171
+ updatedAt: new Date().toISOString(),
172
+ }, null, 2) + '\n');
173
+ }
174
+ function packagedFraimShimSource(command, runtime) {
175
+ const { executable, script } = runtime;
176
+ const commandArg = command === 'mcp' ? ' mcp' : '';
177
+ if (process.platform === 'win32') {
178
+ return [
179
+ '@echo off',
180
+ 'setlocal',
181
+ 'set "ELECTRON_RUN_AS_NODE=1"',
182
+ `"${windowsBatchPath(executable)}" "${windowsBatchPath(script)}"${commandArg} %*`,
183
+ 'exit /b %ERRORLEVEL%',
184
+ '',
185
+ ].join('\r\n');
186
+ }
187
+ return [
188
+ '#!/usr/bin/env sh',
189
+ 'set -eu',
190
+ 'export ELECTRON_RUN_AS_NODE=1',
191
+ `exec ${posixSingleQuote(executable)} ${posixSingleQuote(script)}${commandArg} "$@"`,
192
+ '',
193
+ ].join('\n');
194
+ }
195
+ const windowsFraimMcpShimSource = `@echo off
196
+ setlocal
197
+ for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
198
+ ${(0, windows_shim_path_search_1.windowsPathSearchLines)('NODE_EXE', 'node').join('\n')}
199
+ if defined NODE_EXE (
200
+ "%NODE_EXE%" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
201
+ exit /b %ERRORLEVEL%
202
+ )
203
+ if exist "%FRAIM_USER_DIR_VALUE%\\node\\node.exe" (
204
+ set "PATH=%FRAIM_USER_DIR_VALUE%\\node;%PATH%"
205
+ "%FRAIM_USER_DIR_VALUE%\\node\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
206
+ exit /b %ERRORLEVEL%
207
+ )
208
+ for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
209
+ if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" (
210
+ set "PATH=%FRAIM_USER_DIR_VALUE%\\node\\%%D;%PATH%"
211
+ "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\node.exe" "%FRAIM_USER_DIR_VALUE%\\bin\\fraim-mcp-latest.js" %*
212
+ exit /b %ERRORLEVEL%
213
+ )
214
+ )
215
+ echo [fraim-mcp] Could not find node on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
216
+ exit /b 1
146
217
  `;
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
218
+ const windowsFraimNpxShimSource = `@echo off
219
+ setlocal
220
+ for %%I in ("%~dp0..") do set "FRAIM_USER_DIR_VALUE=%%~fI"
221
+ ${(0, windows_shim_path_search_1.windowsPathSearchLines)('NPX_CMD', 'npx').join('\n')}
222
+ if defined NPX_CMD (
223
+ "%NPX_CMD%" %*
224
+ exit /b %ERRORLEVEL%
225
+ )
226
+ if exist "%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" (
227
+ "%FRAIM_USER_DIR_VALUE%\\node\\npx.cmd" %*
228
+ exit /b %ERRORLEVEL%
229
+ )
230
+ for /f "delims=" %%D in ('dir /b /ad /o-n "%FRAIM_USER_DIR_VALUE%\\node\\node-v*" 2^>nul') do (
231
+ if exist "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" (
232
+ "%FRAIM_USER_DIR_VALUE%\\node\\%%D\\npx.cmd" %*
233
+ exit /b %ERRORLEVEL%
234
+ )
235
+ )
236
+ echo [fraim-npx] Could not find npx on PATH or in "%FRAIM_USER_DIR_VALUE%\\node" 1>&2
237
+ exit /b 1
167
238
  `;
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
239
+ const posixFraimMcpShimSource = `#!/usr/bin/env sh
240
+ set -eu
241
+ SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
242
+ FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
243
+ LAUNCHER="$FRAIM_USER_DIR_VALUE/bin/fraim-mcp-latest.js"
244
+
245
+ if command -v node >/dev/null 2>&1; then
246
+ exec node "$LAUNCHER" "$@"
247
+ fi
248
+ if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/node" ]; then
249
+ PATH="$FRAIM_USER_DIR_VALUE/node/bin:$PATH"
250
+ export PATH
251
+ exec "$FRAIM_USER_DIR_VALUE/node/bin/node" "$LAUNCHER" "$@"
252
+ fi
253
+ if [ -x "$FRAIM_USER_DIR_VALUE/node/node" ]; then
254
+ PATH="$FRAIM_USER_DIR_VALUE/node:$PATH"
255
+ export PATH
256
+ exec "$FRAIM_USER_DIR_VALUE/node/node" "$LAUNCHER" "$@"
257
+ fi
258
+
259
+ echo "[fraim-mcp] Could not find node on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
260
+ exit 1
190
261
  `;
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
262
+ const posixFraimNpxShimSource = `#!/usr/bin/env sh
263
+ set -eu
264
+ SHIM_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
265
+ FRAIM_USER_DIR_VALUE=$(dirname "$SHIM_DIR")
266
+
267
+ if command -v npx >/dev/null 2>&1; then
268
+ exec npx "$@"
269
+ fi
270
+ if [ -x "$FRAIM_USER_DIR_VALUE/node/bin/npx" ]; then
271
+ exec "$FRAIM_USER_DIR_VALUE/node/bin/npx" "$@"
272
+ fi
273
+ if [ -x "$FRAIM_USER_DIR_VALUE/node/npx" ]; then
274
+ exec "$FRAIM_USER_DIR_VALUE/node/npx" "$@"
275
+ fi
276
+
277
+ echo "[fraim-npx] Could not find npx on PATH or in $FRAIM_USER_DIR_VALUE/node" >&2
278
+ exit 1
208
279
  `;
209
280
  const writeFileIfChanged = (filePath, content, mode) => {
210
281
  if (!fs_1.default.existsSync(filePath) || fs_1.default.readFileSync(filePath, 'utf8') !== content) {
@@ -223,9 +294,23 @@ function ensureFraimMcpLatestLauncher() {
223
294
  const launcherPath = getFraimMcpLatestLauncherPath();
224
295
  const launcherDir = path_1.default.dirname(launcherPath);
225
296
  fs_1.default.mkdirSync(launcherDir, { recursive: true });
226
- writeFileIfChanged(launcherPath, launcherSource, process.platform === 'win32' ? undefined : 0o755);
227
297
  const fraimMcpShimPath = getFraimMcpShimPath();
228
298
  const fraimNpxShimPath = getFraimNpxShimPath();
299
+ const packagedRuntime = getPackagedFraimRuntime();
300
+ if (packagedRuntime) {
301
+ const fraimCliShimPath = getFraimCliShimPath();
302
+ if (runtimeFromEnv()) {
303
+ writePackagedRuntimeMetadata(packagedRuntime);
304
+ }
305
+ writeFileIfChanged(fraimMcpShimPath, packagedFraimShimSource('mcp', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
306
+ writeFileIfChanged(fraimCliShimPath, packagedFraimShimSource('cli', packagedRuntime), process.platform === 'win32' ? undefined : 0o755);
307
+ return {
308
+ command: fraimMcpShimPath,
309
+ args: [],
310
+ path: packagedRuntime.script,
311
+ };
312
+ }
313
+ writeFileIfChanged(launcherPath, launcherSource, process.platform === 'win32' ? undefined : 0o755);
229
314
  writeFileIfChanged(fraimMcpShimPath, process.platform === 'win32' ? windowsFraimMcpShimSource : posixFraimMcpShimSource, process.platform === 'win32' ? undefined : 0o755);
230
315
  writeFileIfChanged(fraimNpxShimPath, process.platform === 'win32' ? windowsFraimNpxShimSource : posixFraimNpxShimSource, process.platform === 'win32' ? undefined : 0o755);
231
316
  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 exports.BASE_MCP_SERVERS.find(server => server.id === id);
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 exports.BASE_MCP_SERVERS.map(s => s.id);
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 exports.BASE_MCP_SERVERS) {
183
+ for (const def of activeBaseMCPServers()) {
176
184
  servers.set(def.id, def.buildServer(fraimKey));
177
185
  }
178
186
  return servers;