@agi-cli/install 0.1.31 → 0.1.33

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agi-cli/install",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
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": "./install.js"
28
+ "agi": "./start.js"
29
29
  },
30
30
  "files": [
31
- "install.js",
31
+ "start.js",
32
32
  "README.md"
33
33
  ],
34
34
  "scripts": {
35
- "postinstall": "node install.js"
35
+ "postinstall": "node start.js"
36
36
  }
37
37
  }
@@ -1,16 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { existsSync, createWriteStream, chmodSync, mkdirSync } from 'fs';
3
+ import {
4
+ existsSync,
5
+ createWriteStream,
6
+ chmodSync,
7
+ mkdirSync,
8
+ statSync,
9
+ } from 'fs';
4
10
  import { resolve, dirname } from 'path';
5
11
  import { fileURLToPath } from 'url';
6
12
  import { get } from 'https';
7
13
  import { homedir, platform, arch } from 'os';
8
- import { spawnSync } from 'child_process';
14
+ import { spawnSync, spawn } from 'child_process';
9
15
 
10
16
  const REPO = 'nitishxyz/agi';
11
17
  const BIN_NAME = 'agi';
12
18
 
13
- // Skip if running in a workspace (local development)
14
19
  function isInWorkspace() {
15
20
  const __dirname = dirname(fileURLToPath(import.meta.url));
16
21
  const workspaceRoot = resolve(__dirname, '../../');
@@ -20,6 +25,28 @@ function isInWorkspace() {
20
25
  );
21
26
  }
22
27
 
28
+ function findBinaryInPath() {
29
+ const pathDirs = (process.env.PATH || '').split(':');
30
+ const ext = platform() === 'win32' ? '.exe' : '';
31
+ const currentScript = fileURLToPath(import.meta.url);
32
+
33
+ for (const dir of pathDirs) {
34
+ const binPath = resolve(dir, `${BIN_NAME}${ext}`);
35
+ if (existsSync(binPath)) {
36
+ try {
37
+ const stat = statSync(binPath);
38
+ if (stat.isFile() && binPath !== currentScript) {
39
+ const result = spawnSync('file', [binPath], { encoding: 'utf8' });
40
+ if (!result.stdout.includes('script text')) {
41
+ return binPath;
42
+ }
43
+ }
44
+ } catch (err) {}
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+
23
50
  function getPlatformInfo() {
24
51
  const platformMap = {
25
52
  darwin: 'darwin',
@@ -43,9 +70,11 @@ function getPlatformInfo() {
43
70
  return { os, arch: architecture, ext };
44
71
  }
45
72
 
46
- function download(url, dest) {
73
+ function downloadWithProgress(url, dest) {
47
74
  return new Promise((resolve, reject) => {
48
75
  const file = createWriteStream(dest);
76
+ let totalBytes = 0;
77
+ let downloadedBytes = 0;
49
78
 
50
79
  function handleRedirect(response) {
51
80
  if (
@@ -55,9 +84,27 @@ function download(url, dest) {
55
84
  ) {
56
85
  get(response.headers.location, handleRedirect);
57
86
  } else if (response.statusCode === 200) {
87
+ totalBytes = Number.parseInt(
88
+ response.headers['content-length'] || '0',
89
+ 10,
90
+ );
91
+
92
+ response.on('data', (chunk) => {
93
+ downloadedBytes += chunk.length;
94
+ if (totalBytes > 0) {
95
+ const percent = ((downloadedBytes / totalBytes) * 100).toFixed(1);
96
+ const downloadedMB = (downloadedBytes / 1024 / 1024).toFixed(1);
97
+ const totalMB = (totalBytes / 1024 / 1024).toFixed(1);
98
+ process.stdout.write(
99
+ `\rDownloading: ${percent}% (${downloadedMB}MB / ${totalMB}MB)`,
100
+ );
101
+ }
102
+ });
103
+
58
104
  response.pipe(file);
59
105
  file.on('finish', () => {
60
106
  file.close();
107
+ process.stdout.write('\n');
61
108
  resolve();
62
109
  });
63
110
  } else {
@@ -73,11 +120,6 @@ function download(url, dest) {
73
120
  }
74
121
 
75
122
  async function install() {
76
- if (isInWorkspace()) {
77
- console.log('Detected workspace environment, skipping install script.');
78
- return;
79
- }
80
-
81
123
  try {
82
124
  const { os, arch: architecture, ext } = getPlatformInfo();
83
125
  const asset = `${BIN_NAME}-${os}-${architecture}${ext}`;
@@ -85,26 +127,20 @@ async function install() {
85
127
 
86
128
  console.log(`Installing ${BIN_NAME} (${os}/${architecture})...`);
87
129
 
88
- // Determine install directory
89
130
  const userBin = resolve(homedir(), '.local', 'bin');
90
131
  mkdirSync(userBin, { recursive: true });
91
132
  const binPath = resolve(userBin, `${BIN_NAME}${ext}`);
92
133
 
93
- // Download
94
- console.log(`Downloading from ${url}...`);
95
- await download(url, binPath);
134
+ await downloadWithProgress(url, binPath);
96
135
 
97
- // Make executable
98
136
  chmodSync(binPath, 0o755);
99
137
 
100
- // Verify
101
138
  const result = spawnSync(binPath, ['--version'], { encoding: 'utf8' });
102
139
  if (result.status === 0) {
103
140
  console.log(`\n✓ ${BIN_NAME} installed successfully!`);
104
141
  console.log(`Version: ${result.stdout.trim()}`);
105
142
  console.log(`Location: ${binPath}`);
106
143
 
107
- // Check if in PATH
108
144
  const pathDirs = (process.env.PATH || '').split(':');
109
145
  if (!pathDirs.includes(userBin)) {
110
146
  console.log(`\n⚠️ Add ${userBin} to your PATH:`);
@@ -120,6 +156,7 @@ async function install() {
120
156
  }
121
157
 
122
158
  console.log(`\nRun: ${BIN_NAME} --help`);
159
+ return binPath;
123
160
  } catch (error) {
124
161
  console.error('Failed to install agi CLI:', error.message);
125
162
  console.error('\nPlease try installing manually:');
@@ -128,4 +165,35 @@ async function install() {
128
165
  }
129
166
  }
130
167
 
131
- install();
168
+ async function main() {
169
+ if (isInWorkspace()) {
170
+ console.log('Detected workspace environment, skipping install script.');
171
+ return;
172
+ }
173
+
174
+ const binaryPath = findBinaryInPath();
175
+
176
+ if (binaryPath) {
177
+ const child = spawn(binaryPath, process.argv.slice(2), {
178
+ stdio: 'inherit',
179
+ });
180
+
181
+ child.on('exit', (code) => {
182
+ process.exit(code || 0);
183
+ });
184
+ } else {
185
+ const installedPath = await install();
186
+
187
+ if (process.argv.length > 2) {
188
+ const child = spawn(installedPath, process.argv.slice(2), {
189
+ stdio: 'inherit',
190
+ });
191
+
192
+ child.on('exit', (code) => {
193
+ process.exit(code || 0);
194
+ });
195
+ }
196
+ }
197
+ }
198
+
199
+ main();