feat: prepare Zhinian desktop pilot
This commit is contained in:
@@ -53,11 +53,16 @@ async function setupTarget(id) {
|
||||
const tempDir = path.join(ROOT_DIR, 'temp_uv_extract');
|
||||
const archivePath = path.join(ROOT_DIR, target.filename);
|
||||
const downloadUrl = `${BASE_URL}/${target.filename}`;
|
||||
const destBin = path.join(targetDir, target.binName);
|
||||
|
||||
echo(chalk.blue`\n📦 Setting up uv for ${id}...`);
|
||||
|
||||
// Cleanup & Prep
|
||||
await fs.remove(targetDir);
|
||||
// Cleanup temporary files only. Do not remove targetDir: it may also contain
|
||||
// the bundled Node/npm runtime used by the packaged app.
|
||||
if (process.env.FORCE_BUNDLED_UV_REFRESH !== '1' && await fs.pathExists(destBin)) {
|
||||
echo(chalk.green`✅ Already prepared: ${destBin}`);
|
||||
return;
|
||||
}
|
||||
await fs.remove(tempDir);
|
||||
await fs.ensureDir(targetDir);
|
||||
await fs.ensureDir(tempDir);
|
||||
@@ -65,8 +70,13 @@ async function setupTarget(id) {
|
||||
try {
|
||||
// Download
|
||||
echo`⬇️ Downloading: ${downloadUrl}`;
|
||||
const response = await fetch(downloadUrl);
|
||||
if (!response.ok) throw new Error(`Failed to download: ${response.statusText}`);
|
||||
let response;
|
||||
try {
|
||||
response = await fetchWithRetry(downloadUrl);
|
||||
} catch (error) {
|
||||
if (await copyLocalUvFallback(id, destBin)) return;
|
||||
throw error;
|
||||
}
|
||||
const buffer = await response.arrayBuffer();
|
||||
await fs.writeFile(archivePath, Buffer.from(buffer));
|
||||
|
||||
@@ -88,7 +98,6 @@ async function setupTarget(id) {
|
||||
// uv archives usually contain a folder named after the target
|
||||
const folderName = target.filename.replace('.tar.gz', '').replace('.zip', '');
|
||||
const sourceBin = path.join(tempDir, folderName, target.binName);
|
||||
const destBin = path.join(targetDir, target.binName);
|
||||
|
||||
if (await fs.pathExists(sourceBin)) {
|
||||
await fs.move(sourceBin, destBin, { overwrite: true });
|
||||
@@ -115,11 +124,54 @@ async function setupTarget(id) {
|
||||
}
|
||||
}
|
||||
|
||||
async function copyLocalUvFallback(id, destBin) {
|
||||
const currentId = `${os.platform()}-${os.arch()}`;
|
||||
if (id !== currentId) return false;
|
||||
|
||||
try {
|
||||
const { execFileSync } = await import('node:child_process');
|
||||
const command = os.platform() === 'win32' ? 'where.exe' : 'which';
|
||||
const output = execFileSync(command, ['uv'], { encoding: 'utf8' });
|
||||
const localUv = output.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
||||
if (!localUv) return false;
|
||||
echo(chalk.yellow`⚠️ Download failed; using local uv fallback: ${localUv}`);
|
||||
await fs.copy(localUv, destBin, { overwrite: true, dereference: true });
|
||||
if (os.platform() !== 'win32') {
|
||||
await fs.chmod(destBin, 0o755);
|
||||
}
|
||||
echo(chalk.green`✅ Success: ${destBin}`);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchWithRetry(url, attempts = 3) {
|
||||
let lastError;
|
||||
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(`Failed to download: ${response.status} ${response.statusText}`);
|
||||
return response;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (attempt < attempts) {
|
||||
echo(chalk.yellow`⚠️ Download failed (attempt ${attempt}/${attempts}), retrying...`);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500 * attempt));
|
||||
}
|
||||
}
|
||||
}
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
// Main logic
|
||||
const downloadAll = argv.all;
|
||||
const platform = argv.platform;
|
||||
const target = argv.target;
|
||||
|
||||
if (downloadAll) {
|
||||
if (target) {
|
||||
await setupTarget(String(target));
|
||||
} else if (downloadAll) {
|
||||
// Download for all platforms
|
||||
echo(chalk.cyan`🌐 Downloading uv binaries for ALL supported platforms...`);
|
||||
for (const id of Object.keys(TARGETS)) {
|
||||
|
||||
Reference in New Issue
Block a user