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/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 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);
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
- 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
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 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;