squad-station 0.8.16 → 0.8.17

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.
Files changed (2) hide show
  1. package/bin/run.js +113 -25
  2. package/package.json +1 -1
package/bin/run.js CHANGED
@@ -11,6 +11,8 @@ const subcommand = process.argv[2];
11
11
 
12
12
  if (subcommand === 'install') {
13
13
  install();
14
+ } else if (subcommand === 'uninstall') {
15
+ uninstall();
14
16
  } else {
15
17
  proxyToBinary();
16
18
  }
@@ -43,7 +45,7 @@ function install() {
43
45
 
44
46
  function installBinary() {
45
47
  // Binary version — may differ from npm package version
46
- var VERSION = '0.8.16';
48
+ var VERSION = '0.8.17';
47
49
  var REPO = 'thientranhung/squad-station';
48
50
 
49
51
  var isWindows = process.platform === 'win32';
@@ -126,29 +128,34 @@ function findBestInstallDir() {
126
128
  var pathSep = isWindows ? ';' : ':';
127
129
  var pathDirs = (process.env.PATH || '').split(pathSep).filter(Boolean);
128
130
 
129
- // Candidate directories in preference order
131
+ // Primary: ~/.squad/bin our own directory, does not need to be on PATH
132
+ var squadBin = path.join(home, '.squad', 'bin');
133
+ try {
134
+ fs.mkdirSync(squadBin, { recursive: true });
135
+ fs.accessSync(squadBin, fs.constants.W_OK);
136
+ return squadBin;
137
+ } catch (_) {
138
+ // Fall through to other candidates
139
+ }
140
+
141
+ // Secondary candidates — must be on PATH and writable
130
142
  var candidates = isWindows
131
143
  ? [
132
144
  path.join(home, '.local', 'bin'),
133
145
  path.join(home, 'AppData', 'Local', 'Microsoft', 'WindowsApps'),
134
146
  ]
135
147
  : [
136
- '/usr/local/bin',
137
148
  path.join(home, '.local', 'bin'),
138
- path.join(home, '.cargo', 'bin'),
139
- '/opt/homebrew/bin',
149
+ '/usr/local/bin',
140
150
  ];
141
151
 
142
- // Pick the first candidate that is already in PATH and is writable
143
152
  for (var i = 0; i < candidates.length; i++) {
144
153
  var dir = candidates[i];
145
- // Check if this directory is in PATH
146
154
  var inPath = pathDirs.some(function(p) {
147
155
  return path.resolve(p) === path.resolve(dir);
148
156
  });
149
157
  if (!inPath) continue;
150
158
 
151
- // Check if writable (create if needed)
152
159
  try {
153
160
  fs.mkdirSync(dir, { recursive: true });
154
161
  fs.accessSync(dir, fs.constants.W_OK);
@@ -158,10 +165,9 @@ function findBestInstallDir() {
158
165
  }
159
166
  }
160
167
 
161
- // Fallback: ~/.local/bin (may not be in PATH — we'll warn later)
162
- var fallback = path.join(home, '.local', 'bin');
163
- fs.mkdirSync(fallback, { recursive: true });
164
- return fallback;
168
+ // Fallback: ~/.squad/bin (already created above if writable)
169
+ fs.mkdirSync(squadBin, { recursive: true });
170
+ return squadBin;
165
171
  }
166
172
 
167
173
  // Verify the installed binary is callable. If not, print PATH instructions.
@@ -175,35 +181,117 @@ function verifyInPath(destPath, installDir) {
175
181
  return;
176
182
  }
177
183
 
178
- // Not in PATH — print platform-specific instructions
184
+ // Not in PATH — print instructions
179
185
  console.log('');
180
186
  console.log(' \x1b[33m⚠ squad-station is not in your PATH\x1b[0m');
181
187
  console.log(' The binary was installed to: \x1b[36m' + installDir + '\x1b[0m');
182
188
  console.log('');
183
- console.log(' Add it to your PATH:');
184
- console.log('');
185
189
 
186
- if (process.platform === 'darwin') {
187
- console.log(' \x1b[2m# macOS (zsh) — add to ~/.zshrc:\x1b[0m');
188
- console.log(' \x1b[36mexport PATH="' + installDir + ':$PATH"\x1b[0m');
190
+ if (isWindows) {
191
+ console.log(' Add to your PATH:');
189
192
  console.log('');
190
- console.log(' Then reload: \x1b[36msource ~/.zshrc\x1b[0m');
191
- } else if (isWindows) {
192
193
  console.log(' \x1b[2m# Windows (PowerShell) — run as Administrator:\x1b[0m');
193
194
  console.log(' \x1b[36m[Environment]::SetEnvironmentVariable("Path",\x1b[0m');
194
195
  console.log(' \x1b[36m [Environment]::GetEnvironmentVariable("Path", "User") + ";' + installDir + '", "User")\x1b[0m');
195
196
  console.log('');
196
197
  console.log(' Then restart your terminal.');
197
198
  } else {
198
- // Linux
199
- console.log(' \x1b[2m# Linux (bash) add to ~/.bashrc:\x1b[0m');
200
- console.log(' \x1b[36mexport PATH="' + installDir + ':$PATH"\x1b[0m');
201
- console.log('');
202
- console.log(' Then reload: \x1b[36msource ~/.bashrc\x1b[0m');
199
+ var shellProfile = process.platform === 'darwin' ? '~/.zshrc' : '~/.bashrc';
200
+ console.log(' Add to your shell profile: \x1b[36mexport PATH="$HOME/.squad/bin:$PATH"\x1b[0m');
201
+ console.log(' Then restart your terminal or run: \x1b[36msource ' + shellProfile + '\x1b[0m');
203
202
  }
204
203
  console.log('');
205
204
  }
206
205
 
206
+ // ── Uninstall ───────────────────────────────────────────────────────
207
+ // Find and remove all squad-station binaries from known locations.
208
+
209
+ function uninstall() {
210
+ var home = process.env.HOME || process.env.USERPROFILE || '';
211
+ var isWindows = process.platform === 'win32';
212
+ var binaryName = isWindows ? 'squad-station.exe' : 'squad-station';
213
+
214
+ // Search directories: current install locations + legacy locations
215
+ var searchDirs = isWindows
216
+ ? [
217
+ path.join(home, '.squad', 'bin'),
218
+ path.join(home, '.local', 'bin'),
219
+ path.join(home, 'AppData', 'Local', 'Microsoft', 'WindowsApps'),
220
+ ]
221
+ : [
222
+ path.join(home, '.squad', 'bin'),
223
+ path.join(home, '.local', 'bin'),
224
+ '/usr/local/bin',
225
+ path.join(home, '.cargo', 'bin'),
226
+ '/opt/homebrew/bin',
227
+ ];
228
+
229
+ console.log('\n\x1b[32m══════════════════════════════════\x1b[0m');
230
+ console.log(' \x1b[1mSquad Station Uninstall\x1b[0m');
231
+ console.log('\x1b[32m══════════════════════════════════\x1b[0m\n');
232
+
233
+ // Find all existing binaries
234
+ var found = [];
235
+ for (var i = 0; i < searchDirs.length; i++) {
236
+ var binPath = path.join(searchDirs[i], binaryName);
237
+ if (fs.existsSync(binPath)) {
238
+ var version = '(unknown version)';
239
+ try {
240
+ var result = spawnSync(binPath, ['--version'], { encoding: 'utf8', timeout: 5000 });
241
+ if (result.stdout && result.stdout.trim()) {
242
+ version = result.stdout.trim();
243
+ }
244
+ } catch (_) {}
245
+ found.push({ path: binPath, version: version });
246
+ }
247
+ }
248
+
249
+ if (found.length === 0) {
250
+ console.log(' No squad-station binaries found.\n');
251
+ return;
252
+ }
253
+
254
+ console.log(' Found ' + found.length + ' binary(ies):\n');
255
+ for (var j = 0; j < found.length; j++) {
256
+ console.log(' \x1b[36m' + found[j].path + '\x1b[0m ' + found[j].version);
257
+ }
258
+ console.log('');
259
+
260
+ // Ask for confirmation (read single line from stdin)
261
+ process.stdout.write(' Remove these binaries? [y/N] ');
262
+ var buf = Buffer.alloc(128);
263
+ var bytesRead = 0;
264
+ try {
265
+ bytesRead = fs.readSync(0, buf, 0, buf.length);
266
+ } catch (_) {
267
+ console.log('\n Aborted.\n');
268
+ return;
269
+ }
270
+ var answer = buf.toString('utf8', 0, bytesRead).trim().toLowerCase();
271
+
272
+ if (answer !== 'y' && answer !== 'yes') {
273
+ console.log(' Aborted.\n');
274
+ return;
275
+ }
276
+
277
+ // Delete each binary
278
+ var removed = 0;
279
+ for (var k = 0; k < found.length; k++) {
280
+ try {
281
+ fs.unlinkSync(found[k].path);
282
+ console.log(' \x1b[32m✓\x1b[0m Removed ' + found[k].path);
283
+ removed++;
284
+ } catch (e) {
285
+ console.log(' \x1b[31m✗\x1b[0m Failed to remove ' + found[k].path + ': ' + e.message);
286
+ }
287
+ }
288
+
289
+ console.log('');
290
+ if (removed > 0) {
291
+ console.log(' Uninstalled. You can also remove ~/.squad/bin from your PATH if no longer needed.\n');
292
+ }
293
+ }
294
+
207
295
  function scaffoldProject(force) {
208
296
  // Source: bundled .squad/ directory inside npm package
209
297
  var pkgRoot = path.join(__dirname, '..');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squad-station",
3
- "version": "0.8.16",
3
+ "version": "0.8.17",
4
4
  "description": "Message routing and orchestration for AI agent squads",
5
5
  "repository": {
6
6
  "type": "git",