+175
-24
@@ -77,2 +77,10 @@ #!/usr/bin/env node | ||
| function isIllegalInstructionExit(code, signal) { | ||
| const unsignedCode = getUnsignedExitCode(code) | ||
| return ( | ||
| signal === 'SIGILL' || | ||
| (process.platform === 'win32' && unsignedCode === 0xC000001D) | ||
| ) | ||
| } | ||
| function createConfig(packageName) { | ||
@@ -168,2 +176,3 @@ const homeDir = os.homedir() | ||
| 'linux-x64': `${packageName}-linux-x64.tar.gz`, | ||
| 'linux-x64-baseline': `${packageName}-linux-x64-baseline.tar.gz`, | ||
| 'linux-arm64': `${packageName}-linux-arm64.tar.gz`, | ||
@@ -173,4 +182,10 @@ 'darwin-x64': `${packageName}-darwin-x64.tar.gz`, | ||
| 'win32-x64': `${packageName}-win32-x64.tar.gz`, | ||
| 'win32-x64-baseline': `${packageName}-win32-x64-baseline.tar.gz`, | ||
| } | ||
| const BASELINE_FALLBACK_TARGETS = { | ||
| 'linux-x64': 'linux-x64-baseline', | ||
| 'win32-x64': 'win32-x64-baseline', | ||
| } | ||
| const term = { | ||
@@ -192,2 +207,80 @@ clearLine: () => { | ||
| function getPlatformKey() { | ||
| return `${process.platform}-${process.arch}` | ||
| } | ||
| function getTargetOverride() { | ||
| const envNames = [ | ||
| `${packageName.toUpperCase()}_BINARY_TARGET`, | ||
| 'CODEBUFF_BINARY_TARGET', | ||
| 'CLI_BINARY_TARGET', | ||
| ] | ||
| for (const envName of envNames) { | ||
| const target = process.env[envName] | ||
| if (target && PLATFORM_TARGETS[target]) { | ||
| return target | ||
| } | ||
| } | ||
| return null | ||
| } | ||
| function linuxCpuHasAvx2() { | ||
| if (process.platform !== 'linux' || process.arch !== 'x64') { | ||
| return true | ||
| } | ||
| try { | ||
| return /\bavx2\b/i.test(fs.readFileSync('/proc/cpuinfo', 'utf8')) | ||
| } catch { | ||
| return true | ||
| } | ||
| } | ||
| function getDefaultTargetKey() { | ||
| const override = getTargetOverride() | ||
| if (override) { | ||
| return override | ||
| } | ||
| const platformKey = getPlatformKey() | ||
| if (platformKey === 'linux-x64' && !linuxCpuHasAvx2()) { | ||
| return 'linux-x64-baseline' | ||
| } | ||
| return platformKey | ||
| } | ||
| function getBaselineFallbackTargetKey() { | ||
| // Windows has no reliable plain-Node CPU feature check here, so we keep | ||
| // the fast x64 binary first and fall back after the native SIGILL code. | ||
| return BASELINE_FALLBACK_TARGETS[getPlatformKey()] || null | ||
| } | ||
| function isTargetAllowedForThisMachine(target) { | ||
| const override = getTargetOverride() | ||
| if (override) { | ||
| return target === override | ||
| } | ||
| return ( | ||
| target === getDefaultTargetKey() || | ||
| target === getBaselineFallbackTargetKey() | ||
| ) | ||
| } | ||
| function getDownloadTargetKey() { | ||
| const override = getTargetOverride() | ||
| if (override) { | ||
| return override | ||
| } | ||
| const metadata = getCurrentMetadata() | ||
| if (metadata?.target && isTargetAllowedForThisMachine(metadata.target)) { | ||
| return metadata.target | ||
| } | ||
| return getDefaultTargetKey() | ||
| } | ||
| async function getLatestVersion() { | ||
@@ -221,9 +314,13 @@ try { | ||
| try { | ||
| if (!fs.existsSync(CONFIG.metadataPath)) { | ||
| const metadata = getCurrentMetadata() | ||
| if (!metadata) { | ||
| return null | ||
| } | ||
| const metadata = JSON.parse(fs.readFileSync(CONFIG.metadataPath, 'utf8')) | ||
| if (!fs.existsSync(CONFIG.binaryPath)) { | ||
| return null | ||
| } | ||
| const metadataTarget = metadata.target || getPlatformKey() | ||
| if (!isTargetAllowedForThisMachine(metadataTarget)) { | ||
| return null | ||
| } | ||
| return metadata.version || null | ||
@@ -235,2 +332,13 @@ } catch (error) { | ||
| function getCurrentMetadata() { | ||
| try { | ||
| if (!fs.existsSync(CONFIG.metadataPath)) { | ||
| return null | ||
| } | ||
| return JSON.parse(fs.readFileSync(CONFIG.metadataPath, 'utf8')) | ||
| } catch { | ||
| return null | ||
| } | ||
| } | ||
| function compareVersions(v1, v2) { | ||
@@ -312,9 +420,8 @@ if (!v1 || !v2) return 0 | ||
| async function downloadBinary(version) { | ||
| const platformKey = `${process.platform}-${process.arch}` | ||
| const fileName = PLATFORM_TARGETS[platformKey] | ||
| async function downloadBinary(version, targetKey = getDownloadTargetKey()) { | ||
| const fileName = PLATFORM_TARGETS[targetKey] | ||
| if (!fileName) { | ||
| const error = new Error(`Unsupported platform: ${process.platform} ${process.arch}`) | ||
| trackUpdateFailed(error.message, version, { stage: 'platform_check' }) | ||
| trackUpdateFailed(error.message, version, { stage: 'platform_check', target: targetKey }) | ||
| throw error | ||
@@ -341,3 +448,3 @@ } | ||
| const error = new Error(`Download failed: HTTP ${res.statusCode}`) | ||
| trackUpdateFailed(error.message, version, { stage: 'http_download', statusCode: res.statusCode }) | ||
| trackUpdateFailed(error.message, version, { stage: 'http_download', statusCode: res.statusCode, target: targetKey }) | ||
| throw error | ||
@@ -384,3 +491,3 @@ } | ||
| ) | ||
| trackUpdateFailed(error.message, version, { stage: 'extraction' }) | ||
| trackUpdateFailed(error.message, version, { stage: 'extraction', target: targetKey }) | ||
| throw error | ||
@@ -435,3 +542,3 @@ } | ||
| CONFIG.metadataPath, | ||
| JSON.stringify({ version }, null, 2), | ||
| JSON.stringify({ version, target: targetKey }, null, 2), | ||
| ) | ||
@@ -518,11 +625,4 @@ } finally { | ||
| const newChild = spawnInstalledBinary({ detached: false }) | ||
| attachExitHandler(newChild) | ||
| newChild.on('exit', (code, signal) => { | ||
| resetTerminal({ | ||
| exitAlternateScreen: shouldExitAlternateScreen(code, signal), | ||
| }) | ||
| printCrashDiagnostics(code, signal) | ||
| process.exit(signal ? 1 : (code || 0)) | ||
| }) | ||
| return new Promise(() => {}) | ||
@@ -538,5 +638,3 @@ } | ||
| const unsignedCode = getUnsignedExitCode(code) | ||
| const isIllegalInstruction = | ||
| signal === 'SIGILL' || | ||
| (process.platform === 'win32' && unsignedCode === 0xC000001D) | ||
| const isIllegalInstruction = isIllegalInstructionExit(code, signal) | ||
| const isAccessViolation = | ||
@@ -650,8 +748,53 @@ signal === 'SIGSEGV' || | ||
| async function main() { | ||
| await ensureBinaryExists() | ||
| async function tryFallbackToBaseline(code, signal) { | ||
| if (!isIllegalInstructionExit(code, signal)) { | ||
| return false | ||
| } | ||
| const child = spawnInstalledBinary() | ||
| const fallbackTarget = getBaselineFallbackTargetKey() | ||
| if (!fallbackTarget) { | ||
| return false | ||
| } | ||
| const exitListener = (code, signal) => { | ||
| const metadata = getCurrentMetadata() | ||
| const currentTarget = metadata?.target || getDefaultTargetKey() | ||
| if (currentTarget === fallbackTarget) { | ||
| return false | ||
| } | ||
| const version = metadata?.version || (await getLatestVersion()) | ||
| if (!version) { | ||
| return false | ||
| } | ||
| resetTerminal({ | ||
| exitAlternateScreen: shouldExitAlternateScreen(code, signal), | ||
| }) | ||
| console.error('') | ||
| console.error( | ||
| `${packageName} is switching to the older-CPU binary for this machine.`, | ||
| ) | ||
| try { | ||
| await downloadBinary(version, fallbackTarget) | ||
| } catch (error) { | ||
| term.clearLine() | ||
| console.error(`Failed to download ${fallbackTarget}: ${error.message}`) | ||
| return false | ||
| } | ||
| const child = spawnInstalledBinary({ detached: false }) | ||
| attachExitHandler(child, false) | ||
| return true | ||
| } | ||
| function attachExitHandler(child, allowBaselineFallback = true) { | ||
| const exitListener = async (code, signal) => { | ||
| if ( | ||
| allowBaselineFallback && | ||
| (await tryFallbackToBaseline(code, signal)) | ||
| ) { | ||
| return | ||
| } | ||
| resetTerminal({ | ||
@@ -665,3 +808,11 @@ exitAlternateScreen: shouldExitAlternateScreen(code, signal), | ||
| child.on('exit', exitListener) | ||
| return exitListener | ||
| } | ||
| async function main() { | ||
| await ensureBinaryExists() | ||
| const child = spawnInstalledBinary() | ||
| const exitListener = attachExitHandler(child) | ||
| setTimeout(() => { | ||
@@ -668,0 +819,0 @@ checkForUpdates(child, exitListener) |
+5
-4
| { | ||
| "name": "freebuff", | ||
| "version": "0.0.98", | ||
| "version": "0.0.99", | ||
| "description": "The world's strongest free coding agent", | ||
@@ -36,8 +36,9 @@ "license": "MIT", | ||
| "type": "git", | ||
| "url": "https://github.com/CodebuffAI/codebuff.git" | ||
| "url": "git+https://github.com/CodebuffAI/freebuff-private.git" | ||
| }, | ||
| "homepage": "https://codebuff.com", | ||
| "homepage": "https://freebuff.com", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| "access": "public", | ||
| "provenance": false | ||
| } | ||
| } |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
30000
13.46%877
16.93%