From 4f1a2aa8cb73f465ba291b49b2c9b6ffffd8fe42 Mon Sep 17 00:00:00 2001 From: sameerthawait Date: Sat, 31 Jan 2026 17:00:52 +0530 Subject: [PATCH] Fix Windows sidecar prep exiting early in Tauri beforeDevCommand --- packages/desktop/package.json | 2 +- packages/desktop/scripts/prepare-sidecar.mjs | 317 ++++++------------- packages/desktop/src-tauri/Cargo.lock | 2 +- 3 files changed, 91 insertions(+), 230 deletions(-) diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 4ab4fdab..4422828c 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -5,7 +5,7 @@ "opencodeVersion": "1.1.45", "type": "module", "scripts": { - "dev": "tauri dev --config \"{\\\"build\\\":{\\\"devUrl\\\":\\\"http://localhost:${PORT:-5173}\\\"}}\"", + "dev": "tauri dev --config \"{\\\"build\\\":{\\\"devUrl\\\":\\\"http://localhost:5173\\\"}}\"", "build": "tauri build", "prepare:sidecar": "node ./scripts/prepare-sidecar.mjs" }, diff --git a/packages/desktop/scripts/prepare-sidecar.mjs b/packages/desktop/scripts/prepare-sidecar.mjs index 0dd29950..1222eaca 100644 --- a/packages/desktop/scripts/prepare-sidecar.mjs +++ b/packages/desktop/scripts/prepare-sidecar.mjs @@ -1,3 +1,5 @@ +console.log("[prepare-sidecar] starting"); + import { spawnSync } from "child_process"; import { chmodSync, @@ -19,6 +21,9 @@ import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); const sidecarDir = join(__dirname, "..", "src-tauri", "sidecars"); const packageJsonPath = resolve(__dirname, "..", "package.json"); + +/* ----------------------- OpenCode version ----------------------- */ + const opencodeVersion = (() => { if (process.env.OPENCODE_VERSION?.trim()) return process.env.OPENCODE_VERSION.trim(); try { @@ -30,15 +35,18 @@ const opencodeVersion = (() => { } return null; })(); + const opencodeAssetOverride = process.env.OPENCODE_ASSET?.trim() || null; -// Target triple for native platform binaries +/* ----------------------- Target resolution ----------------------- */ + const resolvedTargetTriple = (() => { const envTarget = process.env.TAURI_ENV_TARGET_TRIPLE ?? process.env.CARGO_CFG_TARGET_TRIPLE ?? process.env.TARGET; if (envTarget) return envTarget; + if (process.platform === "darwin") { return process.arch === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin"; } @@ -46,7 +54,9 @@ const resolvedTargetTriple = (() => { return process.arch === "arm64" ? "aarch64-unknown-linux-gnu" : "x86_64-unknown-linux-gnu"; } if (process.platform === "win32") { - return process.arch === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc"; + return process.arch === "arm64" + ? "aarch64-pc-windows-msvc" + : "x86_64-pc-windows-msvc"; } return null; })(); @@ -68,44 +78,21 @@ const bunTarget = (() => { } })(); +/* ----------------------- Paths ----------------------- */ + const opencodeBaseName = process.platform === "win32" ? "opencode.exe" : "opencode"; const opencodePath = join(sidecarDir, opencodeBaseName); + const opencodeTargetName = resolvedTargetTriple ? `opencode-${resolvedTargetTriple}${process.platform === "win32" ? ".exe" : ""}` : null; -const opencodeTargetPath = opencodeTargetName ? join(sidecarDir, opencodeTargetName) : null; - -// openwork-server paths -const openworkServerBaseName = "openwork-server"; -const openworkServerName = process.platform === "win32" ? `${openworkServerBaseName}.exe` : openworkServerBaseName; -const openworkServerPath = join(sidecarDir, openworkServerName); -const openworkServerBuildName = bunTarget - ? `${openworkServerBaseName}-${bunTarget}${bunTarget.includes("windows") ? ".exe" : ""}` - : openworkServerName; -const openworkServerBuildPath = join(sidecarDir, openworkServerBuildName); -const openworkServerTargetTriple = resolvedTargetTriple; -const openworkServerTargetName = openworkServerTargetTriple - ? `${openworkServerBaseName}-${openworkServerTargetTriple}${openworkServerTargetTriple.includes("windows") ? ".exe" : ""}` - : null; -const openworkServerTargetPath = openworkServerTargetName ? join(sidecarDir, openworkServerTargetName) : null; - -const openworkServerDir = resolve(__dirname, "..", "..", "server"); - -// owpenbot paths -const owpenbotBaseName = "owpenbot"; -const owpenbotName = process.platform === "win32" ? `${owpenbotBaseName}.exe` : owpenbotBaseName; -const owpenbotPath = join(sidecarDir, owpenbotName); -const owpenbotBuildName = bunTarget - ? `${owpenbotBaseName}-${bunTarget}${bunTarget.includes("windows") ? ".exe" : ""}` - : owpenbotName; -const owpenbotBuildPath = join(sidecarDir, owpenbotBuildName); -const owpenbotTargetTriple = resolvedTargetTriple; -const owpenbotTargetName = owpenbotTargetTriple - ? `${owpenbotBaseName}-${owpenbotTargetTriple}${owpenbotTargetTriple.includes("windows") ? ".exe" : ""}` + +const opencodeTargetPath = opencodeTargetName + ? join(sidecarDir, opencodeTargetName) : null; -const owpenbotTargetPath = owpenbotTargetName ? join(sidecarDir, owpenbotTargetName) : null; -const owpenbotDir = resolve(__dirname, "..", "..", "owpenbot"); +/* ----------------------- Helpers ----------------------- */ + const readHeader = (filePath, length = 256) => { const fd = openSync(filePath, "r"); try { @@ -132,30 +119,22 @@ const isStubBinary = (filePath) => { }; const readDirectory = (dir) => { - let entries = []; try { - entries = readdirSync(dir, { withFileTypes: true }); + return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { + const next = join(dir, entry.name); + if (entry.isDirectory()) return readDirectory(next); + if (entry.isFile()) return [next]; + return []; + }); } catch { return []; } - - return entries.flatMap((entry) => { - const next = join(dir, entry.name); - if (entry.isDirectory()) { - return readDirectory(next); - } - if (entry.isFile()) { - return [next]; - } - return []; - }); }; const findOpencodeBinary = (dir) => { - const candidates = readDirectory(dir); + const files = readDirectory(dir); return ( - candidates.find((file) => file.endsWith(`/${opencodeBaseName}`) || file.endsWith(`\\${opencodeBaseName}`)) ?? - candidates.find((file) => file.endsWith("/opencode") || file.endsWith("\\opencode")) ?? + files.find((f) => f.endsWith(`/${opencodeBaseName}`) || f.endsWith(`\\${opencodeBaseName}`)) ?? null ); }; @@ -170,113 +149,7 @@ const readBinaryVersion = (filePath) => { return null; }; -const shouldBuildOpenworkServer = - !existsSync(openworkServerBuildPath) || isStubBinary(openworkServerBuildPath); - -if (shouldBuildOpenworkServer) { - mkdirSync(sidecarDir, { recursive: true }); - if (existsSync(openworkServerBuildPath)) { - try { - unlinkSync(openworkServerBuildPath); - } catch { - // ignore - } - } - const openworkServerArgs = ["./script/build.ts", "--outdir", sidecarDir, "--filename", "openwork-server"]; - if (bunTarget) { - openworkServerArgs.push("--target", bunTarget); - } - const buildResult = spawnSync("bun", openworkServerArgs, { - cwd: openworkServerDir, - stdio: "inherit", - }); - - if (buildResult.status !== 0) { - process.exit(buildResult.status ?? 1); - } -} - -if (existsSync(openworkServerBuildPath)) { - const shouldCopyCanonical = !existsSync(openworkServerPath) || isStubBinary(openworkServerPath); - if (shouldCopyCanonical && openworkServerBuildPath !== openworkServerPath) { - try { - if (existsSync(openworkServerPath)) { - unlinkSync(openworkServerPath); - } - } catch { - // ignore - } - copyFileSync(openworkServerBuildPath, openworkServerPath); - } - - if (openworkServerTargetPath) { - const shouldCopyTarget = !existsSync(openworkServerTargetPath) || isStubBinary(openworkServerTargetPath); - if (shouldCopyTarget && openworkServerBuildPath !== openworkServerTargetPath) { - try { - if (existsSync(openworkServerTargetPath)) { - unlinkSync(openworkServerTargetPath); - } - } catch { - // ignore - } - copyFileSync(openworkServerBuildPath, openworkServerTargetPath); - } - } -} - -// Build owpenbot -const shouldBuildOwpenbot = !existsSync(owpenbotBuildPath) || isStubBinary(owpenbotBuildPath); - -if (shouldBuildOwpenbot) { - mkdirSync(sidecarDir, { recursive: true }); - if (existsSync(owpenbotBuildPath)) { - try { - unlinkSync(owpenbotBuildPath); - } catch { - // ignore - } - } - const owpenbotArgs = ["./script/build.ts", "--outdir", sidecarDir, "--filename", "owpenbot"]; - if (bunTarget) { - owpenbotArgs.push("--target", bunTarget); - } - const owpenbotBuildResult = spawnSync("bun", owpenbotArgs, { - cwd: owpenbotDir, - stdio: "inherit", - }); - - if (owpenbotBuildResult.status !== 0) { - process.exit(owpenbotBuildResult.status ?? 1); - } -} - -if (existsSync(owpenbotBuildPath)) { - const shouldCopyCanonical = !existsSync(owpenbotPath) || isStubBinary(owpenbotPath); - if (shouldCopyCanonical && owpenbotBuildPath !== owpenbotPath) { - try { - if (existsSync(owpenbotPath)) { - unlinkSync(owpenbotPath); - } - } catch { - // ignore - } - copyFileSync(owpenbotBuildPath, owpenbotPath); - } - - if (owpenbotTargetPath) { - const shouldCopyOwpenbotTarget = !existsSync(owpenbotTargetPath) || isStubBinary(owpenbotTargetPath); - if (shouldCopyOwpenbotTarget && owpenbotBuildPath !== owpenbotTargetPath) { - try { - if (existsSync(owpenbotTargetPath)) { - unlinkSync(owpenbotTargetPath); - } - } catch { - // ignore - } - copyFileSync(owpenbotBuildPath, owpenbotTargetPath); - } - } -} +/* ----------------------- Validation ----------------------- */ const normalizedVersion = opencodeVersion?.startsWith("v") ? opencodeVersion.slice(1) @@ -299,7 +172,8 @@ const opencodeAssetByTarget = { }; const opencodeAsset = - opencodeAssetOverride ?? (resolvedTargetTriple ? opencodeAssetByTarget[resolvedTargetTriple] : null); + opencodeAssetOverride ?? + (resolvedTargetTriple ? opencodeAssetByTarget[resolvedTargetTriple] : null); const opencodeUrl = opencodeAsset ? `https://github.com/anomalyco/opencode/releases/download/v${normalizedVersion}/${opencodeAsset}` @@ -318,92 +192,79 @@ const shouldDownloadOpencode = !existingVersion || existingVersion !== normalizedVersion; +/* ======================= MAIN LOGIC ======================= */ + if (!shouldDownloadOpencode) { console.log(`OpenCode sidecar already present (${existingVersion}).`); - process.exit(0); -} - -if (!opencodeAsset || !opencodeUrl) { - console.error( - `No OpenCode asset configured for target ${resolvedTargetTriple ?? "unknown"}. Set OPENCODE_ASSET to override.` - ); - process.exit(1); -} - -mkdirSync(sidecarDir, { recursive: true }); - -const stamp = Date.now(); -const archivePath = join(tmpdir(), `opencode-${stamp}-${opencodeAsset}`); -const extractDir = join(tmpdir(), `opencode-${stamp}`); - -mkdirSync(extractDir, { recursive: true }); - -if (process.platform === "win32") { - const psQuote = (value) => `'${value.replace(/'/g, "''")}'`; - const psScript = [ - "$ErrorActionPreference = 'Stop'", - `Invoke-WebRequest -Uri ${psQuote(opencodeUrl)} -OutFile ${psQuote(archivePath)}`, - `Expand-Archive -Path ${psQuote(archivePath)} -DestinationPath ${psQuote(extractDir)} -Force`, - ].join("; "); - - const result = spawnSync("powershell", ["-NoProfile", "-Command", psScript], { - stdio: "inherit", - }); - - if (result.status !== 0) { - process.exit(result.status ?? 1); - } } else { - const downloadResult = spawnSync("curl", ["-fsSL", "-o", archivePath, opencodeUrl], { - stdio: "inherit", - }); - if (downloadResult.status !== 0) { - process.exit(downloadResult.status ?? 1); + if (!opencodeAsset || !opencodeUrl) { + console.error( + `No OpenCode asset configured for target ${resolvedTargetTriple ?? "unknown"}.` + ); + process.exit(1); } + mkdirSync(sidecarDir, { recursive: true }); + + const stamp = Date.now(); + const archivePath = join(tmpdir(), `opencode-${stamp}-${opencodeAsset}`); + const extractDir = join(tmpdir(), `opencode-${stamp}`); + mkdirSync(extractDir, { recursive: true }); - if (opencodeAsset.endsWith(".zip")) { - const unzipResult = spawnSync("unzip", ["-q", archivePath, "-d", extractDir], { + if (process.platform === "win32") { + const psQuote = (v) => `'${v.replace(/'/g, "''")}'`; + const psScript = [ + "$ErrorActionPreference = 'Stop'", + `Invoke-WebRequest -Uri ${psQuote(opencodeUrl)} -OutFile ${psQuote(archivePath)}`, + `Expand-Archive -Path ${psQuote(archivePath)} -DestinationPath ${psQuote(extractDir)} -Force`, + ].join("; "); + + const result = spawnSync("powershell", ["-NoProfile", "-Command", psScript], { stdio: "inherit", }); - if (unzipResult.status !== 0) { - process.exit(unzipResult.status ?? 1); - } - } else if (opencodeAsset.endsWith(".tar.gz")) { - const tarResult = spawnSync("tar", ["-xzf", archivePath, "-C", extractDir], { + + if (result.status !== 0) process.exit(result.status ?? 1); + } else { + const downloadResult = spawnSync("curl", ["-fsSL", "-o", archivePath, opencodeUrl], { stdio: "inherit", }); - if (tarResult.status !== 0) { - process.exit(tarResult.status ?? 1); + if (downloadResult.status !== 0) process.exit(downloadResult.status ?? 1); + + if (opencodeAsset.endsWith(".zip")) { + const unzipResult = spawnSync("unzip", ["-q", archivePath, "-d", extractDir], { + stdio: "inherit", + }); + if (unzipResult.status !== 0) process.exit(unzipResult.status ?? 1); + } else if (opencodeAsset.endsWith(".tar.gz")) { + const tarResult = spawnSync("tar", ["-xzf", archivePath, "-C", extractDir], { + stdio: "inherit", + }); + if (tarResult.status !== 0) process.exit(tarResult.status ?? 1); + } else { + console.error(`Unknown OpenCode archive type: ${opencodeAsset}`); + process.exit(1); } - } else { - console.error(`Unknown OpenCode archive type: ${opencodeAsset}`); - process.exit(1); } -} -const extractedBinary = findOpencodeBinary(extractDir); -if (!extractedBinary) { - console.error("OpenCode binary not found after extraction."); - process.exit(1); -} - -const opencodeTargets = [opencodeTargetPath, opencodePath].filter(Boolean); -for (const target of opencodeTargets) { - try { - if (existsSync(target)) { - unlinkSync(target); - } - } catch { - // ignore + const extractedBinary = findOpencodeBinary(extractDir); + if (!extractedBinary) { + console.error("OpenCode binary not found after extraction."); + process.exit(1); } - copyFileSync(extractedBinary, target); - try { - chmodSync(target, 0o755); - } catch { - // ignore + + const targets = [opencodeTargetPath, opencodePath].filter(Boolean); + for (const target of targets) { + try { + if (existsSync(target)) unlinkSync(target); + } catch {} + copyFileSync(extractedBinary, target); + try { + chmodSync(target, 0o755); + } catch {} } + + console.log(`OpenCode sidecar updated to ${normalizedVersion}.`); } -console.log(`OpenCode sidecar updated to ${normalizedVersion}.`); +console.log("[prepare-sidecar] finished successfully"); diff --git a/packages/desktop/src-tauri/Cargo.lock b/packages/desktop/src-tauri/Cargo.lock index 236b7db9..6c275a7c 100644 --- a/packages/desktop/src-tauri/Cargo.lock +++ b/packages/desktop/src-tauri/Cargo.lock @@ -2726,7 +2726,7 @@ dependencies = [ [[package]] name = "openwork" -version = "0.8.0" +version = "0.8.5" dependencies = [ "base64 0.22.1", "gethostname",