codecane 1.0.402 ā 1.0.404
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 +3 -3
- package/scripts/codebuff-wrapper.js +291 -27
- package/scripts/download-binary.js +0 -153
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codecane",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.404",
|
|
4
4
|
"description": "AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"scripts/codebuff-wrapper.js",
|
|
11
|
-
"scripts/download-binary.js",
|
|
12
11
|
"README.md"
|
|
13
12
|
],
|
|
14
13
|
"os": [
|
|
@@ -24,7 +23,8 @@
|
|
|
24
23
|
"node": ">=16"
|
|
25
24
|
},
|
|
26
25
|
"dependencies": {
|
|
27
|
-
"tar": "^6.2.0"
|
|
26
|
+
"tar": "^6.2.0",
|
|
27
|
+
"adm-zip": "^0.5.10"
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
@@ -4,44 +4,308 @@ const fs = require('fs')
|
|
|
4
4
|
const path = require('path')
|
|
5
5
|
const os = require('os')
|
|
6
6
|
const { spawn, execSync } = require('child_process')
|
|
7
|
+
const https = require('https')
|
|
8
|
+
const zlib = require('zlib')
|
|
9
|
+
const tar = require('tar')
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
// Configuration
|
|
12
|
+
const CONFIG = {
|
|
13
|
+
homeDir: os.homedir(),
|
|
14
|
+
configDir: path.join(os.homedir(), '.config', 'manicode'),
|
|
15
|
+
binaryName: process.platform === 'win32' ? 'codebuff.exe' : 'codebuff',
|
|
16
|
+
githubRepo: 'CodebuffAI/codebuff-community',
|
|
17
|
+
userAgent: 'codebuff-cli',
|
|
18
|
+
requestTimeout: 10000,
|
|
19
|
+
updateCheckTimeout: 5000,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
CONFIG.binaryPath = path.join(CONFIG.configDir, CONFIG.binaryName)
|
|
23
|
+
|
|
24
|
+
// Platform target mapping
|
|
25
|
+
const PLATFORM_TARGETS = {
|
|
26
|
+
'linux-x64': 'codebuff-linux-x64.tar.gz',
|
|
27
|
+
'linux-arm64': 'codebuff-linux-arm64.tar.gz',
|
|
28
|
+
'darwin-x64': 'codebuff-darwin-x64.tar.gz',
|
|
29
|
+
'darwin-arm64': 'codebuff-darwin-arm64.tar.gz',
|
|
30
|
+
'win32-x64': 'codebuff-win32-x64.zip',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Utility functions
|
|
34
|
+
function httpGet(url, options = {}) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const parsedUrl = new URL(url)
|
|
37
|
+
const reqOptions = {
|
|
38
|
+
hostname: parsedUrl.hostname,
|
|
39
|
+
path: parsedUrl.pathname + parsedUrl.search,
|
|
40
|
+
headers: {
|
|
41
|
+
'User-Agent': CONFIG.userAgent,
|
|
42
|
+
...options.headers,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
12
45
|
|
|
13
|
-
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
46
|
+
const req = https.get(reqOptions, (res) => {
|
|
47
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
48
|
+
return httpGet(res.headers.location, options)
|
|
49
|
+
.then(resolve)
|
|
50
|
+
.catch(reject)
|
|
51
|
+
}
|
|
52
|
+
resolve(res)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
req.on('error', reject)
|
|
56
|
+
|
|
57
|
+
const timeout = options.timeout || CONFIG.requestTimeout
|
|
58
|
+
req.setTimeout(timeout, () => {
|
|
59
|
+
req.destroy()
|
|
60
|
+
reject(new Error('Request timeout'))
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function getLatestVersion() {
|
|
17
66
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
67
|
+
const res = await httpGet(
|
|
68
|
+
`https://api.github.com/repos/${CONFIG.githubRepo}/releases/latest`
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
let data = ''
|
|
72
|
+
for await (const chunk of res) {
|
|
73
|
+
data += chunk
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const release = JSON.parse(data)
|
|
77
|
+
return release.tag_name?.replace(/^v/, '') || null
|
|
21
78
|
} catch (error) {
|
|
22
|
-
|
|
23
|
-
console.error('Please try running: npm install -g codebuff')
|
|
24
|
-
process.exit(1)
|
|
79
|
+
return null
|
|
25
80
|
}
|
|
26
81
|
}
|
|
27
82
|
|
|
28
|
-
|
|
29
|
-
if (
|
|
83
|
+
function getCurrentVersion() {
|
|
84
|
+
if (!fs.existsSync(CONFIG.binaryPath)) return null
|
|
85
|
+
|
|
30
86
|
try {
|
|
31
|
-
|
|
87
|
+
const result = execSync(`"${CONFIG.binaryPath}" --version`, {
|
|
88
|
+
encoding: 'utf-8',
|
|
89
|
+
stdio: 'pipe',
|
|
90
|
+
timeout: 1000,
|
|
91
|
+
})
|
|
92
|
+
return result.trim()
|
|
32
93
|
} catch (error) {
|
|
33
|
-
|
|
34
|
-
console.error('Please try running: npm install -g codebuff')
|
|
35
|
-
process.exit(1)
|
|
94
|
+
return null
|
|
36
95
|
}
|
|
37
96
|
}
|
|
38
97
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
98
|
+
function compareVersions(v1, v2) {
|
|
99
|
+
if (!v1 || !v2) return 0
|
|
100
|
+
|
|
101
|
+
const parts1 = v1.split('.').map(Number)
|
|
102
|
+
const parts2 = v2.split('.').map(Number)
|
|
103
|
+
|
|
104
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
105
|
+
const p1 = parts1[i] || 0
|
|
106
|
+
const p2 = parts2[i] || 0
|
|
107
|
+
|
|
108
|
+
if (p1 < p2) return -1
|
|
109
|
+
if (p1 > p2) return 1
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return 0
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function showProgress(downloaded, total) {
|
|
116
|
+
if (total > 0) {
|
|
117
|
+
const percentage = Math.round((downloaded / total) * 100)
|
|
118
|
+
process.stderr.write(`\r${percentage}%`)
|
|
119
|
+
} else {
|
|
120
|
+
const downloadedMB = (downloaded / 1024 / 1024).toFixed(1)
|
|
121
|
+
process.stderr.write(`\r${downloadedMB} MB`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function downloadBinary(version) {
|
|
126
|
+
const platformKey = `${process.platform}-${process.arch}`
|
|
127
|
+
const fileName = PLATFORM_TARGETS[platformKey]
|
|
128
|
+
|
|
129
|
+
if (!fileName) {
|
|
130
|
+
throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const downloadUrl = `https://github.com/${CONFIG.githubRepo}/releases/download/v${version}/${fileName}`
|
|
134
|
+
|
|
135
|
+
// Ensure config directory exists
|
|
136
|
+
fs.mkdirSync(CONFIG.configDir, { recursive: true })
|
|
137
|
+
|
|
138
|
+
console.log(`Downloading codebuff v${version}...`)
|
|
139
|
+
|
|
140
|
+
const res = await httpGet(downloadUrl)
|
|
141
|
+
|
|
142
|
+
if (res.statusCode !== 200) {
|
|
143
|
+
throw new Error(`Download failed: HTTP ${res.statusCode}`)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const totalSize = parseInt(res.headers['content-length'] || '0', 10)
|
|
147
|
+
let downloadedSize = 0
|
|
148
|
+
let lastProgressTime = Date.now()
|
|
149
|
+
|
|
150
|
+
const chunks = []
|
|
151
|
+
|
|
152
|
+
for await (const chunk of res) {
|
|
153
|
+
chunks.push(chunk)
|
|
154
|
+
downloadedSize += chunk.length
|
|
155
|
+
|
|
156
|
+
const now = Date.now()
|
|
157
|
+
if (now - lastProgressTime >= 100 || downloadedSize === totalSize) {
|
|
158
|
+
lastProgressTime = now
|
|
159
|
+
showProgress(downloadedSize, totalSize)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
process.stderr.write('\n')
|
|
164
|
+
console.log('Extracting...')
|
|
165
|
+
|
|
166
|
+
const buffer = Buffer.concat(chunks)
|
|
167
|
+
|
|
168
|
+
if (fileName.endsWith('.zip')) {
|
|
169
|
+
// Windows ZIP extraction
|
|
170
|
+
const AdmZip = require('adm-zip')
|
|
171
|
+
const zipPath = path.join(CONFIG.configDir, fileName)
|
|
172
|
+
|
|
173
|
+
fs.writeFileSync(zipPath, buffer)
|
|
174
|
+
|
|
175
|
+
const zip = new AdmZip(zipPath)
|
|
176
|
+
zip.extractAllTo(CONFIG.configDir, true)
|
|
177
|
+
|
|
178
|
+
fs.unlinkSync(zipPath)
|
|
179
|
+
} else {
|
|
180
|
+
// Unix tar.gz extraction
|
|
181
|
+
await new Promise((resolve, reject) => {
|
|
182
|
+
const gunzip = zlib.createGunzip()
|
|
183
|
+
const extract = tar.extract({ cwd: CONFIG.configDir })
|
|
184
|
+
|
|
185
|
+
gunzip.pipe(extract).on('finish', resolve).on('error', reject)
|
|
186
|
+
|
|
187
|
+
gunzip.end(buffer)
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Rename extracted binary to standard name
|
|
192
|
+
const extractedName = fileName.replace(/\.(tar\.gz|zip)$/, '')
|
|
193
|
+
const extractedPath = path.join(CONFIG.configDir, extractedName)
|
|
194
|
+
|
|
195
|
+
if (fs.existsSync(extractedPath)) {
|
|
196
|
+
if (process.platform !== 'win32') {
|
|
197
|
+
fs.chmodSync(extractedPath, 0o755)
|
|
198
|
+
}
|
|
199
|
+
fs.renameSync(extractedPath, CONFIG.binaryPath)
|
|
200
|
+
} else {
|
|
201
|
+
throw new Error(`Binary not found after extraction`)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function ensureBinaryExists() {
|
|
206
|
+
if (!fs.existsSync(CONFIG.binaryPath)) {
|
|
207
|
+
const version = await getLatestVersion()
|
|
208
|
+
if (!version) {
|
|
209
|
+
console.error('ā Failed to determine latest version')
|
|
210
|
+
console.error('Please check your internet connection and try again')
|
|
211
|
+
process.exit(1)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
await downloadBinary(version)
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error('ā Failed to download codebuff:', error.message)
|
|
218
|
+
console.error('Please try again later.')
|
|
219
|
+
process.exit(1)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Verify binary is executable (Unix only)
|
|
224
|
+
if (process.platform !== 'win32') {
|
|
225
|
+
try {
|
|
226
|
+
fs.accessSync(CONFIG.binaryPath, fs.constants.X_OK)
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error(`ā Binary is not executable: ${CONFIG.binaryPath}`)
|
|
229
|
+
console.error('Run: chmod +x', CONFIG.binaryPath)
|
|
230
|
+
process.exit(1)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function checkForUpdates(runningProcess, exitListener) {
|
|
236
|
+
try {
|
|
237
|
+
const currentVersion = getCurrentVersion()
|
|
238
|
+
if (!currentVersion) return
|
|
239
|
+
|
|
240
|
+
const latestVersion = await getLatestVersion()
|
|
241
|
+
if (!latestVersion) return
|
|
242
|
+
|
|
243
|
+
console.log(`Current version: ${currentVersion}`)
|
|
244
|
+
console.log(`Latest version: ${latestVersion}`)
|
|
245
|
+
|
|
246
|
+
if (compareVersions(currentVersion, latestVersion) < 0) {
|
|
247
|
+
process.stdout.write(`Updating...`)
|
|
248
|
+
|
|
249
|
+
// Remove the specific exit listener to prevent it from interfering with the update
|
|
250
|
+
runningProcess.removeListener('exit', exitListener)
|
|
251
|
+
|
|
252
|
+
// Kill the running process
|
|
253
|
+
runningProcess.kill('SIGTERM')
|
|
254
|
+
|
|
255
|
+
// Wait for the process to actually exit
|
|
256
|
+
await new Promise((resolve) => {
|
|
257
|
+
runningProcess.on('exit', resolve)
|
|
258
|
+
// Fallback timeout in case the process doesn't exit gracefully
|
|
259
|
+
setTimeout(() => {
|
|
260
|
+
if (!runningProcess.killed) {
|
|
261
|
+
runningProcess.kill('SIGKILL')
|
|
262
|
+
}
|
|
263
|
+
resolve()
|
|
264
|
+
}, 5000)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
await downloadBinary(latestVersion)
|
|
268
|
+
|
|
269
|
+
// Restart with new binary
|
|
270
|
+
const newChild = spawn(CONFIG.binaryPath, process.argv.slice(2), {
|
|
271
|
+
stdio: 'inherit',
|
|
272
|
+
cwd: process.cwd(),
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
newChild.on('exit', (code) => {
|
|
276
|
+
process.exit(code || 0)
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
} catch (error) {
|
|
280
|
+
// Silently ignore update check errors
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async function main() {
|
|
285
|
+
// Ensure binary exists
|
|
286
|
+
await ensureBinaryExists()
|
|
287
|
+
|
|
288
|
+
// Start codebuff
|
|
289
|
+
const child = spawn(CONFIG.binaryPath, process.argv.slice(2), {
|
|
290
|
+
stdio: 'inherit',
|
|
291
|
+
cwd: process.cwd(),
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
// Store reference to the exit listener so we can remove it during updates
|
|
295
|
+
const exitListener = (code) => {
|
|
296
|
+
process.exit(code || 0)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
child.on('exit', exitListener)
|
|
300
|
+
|
|
301
|
+
// Check for updates in background
|
|
302
|
+
setTimeout(() => {
|
|
303
|
+
checkForUpdates(child, exitListener)
|
|
304
|
+
}, 100)
|
|
305
|
+
}
|
|
44
306
|
|
|
45
|
-
|
|
46
|
-
|
|
307
|
+
// Run the main function
|
|
308
|
+
main().catch((error) => {
|
|
309
|
+
console.error('ā Unexpected error:', error.message)
|
|
310
|
+
process.exit(1)
|
|
47
311
|
})
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const https = require('https')
|
|
4
|
-
const fs = require('fs')
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const os = require('os')
|
|
7
|
-
const { platform, arch } = process
|
|
8
|
-
|
|
9
|
-
// Get version from package.json
|
|
10
|
-
const packageJsonPath = path.join(__dirname, '..', 'package.json')
|
|
11
|
-
let version
|
|
12
|
-
try {
|
|
13
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
14
|
-
version = packageJson.version
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error('ā Could not read package.json version')
|
|
17
|
-
process.exit(1)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const targets = {
|
|
21
|
-
'linux-x64': 'codebuff-linux-x64.tar.gz',
|
|
22
|
-
'linux-arm64': 'codebuff-linux-arm64.tar.gz',
|
|
23
|
-
'darwin-x64': 'codebuff-darwin-x64.tar.gz',
|
|
24
|
-
'darwin-arm64': 'codebuff-darwin-arm64.tar.gz',
|
|
25
|
-
'win32-x64': 'codebuff-win32-x64.zip'
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const key = `${platform}-${arch}`
|
|
29
|
-
const file = targets[key]
|
|
30
|
-
|
|
31
|
-
if (!file) {
|
|
32
|
-
console.error(`ā Unsupported platform: ${platform} ${arch}`)
|
|
33
|
-
console.error('Supported platforms:', Object.keys(targets).join(', '))
|
|
34
|
-
process.exit(1)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const url = `https://github.com/CodebuffAI/codebuff-community/releases/download/v${version}/${file}`
|
|
38
|
-
const homeDir = os.homedir()
|
|
39
|
-
const manicodeDir = path.join(homeDir, '.config', 'manicode')
|
|
40
|
-
const binaryName = platform === 'win32' ? 'codebuff.exe' : 'codebuff'
|
|
41
|
-
const binaryPath = path.join(manicodeDir, binaryName)
|
|
42
|
-
|
|
43
|
-
// Check if binary already exists
|
|
44
|
-
if (fs.existsSync(binaryPath)) {
|
|
45
|
-
console.log('ā
Binary already exists')
|
|
46
|
-
process.exit(0)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Create .config/manicode directory
|
|
50
|
-
fs.mkdirSync(manicodeDir, { recursive: true })
|
|
51
|
-
|
|
52
|
-
console.log(`ā¬ļø Downloading ${file} from GitHub releases...`)
|
|
53
|
-
console.log(`š Installing to: ${manicodeDir}`)
|
|
54
|
-
|
|
55
|
-
const request = https.get(url, (res) => {
|
|
56
|
-
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
57
|
-
// Follow redirect
|
|
58
|
-
return https.get(res.headers.location, handleResponse)
|
|
59
|
-
}
|
|
60
|
-
handleResponse(res)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
request.on('error', (err) => {
|
|
64
|
-
console.error(`ā Download failed: ${err.message}`)
|
|
65
|
-
process.exit(1)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
function handleResponse(res) {
|
|
69
|
-
if (res.statusCode !== 200) {
|
|
70
|
-
console.error(`ā Download failed: HTTP ${res.statusCode}`)
|
|
71
|
-
console.error(`URL: ${url}`)
|
|
72
|
-
process.exit(1)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const totalSize = parseInt(res.headers['content-length'] || '0', 10)
|
|
76
|
-
let downloadedSize = 0
|
|
77
|
-
let lastProgressTime = Date.now()
|
|
78
|
-
|
|
79
|
-
// Show progress for downloads
|
|
80
|
-
const showProgress = (downloaded, total) => {
|
|
81
|
-
const now = Date.now()
|
|
82
|
-
// Update progress every 100ms to avoid too frequent updates
|
|
83
|
-
if (now - lastProgressTime < 100 && downloaded < total) return
|
|
84
|
-
lastProgressTime = now
|
|
85
|
-
|
|
86
|
-
if (total > 0) {
|
|
87
|
-
const percentage = Math.round((downloaded / total) * 100)
|
|
88
|
-
const downloadedMB = (downloaded / 1024 / 1024).toFixed(1)
|
|
89
|
-
const totalMB = (total / 1024 / 1024).toFixed(1)
|
|
90
|
-
process.stderr.write(`\rš„ Downloaded ${downloadedMB}MB / ${totalMB}MB (${percentage}%)`)
|
|
91
|
-
} else {
|
|
92
|
-
const downloadedMB = (downloaded / 1024 / 1024).toFixed(1)
|
|
93
|
-
process.stderr.write(`\rš„ Downloaded ${downloadedMB}MB`)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
res.on('data', (chunk) => {
|
|
98
|
-
downloadedSize += chunk.length
|
|
99
|
-
showProgress(downloadedSize, totalSize)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
if (file.endsWith('.zip')) {
|
|
103
|
-
// Handle zip files (Windows)
|
|
104
|
-
const zipPath = path.join(manicodeDir, file)
|
|
105
|
-
const writeStream = fs.createWriteStream(zipPath)
|
|
106
|
-
|
|
107
|
-
res.pipe(writeStream)
|
|
108
|
-
|
|
109
|
-
writeStream.on('finish', () => {
|
|
110
|
-
process.stderr.write('\n') // New line after progress
|
|
111
|
-
console.log('š¦ Extracting...')
|
|
112
|
-
// Extract zip file
|
|
113
|
-
const { execSync } = require('child_process')
|
|
114
|
-
try {
|
|
115
|
-
execSync(`cd "${manicodeDir}" && unzip -o "${file}"`, { stdio: 'inherit' })
|
|
116
|
-
fs.unlinkSync(zipPath) // Clean up zip file
|
|
117
|
-
console.log('ā
codebuff installed successfully!')
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error('ā Failed to extract zip:', error.message)
|
|
120
|
-
process.exit(1)
|
|
121
|
-
}
|
|
122
|
-
})
|
|
123
|
-
} else {
|
|
124
|
-
// Handle tar.gz files (Unix)
|
|
125
|
-
const zlib = require('zlib')
|
|
126
|
-
const tar = require('tar')
|
|
127
|
-
|
|
128
|
-
res.pipe(zlib.createGunzip())
|
|
129
|
-
.pipe(tar.extract({ cwd: manicodeDir }))
|
|
130
|
-
.on('finish', () => {
|
|
131
|
-
process.stderr.write('\n') // New line after progress
|
|
132
|
-
// The extracted binary will have the platform/arch in the name
|
|
133
|
-
const extractedBinaryName = file.replace('.tar.gz', '').replace('.zip', '')
|
|
134
|
-
const finalBinaryName = platform === 'win32' ? 'codebuff.exe' : 'codebuff'
|
|
135
|
-
const extractedBinaryPath = path.join(manicodeDir, extractedBinaryName)
|
|
136
|
-
const finalBinaryPath = path.join(manicodeDir, finalBinaryName)
|
|
137
|
-
|
|
138
|
-
if (fs.existsSync(extractedBinaryPath)) {
|
|
139
|
-
fs.chmodSync(extractedBinaryPath, 0o755)
|
|
140
|
-
// Rename to the standard name
|
|
141
|
-
fs.renameSync(extractedBinaryPath, finalBinaryPath)
|
|
142
|
-
console.log('ā
codebuff installed successfully!')
|
|
143
|
-
} else {
|
|
144
|
-
console.error(`ā Binary not found at ${extractedBinaryPath}`)
|
|
145
|
-
process.exit(1)
|
|
146
|
-
}
|
|
147
|
-
})
|
|
148
|
-
.on('error', (err) => {
|
|
149
|
-
console.error(`ā Extraction failed: ${err.message}`)
|
|
150
|
-
process.exit(1)
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
}
|