From 82caf064e0eed2a848ede1f51f16a6f96483034b Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Sun, 8 Feb 2026 15:44:42 +0100 Subject: [PATCH] fix(coding-agent): use tar instead of unzip for .zip extraction on Windows Windows does not ship with unzip, causing fd/rg download to fail on first run in PowerShell. Use tar (bsdtar, available on Windows 10+) for both .tar.gz and .zip extraction. Also adds proper error checking on the extraction result. fixes #1348 --- packages/coding-agent/CHANGELOG.md | 4 ++++ packages/coding-agent/src/utils/tools-manager.ts | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 4229072c..ca39e488 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed fd/rg download failing on Windows due to `unzip` not being available; now uses `tar` for both `.tar.gz` and `.zip` extraction, with proper error reporting ([#1348](https://github.com/badlogic/pi-mono/issues/1348)) + ## [0.52.8] - 2026-02-07 ### New Features diff --git a/packages/coding-agent/src/utils/tools-manager.ts b/packages/coding-agent/src/utils/tools-manager.ts index 53d2c513..8f5853fc 100644 --- a/packages/coding-agent/src/utils/tools-manager.ts +++ b/packages/coding-agent/src/utils/tools-manager.ts @@ -153,10 +153,18 @@ async function downloadTool(tool: "fd" | "rg"): Promise { mkdirSync(extractDir, { recursive: true }); try { - if (assetName.endsWith(".tar.gz")) { - spawnSync("tar", ["xzf", archivePath, "-C", extractDir], { stdio: "pipe" }); - } else if (assetName.endsWith(".zip")) { - spawnSync("unzip", ["-o", archivePath, "-d", extractDir], { stdio: "pipe" }); + // Use tar for both .tar.gz and .zip extraction. Windows 10+ ships bsdtar + // which handles both formats, avoiding the need for `unzip` (not available + // on Windows by default). + const extractResult = assetName.endsWith(".tar.gz") + ? spawnSync("tar", ["xzf", archivePath, "-C", extractDir], { stdio: "pipe" }) + : assetName.endsWith(".zip") + ? spawnSync("tar", ["xf", archivePath, "-C", extractDir], { stdio: "pipe" }) + : null; + + if (!extractResult || extractResult.error || extractResult.status !== 0) { + const errMsg = extractResult?.error?.message ?? extractResult?.stderr?.toString().trim() ?? "unknown error"; + throw new Error(`Failed to extract ${assetName}: ${errMsg}`); } // Find the binary in extracted files