feat: add Windows ARM64 support with x64-baseline CLI workaround (#2537)

* feat: add Windows ARM64 support with x64-baseline CLI workaround

Windows ARM64 native opencode.exe fails with a Bun FFI/TinyCC dlopen
error (anomalyco/opencode#19130). As a temporary workaround:

- Bundle x64-baseline OpenCode CLI on ARM64 instead of native ARM64
  (prepare-opencode-cli.mjs, env-runtime.js)
- Disable OpenCode self-upgrade on ARM64 in server, VS Code, and UI
  (upgrade-capability.js, opencode-upgrade-runtime.ts, useUIStore.ts,
  OpenCodeCliSettings.tsx, search.ts, SettingsView.tsx, platform.ts)
- Add ARM64 Windows cross-compile builds to release and smoke workflows
  (release.yml, release-desktop-smoke.yml)
- Refactor Windows latest.yml to use combine-electron-manifests pattern
  matching macOS, since two arches now produce per-arch manifests

The CI ARM64 build itself is permanent; only the x64-baseline CLI
bundling and upgrade disablement are temporary and should be reverted
when the upstream issue is resolved.

* fix(desktop): select Windows updater by architecture

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
Howon Lee
2026-07-30 20:07:08 +03:00
committed by GitHub
co-authored by Bohdan Triapitsyn
parent 5792a3d2e2
commit 09f0c64839
18 changed files with 206 additions and 30 deletions
+33
View File
@@ -7,6 +7,39 @@ export const isCapacitorApp = (): boolean => {
return capacitor?.isNativePlatform?.() === true || window.location.protocol === 'capacitor:';
};
// TEMPORARY WORKAROUND — Windows ARM64: native opencode.exe fails with a Bun
// FFI/TinyCC dlopen error (https://github.com/anomalyco/opencode/issues/19130).
// Suppress OpenCode update UI on ARM64 so it can't self-upgrade to the broken
// ARM64 build. Remove this helper and its call sites when resolved upstream.
export const isWindowsArm64 = (): boolean => {
if (typeof window === 'undefined') return false;
const electronArch = window.__OPENCHAMBER_ELECTRON__?.arch?.toLowerCase?.();
if (electronArch === 'arm64' || electronArch === 'aarch64') {
const platform = (navigator.platform || '').toLowerCase();
return platform.includes('win');
}
const vscodeArch = (window as { __VSCODE_CONFIG__?: { arch?: string } }).__VSCODE_CONFIG__?.arch?.toLowerCase?.();
if (vscodeArch === 'arm64' || vscodeArch === 'aarch64') {
const platform = (navigator.platform || '').toLowerCase();
return platform.includes('win');
}
const nav = (navigator as Navigator & { userAgentData?: { architecture?: string; platform?: string } }).userAgentData;
if (nav?.architecture?.toLowerCase?.() === 'arm64' || nav?.architecture?.toLowerCase?.() === 'aarch64') {
const platform = (nav.platform || navigator.platform || '').toLowerCase();
return platform.includes('win');
}
const ua = navigator.userAgent.toLowerCase();
if ((ua.includes('aarch64') || ua.includes('arm64') || ua.includes('armv')) && ua.includes('windows')) {
return true;
}
return false;
};
/**
* True when running inside the native Capacitor shell on an iPad.
* Capacitor reports 'ios' for both iPhone and iPad; iPadOS WKWebView
+3 -1
View File
@@ -26,6 +26,8 @@ interface SettingsSearchAvailabilityContext extends SettingsRuntimeContext {
isWindows: boolean;
// Linux desktop shell — for controls that only render on linux.
isLinux: boolean;
// Windows ARM64 — temporary workaround gate (see opencode#19130).
isWindowsArm64: boolean;
}
const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
@@ -470,7 +472,7 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
page: 'general',
titleKey: 'settings.openchamber.opencodeCli.field.showUpdateNotifications',
keywords: ['opencode', 'cli', 'updates'],
isAvailable: (ctx) => !ctx.isVSCode,
isAvailable: (ctx) => !ctx.isVSCode && !ctx.isWindowsArm64,
},
{
id: 'sessions.agent-control-tool',