@openagents-org/agent-launcher 0.2.139 → 0.2.141

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagents-org/agent-launcher",
3
- "version": "0.2.139",
3
+ "version": "0.2.141",
4
4
  "description": "OpenAgents Launcher — install, configure, and run AI coding agents from your terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/registry.json CHANGED
@@ -616,7 +616,7 @@
616
616
  "requires": ["python3"],
617
617
  "macos": "curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --skip-setup",
618
618
  "linux": "curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --skip-setup",
619
- "windows": "wsl.exe -e bash -lc \"curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash -s -- --skip-setup\""
619
+ "windows": "\"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoProfile -ExecutionPolicy Bypass -Command \"Invoke-RestMethod -UseBasicParsing 'https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1' | Invoke-Expression\""
620
620
  },
621
621
  "launch": {
622
622
  "args": []
@@ -305,6 +305,15 @@ class ClaudeAdapter extends BaseAdapter {
305
305
  if (jsMatch) {
306
306
  return [nodeBin, path.resolve(cmdDir, jsMatch[1])];
307
307
  }
308
+ // .cmd shims that forward to a native .exe (e.g. Claude Code's
309
+ // claude.cmd → @anthropic-ai/claude-code/bin/claude.exe). Resolve to the
310
+ // exe and spawn it directly. Wrapping such a .cmd in `cmd.exe /c` caps the
311
+ // command line at cmd.exe's 8191-char limit, which truncates the ~14KB
312
+ // --append-system-prompt and makes the agent hang ("command line too long").
313
+ const exeMatch = cmdContent.match(/%dp0%\\([^\s"*?]+\.exe)/i);
314
+ if (exeMatch) {
315
+ return [path.resolve(cmdDir, exeMatch[1])];
316
+ }
308
317
  } else {
309
318
  // Unix: symlink → resolve to actual .js file
310
319
  try {
@@ -564,7 +573,7 @@ class ClaudeAdapter extends BaseAdapter {
564
573
  const resolved = this._resolveToNodeCmd(oaBin);
565
574
  if (resolved) {
566
575
  mcpCommand = resolved[0];
567
- mcpFinalArgs = [resolved[1], ...mcpArgs];
576
+ mcpFinalArgs = [...resolved.slice(1), ...mcpArgs];
568
577
  } else {
569
578
  mcpCommand = oaBin;
570
579
  }
@@ -689,7 +698,7 @@ class ClaudeAdapter extends BaseAdapter {
689
698
  const resolved = this._resolveToNodeCmd(filteredCmd[0]);
690
699
  let finalCmd = filteredCmd;
691
700
  if (resolved) {
692
- finalCmd = [resolved[0], resolved[1], ...filteredCmd.slice(1)];
701
+ finalCmd = [...resolved, ...filteredCmd.slice(1)];
693
702
  } else if (IS_WINDOWS && filteredCmd[0].toLowerCase().endsWith('.cmd')) {
694
703
  finalCmd = ['cmd.exe', '/c', ...filteredCmd];
695
704
  }
@@ -999,6 +1008,30 @@ class ClaudeAdapter extends BaseAdapter {
999
1008
  }
1000
1009
  }
1001
1010
 
1011
+ // Third-party Anthropic-compatible relays (the common reason a custom
1012
+ // ANTHROPIC_BASE_URL is set) authenticate via `Authorization: Bearer`, which
1013
+ // the Claude CLI only sends when ANTHROPIC_AUTH_TOKEN is set. With just
1014
+ // ANTHROPIC_API_KEY the CLI sends `x-api-key`, which most relays ignore — the
1015
+ // relay then rejects every request as 401 "invalid token / 无效的令牌". When a
1016
+ // non-official base URL is configured and no auth token was provided, mirror
1017
+ // the API key into ANTHROPIC_AUTH_TOKEN (it outranks the API key in Claude
1018
+ // Code's auth precedence) so the CLI uses Bearer auth. The launcher normally
1019
+ // sets this when saving env; this is the runtime backstop for envs saved by
1020
+ // an older launcher or coming from any other source. The official
1021
+ // api.anthropic.com endpoint keeps x-api-key, so it is left untouched.
1022
+ const anthropicBase = (cleanEnv.ANTHROPIC_BASE_URL || '').trim();
1023
+ const anthropicKey = (cleanEnv.ANTHROPIC_API_KEY || '').trim();
1024
+ if (anthropicKey && anthropicBase && !(cleanEnv.ANTHROPIC_AUTH_TOKEN || '').trim()) {
1025
+ let officialAnthropic = false;
1026
+ try {
1027
+ const host = new URL(anthropicBase).hostname.toLowerCase();
1028
+ officialAnthropic = host === 'anthropic.com' || host.endsWith('.anthropic.com');
1029
+ } catch { officialAnthropic = false; }
1030
+ if (!officialAnthropic) {
1031
+ cleanEnv.ANTHROPIC_AUTH_TOKEN = anthropicKey;
1032
+ }
1033
+ }
1034
+
1002
1035
  // Spawn a persistent process and send the first message via stdin
1003
1036
  let effectiveContent = content;
1004
1037
  for (let attempt = 0; attempt < 2; attempt++) {
@@ -24,6 +24,9 @@ const { buildOpenclawSystemPrompt } = require('./workspace-prompt');
24
24
  const { whichBinary, getEnhancedEnv } = require('../paths');
25
25
 
26
26
  const IS_WINDOWS = process.platform === 'win32';
27
+ const HERMES_INSTALL_HINT = IS_WINDOWS
28
+ ? 'powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex"'
29
+ : 'curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash';
27
30
  const SESSION_ID_RE = /session_id:\s*(\S+)/;
28
31
  const MAX_HISTORY_ENTRIES = 12;
29
32
 
@@ -56,7 +59,7 @@ class HermesAdapter extends BaseAdapter {
56
59
  if (this._hermesBin) {
57
60
  this._log(`Using Hermes binary: ${this._hermesBin} (profile=${this.hermesProfile})`);
58
61
  } else {
59
- this._log('Warning: hermes CLI not found. Install: curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash');
62
+ this._log(`Warning: hermes CLI not found. Install: ${HERMES_INSTALL_HINT}`);
60
63
  }
61
64
  }
62
65
 
@@ -76,7 +79,9 @@ class HermesAdapter extends BaseAdapter {
76
79
  try {
77
80
  const env = getEnhancedEnv();
78
81
  if (IS_WINDOWS) {
79
- // Native Windows unsupported upstream — we try anyway for WSL cases
82
+ // Native Windows is supported (install.ps1). The installer adds
83
+ // venv\Scripts to the user PATH; a running daemon won't see that update,
84
+ // hence the enriched env + the explicit candidates in Tier 2.
80
85
  const r = execSync('where hermes.exe 2>nul || where hermes.cmd 2>nul || where hermes 2>nul', {
81
86
  encoding: 'utf-8', timeout: 5000, windowsHide: true, env,
82
87
  });
@@ -88,9 +93,16 @@ class HermesAdapter extends BaseAdapter {
88
93
  }
89
94
  } catch {}
90
95
 
91
- // Tier 2: Common install locations. The installer drops `hermes` in
92
- // ~/.local/bin and (on Windows) ~/.hermes/bin.
96
+ // Tier 2: Common install locations. The native Windows installer
97
+ // (install.ps1) provisions a portable venv and drops hermes.exe under
98
+ // %LOCALAPPDATA%\hermes\hermes-agent\venv\Scripts (with the uv shim in
99
+ // %LOCALAPPDATA%\hermes\bin). The Unix installer uses ~/.local/bin.
100
+ const localAppData = process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
93
101
  const candidates = IS_WINDOWS ? [
102
+ path.join(localAppData, 'hermes', 'hermes-agent', 'venv', 'Scripts', 'hermes.exe'),
103
+ path.join(localAppData, 'hermes', 'hermes-agent', 'venv', 'Scripts', 'hermes.cmd'),
104
+ path.join(localAppData, 'hermes', 'bin', 'hermes.exe'),
105
+ path.join(localAppData, 'hermes', 'bin', 'hermes.cmd'),
94
106
  path.join(home, '.hermes', 'bin', 'hermes.exe'),
95
107
  path.join(home, '.hermes', 'bin', 'hermes.cmd'),
96
108
  path.join(home, '.hermes', 'bin', 'hermes'),
@@ -111,10 +123,10 @@ class HermesAdapter extends BaseAdapter {
111
123
  const viaWhich = whichBinary('hermes');
112
124
  if (viaWhich) return viaWhich;
113
125
 
114
- // Tier 4 (Windows only): Hermes is not supported natively on Windows — it
115
- // installs and runs inside WSL2. If a WSL distro has hermes on its login
116
- // PATH, resolve its absolute in-WSL path; _runHermes then invokes it as
117
- // `wsl -e <path> …`.
126
+ // Tier 4 (Windows only): fall back to a WSL install if one exists. Native
127
+ // Windows (Tiers 1-3) is preferred, but a user who set hermes up inside
128
+ // WSL2 still works — resolve its absolute in-WSL path; _runHermes then
129
+ // invokes it as `wsl -e <path> …`.
118
130
  if (IS_WINDOWS) {
119
131
  const wslPath = this._resolveWslHermes();
120
132
  if (wslPath) {
@@ -283,7 +295,7 @@ class HermesAdapter extends BaseAdapter {
283
295
 
284
296
  _buildHermesCmd(prompt, resumeSessionId) {
285
297
  if (!this._hermesBin) {
286
- throw new Error('hermes CLI not found. Install with: curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash');
298
+ throw new Error(`hermes CLI not found. Install with: ${HERMES_INSTALL_HINT}`);
287
299
  }
288
300
  const args = [];
289
301
  if (this.hermesProfile && this.hermesProfile !== 'default') {
package/src/paths.js CHANGED
@@ -197,6 +197,15 @@ function _addWindowsPaths(dirs) {
197
197
  if (localAppData) _push(dirs, path.join(localAppData, 'cursor-agent'));
198
198
  _push(dirs, path.join(HOME, '.local', 'bin'));
199
199
 
200
+ // Hermes CLI native (no-WSL) installer drops hermes.exe in the portable
201
+ // venv's Scripts dir and the uv shim in %LOCALAPPDATA%\hermes\bin. Same
202
+ // registry-PATH staleness as Cursor — add explicitly so an already-running
203
+ // daemon resolves hermes via `where` without a reboot.
204
+ if (localAppData) {
205
+ _push(dirs, path.join(localAppData, 'hermes', 'hermes-agent', 'venv', 'Scripts'));
206
+ _push(dirs, path.join(localAppData, 'hermes', 'bin'));
207
+ }
208
+
200
209
  // Node.js install
201
210
  _push(dirs, path.join(programFiles, 'nodejs'));
202
211