@openagents-org/agent-launcher 0.2.186 → 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/src/probe.js CHANGED
@@ -58,6 +58,24 @@ const CODE = {
58
58
  CLI_ERROR: 'cli_error',
59
59
  };
60
60
 
61
+ /**
62
+ * The install command for THIS device's platform.
63
+ *
64
+ * `entry.install_command` comes off the catalog API, which picks macOS → Linux
65
+ * → Windows with no idea who is asking — so a Windows user was told to fix a
66
+ * missing CLI by running a `curl … | bash` one-liner that cannot work there.
67
+ * The entry's own per-platform `install` block is the authority (same rule as
68
+ * Installer._getInstallCommand); the flat field stays as the fallback for
69
+ * catalog entries that carry nothing else.
70
+ */
71
+ function installCommandFor(entry) {
72
+ const inst = (entry && entry.install) || {};
73
+ const plat = process.platform === 'darwin' ? 'macos'
74
+ : process.platform === 'win32' ? 'windows'
75
+ : 'linux';
76
+ return inst[plat] || inst.command || inst.npm || (entry && entry.install_command) || null;
77
+ }
78
+
61
79
  /** Redact anything that looks like a secret before output leaves the device. */
62
80
  function scrub(text) {
63
81
  if (!text) return '';
@@ -129,7 +147,10 @@ function buildGuidance(code, entry, agentEnv, extra = {}) {
129
147
  switch (code) {
130
148
  case CODE.NOT_INSTALLED:
131
149
  lines.push(`${label} is not installed on this device. Install it from the launcher's Install page.`);
132
- if (entry && entry.install_command) lines.push(`Or install manually: ${entry.install_command}`);
150
+ {
151
+ const cmd = installCommandFor(entry);
152
+ if (cmd) lines.push(`Or install manually: ${cmd}`);
153
+ }
133
154
  break;
134
155
  case CODE.INVALID_API_KEY:
135
156
  case CODE.MISSING_API_KEY:
@@ -388,4 +409,4 @@ async function probeAgentType(connector, type, opts = {}) {
388
409
  });
389
410
  }
390
411
 
391
- module.exports = { probeAgentType, classifyFailure, buildGuidance, authFlavor, scrub, CODE, DEFAULT_TIMEOUT_MS };
412
+ module.exports = { probeAgentType, classifyFailure, buildGuidance, authFlavor, installCommandFor, scrub, CODE, DEFAULT_TIMEOUT_MS };
@@ -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 { execSync, spawnSync } = require('child_process');
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
- const lookup = opts.lookup || (() =>
191
- execSync(platform === 'win32' ? 'where npm' : 'which npm', {
192
- encoding: 'utf-8', timeout: 3000,
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'; }