// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. ========= /* global console, process */ // @ts-check import AdmZip from 'adm-zip'; import fs from 'fs'; import os from 'os'; import path from 'path'; import * as tar from 'tar'; import { downloadWithRedirects } from './download.js'; // Base URL for downloading uv binaries const UV_RELEASE_BASE_URL = 'https://github.com/astral-sh/uv/releases/download'; const DEFAULT_UV_VERSION = '0.6.14'; // Mapping of platform+arch to binary package name const UV_PACKAGES = { 'darwin-arm64': 'uv-aarch64-apple-darwin.tar.gz', 'darwin-x64': 'uv-x86_64-apple-darwin.tar.gz', 'win32-arm64': 'uv-aarch64-pc-windows-msvc.zip', 'win32-ia32': 'uv-i686-pc-windows-msvc.zip', 'win32-x64': 'uv-x86_64-pc-windows-msvc.zip', 'linux-arm64': 'uv-aarch64-unknown-linux-gnu.tar.gz', 'linux-ia32': 'uv-i686-unknown-linux-gnu.tar.gz', 'linux-ppc64': 'uv-powerpc64-unknown-linux-gnu.tar.gz', 'linux-ppc64le': 'uv-powerpc64le-unknown-linux-gnu.tar.gz', 'linux-s390x': 'uv-s390x-unknown-linux-gnu.tar.gz', 'linux-x64': 'uv-x86_64-unknown-linux-gnu.tar.gz', 'linux-armv7l': 'uv-armv7-unknown-linux-gnueabihf.tar.gz', // MUSL variants 'linux-musl-arm64': 'uv-aarch64-unknown-linux-musl.tar.gz', 'linux-musl-ia32': 'uv-i686-unknown-linux-musl.tar.gz', 'linux-musl-x64': 'uv-x86_64-unknown-linux-musl.tar.gz', 'linux-musl-armv6l': 'uv-arm-unknown-linux-musleabihf.tar.gz', 'linux-musl-armv7l': 'uv-armv7-unknown-linux-musleabihf.tar.gz', }; /** * Downloads and extracts the uv binary for the specified platform and architecture * @param {string} platform Platform to download for (e.g., 'darwin', 'win32', 'linux') * @param {string} arch Architecture to download for (e.g., 'x64', 'arm64') * @param {string} version Version of uv to download * @param {boolean} isMusl Whether to use MUSL variant for Linux */ async function downloadUvBinary( uv_download_url, platform, arch, version = DEFAULT_UV_VERSION, isMusl = false ) { console.log('[START] downloadUvBinary:', uv_download_url); const platformKey = isMusl ? `${platform}-musl-${arch}` : `${platform}-${arch}`; const packageName = UV_PACKAGES[platformKey]; if (!packageName) { console.error(`No binary available for ${platformKey}`); return false; } // Create output directory structure const binDir = path.join(os.homedir(), '.eigent', 'bin'); // Ensure directories exist fs.mkdirSync(binDir, { recursive: true }); // Download URL for the specific binary const downloadUrl = `${uv_download_url}/${version}/${packageName}`; const tempdir = os.tmpdir(); // Use unique temp filename to avoid race conditions when multiple processes install simultaneously const uniqueSuffix = `${process.pid}-${Date.now()}`; const tempFilename = path.join(tempdir, `${uniqueSuffix}-${packageName}`); try { console.log(`Downloading uv ${version} for ${platformKey}...`); console.log(`URL: ${downloadUrl}`); if (fs.existsSync(tempFilename)) fs.unlinkSync(tempFilename); await downloadWithRedirects(downloadUrl, tempFilename); console.log(`Extracting ${packageName} to ${binDir}...`); if (packageName.endsWith('.zip')) { // use adm-zip to handle zip file const zip = new AdmZip(tempFilename); zip.extractAllTo(binDir, true); fs.unlinkSync(tempFilename); console.log( `Successfully installed uv ${version} for ${platform}-${arch}` ); return true; } else { // handle tar.gz file await tar.x({ file: tempFilename, cwd: binDir, strip: 1, z: true, filter: (path) => { // Only extract the uv binary return path.endsWith('uv') || path.endsWith('uv.exe'); }, }); // Set executable permissions for non-Windows platforms if (platform !== 'win32') { const uvPath = path.join(binDir, 'uv'); if (fs.existsSync(uvPath)) { try { fs.chmodSync(uvPath, '755'); } catch (error) { console.warn( `Warning: Failed to set executable permissions: ${error.message}` ); } } } // Clean up fs.unlinkSync(tempFilename); } console.log(`Successfully installed uv ${version} for ${platform}-${arch}`); return true; } catch (error) { console.error(`Error installing uv for ${platformKey}: ${error.message}`); if (fs.existsSync(tempFilename)) { fs.unlinkSync(tempFilename); } // Check if binDir is empty and remove it if so try { const files = fs.readdirSync(binDir); if (files.length === 0) { fs.rmSync(binDir, { recursive: true }); console.log(`Removed empty directory: ${binDir}`); } } catch (cleanupError) { console.warn( `Warning: Failed to clean up directory: ${cleanupError.message}` ); } return false; } } /** * Detects current platform and architecture */ function detectPlatformAndArch() { const platform = os.platform(); const arch = os.arch(); const isMusl = platform === 'linux' && detectIsMusl(); return { platform, arch, isMusl }; } /** * Attempts to detect if running on MUSL libc */ function detectIsMusl() { try { // Simple check for Alpine Linux which uses MUSL const output = fs.readFileSync('/etc/os-release', 'utf8'); return output.toLowerCase().includes('alpine'); } catch (error) { console.error(`Error detecting MUSL: ${error}`); return false; } } /** * Main function to install uv */ async function installUv() { // Get the latest version if no specific version is provided const version = DEFAULT_UV_VERSION; console.log(`Using uv version: ${version}`); const { platform, arch, isMusl } = detectPlatformAndArch(); console.log( `Installing uv ${version} for ${platform}-${arch}${ isMusl ? ' (MUSL)' : '' }...` ); let isInstalled = await downloadUvBinary( UV_RELEASE_BASE_URL, platform, arch, version, isMusl ); if (!isInstalled) { throw new Error(`Failed to download uv ${version} from default source`); } } // Run the installation installUv() .then(() => { console.log('Installation successful'); process.exit(0); }) .catch((error) => { console.error('Installation failed:', error); process.exit(1); });