| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #!/usr/bin/env node
- import childProcess from "child_process"
- import fs from "fs"
- import os from "os"
- import path from "path"
- import { createRequire } from "module"
- import { fileURLToPath } from "url"
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
- const require = createRequire(import.meta.url)
- const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"))
- const platformMap = {
- darwin: "darwin",
- linux: "linux",
- win32: "windows",
- }
- const archMap = {
- x64: "x64",
- arm64: "arm64",
- arm: "arm",
- }
- const platform = platformMap[os.platform()] ?? os.platform()
- const arch = archMap[os.arch()] ?? os.arch()
- const base = `opencode-${platform}-${arch}`
- const sourceBinary = platform === "windows" ? "opencode.exe" : "kirincode"
- const targetBinary = path.join(__dirname, "bin", "opencode.exe")
- function supportsAvx2() {
- if (arch !== "x64") return false
- if (platform === "linux") {
- try {
- return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
- } 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") {
- const command =
- '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
- for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
- try {
- const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
- encoding: "utf8",
- timeout: 3000,
- windowsHide: true,
- })
- if (result.status !== 0) continue
- const output = (result.stdout || "").trim().toLowerCase()
- if (output === "true" || output === "1") return true
- if (output === "false" || output === "0") return false
- } catch {
- continue
- }
- }
- }
- return false
- }
- function isMusl() {
- if (platform !== "linux") return false
- try {
- if (fs.existsSync("/etc/alpine-release")) return true
- } catch {
- // Ignore filesystem probes that are blocked by the host.
- }
- try {
- const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
- return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl")
- } catch {
- return false
- }
- }
- function packageNames() {
- const baseline = arch === "x64" && !supportsAvx2()
- if (platform === "linux") {
- if (isMusl()) {
- if (arch === "x64")
- return baseline
- ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
- : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
- return [`${base}-musl`, base]
- }
- if (arch === "x64")
- return baseline
- ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
- : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
- return [base, `${base}-musl`]
- }
- if (arch === "x64") return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]
- return [base]
- }
- function resolveBinary(name) {
- const packageJsonPath = require.resolve(`${name}/package.json`)
- const binaryPath = path.join(path.dirname(packageJsonPath), "bin", sourceBinary)
- if (!fs.existsSync(binaryPath)) throw new Error(`Binary not found at ${binaryPath}`)
- return binaryPath
- }
- function installPackage(name) {
- const version = packageJson.optionalDependencies?.[name]
- if (!version) return
- const temp = fs.mkdtempSync(path.join(os.tmpdir(), "opencode-install-"))
- try {
- const result = childProcess.spawnSync(
- "npm",
- ["install", "--ignore-scripts", "--no-save", "--loglevel=error", "--prefix", temp, `${name}@${version}`],
- { stdio: "inherit", windowsHide: true },
- )
- if (result.status !== 0) return
- const packageDir = path.join(temp, "node_modules", name)
- copyBinary(path.join(packageDir, "bin", sourceBinary), targetBinary)
- return true
- } finally {
- fs.rmSync(temp, { recursive: true, force: true })
- }
- }
- function copyBinary(source, target) {
- if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
- fs.mkdirSync(path.dirname(target), { recursive: true })
- if (fs.existsSync(target)) fs.unlinkSync(target)
- try {
- fs.linkSync(source, target)
- } catch {
- fs.copyFileSync(source, target)
- }
- fs.chmodSync(target, 0o755)
- }
- function verifyBinary() {
- const result = childProcess.spawnSync(targetBinary, ["--version"], {
- encoding: "utf8",
- stdio: "ignore",
- windowsHide: true,
- })
- return result.status === 0
- }
- function main() {
- for (const name of packageNames()) {
- try {
- copyBinary(resolveBinary(name), targetBinary)
- if (verifyBinary()) return
- } catch {
- if (installPackage(name) && verifyBinary()) return
- }
- }
- throw new Error(
- `It seems your package manager failed to install the right kirincode CLI package. Try manually installing ${packageNames()
- .map((name) => JSON.stringify(name))
- .join(" or ")}.`,
- )
- }
- try {
- main()
- } catch (error) {
- console.error(error.message)
- process.exit(1)
- }
|