@openagents-org/agent-launcher 0.2.89 → 0.2.91

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.89",
3
+ "version": "0.2.91",
4
4
  "description": "OpenAgents Launcher — install, configure, and run AI coding agents from your terminal",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -111,8 +111,8 @@ class ClaudeAdapter extends BaseAdapter {
111
111
  const home = os.homedir();
112
112
  const candidates = IS_WINDOWS
113
113
  ? [path.join(home, '.openagents', 'nodejs', 'node.exe')]
114
- : [path.join(home, '.openagents', 'nodejs', 'bin', 'node'),
115
- path.join(home, '.openagents', 'nodejs', 'node')];
114
+ : [path.join(home, '.openagents', 'nodejs', 'node'),
115
+ path.join(home, '.openagents', 'nodejs', 'bin', 'node')];
116
116
  for (const c of candidates) {
117
117
  if (fs.existsSync(c)) return c;
118
118
  }
@@ -247,9 +247,9 @@ class OpenClawAdapter extends BaseAdapter {
247
247
 
248
248
  // Always spawn node + openclaw.mjs directly (no shims, no cmd.exe, cross-platform)
249
249
  const portableDir = path.join(os.homedir(), '.openagents', 'nodejs');
250
- const nodeBin = IS_WINDOWS
251
- ? path.join(portableDir, 'node.exe')
252
- : path.join(portableDir, 'bin', 'node');
250
+ // Unified path first (symlink on Unix), then legacy bin/ fallback
251
+ const nodeUnified = path.join(portableDir, IS_WINDOWS ? 'node.exe' : 'node');
252
+ const nodeBin = fs.existsSync(nodeUnified) ? nodeUnified : path.join(portableDir, 'bin', 'node');
253
253
  // Check isolated runtime first, then legacy
254
254
  const runtimeMjs = path.join(getRuntimePrefix('openclaw'), 'node_modules', 'openclaw', 'openclaw.mjs');
255
255
  const legacyMjs = path.join(portableDir, 'node_modules', 'openclaw', 'openclaw.mjs');
package/src/cli.js CHANGED
@@ -207,10 +207,10 @@ async function cmdSearch(connector, flags, positional) {
207
207
  try {
208
208
  catalog = await connector.getCatalog();
209
209
  } catch {
210
- catalog = connector.registry.getCatalogSync().map((e) => ({
211
- ...e,
212
- installed: connector.isInstalled(e.name),
213
- }));
210
+ catalog = connector.registry.getCatalogSync().map((e) => {
211
+ const info = connector.installer.getInstallInfo(e.name);
212
+ return { ...e, installed: info.installed, managed: info.managed, location: info.location };
213
+ });
214
214
  }
215
215
 
216
216
  if (query) {
@@ -253,9 +253,10 @@ async function cmdRuntimes(connector) {
253
253
  try {
254
254
  catalog = await connector.getCatalog();
255
255
  } catch {
256
- catalog = connector.registry.getCatalogSync().map((e) => ({
257
- ...e, installed: connector.isInstalled(e.name),
258
- }));
256
+ catalog = connector.registry.getCatalogSync().map((e) => {
257
+ const info = connector.installer.getInstallInfo(e.name);
258
+ return { ...e, installed: info.installed, managed: info.managed, location: info.location };
259
+ });
259
260
  }
260
261
 
261
262
  const installed = catalog.filter((e) => e.installed);
package/src/index.js CHANGED
@@ -33,10 +33,10 @@ class AgentConnector {
33
33
  async getCatalog() {
34
34
  const catalog = await this.registry.getCatalog();
35
35
  // Always re-check installed status (don't trust cached value)
36
- return catalog.map((entry) => ({
37
- ...entry,
38
- installed: this.installer.isInstalled(entry.name),
39
- }));
36
+ return catalog.map((entry) => {
37
+ const info = this.installer.getInstallInfo(entry.name);
38
+ return { ...entry, installed: info.installed, managed: info.managed, location: info.location };
39
+ });
40
40
  }
41
41
 
42
42
  /**
package/src/installer.js CHANGED
@@ -35,7 +35,22 @@ class Installer {
35
35
  * Check if an agent type is installed.
36
36
  * Checks binary on PATH first, then marker files.
37
37
  */
38
+ /**
39
+ * Check if an agent type is installed.
40
+ * @returns {boolean} true if installed (any location)
41
+ */
38
42
  isInstalled(agentType) {
43
+ return this.getInstallInfo(agentType).installed;
44
+ }
45
+
46
+ /**
47
+ * Get detailed install info for an agent type.
48
+ * @returns {{ installed: boolean, managed: boolean, location: string|null }}
49
+ * - installed: true if the agent is found anywhere
50
+ * - managed: true if installed inside ~/.openagents/ (can be uninstalled by launcher)
51
+ * - location: 'runtime' | 'legacy' | 'global' | null
52
+ */
53
+ getInstallInfo(agentType) {
39
54
  const entry = this.registry.getEntry(agentType);
40
55
  const npmPkg = entry && entry.install ? entry.install.npm_package : null;
41
56
  const binary = entry && entry.install ? entry.install.binary : agentType;
@@ -49,17 +64,21 @@ class Installer {
49
64
 
50
65
  // Check isolated runtime prefix first (~/.openagents/runtimes/<type>/)
51
66
  const runtimeModules = path.join(getRuntimePrefix(agentType), 'node_modules');
52
- if (fs.existsSync(path.join(runtimeModules, pkgName, 'package.json'))) return true;
67
+ if (fs.existsSync(path.join(runtimeModules, pkgName, 'package.json'))) {
68
+ return { installed: true, managed: true, location: 'runtime' };
69
+ }
53
70
 
54
71
  // Legacy: check shared prefix (~/.openagents/nodejs/node_modules/)
55
72
  const legacyModules = path.join(os.homedir(), '.openagents', 'nodejs', 'node_modules');
56
- if (fs.existsSync(path.join(legacyModules, pkgName, 'package.json'))) return true;
73
+ if (fs.existsSync(path.join(legacyModules, pkgName, 'package.json'))) {
74
+ return { installed: true, managed: true, location: 'legacy' };
75
+ }
57
76
 
58
77
  // Fallback: check if binary exists on PATH (system install)
59
78
  const binaryPath = this._whichBinary(agentType);
60
79
  if (!binaryPath) {
61
80
  try { fs.unlinkSync(path.join(this.markersDir, agentType)); } catch {}
62
- return false;
81
+ return { installed: false, managed: false, location: null };
63
82
  }
64
83
 
65
84
  // Verify it's not a stale shim pointing to a missing package
@@ -72,11 +91,13 @@ class Installer {
72
91
  for (const ext of ['', '.cmd', '.ps1']) {
73
92
  try { const p = path.join(path.dirname(binaryPath), binary + ext); if (fs.existsSync(p)) fs.unlinkSync(p); } catch {}
74
93
  }
75
- return false;
94
+ return { installed: false, managed: false, location: null };
76
95
  }
96
+ return { installed: true, managed: true, location: 'legacy' };
77
97
  }
78
98
 
79
- return true;
99
+ // Binary found outside ~/.openagents/ — global/system install
100
+ return { installed: true, managed: false, location: 'global' };
80
101
  }
81
102
 
82
103
  /**