From d0955bfe905e3efd2f8209e2d77a77ccf3fe9e09 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:28:19 +1000 Subject: [PATCH 1/5] fix: baseline CPU detection --- install | 14 ++++ packages/desktop/scripts/predev.ts | 4 +- packages/desktop/scripts/utils.ts | 6 +- packages/opencode/bin/opencode | 123 ++++++++++++++++++++++++++--- 4 files changed, 131 insertions(+), 16 deletions(-) diff --git a/install b/install index 22b7ca39ed7..8361f903ed3 100755 --- a/install +++ b/install @@ -141,6 +141,20 @@ else needs_baseline=true fi fi + + if [ "$os" = "windows" ]; then + ps="(Add-Type -MemberDefinition \"[DllImport(\"\"kernel32.dll\"\")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);\" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)" + out="" + if command -v powershell.exe >/dev/null 2>&1; then + out=$(powershell.exe -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true) + elif command -v pwsh >/dev/null 2>&1; then + out=$(pwsh -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true) + fi + out=$(echo "$out" | tr -d '\r' | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]') + if [ "$out" != "true" ] && [ "$out" != "1" ]; then + needs_baseline=true + fi + fi fi target="$os-$arch" diff --git a/packages/desktop/scripts/predev.ts b/packages/desktop/scripts/predev.ts index 3e14250b1aa..072567758f9 100644 --- a/packages/desktop/scripts/predev.ts +++ b/packages/desktop/scripts/predev.ts @@ -8,6 +8,8 @@ const sidecarConfig = getCurrentSidecar(RUST_TARGET) const binaryPath = windowsify(`../opencode/dist/${sidecarConfig.ocBinary}/bin/opencode`) -await $`cd ../opencode && bun run build --single` +await (sidecarConfig.ocBinary.includes("-baseline") + ? $`cd ../opencode && bun run build --single --baseline` + : $`cd ../opencode && bun run build --single`) await copyBinaryToSidecarFolder(binaryPath, RUST_TARGET) diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts index c3019f0b970..2629eb466c0 100644 --- a/packages/desktop/scripts/utils.ts +++ b/packages/desktop/scripts/utils.ts @@ -8,17 +8,17 @@ export const SIDECAR_BINARIES: Array<{ rustTarget: string; ocBinary: string; ass }, { rustTarget: "x86_64-apple-darwin", - ocBinary: "opencode-darwin-x64", + ocBinary: "opencode-darwin-x64-baseline", assetExt: "zip", }, { rustTarget: "x86_64-pc-windows-msvc", - ocBinary: "opencode-windows-x64", + ocBinary: "opencode-windows-x64-baseline", assetExt: "zip", }, { rustTarget: "x86_64-unknown-linux-gnu", - ocBinary: "opencode-linux-x64", + ocBinary: "opencode-linux-x64-baseline", assetExt: "tar.gz", }, { diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index e35cc00944d..900e6e430c8 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -47,20 +47,119 @@ if (!arch) { const base = "opencode-" + platform + "-" + arch const binary = platform === "windows" ? "opencode.exe" : "opencode" +function supportsAvx2() { + if (arch !== "x64") return false + + if (platform === "linux") { + try { + return fs.readFileSync("/proc/cpuinfo", "utf8").toLowerCase().includes(" avx2") + } catch { + return false + } + } + + if (platform === "darwin") { + try { + const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], { + encoding: "utf8", + timeout: 1500, + }) + if (result.status !== 0) return false + return (result.stdout || "").trim() === "1" + } catch { + return false + } + } + + if (platform === "windows") { + try { + const { dlopen } = require("bun:ffi") + const k32 = dlopen("kernel32.dll", { + IsProcessorFeaturePresent: { args: ["u32"], returns: "i32" }, + }) + return k32.symbols.IsProcessorFeaturePresent(40) !== 0 + } catch { + // ignore + } + + const cmd = + '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)' + + for (const exe of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) { + try { + const result = childProcess.spawnSync(exe, ["-NoProfile", "-NonInteractive", "-Command", cmd], { + encoding: "utf8", + timeout: 3000, + windowsHide: true, + }) + if (result.status !== 0) continue + const out = (result.stdout || "").trim().toLowerCase() + if (out === "true" || out === "1") return true + if (out === "false" || out === "0") return false + } catch { + continue + } + } + + return false + } + + return false +} + +const names = (() => { + const avx2 = supportsAvx2() + const baseline = arch === "x64" && !avx2 + + if (platform === "linux") { + const musl = (() => { + try { + if (fs.existsSync("/etc/alpine-release")) return true + } catch { + // ignore + } + + try { + const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" }) + const text = ((result.stdout || "") + (result.stderr || "")).toLowerCase() + if (text.includes("musl")) return true + } catch { + // ignore + } + + return false + })() + + if (musl) { + if (arch === "x64") { + if (baseline) return [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base] + return [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`] + } + return [`${base}-musl`, base] + } + + if (arch === "x64") { + if (baseline) return [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`] + return [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`] + } + return [base, `${base}-musl`] + } + + if (arch === "x64") { + if (baseline) return [`${base}-baseline`, base] + return [base, `${base}-baseline`] + } + return [base] +})() + function findBinary(startDir) { let current = startDir for (;;) { const modules = path.join(current, "node_modules") if (fs.existsSync(modules)) { - const entries = fs.readdirSync(modules) - for (const entry of entries) { - if (!entry.startsWith(base)) { - continue - } - const candidate = path.join(modules, entry, "bin", binary) - if (fs.existsSync(candidate)) { - return candidate - } + for (const name of names) { + const candidate = path.join(modules, name, "bin", binary) + if (fs.existsSync(candidate)) return candidate } } const parent = path.dirname(current) @@ -74,9 +173,9 @@ function findBinary(startDir) { const resolved = findBinary(scriptDir) if (!resolved) { console.error( - 'It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "' + - base + - '" package', + "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing " + + names.map((n) => `\"${n}\"`).join(" or ") + + " package", ) process.exit(1) } From b2cab9d1f4f116f21598d12f381f61a9e74c2d83 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:38:18 +1000 Subject: [PATCH 2/5] 1.3.9 again again --- bun.lock | 6 +++--- package.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bun.lock b/bun.lock index 6c65d91d08f..f3590f53d2f 100644 --- a/bun.lock +++ b/bun.lock @@ -522,7 +522,7 @@ "@tailwindcss/vite": "4.1.11", "@tsconfig/bun": "1.0.9", "@tsconfig/node22": "22.0.2", - "@types/bun": "1.3.5", + "@types/bun": "1.3.9", "@types/luxon": "3.7.1", "@types/node": "22.13.9", "@types/semver": "7.7.1", @@ -1853,7 +1853,7 @@ "@types/braces": ["@types/braces@3.0.5", "", {}, "sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w=="], - "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="], + "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], @@ -2181,7 +2181,7 @@ "bun-pty": ["bun-pty@0.4.8", "", {}, "sha512-rO70Mrbr13+jxHHHu2YBkk2pNqrJE5cJn29WE++PUr+GFA0hq/VgtQPZANJ8dJo6d7XImvBk37Innt8GM7O28w=="], - "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], + "bun-types": ["bun-types@1.3.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], "bun-webgpu": ["bun-webgpu@0.1.4", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.4", "bun-webgpu-darwin-x64": "^0.1.4", "bun-webgpu-linux-x64": "^0.1.4", "bun-webgpu-win32-x64": "^0.1.4" } }, "sha512-Kw+HoXl1PMWJTh9wvh63SSRofTA8vYBFCw0XEP1V1fFdQEDhI8Sgf73sdndE/oDpN/7CMx0Yv/q8FCvO39ROMQ=="], diff --git a/package.json b/package.json index 61ee419736b..c396905d458 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "AI-powered development tool", "private": true, "type": "module", - "packageManager": "bun@1.3.5", + "packageManager": "bun@1.3.9", "scripts": { "dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts", "dev:desktop": "bun --cwd packages/desktop tauri dev", @@ -23,7 +23,7 @@ "packages/slack" ], "catalog": { - "@types/bun": "1.3.5", + "@types/bun": "1.3.9", "@octokit/rest": "22.0.0", "@hono/zod-validator": "0.4.2", "ulid": "3.0.1", From 49d1c2ece6338240286ae6a57dbf184a022822f6 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:45:01 +1000 Subject: [PATCH 3/5] clean and fallback to baseline if pwsh detection fails --- packages/opencode/bin/opencode | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index 900e6e430c8..2ed69589388 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -72,16 +72,6 @@ function supportsAvx2() { } if (platform === "windows") { - try { - const { dlopen } = require("bun:ffi") - const k32 = dlopen("kernel32.dll", { - IsProcessorFeaturePresent: { args: ["u32"], returns: "i32" }, - }) - return k32.symbols.IsProcessorFeaturePresent(40) !== 0 - } catch { - // ignore - } - const cmd = '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)' @@ -101,7 +91,7 @@ function supportsAvx2() { } } - return false + return true } return false From 32ef1c644bc8748860847c144584eee6d4c442fd Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:47:18 +1000 Subject: [PATCH 4/5] Update opencode --- packages/opencode/bin/opencode | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index 2ed69589388..ff2d9149092 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -91,7 +91,7 @@ function supportsAvx2() { } } - return true + return false } return false From 04ecd346daf1aa5a6850b5d24a887b4fa59ec187 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:55:39 +1000 Subject: [PATCH 5/5] some failure modes --- install | 2 +- packages/opencode/bin/opencode | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/install b/install index 8361f903ed3..b0716d53208 100755 --- a/install +++ b/install @@ -130,7 +130,7 @@ else needs_baseline=false if [ "$arch" = "x64" ]; then if [ "$os" = "linux" ]; then - if ! grep -qi avx2 /proc/cpuinfo 2>/dev/null; then + if ! grep -qwi avx2 /proc/cpuinfo 2>/dev/null; then needs_baseline=true fi fi diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index ff2d9149092..d73bbce2677 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -52,7 +52,7 @@ function supportsAvx2() { if (platform === "linux") { try { - return fs.readFileSync("/proc/cpuinfo", "utf8").toLowerCase().includes(" avx2") + return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8")) } catch { return false }