agent-relay 2.1.18 → 2.1.20

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/README.md CHANGED
@@ -198,4 +198,4 @@ Apache-2.0 — Copyright 2025 Agent Workforce Incorporated
198
198
 
199
199
  ---
200
200
 
201
- **Links:** [Documentation](https://docs.agent-relay.com/) · [Issues](https://github.com/AgentWorkforce/relay/issues) · [Cloud](https://agent-relay.com)
201
+ **Links:** [Documentation](https://docs.agent-relay.com/) · [Issues](https://github.com/AgentWorkforce/relay/issues) · [Cloud](https://agent-relay.com) · [Discord](https://discord.gg/6E6CTxM8um)
@@ -40,14 +40,14 @@ import { fileURLToPath } from 'node:url';
40
40
  function findDashboardBinary() {
41
41
  const binaryName = 'relay-dashboard-server';
42
42
  const homeDir = process.env.HOME || process.env.USERPROFILE || '';
43
- // Common locations to check
43
+ // Check explicit install locations FIRST (before PATH) so the bash installer
44
+ // version takes precedence over stale package-manager installs in PATH
44
45
  const searchPaths = [
45
- // In PATH (using which/where)
46
- binaryName,
47
- // Common installation directories
48
46
  path.join(homeDir, '.local', 'bin', binaryName),
49
47
  path.join(homeDir, '.agent-relay', 'bin', binaryName),
50
48
  '/usr/local/bin/' + binaryName,
49
+ // Fall back to PATH lookup
50
+ binaryName,
51
51
  ];
52
52
  for (const searchPath of searchPaths) {
53
53
  try {
@@ -1151,7 +1151,7 @@ program
1151
1151
  // uninstall - Remove agent-relay from the current project
1152
1152
  program
1153
1153
  .command('uninstall')
1154
- .description('Remove agent-relay data and configuration from the current project')
1154
+ .description('Remove agent-relay data, configuration, and global binaries')
1155
1155
  .option('--keep-data', 'Keep message history and database (only remove runtime files)')
1156
1156
  .option('--zed', 'Also remove Zed editor configuration')
1157
1157
  .option('--zed-name <name>', 'Name of the Zed agent server entry to remove (default: Agent Relay)')
@@ -1164,56 +1164,54 @@ program
1164
1164
  const filesToRemove = [];
1165
1165
  const dirsToRemove = [];
1166
1166
  const actions = [];
1167
- // Check if .agent-relay directory exists
1168
- if (!fs.existsSync(paths.dataDir)) {
1169
- console.log('Agent Relay is not installed in this project.');
1170
- console.log(`(No ${paths.dataDir} directory found)`);
1171
- return;
1172
- }
1173
- // Stop daemon if running
1174
- const pidPath = pidFilePathForSocket(paths.socketPath);
1175
- if (fs.existsSync(pidPath)) {
1176
- const pid = Number(fs.readFileSync(pidPath, 'utf-8').trim());
1177
- try {
1178
- process.kill(pid, 0); // Check if running
1179
- actions.push(`Stop daemon (pid: ${pid})`);
1180
- if (!options.dryRun) {
1181
- try {
1182
- process.kill(pid, 'SIGTERM');
1183
- // Wait briefly for graceful shutdown
1184
- await new Promise(resolve => setTimeout(resolve, 2000));
1167
+ // Check if .agent-relay directory exists (still continue for global binary cleanup)
1168
+ const hasProjectData = fs.existsSync(paths.dataDir);
1169
+ if (hasProjectData) {
1170
+ // Stop daemon if running
1171
+ const pidPath = pidFilePathForSocket(paths.socketPath);
1172
+ if (fs.existsSync(pidPath)) {
1173
+ const pid = Number(fs.readFileSync(pidPath, 'utf-8').trim());
1174
+ try {
1175
+ process.kill(pid, 0); // Check if running
1176
+ actions.push(`Stop daemon (pid: ${pid})`);
1177
+ if (!options.dryRun) {
1178
+ try {
1179
+ process.kill(pid, 'SIGTERM');
1180
+ // Wait briefly for graceful shutdown
1181
+ await new Promise(resolve => setTimeout(resolve, 2000));
1182
+ }
1183
+ catch { /* ignore */ }
1185
1184
  }
1186
- catch { /* ignore */ }
1187
1185
  }
1186
+ catch { /* not running */ }
1188
1187
  }
1189
- catch { /* not running */ }
1190
- }
1191
- // Collect files to remove
1192
- if (options.keepData) {
1193
- // Only remove runtime files, keep database
1194
- const runtimeFiles = ['relay.sock', 'runtime.json', 'daemon.pid', '.project'];
1195
- for (const file of runtimeFiles) {
1196
- const filePath = path.join(paths.dataDir, file);
1197
- if (fs.existsSync(filePath)) {
1198
- filesToRemove.push(filePath);
1188
+ // Collect files to remove
1189
+ if (options.keepData) {
1190
+ // Only remove runtime files, keep database
1191
+ const runtimeFiles = ['relay.sock', 'runtime.json', 'daemon.pid', '.project'];
1192
+ for (const file of runtimeFiles) {
1193
+ const filePath = path.join(paths.dataDir, file);
1194
+ if (fs.existsSync(filePath)) {
1195
+ filesToRemove.push(filePath);
1196
+ }
1199
1197
  }
1200
- }
1201
- // Remove mcp-identity-* files
1202
- try {
1203
- const files = fs.readdirSync(paths.dataDir);
1204
- for (const file of files) {
1205
- if (file.startsWith('mcp-identity')) {
1206
- filesToRemove.push(path.join(paths.dataDir, file));
1198
+ // Remove mcp-identity-* files
1199
+ try {
1200
+ const files = fs.readdirSync(paths.dataDir);
1201
+ for (const file of files) {
1202
+ if (file.startsWith('mcp-identity')) {
1203
+ filesToRemove.push(path.join(paths.dataDir, file));
1204
+ }
1207
1205
  }
1208
1206
  }
1207
+ catch { /* ignore */ }
1208
+ actions.push('Remove runtime files (keeping database and message history)');
1209
+ }
1210
+ else {
1211
+ // Remove entire .agent-relay directory
1212
+ dirsToRemove.push(paths.dataDir);
1213
+ actions.push(`Remove ${paths.dataDir}/ directory (including message history)`);
1209
1214
  }
1210
- catch { /* ignore */ }
1211
- actions.push('Remove runtime files (keeping database and message history)');
1212
- }
1213
- else {
1214
- // Remove entire .agent-relay directory
1215
- dirsToRemove.push(paths.dataDir);
1216
- actions.push(`Remove ${paths.dataDir}/ directory (including message history)`);
1217
1215
  }
1218
1216
  // Zed configuration
1219
1217
  if (options.zed) {
@@ -1236,6 +1234,75 @@ program
1236
1234
  }
1237
1235
  }
1238
1236
  }
1237
+ // Global install cleanup (bash installer / install.sh artifacts)
1238
+ const home = homedir();
1239
+ const installDir = process.env.AGENT_RELAY_INSTALL_DIR || path.join(home, '.agent-relay');
1240
+ const binDir = process.env.AGENT_RELAY_BIN_DIR || path.join(home, '.local', 'bin');
1241
+ // Binaries placed by install.sh into BIN_DIR
1242
+ const globalBinaries = [
1243
+ path.join(binDir, 'agent-relay'),
1244
+ path.join(binDir, 'relay-dashboard-server'),
1245
+ path.join(binDir, 'relay-acp'),
1246
+ ];
1247
+ for (const bin of globalBinaries) {
1248
+ if (fs.existsSync(bin)) {
1249
+ filesToRemove.push(bin);
1250
+ actions.push(`Remove ${bin}`);
1251
+ }
1252
+ }
1253
+ // relay-pty binary in INSTALL_DIR/bin/
1254
+ const relayPtyPath = path.join(installDir, 'bin', 'relay-pty');
1255
+ if (fs.existsSync(relayPtyPath)) {
1256
+ filesToRemove.push(relayPtyPath);
1257
+ actions.push(`Remove ${relayPtyPath}`);
1258
+ }
1259
+ // INSTALL_DIR itself (e.g. ~/.agent-relay) if it exists and is different from project .agent-relay
1260
+ if (fs.existsSync(installDir) && path.resolve(installDir) !== path.resolve(paths.dataDir)) {
1261
+ dirsToRemove.push(installDir);
1262
+ actions.push(`Remove install directory ${installDir}/`);
1263
+ }
1264
+ // Dashboard UI files (~/.relay/dashboard/)
1265
+ const dashboardDir = path.join(home, '.relay', 'dashboard');
1266
+ if (fs.existsSync(dashboardDir)) {
1267
+ dirsToRemove.push(dashboardDir);
1268
+ actions.push(`Remove dashboard UI files from ${dashboardDir}/`);
1269
+ }
1270
+ // Package manager global install cleanup
1271
+ const packagesToCheck = ['agent-relay', '@agent-relay/acp-bridge', '@agent-relay/dashboard-server'];
1272
+ const npmGlobalPackages = [];
1273
+ const pnpmGlobalPackages = [];
1274
+ // npm global
1275
+ try {
1276
+ const npmPrefix = execSync('npm prefix -g', { encoding: 'utf-8', timeout: 5000 }).trim();
1277
+ const npmGlobalModules = path.join(npmPrefix, 'lib', 'node_modules');
1278
+ for (const pkg of packagesToCheck) {
1279
+ if (fs.existsSync(path.join(npmGlobalModules, pkg))) {
1280
+ npmGlobalPackages.push(pkg);
1281
+ }
1282
+ }
1283
+ if (npmGlobalPackages.length > 0) {
1284
+ actions.push(`npm uninstall -g ${npmGlobalPackages.join(', ')}`);
1285
+ }
1286
+ }
1287
+ catch { /* npm not available */ }
1288
+ // pnpm global
1289
+ try {
1290
+ const pnpmRoot = execSync('pnpm root -g', { encoding: 'utf-8', timeout: 5000 }).trim();
1291
+ for (const pkg of packagesToCheck) {
1292
+ if (fs.existsSync(path.join(pnpmRoot, pkg))) {
1293
+ pnpmGlobalPackages.push(pkg);
1294
+ }
1295
+ }
1296
+ if (pnpmGlobalPackages.length > 0) {
1297
+ actions.push(`pnpm remove -g ${pnpmGlobalPackages.join(', ')}`);
1298
+ }
1299
+ }
1300
+ catch { /* pnpm not available */ }
1301
+ // Nothing to do
1302
+ if (actions.length === 0) {
1303
+ console.log('Agent Relay is not installed (no project data or global binaries found).');
1304
+ return;
1305
+ }
1239
1306
  // Show what will be done
1240
1307
  console.log('');
1241
1308
  console.log('Agent Relay Uninstall');
@@ -1265,24 +1332,52 @@ program
1265
1332
  }
1266
1333
  // Perform removal
1267
1334
  console.log('');
1335
+ // Helper: display path relative to project if inside it, absolute otherwise
1336
+ const displayPath = (p) => {
1337
+ const rel = path.relative(paths.projectRoot, p);
1338
+ return rel.startsWith('..') ? p : rel;
1339
+ };
1268
1340
  // Remove files
1269
1341
  for (const file of filesToRemove) {
1270
1342
  try {
1271
1343
  fs.unlinkSync(file);
1272
- console.log(` ✓ Removed ${path.relative(paths.projectRoot, file)}`);
1344
+ console.log(` ✓ Removed ${displayPath(file)}`);
1273
1345
  }
1274
1346
  catch (err) {
1275
- console.log(` ✗ Failed to remove ${path.relative(paths.projectRoot, file)}: ${err.message}`);
1347
+ console.log(` ✗ Failed to remove ${displayPath(file)}: ${err.message}`);
1276
1348
  }
1277
1349
  }
1278
1350
  // Remove directories
1279
1351
  for (const dir of dirsToRemove) {
1280
1352
  try {
1281
1353
  fs.rmSync(dir, { recursive: true, force: true });
1282
- console.log(` ✓ Removed ${path.relative(paths.projectRoot, dir)}/`);
1354
+ console.log(` ✓ Removed ${displayPath(dir)}/`);
1355
+ }
1356
+ catch (err) {
1357
+ console.log(` ✗ Failed to remove ${displayPath(dir)}/: ${err.message}`);
1358
+ }
1359
+ }
1360
+ // Remove package manager global packages
1361
+ for (const pkg of npmGlobalPackages) {
1362
+ try {
1363
+ execSync(`npm uninstall -g ${pkg}`, { encoding: 'utf-8', timeout: 30000, stdio: 'pipe' });
1364
+ console.log(` ✓ npm uninstall -g ${pkg}`);
1365
+ }
1366
+ catch (err) {
1367
+ const stderr = err.stderr?.toString?.() || '';
1368
+ const hint = stderr.includes('EACCES') ? ' (try with sudo)' : '';
1369
+ console.log(` ✗ Failed to npm uninstall -g ${pkg}${hint}: ${stderr || err.message}`);
1370
+ }
1371
+ }
1372
+ for (const pkg of pnpmGlobalPackages) {
1373
+ try {
1374
+ execSync(`pnpm remove -g ${pkg}`, { encoding: 'utf-8', timeout: 30000, stdio: 'pipe' });
1375
+ console.log(` ✓ pnpm remove -g ${pkg}`);
1283
1376
  }
1284
1377
  catch (err) {
1285
- console.log(` ✗ Failed to remove ${path.relative(paths.projectRoot, dir)}/: ${err.message}`);
1378
+ const stderr = err.stderr?.toString?.() || '';
1379
+ const hint = stderr.includes('EACCES') ? ' (try with sudo)' : '';
1380
+ console.log(` ✗ Failed to pnpm remove -g ${pkg}${hint}: ${stderr || err.message}`);
1286
1381
  }
1287
1382
  }
1288
1383
  // Remove Zed config