forgecode 1.9.0 โ 1.10.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/android/arm64/forge-aarch64-linux-android +0 -0
- package/bin/darwin/arm64/forge-aarch64-apple-darwin +0 -0
- package/bin/darwin/x64/forge-x86_64-apple-darwin +0 -0
- package/bin/linux/arm64/forge-aarch64-unknown-linux-gnu +0 -0
- package/bin/linux/arm64/forge-aarch64-unknown-linux-musl +0 -0
- package/bin/linux/x64/forge-x86_64-unknown-linux-gnu +0 -0
- package/bin/linux/x64/forge-x86_64-unknown-linux-musl +0 -0
- package/bin/win32/arm64/forge-aarch64-pc-windows-msvc.exe +0 -0
- package/bin/win32/x64/forge-x86_64-pc-windows-msvc.exe +0 -0
- package/forge.js +189 -29
- package/install.js +20 -365
- package/package.json +9 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/forge.js
CHANGED
|
@@ -1,44 +1,204 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { join } = require('path');
|
|
4
|
-
const { spawn } = require('child_process');
|
|
4
|
+
const { spawn, spawnSync } = require('child_process');
|
|
5
5
|
const { existsSync } = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const { platform, arch } = process;
|
|
6
8
|
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Function to check if running on Android
|
|
10
|
+
function isAndroid() {
|
|
11
|
+
try {
|
|
12
|
+
// Check for Android-specific system properties
|
|
13
|
+
const result = spawnSync('getprop', ['ro.build.version.release'], { encoding: 'utf8' });
|
|
14
|
+
if (result.status === 0 && result.stdout) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {
|
|
18
|
+
// getprop command not available, probably not Android
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check for Termux environment
|
|
22
|
+
if (process.env.PREFIX && process.env.PREFIX.includes('com.termux')) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Check for Android-specific environment variables
|
|
27
|
+
if (process.env.ANDROID_ROOT || process.env.ANDROID_DATA) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Check for Android-specific system properties
|
|
32
|
+
if (existsSync('/system/build.prop')) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Function to get the glibc version on Linux
|
|
40
|
+
function getGlibcVersion() {
|
|
41
|
+
try {
|
|
42
|
+
// Using ldd to get version info (common on most Linux distros)
|
|
43
|
+
const lddOutput =
|
|
44
|
+
spawnSync('ldd', ['--version'], { encoding: 'utf8' }).stderr.toString() ||
|
|
45
|
+
spawnSync('ldd', ['--version'], { encoding: 'utf8' }).stdout.toString();
|
|
46
|
+
|
|
47
|
+
// Check if this is musl libc
|
|
48
|
+
if (lddOutput.toLowerCase().includes('musl')) {
|
|
49
|
+
return { type: 'musl', version: null };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Extract glibc version using regex
|
|
53
|
+
const versionMatch = /\b(\d+\.\d+)\b/.exec(lddOutput);
|
|
54
|
+
if (versionMatch && versionMatch[1]) {
|
|
55
|
+
return { type: 'gnu', version: versionMatch[1] };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Alternative method using GNU-specific getconf
|
|
59
|
+
try {
|
|
60
|
+
const getconfOutput = spawnSync('getconf', ['GNU_LIBC_VERSION'], {
|
|
61
|
+
encoding: 'utf8',
|
|
62
|
+
}).stdout.toString();
|
|
63
|
+
const getconfMatch = /\b(\d+\.\d+)\b/.exec(getconfOutput);
|
|
64
|
+
if (getconfMatch && getconfMatch[1]) {
|
|
65
|
+
return { type: 'gnu', version: getconfMatch[1] };
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
// Ignore error if getconf is not available
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// If we got here, we couldn't get the specific version
|
|
72
|
+
return { type: 'gnu', version: null };
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return { type: 'unknown', version: null };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Check if the glibc version is sufficient for our binary
|
|
79
|
+
function isGlibcVersionSufficient(version) {
|
|
80
|
+
if (!version) return false;
|
|
81
|
+
|
|
82
|
+
// Our binary requires 2.32 or higher
|
|
83
|
+
const requiredVersion = 2.32;
|
|
84
|
+
const currentVersion = parseFloat(version);
|
|
85
|
+
|
|
86
|
+
return currentVersion >= requiredVersion;
|
|
87
|
+
}
|
|
11
88
|
|
|
12
|
-
//
|
|
13
|
-
|
|
89
|
+
// Enhanced libc detection for Linux
|
|
90
|
+
function detectLibcType() {
|
|
91
|
+
if (platform !== 'linux') {
|
|
92
|
+
return null; // Not relevant for non-Linux platforms
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const libcInfo = getGlibcVersion();
|
|
14
96
|
|
|
15
|
-
//
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
97
|
+
// If it's musl, or if it's an older glibc version, prefer musl
|
|
98
|
+
if (
|
|
99
|
+
libcInfo.type === 'musl' ||
|
|
100
|
+
(libcInfo.type === 'gnu' && !isGlibcVersionSufficient(libcInfo.version))
|
|
101
|
+
) {
|
|
102
|
+
return 'musl';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return 'gnu';
|
|
21
106
|
}
|
|
22
107
|
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
|
|
108
|
+
// Map of supported platforms and architectures to binary names
|
|
109
|
+
const PLATFORMS = {
|
|
110
|
+
darwin: {
|
|
111
|
+
x64: 'forge-x86_64-apple-darwin',
|
|
112
|
+
arm64: 'forge-aarch64-apple-darwin',
|
|
113
|
+
},
|
|
114
|
+
linux: {
|
|
115
|
+
x64: {
|
|
116
|
+
gnu: 'forge-x86_64-unknown-linux-gnu',
|
|
117
|
+
musl: 'forge-x86_64-unknown-linux-musl',
|
|
118
|
+
},
|
|
119
|
+
arm64: {
|
|
120
|
+
gnu: 'forge-aarch64-unknown-linux-gnu',
|
|
121
|
+
musl: 'forge-aarch64-unknown-linux-musl',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
win32: {
|
|
125
|
+
x64: 'forge-x86_64-pc-windows-msvc.exe',
|
|
126
|
+
arm64: 'forge-aarch64-pc-windows-msvc.exe',
|
|
127
|
+
},
|
|
128
|
+
android: {
|
|
129
|
+
arm64: 'forge-aarch64-linux-android',
|
|
130
|
+
}
|
|
26
131
|
};
|
|
27
132
|
|
|
28
|
-
//
|
|
29
|
-
|
|
133
|
+
// Helper function to construct binary path
|
|
134
|
+
function buildBinaryPath(platformDir, archDir, binaryName) {
|
|
135
|
+
return join(__dirname, 'bin', platformDir, archDir, binaryName);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Determine the path to the correct binary
|
|
139
|
+
function getBinaryPath() {
|
|
140
|
+
// Check for override
|
|
141
|
+
if (process.env.FORGE_BINARY_PATH) {
|
|
142
|
+
return process.env.FORGE_BINARY_PATH;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Detect actual platform (override for Android)
|
|
146
|
+
const isAndroidEnv = platform === 'linux' && isAndroid();
|
|
147
|
+
const actualPlatform = isAndroidEnv ? 'android' : platform;
|
|
148
|
+
|
|
149
|
+
// Handle Android
|
|
150
|
+
if (actualPlatform === 'android') {
|
|
151
|
+
const binaryName = PLATFORMS.android?.[arch];
|
|
152
|
+
return binaryName ? buildBinaryPath('android', arch, binaryName) : null;
|
|
153
|
+
}
|
|
30
154
|
|
|
31
|
-
// Handle
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
155
|
+
// Handle Linux with libc detection
|
|
156
|
+
if (platform === 'linux') {
|
|
157
|
+
const forceMusl = process.env.FORCE_MUSL === '1';
|
|
158
|
+
const libcType = forceMusl ? 'musl' : (detectLibcType() || 'gnu');
|
|
159
|
+
const binaryName = PLATFORMS.linux?.[arch]?.[libcType];
|
|
160
|
+
return binaryName ? buildBinaryPath(platform, arch, binaryName) : null;
|
|
36
161
|
}
|
|
37
|
-
});
|
|
38
162
|
|
|
39
|
-
// Handle
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
163
|
+
// Handle macOS and Windows
|
|
164
|
+
const binaryName = PLATFORMS[actualPlatform]?.[arch];
|
|
165
|
+
return binaryName ? buildBinaryPath(actualPlatform, arch, binaryName) : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Export for testing
|
|
169
|
+
module.exports = { getBinaryPath };
|
|
170
|
+
|
|
171
|
+
/* istanbul ignore next */
|
|
172
|
+
// Only run if not being required as a module (i.e., being executed directly)
|
|
173
|
+
if (require.main === module) {
|
|
174
|
+
const forgeBinaryPath = getBinaryPath();
|
|
175
|
+
|
|
176
|
+
// Check if the binary exists
|
|
177
|
+
if (!forgeBinaryPath || !existsSync(forgeBinaryPath)) {
|
|
178
|
+
console.error(`โ Forge binary not found for platform: ${platform} (${arch})`);
|
|
179
|
+
console.error('Please check if your system is supported.');
|
|
180
|
+
process.exit(1);
|
|
43
181
|
}
|
|
44
|
-
|
|
182
|
+
|
|
183
|
+
// Configure spawn options
|
|
184
|
+
const spawnOptions = {
|
|
185
|
+
stdio: 'inherit',
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// Spawn the forge process
|
|
189
|
+
const forgeProcess = spawn(forgeBinaryPath, process.argv.slice(2), spawnOptions);
|
|
190
|
+
|
|
191
|
+
// Handle SIGINT (Ctrl+C) based on platform
|
|
192
|
+
process.on('SIGINT', () => {
|
|
193
|
+
if (process.platform !== 'win32') {
|
|
194
|
+
forgeProcess.kill('SIGINT');
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Handle process exit
|
|
199
|
+
forgeProcess.on('exit', code => {
|
|
200
|
+
if (code !== null) {
|
|
201
|
+
process.exit(code);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
package/install.js
CHANGED
|
@@ -1,378 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { platform, arch } = process;
|
|
4
|
-
const { join } = require('path');
|
|
5
|
-
const { chmodSync, copyFileSync, existsSync } = require('fs');
|
|
6
|
-
const { spawnSync } = require('child_process');
|
|
7
|
-
const os = require('os');
|
|
8
4
|
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Check for Android-specific system properties
|
|
13
|
-
const result = spawnSync('getprop', ['ro.build.version.release'], { encoding: 'utf8' });
|
|
14
|
-
if (result.status === 0 && result.stdout) {
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
} catch (e) {
|
|
18
|
-
// getprop command not available, probably not Android
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Check for Termux environment
|
|
22
|
-
if (process.env.PREFIX && process.env.PREFIX.includes('com.termux')) {
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Function to get the glibc version on Linux
|
|
30
|
-
function getGlibcVersion() {
|
|
31
|
-
try {
|
|
32
|
-
// Using ldd to get version info (common on most Linux distros)
|
|
33
|
-
const lddOutput =
|
|
34
|
-
spawnSync('ldd', ['--version'], { encoding: 'utf8' }).stderr.toString() ||
|
|
35
|
-
spawnSync('ldd', ['--version'], { encoding: 'utf8' }).stdout.toString();
|
|
36
|
-
|
|
37
|
-
// Check if this is musl libc
|
|
38
|
-
if (lddOutput.toLowerCase().includes('musl')) {
|
|
39
|
-
return { type: 'musl', version: null };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Extract glibc version using regex
|
|
43
|
-
const versionMatch = /\b(\d+\.\d+)\b/.exec(lddOutput);
|
|
44
|
-
if (versionMatch && versionMatch[1]) {
|
|
45
|
-
return { type: 'gnu', version: versionMatch[1] };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Alternative method using GNU-specific getconf
|
|
49
|
-
try {
|
|
50
|
-
const getconfOutput = spawnSync('getconf', ['GNU_LIBC_VERSION'], {
|
|
51
|
-
encoding: 'utf8',
|
|
52
|
-
}).stdout.toString();
|
|
53
|
-
const getconfMatch = /\b(\d+\.\d+)\b/.exec(getconfOutput);
|
|
54
|
-
if (getconfMatch && getconfMatch[1]) {
|
|
55
|
-
return { type: 'gnu', version: getconfMatch[1] };
|
|
56
|
-
}
|
|
57
|
-
} catch (e) {
|
|
58
|
-
// Ignore error if getconf is not available
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// If we got here, we couldn't get the specific version
|
|
62
|
-
return { type: 'gnu', version: null };
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.warn('Warning: Could not detect libc version details.');
|
|
65
|
-
return { type: 'unknown', version: null };
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Check if the glibc version is sufficient for our binary
|
|
70
|
-
function isGlibcVersionSufficient(version) {
|
|
71
|
-
if (!version) return false;
|
|
72
|
-
|
|
73
|
-
// Our binary requires 2.32 or higher based on the error message
|
|
74
|
-
const requiredVersion = 2.32;
|
|
75
|
-
const currentVersion = parseFloat(version);
|
|
76
|
-
|
|
77
|
-
return currentVersion >= requiredVersion;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Enhanced libc detection for Linux
|
|
81
|
-
function detectLibcType() {
|
|
82
|
-
if (platform !== 'linux') {
|
|
83
|
-
return null; // Not relevant for non-Linux platforms
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const libcInfo = getGlibcVersion();
|
|
87
|
-
console.log(
|
|
88
|
-
`๐ Detected libc: ${libcInfo.type}${libcInfo.version ? ` version ${libcInfo.version}` : ''}`
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// If it's musl, or if it's an older glibc version, prefer musl
|
|
92
|
-
if (
|
|
93
|
-
libcInfo.type === 'musl' ||
|
|
94
|
-
(libcInfo.type === 'gnu' && !isGlibcVersionSufficient(libcInfo.version))
|
|
95
|
-
) {
|
|
96
|
-
return 'musl';
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return 'gnu';
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Test if a binary will run on this system
|
|
103
|
-
function testBinary(binaryPath) {
|
|
104
|
-
try {
|
|
105
|
-
const result = spawnSync(binaryPath, ['--version'], {
|
|
106
|
-
encoding: 'utf8',
|
|
107
|
-
timeout: 5000, // 5 second timeout
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Check if execution was successful (return code 0)
|
|
111
|
-
if (result.status === 0) {
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Check specific errors that indicate glibc version problems
|
|
116
|
-
if (result.stderr && result.stderr.includes('GLIBC_')) {
|
|
117
|
-
console.warn(`โ ๏ธ Binary compatibility issue: ${result.stderr.split('\n')[0]}`);
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return false;
|
|
122
|
-
} catch (error) {
|
|
123
|
-
console.warn(`โ ๏ธ Binary test failed: ${error.message}`);
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Detect if running on Android (Termux or similar)
|
|
129
|
-
function isAndroid() {
|
|
130
|
-
try {
|
|
131
|
-
// Check for Android-specific environment variables
|
|
132
|
-
if (process.env.ANDROID_ROOT || process.env.ANDROID_DATA) {
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Check if running in Termux
|
|
137
|
-
if (process.env.PREFIX && process.env.PREFIX.includes('com.termux')) {
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Check for Android-specific system properties
|
|
142
|
-
const { existsSync } = require('fs');
|
|
143
|
-
if (existsSync('/system/build.prop')) {
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return false;
|
|
148
|
-
} catch (error) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
5
|
+
// Note: This script only performs a basic compatibility check.
|
|
6
|
+
// All platform/architecture detection happens at runtime in forge.js
|
|
7
|
+
// to avoid permission issues during npm install.
|
|
152
8
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
},
|
|
159
|
-
linux: {
|
|
160
|
-
x64: {
|
|
161
|
-
gnu: 'forge-x86_64-unknown-linux-gnu',
|
|
162
|
-
musl: 'forge-x86_64-unknown-linux-musl',
|
|
163
|
-
},
|
|
164
|
-
arm64: {
|
|
165
|
-
gnu: 'forge-aarch64-unknown-linux-gnu',
|
|
166
|
-
musl: 'forge-aarch64-unknown-linux-musl',
|
|
167
|
-
android: 'forge-aarch64-linux-android',
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
win32: {
|
|
171
|
-
x64: 'forge-x86_64-pc-windows-msvc.exe',
|
|
172
|
-
arm64: 'forge-aarch64-pc-windows-msvc.exe',
|
|
173
|
-
},
|
|
174
|
-
android: {
|
|
175
|
-
arm64: 'forge-aarch64-linux-android',
|
|
176
|
-
}
|
|
9
|
+
const SUPPORTED_PLATFORMS = {
|
|
10
|
+
darwin: ['x64', 'arm64'],
|
|
11
|
+
linux: ['x64', 'arm64'],
|
|
12
|
+
win32: ['x64', 'arm64'],
|
|
13
|
+
android: ['arm64']
|
|
177
14
|
};
|
|
178
15
|
|
|
179
|
-
// Platform-specific binary extension
|
|
180
|
-
function getBinaryExtension() {
|
|
181
|
-
return platform === 'win32' ? '.exe' : '';
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Print available platform information for debugging
|
|
185
|
-
function printPlatformInfo() {
|
|
186
|
-
console.log('System Information:');
|
|
187
|
-
console.log(` - Platform: ${platform}`);
|
|
188
|
-
console.log(` - Architecture: ${arch}`);
|
|
189
|
-
console.log(` - Node.js: ${process.version}`);
|
|
190
|
-
console.log(` - OS: ${os.type()} ${os.release()}`);
|
|
191
|
-
|
|
192
|
-
if (platform === 'linux') {
|
|
193
|
-
if (isAndroid()) {
|
|
194
|
-
console.log(` - Environment: Android`);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const libcInfo = getGlibcVersion();
|
|
198
|
-
console.log(
|
|
199
|
-
` - Libc: ${libcInfo.type}${libcInfo.version ? ` version ${libcInfo.version}` : ''}`
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
try {
|
|
203
|
-
const distroInfo = spawnSync('cat', ['/etc/os-release'], {
|
|
204
|
-
encoding: 'utf8',
|
|
205
|
-
}).stdout.toString();
|
|
206
|
-
const distroName = /PRETTY_NAME="([^"]+)"/.exec(distroInfo);
|
|
207
|
-
if (distroName && distroName[1]) {
|
|
208
|
-
console.log(` - Distribution: ${distroName[1]}`);
|
|
209
|
-
}
|
|
210
|
-
} catch (e) {
|
|
211
|
-
// Ignore if we can't get distribution info
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Install binary based on platform and architecture
|
|
217
16
|
function install() {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Check if platform is supported
|
|
228
|
-
if (!PLATFORMS[actualPlatform]) {
|
|
229
|
-
console.error(`โ Unsupported platform: ${actualPlatform}`);
|
|
230
|
-
console.error('Supported platforms: macOS, Linux, Windows, Android');
|
|
231
|
-
process.exit(1);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Check if architecture is supported
|
|
235
|
-
if (!PLATFORMS[actualPlatform][arch]) {
|
|
236
|
-
console.error(`โ Unsupported architecture: ${arch} for platform ${actualPlatform}`);
|
|
237
|
-
console.error(
|
|
238
|
-
`Supported architectures for ${actualPlatform}: ${Object.keys(PLATFORMS[actualPlatform]).join(', ')}`
|
|
239
|
-
);
|
|
240
|
-
process.exit(1);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
let binaryName;
|
|
244
|
-
let binaryPath;
|
|
245
|
-
const targetPath = join(__dirname, 'forge' + getBinaryExtension());
|
|
246
|
-
|
|
247
|
-
// Handle platform-specific binary selection
|
|
248
|
-
if (actualPlatform === 'android') {
|
|
249
|
-
// Android: simple case, just one binary per arch
|
|
250
|
-
binaryName = PLATFORMS[actualPlatform][arch];
|
|
251
|
-
binaryPath = join(__dirname, 'bin', actualPlatform, arch, binaryName);
|
|
252
|
-
} else if (platform === 'linux') {
|
|
253
|
-
// Linux: handle libc type detection
|
|
254
|
-
// Check if running on Android first
|
|
255
|
-
if (isAndroid() && arch === 'arm64' && PLATFORMS[platform][arch]['android']) {
|
|
256
|
-
console.log('๐ค Android platform detected');
|
|
257
|
-
binaryName = PLATFORMS[platform][arch]['android'];
|
|
258
|
-
// Android binaries are stored in darwin/arm64 directory as per update-package.sh
|
|
259
|
-
binaryPath = join(__dirname, 'bin', 'darwin', 'arm64', binaryName);
|
|
260
|
-
} else {
|
|
261
|
-
let libcType = detectLibcType();
|
|
262
|
-
|
|
263
|
-
// Always try musl first if available (it's more portable)
|
|
264
|
-
const muslBinaryName = PLATFORMS[platform][arch]['musl'];
|
|
265
|
-
const muslBinaryPath = join(__dirname, 'bin', platform, arch, muslBinaryName);
|
|
266
|
-
|
|
267
|
-
// Check if musl binary exists
|
|
268
|
-
if (existsSync(muslBinaryPath)) {
|
|
269
|
-
console.log('๐ฆ Found musl binary, which should work on most Linux systems');
|
|
270
|
-
binaryName = muslBinaryName;
|
|
271
|
-
binaryPath = muslBinaryPath;
|
|
272
|
-
}
|
|
273
|
-
// Fall back to detected libc type
|
|
274
|
-
else {
|
|
275
|
-
// Check if the detected libc type is supported in our binaries
|
|
276
|
-
if (!PLATFORMS[platform][arch][libcType]) {
|
|
277
|
-
// If not supported, try the alternative
|
|
278
|
-
libcType = libcType === 'gnu' ? 'musl' : 'gnu';
|
|
279
|
-
console.warn(`โ ๏ธ Detected libc type is not supported, trying ${libcType} instead`);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
binaryName = PLATFORMS[platform][arch][libcType];
|
|
283
|
-
binaryPath = join(__dirname, 'bin', platform, arch, binaryName);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// If binary doesn't exist, try the alternative
|
|
287
|
-
if (!existsSync(binaryPath)) {
|
|
288
|
-
const alternativeLibc = libcType === 'gnu' ? 'musl' : 'gnu';
|
|
289
|
-
const alternativeBinaryName = PLATFORMS[platform][arch][alternativeLibc];
|
|
290
|
-
const alternativeBinaryPath = join(__dirname, 'bin', platform, arch, alternativeBinaryName);
|
|
291
|
-
|
|
292
|
-
if (existsSync(alternativeBinaryPath)) {
|
|
293
|
-
console.warn(`โ ๏ธ Binary for ${libcType} not found, trying ${alternativeLibc} instead`);
|
|
294
|
-
binaryName = alternativeBinaryName;
|
|
295
|
-
binaryPath = alternativeBinaryPath;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
17
|
+
console.log(`๐ฆ Installing forge for ${platform}/${arch}...`);
|
|
18
|
+
|
|
19
|
+
// Basic platform check
|
|
20
|
+
if (!SUPPORTED_PLATFORMS[platform]) {
|
|
21
|
+
console.warn(`โ ๏ธ Warning: Platform '${platform}' might not be supported.`);
|
|
22
|
+
console.warn('Supported platforms: darwin, linux, win32');
|
|
23
|
+
} else if (!SUPPORTED_PLATFORMS[platform].includes(arch)) {
|
|
24
|
+
console.warn(`โ ๏ธ Warning: Architecture '${arch}' on '${platform}' might not be supported.`);
|
|
25
|
+
console.warn(`Supported architectures for ${platform}: ${SUPPORTED_PLATFORMS[platform].join(', ')}`);
|
|
299
26
|
} else {
|
|
300
|
-
|
|
301
|
-
binaryName = PLATFORMS[actualPlatform][arch];
|
|
302
|
-
binaryPath = join(__dirname, 'bin', actualPlatform, arch, binaryName);
|
|
27
|
+
console.log(`โ
System compatible: ${platform}/${arch}`);
|
|
303
28
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (!existsSync(binaryPath)) {
|
|
307
|
-
console.error(`โ Binary not found: ${binaryPath}`);
|
|
308
|
-
console.error(
|
|
309
|
-
'If this is a new architecture or platform, please check the repository for updates.'
|
|
310
|
-
);
|
|
311
|
-
process.exit(1);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
try {
|
|
315
|
-
// Copy binary to target location
|
|
316
|
-
copyFileSync(binaryPath, targetPath);
|
|
317
|
-
// Make binary executable (not needed on Windows)
|
|
318
|
-
if (platform !== 'win32') {
|
|
319
|
-
chmodSync(targetPath, '755');
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// For Linux, test if the binary will actually run
|
|
323
|
-
if (platform === 'linux') {
|
|
324
|
-
console.log('๐งช Testing binary compatibility...');
|
|
325
|
-
if (!testBinary(targetPath)) {
|
|
326
|
-
// If current binary fails and we haven't tried musl yet, try the musl version
|
|
327
|
-
if (binaryName.includes('-gnu')) {
|
|
328
|
-
const muslBinaryName = binaryName.replace('-gnu', '-musl');
|
|
329
|
-
const muslBinaryPath = join(__dirname, 'bin', platform, arch, muslBinaryName);
|
|
330
|
-
|
|
331
|
-
if (existsSync(muslBinaryPath)) {
|
|
332
|
-
console.log('๐ GNU binary not compatible, trying musl binary instead');
|
|
333
|
-
copyFileSync(muslBinaryPath, targetPath);
|
|
334
|
-
chmodSync(targetPath, '755');
|
|
335
|
-
|
|
336
|
-
if (!testBinary(targetPath)) {
|
|
337
|
-
console.error('โ Both GNU and musl binaries failed to run on this system.');
|
|
338
|
-
reportCompatibilityError();
|
|
339
|
-
process.exit(1);
|
|
340
|
-
}
|
|
341
|
-
} else {
|
|
342
|
-
console.error('โ GNU binary not compatible, and musl binary not available.');
|
|
343
|
-
reportCompatibilityError();
|
|
344
|
-
process.exit(1);
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
console.error('โ Binary compatibility test failed.');
|
|
348
|
-
reportCompatibilityError();
|
|
349
|
-
process.exit(1);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
console.log(`โ
Successfully installed forge for ${platform}/${arch}`);
|
|
355
|
-
} catch (error) {
|
|
356
|
-
console.error(`โ Error installing binary: ${error.message}`);
|
|
357
|
-
reportCompatibilityError();
|
|
358
|
-
process.exit(1);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
function reportCompatibilityError() {
|
|
363
|
-
console.error('\n๐ง Possible solutions:');
|
|
364
|
-
console.error('1. Try using the musl binary, which has fewer system dependencies:');
|
|
365
|
-
console.error(' - Set FORCE_MUSL=1 before installing');
|
|
366
|
-
console.error("2. Update your system's glibc to a newer version");
|
|
367
|
-
console.error('3. Contact support with the following information:');
|
|
368
|
-
printPlatformInfo();
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// Check for environment variable to force musl
|
|
372
|
-
if (process.env.FORCE_MUSL === '1' && platform === 'linux') {
|
|
373
|
-
console.log('๐ง FORCE_MUSL=1 environment variable detected, forcing musl binary');
|
|
374
|
-
process.env.FORCE_LIBC = 'musl';
|
|
29
|
+
|
|
30
|
+
console.log("โจ Forge installed successfully. Run 'forge' to start.");
|
|
375
31
|
}
|
|
376
32
|
|
|
377
|
-
// Run installation
|
|
378
33
|
install();
|
package/package.json
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forgecode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Code Forge CLI - an AI-powered coding assistant",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forge": "forge.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
-
"postinstall": "node install.js"
|
|
9
|
+
"postinstall": "node install.js",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"test:watch": "jest --watch",
|
|
12
|
+
"test:coverage": "jest --coverage"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@jest/globals": "^29.7.0",
|
|
16
|
+
"jest": "^29.7.0"
|
|
10
17
|
},
|
|
11
18
|
"repository": {
|
|
12
19
|
"type": "git",
|