lildax.cjs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env node
  2. const childProcess = require("child_process")
  3. const fs = require("fs")
  4. const path = require("path")
  5. const os = require("os")
  6. const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP"]
  7. function run(target) {
  8. const child = childProcess.spawn(target, process.argv.slice(2), { stdio: "inherit" })
  9. child.on("error", (error) => {
  10. console.error(error.message)
  11. process.exit(1)
  12. })
  13. const forwarders = {}
  14. for (const signal of forwardedSignals) {
  15. forwarders[signal] = () => {
  16. try {
  17. child.kill(signal)
  18. } catch {}
  19. }
  20. process.on(signal, forwarders[signal])
  21. }
  22. child.on("exit", (code, signal) => {
  23. for (const forwardedSignal of forwardedSignals) process.removeListener(forwardedSignal, forwarders[forwardedSignal])
  24. if (signal) return process.kill(process.pid, signal)
  25. process.exit(typeof code === "number" ? code : 0)
  26. })
  27. }
  28. const envPath = process.env.OPENCODE_BIN_PATH
  29. const scriptDir = path.dirname(fs.realpathSync(__filename))
  30. const cached = path.join(scriptDir, ".lildax")
  31. const platform = { darwin: "darwin", linux: "linux", win32: "windows" }[os.platform()] || os.platform()
  32. const arch = { x64: "x64", arm64: "arm64", arm: "arm" }[os.arch()] || os.arch()
  33. const base = "@opencode-ai/cli-" + platform + "-" + arch
  34. const binary = platform === "windows" ? "lildax.exe" : "lildax"
  35. function supportsAvx2() {
  36. if (arch !== "x64") return false
  37. if (platform === "linux") {
  38. try {
  39. return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
  40. } catch {
  41. return false
  42. }
  43. }
  44. if (platform === "darwin") {
  45. try {
  46. const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], { encoding: "utf8", timeout: 1500 })
  47. return result.status === 0 && (result.stdout || "").trim() === "1"
  48. } catch {
  49. return false
  50. }
  51. }
  52. if (platform === "windows") {
  53. const command =
  54. '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
  55. for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
  56. try {
  57. const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
  58. encoding: "utf8",
  59. timeout: 3000,
  60. windowsHide: true,
  61. })
  62. if (result.status !== 0) continue
  63. const output = (result.stdout || "").trim().toLowerCase()
  64. if (output === "true" || output === "1") return true
  65. if (output === "false" || output === "0") return false
  66. } catch {
  67. continue
  68. }
  69. }
  70. }
  71. return false
  72. }
  73. const names = (() => {
  74. const baseline = arch === "x64" && !supportsAvx2()
  75. if (platform === "linux") {
  76. const musl = (() => {
  77. try {
  78. if (fs.existsSync("/etc/alpine-release")) return true
  79. const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
  80. return ((result.stdout || "") + (result.stderr || "")).toLowerCase().includes("musl")
  81. } catch {
  82. return false
  83. }
  84. })()
  85. if (musl)
  86. return arch === "x64"
  87. ? baseline
  88. ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
  89. : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
  90. : [`${base}-musl`, base]
  91. return arch === "x64"
  92. ? baseline
  93. ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
  94. : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
  95. : [base, `${base}-musl`]
  96. }
  97. return arch === "x64" ? (baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]) : [base]
  98. })()
  99. function findBinary(startDir) {
  100. let current = startDir
  101. for (;;) {
  102. const modules = path.join(current, "node_modules")
  103. if (fs.existsSync(modules))
  104. for (const name of names) {
  105. const candidate = path.join(modules, name, "bin", binary)
  106. if (fs.existsSync(candidate)) return candidate
  107. }
  108. const parent = path.dirname(current)
  109. if (parent === current) return
  110. current = parent
  111. }
  112. }
  113. const resolved = envPath || (fs.existsSync(cached) ? cached : findBinary(scriptDir))
  114. if (!resolved) {
  115. console.error(
  116. "It seems that your package manager failed to install the right lildax CLI package. Try manually installing " +
  117. names.map((name) => `"${name}"`).join(" or ") +
  118. " package",
  119. )
  120. process.exit(1)
  121. }
  122. run(resolved)