@agi-cli/install 0.1.32 → 0.1.34
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 +4 -4
- package/start.js +247 -0
- package/install.js +0 -131
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/install",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"description": "AI-powered development assistant CLI - npm installer",
|
|
5
5
|
"author": "ntishxyz",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
],
|
|
26
26
|
"type": "module",
|
|
27
27
|
"bin": {
|
|
28
|
-
"agi": "./
|
|
28
|
+
"agi": "./start.js"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
|
-
"
|
|
31
|
+
"start.js",
|
|
32
32
|
"README.md"
|
|
33
33
|
],
|
|
34
34
|
"scripts": {
|
|
35
|
-
"postinstall": "node
|
|
35
|
+
"postinstall": "node start.js"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/start.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
createWriteStream,
|
|
6
|
+
chmodSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
statSync,
|
|
9
|
+
readFileSync,
|
|
10
|
+
appendFileSync,
|
|
11
|
+
} from 'fs';
|
|
12
|
+
import { resolve, dirname } from 'path';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { get } from 'https';
|
|
15
|
+
import { homedir, platform, arch } from 'os';
|
|
16
|
+
import { spawnSync, spawn } from 'child_process';
|
|
17
|
+
|
|
18
|
+
const REPO = 'nitishxyz/agi';
|
|
19
|
+
const BIN_NAME = 'agi';
|
|
20
|
+
|
|
21
|
+
function isInWorkspace() {
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const workspaceRoot = resolve(__dirname, '../../');
|
|
24
|
+
return (
|
|
25
|
+
existsSync(resolve(workspaceRoot, 'apps')) &&
|
|
26
|
+
existsSync(resolve(workspaceRoot, 'packages'))
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function findBinaryInPath() {
|
|
31
|
+
const pathDirs = (process.env.PATH || '').split(':');
|
|
32
|
+
const ext = platform() === 'win32' ? '.exe' : '';
|
|
33
|
+
const currentScript = fileURLToPath(import.meta.url);
|
|
34
|
+
|
|
35
|
+
for (const dir of pathDirs) {
|
|
36
|
+
const binPath = resolve(dir, `${BIN_NAME}${ext}`);
|
|
37
|
+
if (existsSync(binPath)) {
|
|
38
|
+
try {
|
|
39
|
+
const stat = statSync(binPath);
|
|
40
|
+
if (stat.isFile() && binPath !== currentScript) {
|
|
41
|
+
const result = spawnSync('file', [binPath], { encoding: 'utf8' });
|
|
42
|
+
if (!result.stdout.includes('script text')) {
|
|
43
|
+
return binPath;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getPlatformInfo() {
|
|
53
|
+
const platformMap = {
|
|
54
|
+
darwin: 'darwin',
|
|
55
|
+
linux: 'linux',
|
|
56
|
+
win32: 'windows',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const archMap = {
|
|
60
|
+
x64: 'x64',
|
|
61
|
+
arm64: 'arm64',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const os = platformMap[platform()];
|
|
65
|
+
const architecture = archMap[arch()];
|
|
66
|
+
const ext = platform() === 'win32' ? '.exe' : '';
|
|
67
|
+
|
|
68
|
+
if (!os || !architecture) {
|
|
69
|
+
throw new Error(`Unsupported platform: ${platform()}-${arch()}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { os, arch: architecture, ext };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function downloadWithProgress(url, dest) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const file = createWriteStream(dest);
|
|
78
|
+
let totalBytes = 0;
|
|
79
|
+
let downloadedBytes = 0;
|
|
80
|
+
|
|
81
|
+
function handleRedirect(response) {
|
|
82
|
+
if (
|
|
83
|
+
response.statusCode >= 300 &&
|
|
84
|
+
response.statusCode < 400 &&
|
|
85
|
+
response.headers.location
|
|
86
|
+
) {
|
|
87
|
+
get(response.headers.location, handleRedirect);
|
|
88
|
+
} else if (response.statusCode === 200) {
|
|
89
|
+
totalBytes = Number.parseInt(
|
|
90
|
+
response.headers['content-length'] || '0',
|
|
91
|
+
10,
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
response.on('data', (chunk) => {
|
|
95
|
+
downloadedBytes += chunk.length;
|
|
96
|
+
if (totalBytes > 0) {
|
|
97
|
+
const percent = ((downloadedBytes / totalBytes) * 100).toFixed(1);
|
|
98
|
+
const downloadedMB = (downloadedBytes / 1024 / 1024).toFixed(1);
|
|
99
|
+
const totalMB = (totalBytes / 1024 / 1024).toFixed(1);
|
|
100
|
+
process.stdout.write(
|
|
101
|
+
`\rDownloading: ${percent}% (${downloadedMB}MB / ${totalMB}MB)`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
response.pipe(file);
|
|
107
|
+
file.on('finish', () => {
|
|
108
|
+
file.close();
|
|
109
|
+
process.stdout.write('\n');
|
|
110
|
+
resolve();
|
|
111
|
+
});
|
|
112
|
+
} else {
|
|
113
|
+
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
get(url, handleRedirect).on('error', (err) => {
|
|
118
|
+
file.close();
|
|
119
|
+
reject(err);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function updateShellProfile(userBin) {
|
|
125
|
+
// Skip on Windows
|
|
126
|
+
if (platform() === 'win32') return;
|
|
127
|
+
|
|
128
|
+
const shell = process.env.SHELL || '';
|
|
129
|
+
let configFile;
|
|
130
|
+
let shellType;
|
|
131
|
+
|
|
132
|
+
if (shell.includes('zsh')) {
|
|
133
|
+
configFile = resolve(homedir(), '.zshrc');
|
|
134
|
+
shellType = 'zsh';
|
|
135
|
+
} else if (shell.includes('bash')) {
|
|
136
|
+
configFile = resolve(homedir(), '.bashrc');
|
|
137
|
+
shellType = 'bash';
|
|
138
|
+
} else {
|
|
139
|
+
configFile = resolve(homedir(), '.profile');
|
|
140
|
+
shellType = 'shell';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const pathExport = 'export PATH="$HOME/.local/bin:$PATH"';
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
let fileContent = '';
|
|
147
|
+
if (existsSync(configFile)) {
|
|
148
|
+
fileContent = readFileSync(configFile, 'utf8');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Check if .local/bin is already in the config file
|
|
152
|
+
if (fileContent.includes('.local/bin')) {
|
|
153
|
+
console.log(`✓ PATH already configured in ${configFile}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Add the PATH export
|
|
158
|
+
appendFileSync(configFile, `\n${pathExport}\n`);
|
|
159
|
+
console.log(`✓ Added ${userBin} to PATH in ${configFile}`);
|
|
160
|
+
console.log(`✓ Restart your ${shellType} or run: source ${configFile}`);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
// Silently fail if we can't update the profile
|
|
163
|
+
console.log(`⚠️ Could not automatically update ${configFile}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function install() {
|
|
168
|
+
try {
|
|
169
|
+
const { os, arch: architecture, ext } = getPlatformInfo();
|
|
170
|
+
const asset = `${BIN_NAME}-${os}-${architecture}${ext}`;
|
|
171
|
+
const url = `https://github.com/${REPO}/releases/latest/download/${asset}`;
|
|
172
|
+
|
|
173
|
+
console.log(`Installing ${BIN_NAME} (${os}/${architecture})...`);
|
|
174
|
+
|
|
175
|
+
const userBin = resolve(homedir(), '.local', 'bin');
|
|
176
|
+
mkdirSync(userBin, { recursive: true });
|
|
177
|
+
const binPath = resolve(userBin, `${BIN_NAME}${ext}`);
|
|
178
|
+
|
|
179
|
+
await downloadWithProgress(url, binPath);
|
|
180
|
+
|
|
181
|
+
chmodSync(binPath, 0o755);
|
|
182
|
+
|
|
183
|
+
const result = spawnSync(binPath, ['--version'], { encoding: 'utf8' });
|
|
184
|
+
if (result.status === 0) {
|
|
185
|
+
console.log(`\n✓ ${BIN_NAME} installed successfully!`);
|
|
186
|
+
console.log(`Version: ${result.stdout.trim()}`);
|
|
187
|
+
console.log(`Location: ${binPath}`);
|
|
188
|
+
|
|
189
|
+
const pathDirs = (process.env.PATH || '').split(':');
|
|
190
|
+
if (!pathDirs.includes(userBin)) {
|
|
191
|
+
updateShellProfile(userBin);
|
|
192
|
+
console.log(`\n⚠️ Add ${userBin} to your PATH:`);
|
|
193
|
+
console.log(
|
|
194
|
+
` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc`,
|
|
195
|
+
);
|
|
196
|
+
console.log(
|
|
197
|
+
` Or for zsh: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc`,
|
|
198
|
+
);
|
|
199
|
+
} else {
|
|
200
|
+
console.log(`✓ ${userBin} already in PATH`);
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
console.log(`\n✓ Installed to ${binPath}`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
console.log(`\nRun: ${BIN_NAME} --help`);
|
|
207
|
+
return binPath;
|
|
208
|
+
} catch (error) {
|
|
209
|
+
console.error('Failed to install agi CLI:', error.message);
|
|
210
|
+
console.error('\nPlease try installing manually:');
|
|
211
|
+
console.error(' curl -fsSL https://install.agi.nitish.sh | sh');
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async function main() {
|
|
217
|
+
if (isInWorkspace()) {
|
|
218
|
+
console.log('Detected workspace environment, skipping install script.');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const binaryPath = findBinaryInPath();
|
|
223
|
+
|
|
224
|
+
if (binaryPath) {
|
|
225
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
226
|
+
stdio: 'inherit',
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
child.on('exit', (code) => {
|
|
230
|
+
process.exit(code || 0);
|
|
231
|
+
});
|
|
232
|
+
} else {
|
|
233
|
+
const installedPath = await install();
|
|
234
|
+
|
|
235
|
+
if (process.argv.length > 2) {
|
|
236
|
+
const child = spawn(installedPath, process.argv.slice(2), {
|
|
237
|
+
stdio: 'inherit',
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
child.on('exit', (code) => {
|
|
241
|
+
process.exit(code || 0);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
main();
|
package/install.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { existsSync, createWriteStream, chmodSync, mkdirSync } from 'fs';
|
|
4
|
-
import { resolve, dirname } from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
import { get } from 'https';
|
|
7
|
-
import { homedir, platform, arch } from 'os';
|
|
8
|
-
import { spawnSync } from 'child_process';
|
|
9
|
-
|
|
10
|
-
const REPO = 'nitishxyz/agi';
|
|
11
|
-
const BIN_NAME = 'agi';
|
|
12
|
-
|
|
13
|
-
// Skip if running in a workspace (local development)
|
|
14
|
-
function isInWorkspace() {
|
|
15
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const workspaceRoot = resolve(__dirname, '../../');
|
|
17
|
-
return (
|
|
18
|
-
existsSync(resolve(workspaceRoot, 'apps')) &&
|
|
19
|
-
existsSync(resolve(workspaceRoot, 'packages'))
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function getPlatformInfo() {
|
|
24
|
-
const platformMap = {
|
|
25
|
-
darwin: 'darwin',
|
|
26
|
-
linux: 'linux',
|
|
27
|
-
win32: 'windows',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const archMap = {
|
|
31
|
-
x64: 'x64',
|
|
32
|
-
arm64: 'arm64',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const os = platformMap[platform()];
|
|
36
|
-
const architecture = archMap[arch()];
|
|
37
|
-
const ext = platform() === 'win32' ? '.exe' : '';
|
|
38
|
-
|
|
39
|
-
if (!os || !architecture) {
|
|
40
|
-
throw new Error(`Unsupported platform: ${platform()}-${arch()}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return { os, arch: architecture, ext };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function download(url, dest) {
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
48
|
-
const file = createWriteStream(dest);
|
|
49
|
-
|
|
50
|
-
function handleRedirect(response) {
|
|
51
|
-
if (
|
|
52
|
-
response.statusCode >= 300 &&
|
|
53
|
-
response.statusCode < 400 &&
|
|
54
|
-
response.headers.location
|
|
55
|
-
) {
|
|
56
|
-
get(response.headers.location, handleRedirect);
|
|
57
|
-
} else if (response.statusCode === 200) {
|
|
58
|
-
response.pipe(file);
|
|
59
|
-
file.on('finish', () => {
|
|
60
|
-
file.close();
|
|
61
|
-
resolve();
|
|
62
|
-
});
|
|
63
|
-
} else {
|
|
64
|
-
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
get(url, handleRedirect).on('error', (err) => {
|
|
69
|
-
file.close();
|
|
70
|
-
reject(err);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function install() {
|
|
76
|
-
if (isInWorkspace()) {
|
|
77
|
-
console.log('Detected workspace environment, skipping install script.');
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
const { os, arch: architecture, ext } = getPlatformInfo();
|
|
83
|
-
const asset = `${BIN_NAME}-${os}-${architecture}${ext}`;
|
|
84
|
-
const url = `https://github.com/${REPO}/releases/latest/download/${asset}`;
|
|
85
|
-
|
|
86
|
-
console.log(`Installing ${BIN_NAME} (${os}/${architecture})...`);
|
|
87
|
-
|
|
88
|
-
// Determine install directory
|
|
89
|
-
const userBin = resolve(homedir(), '.local', 'bin');
|
|
90
|
-
mkdirSync(userBin, { recursive: true });
|
|
91
|
-
const binPath = resolve(userBin, `${BIN_NAME}${ext}`);
|
|
92
|
-
|
|
93
|
-
// Download
|
|
94
|
-
console.log(`Downloading from ${url}...`);
|
|
95
|
-
await download(url, binPath);
|
|
96
|
-
|
|
97
|
-
// Make executable
|
|
98
|
-
chmodSync(binPath, 0o755);
|
|
99
|
-
|
|
100
|
-
// Verify
|
|
101
|
-
const result = spawnSync(binPath, ['--version'], { encoding: 'utf8' });
|
|
102
|
-
if (result.status === 0) {
|
|
103
|
-
console.log(`\n✓ ${BIN_NAME} installed successfully!`);
|
|
104
|
-
console.log(`Version: ${result.stdout.trim()}`);
|
|
105
|
-
console.log(`Location: ${binPath}`);
|
|
106
|
-
|
|
107
|
-
// Check if in PATH
|
|
108
|
-
const pathDirs = (process.env.PATH || '').split(':');
|
|
109
|
-
if (!pathDirs.includes(userBin)) {
|
|
110
|
-
console.log(`\n⚠️ Add ${userBin} to your PATH:`);
|
|
111
|
-
console.log(
|
|
112
|
-
` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc`,
|
|
113
|
-
);
|
|
114
|
-
console.log(
|
|
115
|
-
` Or for zsh: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc`,
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
console.log(`\n✓ Installed to ${binPath}`);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
console.log(`\nRun: ${BIN_NAME} --help`);
|
|
123
|
-
} catch (error) {
|
|
124
|
-
console.error('Failed to install agi CLI:', error.message);
|
|
125
|
-
console.error('\nPlease try installing manually:');
|
|
126
|
-
console.error(' curl -fsSL https://install.agi.nitish.sh | sh');
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
install();
|