@openagents-org/agent-launcher 0.2.187 → 0.2.188
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/adapters/goose.js +4 -5
- package/src/adapters/nanoclaw-control.js +5 -17
- package/src/adapters/openclaw.js +13 -33
- package/src/installer.js +8 -12
- package/src/paths.js +15 -0
- package/src/update-check.js +5 -5
package/package.json
CHANGED
package/src/adapters/goose.js
CHANGED
|
@@ -42,7 +42,7 @@ const {
|
|
|
42
42
|
buildModePrompt,
|
|
43
43
|
buildPinnedSections,
|
|
44
44
|
} = require('./workspace-prompt');
|
|
45
|
-
const { whichBinary, getEnhancedEnv, defaultAgentWorkdir } = require('../paths');
|
|
45
|
+
const { whichBinary, whereBinary, getEnhancedEnv, defaultAgentWorkdir } = require('../paths');
|
|
46
46
|
|
|
47
47
|
const IS_WINDOWS = process.platform === 'win32';
|
|
48
48
|
|
|
@@ -105,10 +105,9 @@ function findGooseBinary() {
|
|
|
105
105
|
try {
|
|
106
106
|
const env = getEnhancedEnv();
|
|
107
107
|
if (IS_WINDOWS) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const hit = r.split(/\r?\n/)[0].trim();
|
|
108
|
+
// In-process PATH walk, not `where`: its OEM-codepage output mangled
|
|
109
|
+
// non-ASCII profile paths into a hit that could never be spawned.
|
|
110
|
+
const hit = whereBinary(['goose'], env);
|
|
112
111
|
if (hit) return hit;
|
|
113
112
|
} else {
|
|
114
113
|
const hit = execSync('command -v goose', {
|
|
@@ -21,6 +21,7 @@ const path = require('path');
|
|
|
21
21
|
const { execFile, execFileSync } = require('child_process');
|
|
22
22
|
|
|
23
23
|
const { redactSecrets } = require('./nanoclaw-protocol');
|
|
24
|
+
const { whereAll } = require('../paths');
|
|
24
25
|
|
|
25
26
|
const IS_WINDOWS = process.platform === 'win32';
|
|
26
27
|
|
|
@@ -176,14 +177,7 @@ function looksLikeNanoclaw(dir) {
|
|
|
176
177
|
/** Follow `ncl` on PATH back to the checkout root (bin/ncl → <root>). */
|
|
177
178
|
function homeFromNclBinary() {
|
|
178
179
|
try {
|
|
179
|
-
const
|
|
180
|
-
const out = execFileSync(which, ['ncl'], {
|
|
181
|
-
encoding: 'utf-8',
|
|
182
|
-
timeout: 5000,
|
|
183
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
184
|
-
})
|
|
185
|
-
.split(/\r?\n/)[0]
|
|
186
|
-
.trim();
|
|
180
|
+
const out = whichSafe('ncl');
|
|
187
181
|
if (!out) return null;
|
|
188
182
|
let real = out;
|
|
189
183
|
try {
|
|
@@ -233,15 +227,9 @@ function findNanoclawHome(env = process.env) {
|
|
|
233
227
|
|
|
234
228
|
function whichSafe(bin) {
|
|
235
229
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
timeout: 5000,
|
|
240
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
241
|
-
})
|
|
242
|
-
.split(/\r?\n/)[0]
|
|
243
|
-
.trim();
|
|
244
|
-
return out || null;
|
|
230
|
+
// Walks PATH in-process: `where` prints in the OEM codepage, which
|
|
231
|
+
// mangled any non-ASCII profile path when read back as UTF-8.
|
|
232
|
+
return whereAll(bin)[0] || null;
|
|
245
233
|
} catch {
|
|
246
234
|
return null;
|
|
247
235
|
}
|
package/src/adapters/openclaw.js
CHANGED
|
@@ -23,7 +23,7 @@ const { spawn } = require('../wsl');
|
|
|
23
23
|
const BaseAdapter = require('./base');
|
|
24
24
|
const { formatAttachmentsForPrompt } = require('./utils');
|
|
25
25
|
const { buildOpenclawSkillMd, buildOpenclawSystemPrompt, workspaceSkillName } = require('./workspace-prompt');
|
|
26
|
-
const { getRuntimePrefix } = require('../paths');
|
|
26
|
+
const { getRuntimePrefix, whereBinary } = require('../paths');
|
|
27
27
|
|
|
28
28
|
const IS_WINDOWS = process.platform === 'win32';
|
|
29
29
|
const OPENCLAW_STATE_DIR = path.join(
|
|
@@ -74,31 +74,17 @@ class OpenClawAdapter extends BaseAdapter {
|
|
|
74
74
|
const mjs = path.join(portableDir, 'node_modules', 'openclaw', 'openclaw.mjs');
|
|
75
75
|
if (fs.existsSync(mjs)) return mjs;
|
|
76
76
|
|
|
77
|
-
// Fallback:
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
} catch {}
|
|
90
|
-
// Windows: also try without .cmd extension (for system installs on PATH)
|
|
91
|
-
if (IS_WINDOWS) {
|
|
92
|
-
try {
|
|
93
|
-
const result = execSync('where openclaw', { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] })
|
|
94
|
-
.split(/\r?\n/)[0].trim();
|
|
95
|
-
if (result) {
|
|
96
|
-
// Try the .cmd variant of this path
|
|
97
|
-
const cmdPath = result.replace(/(?:\.cmd)?$/i, '.cmd');
|
|
98
|
-
const resolved = this._resolveShimToMjs(cmdPath);
|
|
99
|
-
if (resolved) return resolved;
|
|
100
|
-
}
|
|
101
|
-
} catch {}
|
|
77
|
+
// Fallback: a copy the user installed themselves (npm -g, nvm, a custom
|
|
78
|
+
// npm prefix). whereBinary searches the directories itself instead of
|
|
79
|
+
// shelling out to `where`, which prints in the OEM codepage and mangled
|
|
80
|
+
// any non-ASCII profile path (C:\Users\王…) past recognition.
|
|
81
|
+
const found = whereBinary('openclaw');
|
|
82
|
+
if (found) {
|
|
83
|
+
// Windows: resolve the .cmd shim to openclaw.mjs to avoid spawn issues.
|
|
84
|
+
// Unix: `which` hands back the binary or its symlink, either runs as is.
|
|
85
|
+
const resolved = this._resolveShimToMjs(found);
|
|
86
|
+
if (resolved) return resolved;
|
|
87
|
+
if (!IS_WINDOWS) return found;
|
|
102
88
|
}
|
|
103
89
|
return null;
|
|
104
90
|
}
|
|
@@ -359,13 +345,7 @@ class OpenClawAdapter extends BaseAdapter {
|
|
|
359
345
|
// Unified path first (symlink on Unix), then legacy bin/ fallback, then system node
|
|
360
346
|
const nodeUnified = path.join(portableDir, IS_WINDOWS ? 'node.exe' : 'node');
|
|
361
347
|
let nodeBin = fs.existsSync(nodeUnified) ? nodeUnified : path.join(portableDir, 'bin', 'node');
|
|
362
|
-
if (!fs.existsSync(nodeBin))
|
|
363
|
-
try {
|
|
364
|
-
const cmd = IS_WINDOWS ? 'where node.exe' : 'which node';
|
|
365
|
-
nodeBin = execSync(cmd, { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] })
|
|
366
|
-
.split(/\r?\n/)[0].trim();
|
|
367
|
-
} catch { nodeBin = 'node'; }
|
|
368
|
-
}
|
|
348
|
+
if (!fs.existsSync(nodeBin)) nodeBin = whereBinary('node') || 'node';
|
|
369
349
|
|
|
370
350
|
// binary from _findOpenclawBinary() is already resolved to .mjs when possible
|
|
371
351
|
let spawnBin, spawnArgs;
|
package/src/installer.js
CHANGED
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
resolveManagedNpmBinary,
|
|
15
15
|
resolveManagedNpmPackageBin,
|
|
16
16
|
isNodeShebangScript,
|
|
17
|
+
whereAll,
|
|
17
18
|
} = require('./paths');
|
|
18
19
|
const { isWslBinary, bridgedCommandString, wslHomeUnc } = require('./wsl');
|
|
19
20
|
const { canBlock } = require('./probe-mode');
|
|
@@ -2087,18 +2088,10 @@ class Installer {
|
|
|
2087
2088
|
*/
|
|
2088
2089
|
_hasSystemNode(bundledDir) {
|
|
2089
2090
|
try {
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
const args = process.platform === 'win32' ? ['node'] : ['node'];
|
|
2093
|
-
const out = execFileSync(cmd, args, {
|
|
2094
|
-
encoding: 'utf-8',
|
|
2095
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
2096
|
-
timeout: 5000,
|
|
2097
|
-
windowsHide: true,
|
|
2098
|
-
env: { ...process.env },
|
|
2099
|
-
});
|
|
2091
|
+
// In-process PATH walk: `where` prints in the OEM codepage, so on a
|
|
2092
|
+
// non-ASCII profile its UTF-8-decoded lines never matched bundledDir.
|
|
2100
2093
|
const prefix = (bundledDir || '').toLowerCase();
|
|
2101
|
-
for (const line of
|
|
2094
|
+
for (const line of whereAll('node')) {
|
|
2102
2095
|
if (!prefix || !line.toLowerCase().startsWith(prefix)) return true;
|
|
2103
2096
|
}
|
|
2104
2097
|
return false;
|
|
@@ -2446,7 +2439,10 @@ class Installer {
|
|
|
2446
2439
|
const psTokens = /\b(irm|iwr|iex|Invoke-RestMethod|Invoke-WebRequest|Invoke-Expression|Expand-Archive|Get-[A-Z]\w*|Set-[A-Z]\w*)\b/;
|
|
2447
2440
|
if (!psTokens.test(cmd)) return cmd;
|
|
2448
2441
|
const escaped = cmd.replace(/"/g, '\\"');
|
|
2449
|
-
|
|
2442
|
+
// PowerShell writes to a pipe in the OEM codepage (936 on zh-CN) and this
|
|
2443
|
+
// output is read as UTF-8, so a non-ASCII path in an installer's log or
|
|
2444
|
+
// error came back garbled. Switch the console encoding first.
|
|
2445
|
+
return `powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "[Console]::OutputEncoding=[Text.Encoding]::UTF8; ${escaped}"`;
|
|
2450
2446
|
}
|
|
2451
2447
|
|
|
2452
2448
|
_execShell(cmd, timeoutMs = 300000, envOverride = null) {
|
package/src/paths.js
CHANGED
|
@@ -403,6 +403,20 @@ function whereBinary(names, env) {
|
|
|
403
403
|
return null;
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Every PATH hit for a name, in PATH order — for callers that filter the list
|
|
408
|
+
* (skip the bundled node, find the first one that runs). Like whereBinary it
|
|
409
|
+
* walks PATH in-process: `where` prints in the OEM codepage, and decoding that
|
|
410
|
+
* as UTF-8 mangles any non-ASCII profile path.
|
|
411
|
+
*
|
|
412
|
+
* @param {string} name
|
|
413
|
+
* @param {object} [env] env whose PATH to search (defaults to process.env)
|
|
414
|
+
* @returns {string[]}
|
|
415
|
+
*/
|
|
416
|
+
function whereAll(name, env) {
|
|
417
|
+
return _searchPath(name, env || process.env);
|
|
418
|
+
}
|
|
419
|
+
|
|
406
420
|
/**
|
|
407
421
|
* Drop the bin-dir snapshots and every lookup answered from them — for when a
|
|
408
422
|
* background probe has just learned of directories they did not include.
|
|
@@ -1304,6 +1318,7 @@ module.exports = {
|
|
|
1304
1318
|
getEnhancedEnv,
|
|
1305
1319
|
whichBinary,
|
|
1306
1320
|
whereBinary,
|
|
1321
|
+
whereAll,
|
|
1307
1322
|
resolveManagedNpmBinary,
|
|
1308
1323
|
resolveManagedNpmPackageBin,
|
|
1309
1324
|
isNodeShebangScript,
|
package/src/update-check.js
CHANGED
|
@@ -13,8 +13,9 @@ const fs = require('fs');
|
|
|
13
13
|
const os = require('os');
|
|
14
14
|
const path = require('path');
|
|
15
15
|
const readline = require('readline');
|
|
16
|
-
const {
|
|
16
|
+
const { spawnSync } = require('child_process');
|
|
17
17
|
const { npmUrls } = require('./mirrors');
|
|
18
|
+
const { whereBinary } = require('./paths');
|
|
18
19
|
|
|
19
20
|
const PKG_NAME = '@openagents-org/agent-launcher';
|
|
20
21
|
const CACHE_FILE = path.join(os.homedir(), '.openagents', '.update-check.json');
|
|
@@ -187,10 +188,9 @@ function findNpmBin(opts = {}) {
|
|
|
187
188
|
}
|
|
188
189
|
// PATH fallback (injectable so tests can exercise the hard fallback
|
|
189
190
|
// deterministically regardless of the host OS).
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}).trim().split(/\r?\n/)[0]);
|
|
191
|
+
// Walked in-process rather than via `where`, whose OEM-codepage output
|
|
192
|
+
// mangled non-ASCII profile paths.
|
|
193
|
+
const lookup = opts.lookup || (() => whereBinary('npm'));
|
|
194
194
|
try {
|
|
195
195
|
return lookup() || (platform === 'win32' ? 'npm.cmd' : 'npm');
|
|
196
196
|
} catch { return platform === 'win32' ? 'npm.cmd' : 'npm'; }
|