freebuff 0.0.98 → 0.0.100
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/index.js +175 -24
- package/package.json +5 -4
package/index.js
CHANGED
|
@@ -74,6 +74,14 @@ function shouldExitAlternateScreen(code, signal) {
|
|
|
74
74
|
return Boolean(signal) || isWindowsNativeCrashCode(code)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function isIllegalInstructionExit(code, signal) {
|
|
78
|
+
const unsignedCode = getUnsignedExitCode(code)
|
|
79
|
+
return (
|
|
80
|
+
signal === 'SIGILL' ||
|
|
81
|
+
(process.platform === 'win32' && unsignedCode === 0xC000001D)
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
77
85
|
function createConfig(packageName) {
|
|
78
86
|
const homeDir = os.homedir()
|
|
79
87
|
const configDir = path.join(homeDir, '.config', 'manicode')
|
|
@@ -164,10 +172,17 @@ function trackUpdateFailed(errorMessage, version, context = {}) {
|
|
|
164
172
|
|
|
165
173
|
const PLATFORM_TARGETS = {
|
|
166
174
|
'linux-x64': `${packageName}-linux-x64.tar.gz`,
|
|
175
|
+
'linux-x64-baseline': `${packageName}-linux-x64-baseline.tar.gz`,
|
|
167
176
|
'linux-arm64': `${packageName}-linux-arm64.tar.gz`,
|
|
168
177
|
'darwin-x64': `${packageName}-darwin-x64.tar.gz`,
|
|
169
178
|
'darwin-arm64': `${packageName}-darwin-arm64.tar.gz`,
|
|
170
179
|
'win32-x64': `${packageName}-win32-x64.tar.gz`,
|
|
180
|
+
'win32-x64-baseline': `${packageName}-win32-x64-baseline.tar.gz`,
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const BASELINE_FALLBACK_TARGETS = {
|
|
184
|
+
'linux-x64': 'linux-x64-baseline',
|
|
185
|
+
'win32-x64': 'win32-x64-baseline',
|
|
171
186
|
}
|
|
172
187
|
|
|
173
188
|
const term = {
|
|
@@ -186,6 +201,84 @@ const term = {
|
|
|
186
201
|
},
|
|
187
202
|
}
|
|
188
203
|
|
|
204
|
+
function getPlatformKey() {
|
|
205
|
+
return `${process.platform}-${process.arch}`
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function getTargetOverride() {
|
|
209
|
+
const envNames = [
|
|
210
|
+
`${packageName.toUpperCase()}_BINARY_TARGET`,
|
|
211
|
+
'CODEBUFF_BINARY_TARGET',
|
|
212
|
+
'CLI_BINARY_TARGET',
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
for (const envName of envNames) {
|
|
216
|
+
const target = process.env[envName]
|
|
217
|
+
if (target && PLATFORM_TARGETS[target]) {
|
|
218
|
+
return target
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return null
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function linuxCpuHasAvx2() {
|
|
226
|
+
if (process.platform !== 'linux' || process.arch !== 'x64') {
|
|
227
|
+
return true
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
return /\bavx2\b/i.test(fs.readFileSync('/proc/cpuinfo', 'utf8'))
|
|
232
|
+
} catch {
|
|
233
|
+
return true
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function getDefaultTargetKey() {
|
|
238
|
+
const override = getTargetOverride()
|
|
239
|
+
if (override) {
|
|
240
|
+
return override
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const platformKey = getPlatformKey()
|
|
244
|
+
if (platformKey === 'linux-x64' && !linuxCpuHasAvx2()) {
|
|
245
|
+
return 'linux-x64-baseline'
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return platformKey
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function getBaselineFallbackTargetKey() {
|
|
252
|
+
// Windows has no reliable plain-Node CPU feature check here, so we keep
|
|
253
|
+
// the fast x64 binary first and fall back after the native SIGILL code.
|
|
254
|
+
return BASELINE_FALLBACK_TARGETS[getPlatformKey()] || null
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function isTargetAllowedForThisMachine(target) {
|
|
258
|
+
const override = getTargetOverride()
|
|
259
|
+
if (override) {
|
|
260
|
+
return target === override
|
|
261
|
+
}
|
|
262
|
+
return (
|
|
263
|
+
target === getDefaultTargetKey() ||
|
|
264
|
+
target === getBaselineFallbackTargetKey()
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function getDownloadTargetKey() {
|
|
269
|
+
const override = getTargetOverride()
|
|
270
|
+
if (override) {
|
|
271
|
+
return override
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const metadata = getCurrentMetadata()
|
|
275
|
+
if (metadata?.target && isTargetAllowedForThisMachine(metadata.target)) {
|
|
276
|
+
return metadata.target
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return getDefaultTargetKey()
|
|
280
|
+
}
|
|
281
|
+
|
|
189
282
|
async function getLatestVersion() {
|
|
190
283
|
try {
|
|
191
284
|
const res = await httpGet(
|
|
@@ -214,19 +307,34 @@ function streamToString(stream) {
|
|
|
214
307
|
|
|
215
308
|
function getCurrentVersion() {
|
|
216
309
|
try {
|
|
217
|
-
|
|
310
|
+
const metadata = getCurrentMetadata()
|
|
311
|
+
if (!metadata) {
|
|
218
312
|
return null
|
|
219
313
|
}
|
|
220
|
-
const metadata = JSON.parse(fs.readFileSync(CONFIG.metadataPath, 'utf8'))
|
|
221
314
|
if (!fs.existsSync(CONFIG.binaryPath)) {
|
|
222
315
|
return null
|
|
223
316
|
}
|
|
317
|
+
const metadataTarget = metadata.target || getPlatformKey()
|
|
318
|
+
if (!isTargetAllowedForThisMachine(metadataTarget)) {
|
|
319
|
+
return null
|
|
320
|
+
}
|
|
224
321
|
return metadata.version || null
|
|
225
322
|
} catch (error) {
|
|
226
323
|
return null
|
|
227
324
|
}
|
|
228
325
|
}
|
|
229
326
|
|
|
327
|
+
function getCurrentMetadata() {
|
|
328
|
+
try {
|
|
329
|
+
if (!fs.existsSync(CONFIG.metadataPath)) {
|
|
330
|
+
return null
|
|
331
|
+
}
|
|
332
|
+
return JSON.parse(fs.readFileSync(CONFIG.metadataPath, 'utf8'))
|
|
333
|
+
} catch {
|
|
334
|
+
return null
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
230
338
|
function compareVersions(v1, v2) {
|
|
231
339
|
if (!v1 || !v2) return 0
|
|
232
340
|
|
|
@@ -303,13 +411,12 @@ function createProgressBar(percentage, width = 30) {
|
|
|
303
411
|
return '[' + '█'.repeat(filled) + '░'.repeat(empty) + ']'
|
|
304
412
|
}
|
|
305
413
|
|
|
306
|
-
async function downloadBinary(version) {
|
|
307
|
-
const
|
|
308
|
-
const fileName = PLATFORM_TARGETS[platformKey]
|
|
414
|
+
async function downloadBinary(version, targetKey = getDownloadTargetKey()) {
|
|
415
|
+
const fileName = PLATFORM_TARGETS[targetKey]
|
|
309
416
|
|
|
310
417
|
if (!fileName) {
|
|
311
418
|
const error = new Error(`Unsupported platform: ${process.platform} ${process.arch}`)
|
|
312
|
-
trackUpdateFailed(error.message, version, { stage: 'platform_check' })
|
|
419
|
+
trackUpdateFailed(error.message, version, { stage: 'platform_check', target: targetKey })
|
|
313
420
|
throw error
|
|
314
421
|
}
|
|
315
422
|
|
|
@@ -331,7 +438,7 @@ async function downloadBinary(version) {
|
|
|
331
438
|
if (res.statusCode !== 200) {
|
|
332
439
|
fs.rmSync(CONFIG.tempDownloadDir, { recursive: true })
|
|
333
440
|
const error = new Error(`Download failed: HTTP ${res.statusCode}`)
|
|
334
|
-
trackUpdateFailed(error.message, version, { stage: 'http_download', statusCode: res.statusCode })
|
|
441
|
+
trackUpdateFailed(error.message, version, { stage: 'http_download', statusCode: res.statusCode, target: targetKey })
|
|
335
442
|
throw error
|
|
336
443
|
}
|
|
337
444
|
|
|
@@ -373,7 +480,7 @@ async function downloadBinary(version) {
|
|
|
373
480
|
const error = new Error(
|
|
374
481
|
`Binary not found after extraction. Expected: ${CONFIG.binaryName}, Available files: ${files.join(', ')}`,
|
|
375
482
|
)
|
|
376
|
-
trackUpdateFailed(error.message, version, { stage: 'extraction' })
|
|
483
|
+
trackUpdateFailed(error.message, version, { stage: 'extraction', target: targetKey })
|
|
377
484
|
throw error
|
|
378
485
|
}
|
|
379
486
|
|
|
@@ -423,7 +530,7 @@ async function downloadBinary(version) {
|
|
|
423
530
|
|
|
424
531
|
fs.writeFileSync(
|
|
425
532
|
CONFIG.metadataPath,
|
|
426
|
-
JSON.stringify({ version }, null, 2),
|
|
533
|
+
JSON.stringify({ version, target: targetKey }, null, 2),
|
|
427
534
|
)
|
|
428
535
|
} finally {
|
|
429
536
|
if (fs.existsSync(CONFIG.tempDownloadDir)) {
|
|
@@ -505,14 +612,7 @@ async function checkForUpdates(runningProcess, exitListener) {
|
|
|
505
612
|
await downloadBinary(latestVersion)
|
|
506
613
|
|
|
507
614
|
const newChild = spawnInstalledBinary({ detached: false })
|
|
508
|
-
|
|
509
|
-
newChild.on('exit', (code, signal) => {
|
|
510
|
-
resetTerminal({
|
|
511
|
-
exitAlternateScreen: shouldExitAlternateScreen(code, signal),
|
|
512
|
-
})
|
|
513
|
-
printCrashDiagnostics(code, signal)
|
|
514
|
-
process.exit(signal ? 1 : (code || 0))
|
|
515
|
-
})
|
|
615
|
+
attachExitHandler(newChild)
|
|
516
616
|
|
|
517
617
|
return new Promise(() => {})
|
|
518
618
|
}
|
|
@@ -524,9 +624,7 @@ async function checkForUpdates(runningProcess, exitListener) {
|
|
|
524
624
|
function printCrashDiagnostics(code, signal) {
|
|
525
625
|
// Windows NTSTATUS codes (unsigned DWORD)
|
|
526
626
|
const unsignedCode = getUnsignedExitCode(code)
|
|
527
|
-
const isIllegalInstruction =
|
|
528
|
-
signal === 'SIGILL' ||
|
|
529
|
-
(process.platform === 'win32' && unsignedCode === 0xC000001D)
|
|
627
|
+
const isIllegalInstruction = isIllegalInstructionExit(code, signal)
|
|
530
628
|
const isAccessViolation =
|
|
531
629
|
signal === 'SIGSEGV' ||
|
|
532
630
|
(process.platform === 'win32' && unsignedCode === 0xC0000005)
|
|
@@ -635,12 +733,57 @@ function spawnInstalledBinary(options = {}) {
|
|
|
635
733
|
return child
|
|
636
734
|
}
|
|
637
735
|
|
|
638
|
-
async function
|
|
639
|
-
|
|
736
|
+
async function tryFallbackToBaseline(code, signal) {
|
|
737
|
+
if (!isIllegalInstructionExit(code, signal)) {
|
|
738
|
+
return false
|
|
739
|
+
}
|
|
640
740
|
|
|
641
|
-
const
|
|
741
|
+
const fallbackTarget = getBaselineFallbackTargetKey()
|
|
742
|
+
if (!fallbackTarget) {
|
|
743
|
+
return false
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
const metadata = getCurrentMetadata()
|
|
747
|
+
const currentTarget = metadata?.target || getDefaultTargetKey()
|
|
748
|
+
if (currentTarget === fallbackTarget) {
|
|
749
|
+
return false
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const version = metadata?.version || (await getLatestVersion())
|
|
753
|
+
if (!version) {
|
|
754
|
+
return false
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
resetTerminal({
|
|
758
|
+
exitAlternateScreen: shouldExitAlternateScreen(code, signal),
|
|
759
|
+
})
|
|
760
|
+
console.error('')
|
|
761
|
+
console.error(
|
|
762
|
+
`${packageName} is switching to the older-CPU binary for this machine.`,
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
try {
|
|
766
|
+
await downloadBinary(version, fallbackTarget)
|
|
767
|
+
} catch (error) {
|
|
768
|
+
term.clearLine()
|
|
769
|
+
console.error(`Failed to download ${fallbackTarget}: ${error.message}`)
|
|
770
|
+
return false
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const child = spawnInstalledBinary({ detached: false })
|
|
774
|
+
attachExitHandler(child, false)
|
|
775
|
+
return true
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
function attachExitHandler(child, allowBaselineFallback = true) {
|
|
779
|
+
const exitListener = async (code, signal) => {
|
|
780
|
+
if (
|
|
781
|
+
allowBaselineFallback &&
|
|
782
|
+
(await tryFallbackToBaseline(code, signal))
|
|
783
|
+
) {
|
|
784
|
+
return
|
|
785
|
+
}
|
|
642
786
|
|
|
643
|
-
const exitListener = (code, signal) => {
|
|
644
787
|
resetTerminal({
|
|
645
788
|
exitAlternateScreen: shouldExitAlternateScreen(code, signal),
|
|
646
789
|
})
|
|
@@ -649,6 +792,14 @@ async function main() {
|
|
|
649
792
|
}
|
|
650
793
|
|
|
651
794
|
child.on('exit', exitListener)
|
|
795
|
+
return exitListener
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
async function main() {
|
|
799
|
+
await ensureBinaryExists()
|
|
800
|
+
|
|
801
|
+
const child = spawnInstalledBinary()
|
|
802
|
+
const exitListener = attachExitHandler(child)
|
|
652
803
|
|
|
653
804
|
setTimeout(() => {
|
|
654
805
|
checkForUpdates(child, exitListener)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freebuff",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.100",
|
|
4
4
|
"description": "The world's strongest free coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/CodebuffAI/
|
|
36
|
+
"url": "git+https://github.com/CodebuffAI/freebuff-private.git"
|
|
37
37
|
},
|
|
38
|
-
"homepage": "https://
|
|
38
|
+
"homepage": "https://freebuff.com",
|
|
39
39
|
"publishConfig": {
|
|
40
|
-
"access": "public"
|
|
40
|
+
"access": "public",
|
|
41
|
+
"provenance": false
|
|
41
42
|
}
|
|
42
43
|
}
|