squad-station 0.6.3 → 0.6.6

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 +112 -26
  2. package/package.json +1 -1
package/bin/run.js CHANGED
@@ -43,10 +43,11 @@ function install() {
43
43
 
44
44
  function installBinary() {
45
45
  // Binary version — may differ from npm package version
46
- var VERSION = '0.6.3';
46
+ var VERSION = '0.6.6';
47
47
  var REPO = 'thientranhung/squad-station';
48
48
 
49
- var platformMap = { darwin: 'darwin', linux: 'linux' };
49
+ var isWindows = process.platform === 'win32';
50
+ var platformMap = { darwin: 'darwin', linux: 'linux', win32: 'windows' };
50
51
  var archMap = { x64: 'x86_64', arm64: 'arm64' };
51
52
 
52
53
  var p = platformMap[process.platform];
@@ -58,21 +59,13 @@ function installBinary() {
58
59
  process.exit(1);
59
60
  }
60
61
 
61
- var assetName = 'squad-station-' + p + '-' + a;
62
+ var binaryName = isWindows ? 'squad-station.exe' : 'squad-station';
63
+ var assetName = 'squad-station-' + p + '-' + a + (isWindows ? '.exe' : '');
62
64
  var url = 'https://github.com/' + REPO + '/releases/download/v' + VERSION + '/' + assetName;
63
65
 
64
- // Determine install directory
65
- var installDir = '/usr/local/bin';
66
- var fallback = false;
67
- try {
68
- fs.accessSync(installDir, fs.constants.W_OK);
69
- } catch (_) {
70
- installDir = path.join(process.env.HOME || process.env.USERPROFILE || '~', '.local', 'bin');
71
- fallback = true;
72
- fs.mkdirSync(installDir, { recursive: true });
73
- }
74
-
75
- var destPath = path.join(installDir, 'squad-station');
66
+ // Determine best install directory — pick one already in PATH
67
+ var installDir = findBestInstallDir();
68
+ var destPath = path.join(installDir, binaryName);
76
69
 
77
70
  // Check if binary already exists and is the right version
78
71
  if (fs.existsSync(destPath)) {
@@ -89,26 +82,119 @@ function installBinary() {
89
82
 
90
83
  console.log(' Downloading ' + assetName + ' v' + VERSION + '...');
91
84
 
92
- // Use curl (available on macOS/Linux) for simplicity
93
- var curlResult = spawnSync('curl', [
94
- '-fsSL', '--proto', '=https', '--tlsv1.2',
95
- '-o', destPath,
96
- url
97
- ], { stdio: ['ignore', 'pipe', 'pipe'] });
85
+ if (isWindows) {
86
+ // Use PowerShell on Windows
87
+ var psCmd = 'Invoke-WebRequest -Uri "' + url + '" -OutFile "' + destPath + '" -UseBasicParsing';
88
+ var dlResult = spawnSync('powershell', ['-Command', psCmd], { stdio: ['ignore', 'pipe', 'pipe'] });
89
+ } else {
90
+ // Use curl on macOS/Linux
91
+ var dlResult = spawnSync('curl', [
92
+ '-fsSL', '--proto', '=https', '--tlsv1.2',
93
+ '-o', destPath,
94
+ url
95
+ ], { stdio: ['ignore', 'pipe', 'pipe'] });
96
+ }
98
97
 
99
- if (curlResult.status !== 0) {
100
- var stderr = curlResult.stderr ? curlResult.stderr.toString() : '';
98
+ if (dlResult.status !== 0) {
99
+ var stderr = dlResult.stderr ? dlResult.stderr.toString() : '';
101
100
  console.error(' Download failed: ' + stderr);
102
101
  console.error(' Manual install: https://github.com/' + REPO + '/releases');
103
102
  process.exit(1);
104
103
  }
105
104
 
106
- fs.chmodSync(destPath, 0o755);
105
+ if (!isWindows) {
106
+ fs.chmodSync(destPath, 0o755);
107
+ }
107
108
  console.log(' \x1b[32m✓\x1b[0m Installed squad-station to ' + destPath);
108
109
 
109
- if (fallback) {
110
- console.log(' \x1b[33m!\x1b[0m Add ~/.local/bin to your PATH if not already present.');
110
+ // Verify the binary is actually callable via PATH
111
+ verifyInPath(destPath, installDir);
112
+ }
113
+
114
+ // Find the best install directory that is already in the user's PATH.
115
+ // Returns the first writable candidate in PATH, or falls back to ~/.local/bin.
116
+ function findBestInstallDir() {
117
+ var home = process.env.HOME || process.env.USERPROFILE || '';
118
+ var isWindows = process.platform === 'win32';
119
+ var pathSep = isWindows ? ';' : ':';
120
+ var pathDirs = (process.env.PATH || '').split(pathSep).filter(Boolean);
121
+
122
+ // Candidate directories in preference order
123
+ var candidates = isWindows
124
+ ? [
125
+ path.join(home, '.local', 'bin'),
126
+ path.join(home, 'AppData', 'Local', 'Microsoft', 'WindowsApps'),
127
+ ]
128
+ : [
129
+ '/usr/local/bin',
130
+ path.join(home, '.local', 'bin'),
131
+ path.join(home, '.cargo', 'bin'),
132
+ '/opt/homebrew/bin',
133
+ ];
134
+
135
+ // Pick the first candidate that is already in PATH and is writable
136
+ for (var i = 0; i < candidates.length; i++) {
137
+ var dir = candidates[i];
138
+ // Check if this directory is in PATH
139
+ var inPath = pathDirs.some(function(p) {
140
+ return path.resolve(p) === path.resolve(dir);
141
+ });
142
+ if (!inPath) continue;
143
+
144
+ // Check if writable (create if needed)
145
+ try {
146
+ fs.mkdirSync(dir, { recursive: true });
147
+ fs.accessSync(dir, fs.constants.W_OK);
148
+ return dir;
149
+ } catch (_) {
150
+ continue;
151
+ }
111
152
  }
153
+
154
+ // Fallback: ~/.local/bin (may not be in PATH — we'll warn later)
155
+ var fallback = path.join(home, '.local', 'bin');
156
+ fs.mkdirSync(fallback, { recursive: true });
157
+ return fallback;
158
+ }
159
+
160
+ // Verify the installed binary is callable. If not, print PATH instructions.
161
+ function verifyInPath(destPath, installDir) {
162
+ var isWindows = process.platform === 'win32';
163
+ var checkCmd = isWindows ? 'where' : 'which';
164
+ var checkResult = spawnSync(checkCmd, ['squad-station'], { encoding: 'utf8' });
165
+
166
+ if (checkResult.status === 0 && checkResult.stdout && checkResult.stdout.trim()) {
167
+ // Binary is found in PATH — all good
168
+ return;
169
+ }
170
+
171
+ // Not in PATH — print platform-specific instructions
172
+ console.log('');
173
+ console.log(' \x1b[33m⚠ squad-station is not in your PATH\x1b[0m');
174
+ console.log(' The binary was installed to: \x1b[36m' + installDir + '\x1b[0m');
175
+ console.log('');
176
+ console.log(' Add it to your PATH:');
177
+ console.log('');
178
+
179
+ if (process.platform === 'darwin') {
180
+ console.log(' \x1b[2m# macOS (zsh) — add to ~/.zshrc:\x1b[0m');
181
+ console.log(' \x1b[36mexport PATH="' + installDir + ':$PATH"\x1b[0m');
182
+ console.log('');
183
+ console.log(' Then reload: \x1b[36msource ~/.zshrc\x1b[0m');
184
+ } else if (isWindows) {
185
+ console.log(' \x1b[2m# Windows (PowerShell) — run as Administrator:\x1b[0m');
186
+ console.log(' \x1b[36m[Environment]::SetEnvironmentVariable("Path",\x1b[0m');
187
+ console.log(' \x1b[36m [Environment]::GetEnvironmentVariable("Path", "User") + ";' + installDir + '", "User")\x1b[0m');
188
+ console.log('');
189
+ console.log(' Then restart your terminal.');
190
+ } else {
191
+ // Linux
192
+ console.log(' \x1b[2m# Linux (bash) — add to ~/.bashrc:\x1b[0m');
193
+ console.log(' \x1b[36mexport PATH="' + installDir + ':$PATH"\x1b[0m');
194
+ console.log('');
195
+ console.log(' Then reload: \x1b[36msource ~/.bashrc\x1b[0m');
196
+ }
197
+ console.log('');
112
198
  }
113
199
 
114
200
  function scaffoldProject(force) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squad-station",
3
- "version": "0.6.3",
3
+ "version": "0.6.6",
4
4
  "description": "Message routing and orchestration for AI agent squads",
5
5
  "repository": {
6
6
  "type": "git",