82 lines
2.9 KiB
Go
82 lines
2.9 KiB
Go
package windsurf
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
// Platform identifies a (OS, architecture) pair that Windsurf may support.
|
|
// OS values match runtime.GOOS ("linux", "darwin", "windows"), and Arch
|
|
// values match runtime.GOARCH ("amd64", "arm64").
|
|
type Platform struct {
|
|
OS string
|
|
Arch string
|
|
}
|
|
|
|
// String renders the platform as "os/arch" (e.g. "darwin/arm64").
|
|
func (p Platform) String() string { return p.OS + "/" + p.Arch }
|
|
|
|
// procTranslatedProbe reports whether the current process is running under
|
|
// Rosetta 2 translation (an amd64 Go binary on Apple Silicon). It is mocked
|
|
// by tests.
|
|
var procTranslatedProbe = defaultProcTranslatedProbe
|
|
|
|
// defaultProcTranslatedProbe runs `sysctl sysctl.proc_translated` on darwin
|
|
// and returns true when the value is "1". On non-darwin platforms it always
|
|
// returns false. The sysctl key is only defined on darwin, so we skip the
|
|
// exec on every other OS to avoid spurious errors.
|
|
func defaultProcTranslatedProbe() bool {
|
|
if runtime.GOOS != "darwin" {
|
|
return false
|
|
}
|
|
out, err := exec.Command("sysctl", "-n", "sysctl.proc_translated").Output()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return strings.TrimSpace(string(out)) == "1"
|
|
}
|
|
|
|
// DetectPlatform returns the platform for which we should load the LS binary.
|
|
// It accounts for Rosetta translation: an amd64 Go binary running on Apple
|
|
// Silicon should load the arm64 LS, not the x64 one, because the native
|
|
// Mac arm64 binary performs better and the x64 build may not exist.
|
|
func DetectPlatform() Platform {
|
|
return detectPlatformFor(runtime.GOOS, runtime.GOARCH, procTranslatedProbe())
|
|
}
|
|
|
|
func detectPlatformFor(goos, goarch string, rosetta bool) Platform {
|
|
p := Platform{OS: goos, Arch: goarch}
|
|
if p.OS == "darwin" && p.Arch == "amd64" && rosetta {
|
|
p.Arch = "arm64"
|
|
}
|
|
return p
|
|
}
|
|
|
|
// ErrUnsupportedPlatform is returned when no Windsurf LS binary exists for
|
|
// the current platform. Callers should fall back to ls_mode=docker.
|
|
var ErrUnsupportedPlatform = fmt.Errorf("windsurf: no language server binary for this platform")
|
|
|
|
// BinaryFilename returns the official Windsurf LS binary filename for the
|
|
// given platform, matching the mapping used by the Windsurf VS Code
|
|
// extension (extracted from extension.js PlatformArch enum).
|
|
func BinaryFilename(p Platform) (string, error) {
|
|
switch {
|
|
case p.OS == "linux" && p.Arch == "amd64":
|
|
return "language_server_linux_x64", nil
|
|
case p.OS == "linux" && p.Arch == "arm64":
|
|
return "language_server_linux_arm", nil
|
|
case p.OS == "darwin" && p.Arch == "arm64":
|
|
return "language_server_macos_arm", nil
|
|
case p.OS == "darwin" && p.Arch == "amd64":
|
|
return "language_server_macos_x64", nil
|
|
case p.OS == "windows" && p.Arch == "amd64":
|
|
return "language_server_windows_x64.exe", nil
|
|
case p.OS == "windows" && p.Arch == "arm64":
|
|
return "language_server_windows_arm.exe", nil
|
|
default:
|
|
return "", fmt.Errorf("%w: %s — use ls_mode=docker to run the Linux LS in a container", ErrUnsupportedPlatform, p)
|
|
}
|
|
}
|