@agi-cli/install 0.1.33 → 0.1.35
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 +1 -1
- package/start.js +182 -1
package/package.json
CHANGED
package/start.js
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
chmodSync,
|
|
7
7
|
mkdirSync,
|
|
8
8
|
statSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
appendFileSync,
|
|
9
11
|
} from 'fs';
|
|
10
12
|
import { resolve, dirname } from 'path';
|
|
11
13
|
import { fileURLToPath } from 'url';
|
|
@@ -47,6 +49,91 @@ function findBinaryInPath() {
|
|
|
47
49
|
return null;
|
|
48
50
|
}
|
|
49
51
|
|
|
52
|
+
function getVersion(binaryPath) {
|
|
53
|
+
try {
|
|
54
|
+
const result = spawnSync(binaryPath, ['--version'], { encoding: 'utf8' });
|
|
55
|
+
if (result.status === 0 && result.stdout) {
|
|
56
|
+
// Extract version number from output (e.g., "agi 1.2.3" -> "1.2.3")
|
|
57
|
+
const match = result.stdout.trim().match(/[\d.]+/);
|
|
58
|
+
return match ? match[0] : null;
|
|
59
|
+
}
|
|
60
|
+
} catch (err) {
|
|
61
|
+
// If we can't get version, return null
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getLatestVersion() {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const url = `https://api.github.com/repos/${REPO}/releases/latest`;
|
|
69
|
+
|
|
70
|
+
get(
|
|
71
|
+
url,
|
|
72
|
+
{
|
|
73
|
+
headers: {
|
|
74
|
+
'User-Agent': 'agi-installer',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
(response) => {
|
|
78
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
79
|
+
// Follow redirect
|
|
80
|
+
get(
|
|
81
|
+
response.headers.location,
|
|
82
|
+
{
|
|
83
|
+
headers: {
|
|
84
|
+
'User-Agent': 'agi-installer',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
handleResponse,
|
|
88
|
+
);
|
|
89
|
+
} else {
|
|
90
|
+
handleResponse(response);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleResponse(res) {
|
|
94
|
+
let data = '';
|
|
95
|
+
|
|
96
|
+
res.on('data', (chunk) => {
|
|
97
|
+
data += chunk;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
res.on('end', () => {
|
|
101
|
+
try {
|
|
102
|
+
const json = JSON.parse(data);
|
|
103
|
+
if (json.tag_name) {
|
|
104
|
+
// Remove 'v' prefix if present (e.g., "v1.2.3" -> "1.2.3")
|
|
105
|
+
const version = json.tag_name.replace(/^v/, '');
|
|
106
|
+
resolve(version);
|
|
107
|
+
} else {
|
|
108
|
+
reject(new Error('No tag_name in response'));
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
reject(err);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
).on('error', reject);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function compareVersions(v1, v2) {
|
|
121
|
+
if (!v1 || !v2) return null;
|
|
122
|
+
|
|
123
|
+
const parts1 = v1.split('.').map(Number);
|
|
124
|
+
const parts2 = v2.split('.').map(Number);
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
127
|
+
const part1 = parts1[i] || 0;
|
|
128
|
+
const part2 = parts2[i] || 0;
|
|
129
|
+
|
|
130
|
+
if (part1 > part2) return 1;
|
|
131
|
+
if (part1 < part2) return -1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return 0; // Equal
|
|
135
|
+
}
|
|
136
|
+
|
|
50
137
|
function getPlatformInfo() {
|
|
51
138
|
const platformMap = {
|
|
52
139
|
darwin: 'darwin',
|
|
@@ -119,6 +206,49 @@ function downloadWithProgress(url, dest) {
|
|
|
119
206
|
});
|
|
120
207
|
}
|
|
121
208
|
|
|
209
|
+
function updateShellProfile(userBin) {
|
|
210
|
+
// Skip on Windows
|
|
211
|
+
if (platform() === 'win32') return;
|
|
212
|
+
|
|
213
|
+
const shell = process.env.SHELL || '';
|
|
214
|
+
let configFile;
|
|
215
|
+
let shellType;
|
|
216
|
+
|
|
217
|
+
if (shell.includes('zsh')) {
|
|
218
|
+
configFile = resolve(homedir(), '.zshrc');
|
|
219
|
+
shellType = 'zsh';
|
|
220
|
+
} else if (shell.includes('bash')) {
|
|
221
|
+
configFile = resolve(homedir(), '.bashrc');
|
|
222
|
+
shellType = 'bash';
|
|
223
|
+
} else {
|
|
224
|
+
configFile = resolve(homedir(), '.profile');
|
|
225
|
+
shellType = 'shell';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const pathExport = 'export PATH="$HOME/.local/bin:$PATH"';
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
let fileContent = '';
|
|
232
|
+
if (existsSync(configFile)) {
|
|
233
|
+
fileContent = readFileSync(configFile, 'utf8');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Check if .local/bin is already in the config file
|
|
237
|
+
if (fileContent.includes('.local/bin')) {
|
|
238
|
+
console.log(`✓ PATH already configured in ${configFile}`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Add the PATH export
|
|
243
|
+
appendFileSync(configFile, `\n${pathExport}\n`);
|
|
244
|
+
console.log(`✓ Added ${userBin} to PATH in ${configFile}`);
|
|
245
|
+
console.log(`✓ Restart your ${shellType} or run: source ${configFile}`);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
// Silently fail if we can't update the profile
|
|
248
|
+
console.log(`⚠️ Could not automatically update ${configFile}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
122
252
|
async function install() {
|
|
123
253
|
try {
|
|
124
254
|
const { os, arch: architecture, ext } = getPlatformInfo();
|
|
@@ -143,6 +273,7 @@ async function install() {
|
|
|
143
273
|
|
|
144
274
|
const pathDirs = (process.env.PATH || '').split(':');
|
|
145
275
|
if (!pathDirs.includes(userBin)) {
|
|
276
|
+
updateShellProfile(userBin);
|
|
146
277
|
console.log(`\n⚠️ Add ${userBin} to your PATH:`);
|
|
147
278
|
console.log(
|
|
148
279
|
` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc`,
|
|
@@ -150,6 +281,8 @@ async function install() {
|
|
|
150
281
|
console.log(
|
|
151
282
|
` Or for zsh: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc`,
|
|
152
283
|
);
|
|
284
|
+
} else {
|
|
285
|
+
console.log(`✓ ${userBin} already in PATH`);
|
|
153
286
|
}
|
|
154
287
|
} else {
|
|
155
288
|
console.log(`\n✓ Installed to ${binPath}`);
|
|
@@ -165,15 +298,62 @@ async function install() {
|
|
|
165
298
|
}
|
|
166
299
|
}
|
|
167
300
|
|
|
301
|
+
async function checkAndUpdateVersion(binaryPath) {
|
|
302
|
+
try {
|
|
303
|
+
const currentVersion = getVersion(binaryPath);
|
|
304
|
+
|
|
305
|
+
if (!currentVersion) {
|
|
306
|
+
console.log('⚠️ Could not determine current version');
|
|
307
|
+
return { needsUpdate: false, binaryPath };
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
console.log(`Current version: ${currentVersion}`);
|
|
311
|
+
console.log('Checking for updates...');
|
|
312
|
+
|
|
313
|
+
const latestVersion = await getLatestVersion();
|
|
314
|
+
console.log(`Latest version: ${latestVersion}`);
|
|
315
|
+
|
|
316
|
+
const comparison = compareVersions(currentVersion, latestVersion);
|
|
317
|
+
|
|
318
|
+
if (comparison < 0) {
|
|
319
|
+
// Current version is older
|
|
320
|
+
console.log(
|
|
321
|
+
`\n🔄 New version available: ${currentVersion} → ${latestVersion}`,
|
|
322
|
+
);
|
|
323
|
+
console.log('Updating...\n');
|
|
324
|
+
const newBinaryPath = await install();
|
|
325
|
+
return { needsUpdate: true, binaryPath: newBinaryPath };
|
|
326
|
+
} else if (comparison > 0) {
|
|
327
|
+
// Current version is newer (dev version?)
|
|
328
|
+
console.log(
|
|
329
|
+
`✓ You have a newer version (${currentVersion}) than the latest release`,
|
|
330
|
+
);
|
|
331
|
+
return { needsUpdate: false, binaryPath };
|
|
332
|
+
} else {
|
|
333
|
+
// Versions match
|
|
334
|
+
console.log('✓ You have the latest version');
|
|
335
|
+
return { needsUpdate: false, binaryPath };
|
|
336
|
+
}
|
|
337
|
+
} catch (error) {
|
|
338
|
+
console.log(`⚠️ Could not check for updates: ${error.message}`);
|
|
339
|
+
return { needsUpdate: false, binaryPath };
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
168
343
|
async function main() {
|
|
169
344
|
if (isInWorkspace()) {
|
|
170
345
|
console.log('Detected workspace environment, skipping install script.');
|
|
171
346
|
return;
|
|
172
347
|
}
|
|
173
348
|
|
|
174
|
-
|
|
349
|
+
let binaryPath = findBinaryInPath();
|
|
175
350
|
|
|
176
351
|
if (binaryPath) {
|
|
352
|
+
// Binary exists, check version
|
|
353
|
+
const { needsUpdate, binaryPath: updatedPath } =
|
|
354
|
+
await checkAndUpdateVersion(binaryPath);
|
|
355
|
+
binaryPath = updatedPath;
|
|
356
|
+
|
|
177
357
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
178
358
|
stdio: 'inherit',
|
|
179
359
|
});
|
|
@@ -182,6 +362,7 @@ async function main() {
|
|
|
182
362
|
process.exit(code || 0);
|
|
183
363
|
});
|
|
184
364
|
} else {
|
|
365
|
+
// No binary found, install fresh
|
|
185
366
|
const installedPath = await install();
|
|
186
367
|
|
|
187
368
|
if (process.argv.length > 2) {
|