ai-rulez 1.5.0 → 1.6.0
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/bin/ai-rulez +193 -0
- package/install.js +43 -2
- package/package.json +1 -1
package/bin/ai-rulez
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
|
|
7
|
+
// Path to the actual binary that install.js will create
|
|
8
|
+
// The binary has a different name to avoid conflict with this wrapper script
|
|
9
|
+
const BINARY_NAME = process.platform === 'win32' ? 'ai-rulez-bin.exe' : 'ai-rulez-bin';
|
|
10
|
+
const BINARY_PATH = path.join(__dirname, BINARY_NAME);
|
|
11
|
+
|
|
12
|
+
const REPO_URL = 'https://github.com/Goldziher/ai-rulez';
|
|
13
|
+
const ISSUES_URL = `${REPO_URL}/issues`;
|
|
14
|
+
|
|
15
|
+
function isNetworkError(error) {
|
|
16
|
+
const networkErrors = [
|
|
17
|
+
'ENOTFOUND', 'ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT',
|
|
18
|
+
'EHOSTUNREACH', 'ENETUNREACH', 'EADDRNOTAVAIL', 'ENETDOWN'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
return networkErrors.includes(error.code) ||
|
|
22
|
+
error.message.includes('network') ||
|
|
23
|
+
error.message.includes('fetch') ||
|
|
24
|
+
error.message.includes('download') ||
|
|
25
|
+
error.message.includes('timeout');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isPermissionError(error) {
|
|
29
|
+
return error.code === 'EACCES' ||
|
|
30
|
+
error.code === 'EPERM' ||
|
|
31
|
+
error.message.includes('permission') ||
|
|
32
|
+
error.message.includes('access denied');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function runInstallScript() {
|
|
36
|
+
console.error('⚡ ai-rulez binary not found. Installing...');
|
|
37
|
+
console.error(` Looking for: ${BINARY_PATH}`);
|
|
38
|
+
|
|
39
|
+
const installScript = path.join(__dirname, '..', 'install.js');
|
|
40
|
+
console.error(` Running install script: ${installScript}`);
|
|
41
|
+
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
let errorOutput = '';
|
|
44
|
+
|
|
45
|
+
const child = spawn('node', [installScript], {
|
|
46
|
+
stdio: ['inherit', 'inherit', 'pipe'],
|
|
47
|
+
cwd: path.dirname(installScript),
|
|
48
|
+
env: { ...process.env, AI_RULEZ_DEBUG: '1' }
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.stderr.on('data', (data) => {
|
|
52
|
+
process.stderr.write(data);
|
|
53
|
+
errorOutput += data.toString();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
child.on('exit', (code) => {
|
|
57
|
+
console.error(` Install script exited with code: ${code}`);
|
|
58
|
+
if (code === 0) {
|
|
59
|
+
resolve();
|
|
60
|
+
} else {
|
|
61
|
+
const error = new Error(`Install script failed with code ${code}`);
|
|
62
|
+
error.output = errorOutput;
|
|
63
|
+
reject(error);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
child.on('error', (err) => {
|
|
68
|
+
console.error(` Install script error: ${err.message}`);
|
|
69
|
+
reject(err);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function main() {
|
|
75
|
+
// Check if binary exists
|
|
76
|
+
if (!fs.existsSync(BINARY_PATH)) {
|
|
77
|
+
try {
|
|
78
|
+
// Run the install script if binary is missing
|
|
79
|
+
await runInstallScript();
|
|
80
|
+
|
|
81
|
+
console.error(` Checking if binary exists at: ${BINARY_PATH}`);
|
|
82
|
+
|
|
83
|
+
// Double-check that binary now exists
|
|
84
|
+
if (!fs.existsSync(BINARY_PATH)) {
|
|
85
|
+
console.error('\n❌ Error: Binary still not found after installation attempt');
|
|
86
|
+
console.error('\n🔧 This is unexpected. Please report this issue:');
|
|
87
|
+
console.error(` ${ISSUES_URL}`);
|
|
88
|
+
console.error('\nInclude your platform info:');
|
|
89
|
+
console.error(` Platform: ${process.platform}`);
|
|
90
|
+
console.error(` Architecture: ${process.arch}`);
|
|
91
|
+
console.error(` Node version: ${process.version}`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('\n❌ Installation failed');
|
|
96
|
+
|
|
97
|
+
if (isNetworkError(error)) {
|
|
98
|
+
console.error('\n🌐 Network Issue Detected');
|
|
99
|
+
console.error(' Unable to download ai-rulez binary from GitHub releases.');
|
|
100
|
+
console.error('\n Possible causes:');
|
|
101
|
+
console.error(' • No internet connection');
|
|
102
|
+
console.error(' • GitHub is temporarily unreachable');
|
|
103
|
+
console.error(' • Corporate firewall/proxy blocking GitHub');
|
|
104
|
+
console.error('\n Solutions:');
|
|
105
|
+
console.error(' 1. Check your internet connection');
|
|
106
|
+
console.error(' 2. Try again in a few moments');
|
|
107
|
+
console.error(' 3. If behind a proxy, configure npm proxy settings');
|
|
108
|
+
console.error(' 4. Download the binary manually from:');
|
|
109
|
+
console.error(` ${REPO_URL}/releases`);
|
|
110
|
+
} else if (isPermissionError(error)) {
|
|
111
|
+
console.error('\n🔒 Permission Denied');
|
|
112
|
+
console.error(` Cannot write to: ${path.dirname(BINARY_PATH)}`);
|
|
113
|
+
console.error('\n Solutions:');
|
|
114
|
+
console.error(' 1. Run with appropriate permissions');
|
|
115
|
+
console.error(' 2. Install globally with: npm install -g ai-rulez');
|
|
116
|
+
console.error(' 3. Check directory permissions');
|
|
117
|
+
} else {
|
|
118
|
+
console.error('\n⚠️ Unexpected Error');
|
|
119
|
+
console.error(` ${error.message}`);
|
|
120
|
+
if (error.output && error.output.trim()) {
|
|
121
|
+
console.error('\n Details:');
|
|
122
|
+
console.error(` ${error.output.trim().split('\n').join('\n ')}`);
|
|
123
|
+
}
|
|
124
|
+
console.error('\n This shouldn\'t happen. Please report this issue:');
|
|
125
|
+
console.error(` ${ISSUES_URL}`);
|
|
126
|
+
console.error('\n Include:');
|
|
127
|
+
console.error(' • The error message above');
|
|
128
|
+
console.error(` • Platform: ${process.platform}/${process.arch}`);
|
|
129
|
+
console.error(` • Node version: ${process.version}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Run the actual binary with all arguments
|
|
137
|
+
const proc = spawn(BINARY_PATH, process.argv.slice(2), {
|
|
138
|
+
stdio: 'inherit',
|
|
139
|
+
env: process.env
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
proc.on('exit', (code) => {
|
|
143
|
+
process.exit(code || 0);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
proc.on('error', (err) => {
|
|
147
|
+
console.error('\n❌ Failed to execute ai-rulez binary');
|
|
148
|
+
|
|
149
|
+
if (err.code === 'ENOENT') {
|
|
150
|
+
console.error('\n📁 File Not Found');
|
|
151
|
+
console.error(` Binary path: ${BINARY_PATH}`);
|
|
152
|
+
console.error('\n The file exists but cannot be executed.');
|
|
153
|
+
console.error(' Try reinstalling: npm install -g ai-rulez');
|
|
154
|
+
} else if (err.code === 'EACCES' || err.code === 'EPERM') {
|
|
155
|
+
console.error('\n🔒 Permission Denied');
|
|
156
|
+
console.error(` Binary path: ${BINARY_PATH}`);
|
|
157
|
+
console.error('\n The binary is not executable.');
|
|
158
|
+
console.error('\n Solutions:');
|
|
159
|
+
if (process.platform !== 'win32') {
|
|
160
|
+
console.error(` 1. Make it executable: chmod +x ${BINARY_PATH}`);
|
|
161
|
+
console.error(' 2. Reinstall: npm install -g ai-rulez');
|
|
162
|
+
} else {
|
|
163
|
+
console.error(' 1. Check file permissions in Windows');
|
|
164
|
+
console.error(' 2. Reinstall: npm install -g ai-rulez');
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
console.error('\n⚠️ Unexpected Execution Error');
|
|
168
|
+
console.error(` Error code: ${err.code}`);
|
|
169
|
+
console.error(` Message: ${err.message}`);
|
|
170
|
+
console.error('\n This shouldn\'t happen. Please report this issue:');
|
|
171
|
+
console.error(` ${ISSUES_URL}`);
|
|
172
|
+
console.error('\n Include:');
|
|
173
|
+
console.error(' • The error details above');
|
|
174
|
+
console.error(` • Platform: ${process.platform}/${process.arch}`);
|
|
175
|
+
console.error(` • Node version: ${process.version}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
process.exit(1);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
main().catch(err => {
|
|
183
|
+
console.error('\n❌ Unexpected error in wrapper script');
|
|
184
|
+
console.error(` ${err.message}`);
|
|
185
|
+
if (err.stack) {
|
|
186
|
+
console.error('\n Stack trace:');
|
|
187
|
+
console.error(` ${err.stack.split('\n').slice(1).join('\n ')}`);
|
|
188
|
+
}
|
|
189
|
+
console.error('\n This shouldn\'t happen. Please report this issue:');
|
|
190
|
+
console.error(` ${ISSUES_URL}`);
|
|
191
|
+
console.error('\n Include the full error output above.');
|
|
192
|
+
process.exit(1);
|
|
193
|
+
});
|
package/install.js
CHANGED
|
@@ -82,7 +82,8 @@ function getPlatform() {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function getBinaryName(platform) {
|
|
85
|
-
|
|
85
|
+
// Use a different name to avoid conflict with the wrapper script
|
|
86
|
+
return platform === 'windows' ? 'ai-rulez-bin.exe' : 'ai-rulez-bin';
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
async function downloadBinary(url, dest, retryCount = 0) {
|
|
@@ -242,7 +243,11 @@ async function extractArchive(archivePath, extractDir, platform) {
|
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
async function install() {
|
|
246
|
+
const DEBUG = process.env.AI_RULEZ_DEBUG === '1';
|
|
247
|
+
|
|
245
248
|
try {
|
|
249
|
+
if (DEBUG) console.error('[install.js] Starting installation');
|
|
250
|
+
|
|
246
251
|
// Check Node.js version compatibility
|
|
247
252
|
const nodeVersion = process.version;
|
|
248
253
|
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
|
|
@@ -254,6 +259,7 @@ async function install() {
|
|
|
254
259
|
const { os, arch } = getPlatform();
|
|
255
260
|
const binaryName = getBinaryName(os);
|
|
256
261
|
|
|
262
|
+
if (DEBUG) console.error(`[install.js] Platform: ${os}/${arch}, Binary name: ${binaryName}`);
|
|
257
263
|
|
|
258
264
|
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
259
265
|
const version = packageJson.version;
|
|
@@ -303,10 +309,35 @@ async function install() {
|
|
|
303
309
|
|
|
304
310
|
|
|
305
311
|
console.log('Extracting binary...');
|
|
306
|
-
await extractArchive(archivePath, binDir, os);
|
|
307
312
|
|
|
313
|
+
// Extract to a temp directory first to avoid overwriting the wrapper script
|
|
314
|
+
const tempExtractDir = path.join(__dirname, '.extract-temp');
|
|
315
|
+
if (fs.existsSync(tempExtractDir)) {
|
|
316
|
+
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
|
317
|
+
}
|
|
318
|
+
fs.mkdirSync(tempExtractDir, { recursive: true });
|
|
319
|
+
|
|
320
|
+
await extractArchive(archivePath, tempExtractDir, os);
|
|
308
321
|
|
|
322
|
+
// The archive contains 'ai-rulez' or 'ai-rulez.exe', but we need to rename it
|
|
323
|
+
// to avoid conflict with the wrapper script
|
|
324
|
+
const extractedName = os === 'windows' ? 'ai-rulez.exe' : 'ai-rulez';
|
|
325
|
+
const extractedPath = path.join(tempExtractDir, extractedName);
|
|
309
326
|
const binaryPath = path.join(binDir, binaryName);
|
|
327
|
+
|
|
328
|
+
// Move the extracted binary to the final location
|
|
329
|
+
if (fs.existsSync(extractedPath)) {
|
|
330
|
+
// Remove old binary if it exists
|
|
331
|
+
if (fs.existsSync(binaryPath)) {
|
|
332
|
+
fs.unlinkSync(binaryPath);
|
|
333
|
+
}
|
|
334
|
+
// Move binary from temp to final location
|
|
335
|
+
fs.renameSync(extractedPath, binaryPath);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Clean up temp directory
|
|
339
|
+
fs.rmSync(tempExtractDir, { recursive: true, force: true });
|
|
340
|
+
|
|
310
341
|
if (!fs.existsSync(binaryPath)) {
|
|
311
342
|
throw new Error(`Binary not found after extraction: ${binaryPath}`);
|
|
312
343
|
}
|
|
@@ -347,7 +378,17 @@ async function install() {
|
|
|
347
378
|
|
|
348
379
|
console.log(`✅ ai-rulez ${version} installed successfully for ${os}/${arch}!`);
|
|
349
380
|
|
|
381
|
+
if (DEBUG) {
|
|
382
|
+
console.error(`[install.js] Installation complete`);
|
|
383
|
+
console.error(`[install.js] Binary location: ${binaryPath}`);
|
|
384
|
+
console.error(`[install.js] Exiting with code 0`);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Explicitly exit with success code
|
|
388
|
+
process.exit(0);
|
|
389
|
+
|
|
350
390
|
} catch (error) {
|
|
391
|
+
if (DEBUG) console.error(`[install.js] Installation failed: ${error.message}`);
|
|
351
392
|
console.error('Failed to install ai-rulez binary:', error.message);
|
|
352
393
|
console.error('You can manually download the binary from:');
|
|
353
394
|
console.error(`https://github.com/${REPO_NAME}/releases`);
|
package/package.json
CHANGED