@openagents-org/agent-connector 0.2.9 → 0.3.1
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/package.json +1 -1
- package/src/installer.js +69 -11
package/package.json
CHANGED
package/src/installer.js
CHANGED
|
@@ -84,11 +84,17 @@ class Installer {
|
|
|
84
84
|
throw new Error(`No install definition for agent type: ${agentType}`);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
let cmd = this._getInstallCommand(entry.install);
|
|
88
88
|
if (!cmd) {
|
|
89
89
|
throw new Error(`No install command for ${agentType} on ${Installer.platform()}`);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// Use bundled node/npm if system npm not available
|
|
93
|
+
if (cmd.startsWith('npm install')) {
|
|
94
|
+
const args = cmd.replace('npm install', 'install');
|
|
95
|
+
cmd = this._resolveNpmCommand(args);
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
const output = await this._execShell(cmd);
|
|
93
99
|
this._markInstalled(agentType);
|
|
94
100
|
return { success: true, output };
|
|
@@ -107,14 +113,18 @@ class Installer {
|
|
|
107
113
|
throw new Error(`No install definition for agent type: ${agentType}`);
|
|
108
114
|
}
|
|
109
115
|
|
|
110
|
-
let
|
|
111
|
-
if (!
|
|
116
|
+
let rawCmd = this._getInstallCommand(entry.install);
|
|
117
|
+
if (!rawCmd) {
|
|
112
118
|
throw new Error(`No install command for ${agentType} on ${Installer.platform()}`);
|
|
113
119
|
}
|
|
114
120
|
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
// Resolve npm to use bundled node if system npm is not available
|
|
122
|
+
let cmd = rawCmd;
|
|
123
|
+
if (rawCmd.startsWith('npm install')) {
|
|
124
|
+
const args = rawCmd.replace('npm install', 'install --loglevel=verbose');
|
|
125
|
+
cmd = this._resolveNpmCommand(args);
|
|
126
|
+
} else if (rawCmd.startsWith('pip install') || rawCmd.startsWith('pipx install')) {
|
|
127
|
+
cmd = rawCmd; // pip commands stay as-is
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
if (onData) onData(`$ ${cmd}\n\n`);
|
|
@@ -180,14 +190,16 @@ class Installer {
|
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
const installCmd = this._getInstallCommand(entry.install);
|
|
183
|
-
let
|
|
184
|
-
if (!
|
|
193
|
+
let rawCmd = this._deriveUninstallCommand(installCmd);
|
|
194
|
+
if (!rawCmd) {
|
|
185
195
|
throw new Error(`Cannot derive uninstall command for ${agentType}`);
|
|
186
196
|
}
|
|
187
197
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
// Resolve npm to use bundled node if system npm is not available
|
|
199
|
+
let cmd = rawCmd;
|
|
200
|
+
if (rawCmd.startsWith('npm uninstall')) {
|
|
201
|
+
const args = rawCmd.replace('npm uninstall', 'uninstall --loglevel=verbose');
|
|
202
|
+
cmd = this._resolveNpmCommand(args);
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
if (onData) onData(`$ ${cmd}\n\n`);
|
|
@@ -353,6 +365,52 @@ class Installer {
|
|
|
353
365
|
return env;
|
|
354
366
|
}
|
|
355
367
|
|
|
368
|
+
/**
|
|
369
|
+
* Resolve the npm CLI path. Prefers system npm, falls back to bundled
|
|
370
|
+
* npm module run via Electron's node. Works on machines without Node.js.
|
|
371
|
+
*/
|
|
372
|
+
_resolveNpmCommand(args) {
|
|
373
|
+
// 1. Try system npm
|
|
374
|
+
const { whichBinary } = require('./paths');
|
|
375
|
+
const systemNpm = whichBinary('npm');
|
|
376
|
+
if (systemNpm) return `"${systemNpm}" ${args}`;
|
|
377
|
+
|
|
378
|
+
// 2. Find bundled npm-cli.js (npm is a dependency of the Launcher)
|
|
379
|
+
const nodeExe = process.execPath;
|
|
380
|
+
const candidates = [];
|
|
381
|
+
|
|
382
|
+
// Try require.resolve first — works when npm is in node_modules
|
|
383
|
+
try {
|
|
384
|
+
candidates.push(require.resolve('npm/bin/npm-cli.js'));
|
|
385
|
+
} catch {}
|
|
386
|
+
|
|
387
|
+
// Search common locations relative to the app
|
|
388
|
+
const searchRoots = [
|
|
389
|
+
path.join(path.dirname(nodeExe), 'resources', 'app'), // packaged Electron
|
|
390
|
+
path.join(path.dirname(nodeExe), 'resources', 'app.asar.unpacked'), // asar unpacked
|
|
391
|
+
path.join(path.dirname(nodeExe), '..'), // portable exe temp dir
|
|
392
|
+
process.cwd(), // dev mode
|
|
393
|
+
];
|
|
394
|
+
for (const root of searchRoots) {
|
|
395
|
+
candidates.push(path.join(root, 'node_modules', 'npm', 'bin', 'npm-cli.js'));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Also check system node_modules
|
|
399
|
+
candidates.push(path.join(path.dirname(nodeExe), '..', 'lib', 'node_modules', 'npm', 'bin', 'npm-cli.js'));
|
|
400
|
+
candidates.push(path.join(path.dirname(nodeExe), 'node_modules', 'npm', 'bin', 'npm-cli.js'));
|
|
401
|
+
|
|
402
|
+
for (const p of candidates) {
|
|
403
|
+
try {
|
|
404
|
+
if (p && fs.existsSync(p)) {
|
|
405
|
+
return `"${nodeExe}" "${p}" ${args}`;
|
|
406
|
+
}
|
|
407
|
+
} catch {}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// 3. Last resort
|
|
411
|
+
return `npm ${args}`;
|
|
412
|
+
}
|
|
413
|
+
|
|
356
414
|
_execShell(cmd, timeoutMs = 300000) {
|
|
357
415
|
return new Promise((resolve, reject) => {
|
|
358
416
|
const env = this._buildShellEnv();
|