opencode-ai-nofc 1.14.48 → 1.15.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +7 -7
  2. package/postinstall.mjs +155 -68
package/package.json CHANGED
@@ -6,14 +6,14 @@
6
6
  "scripts": {
7
7
  "postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
8
8
  },
9
- "version": "1.14.48",
9
+ "version": "1.15.10",
10
10
  "license": "MIT",
11
11
  "optionalDependencies": {
12
- "opencode-ai-nofc-darwin-arm64": "1.14.48",
13
- "opencode-ai-nofc-windows-x64": "1.14.48",
14
- "opencode-ai-nofc-linux-arm64": "1.14.48",
15
- "opencode-ai-nofc-linux-x64": "1.14.48",
16
- "opencode-ai-nofc-darwin-x64": "1.14.48",
17
- "opencode-ai-nofc-windows-arm64": "1.14.48"
12
+ "opencode-ai-nofc-darwin-arm64": "1.15.10",
13
+ "opencode-ai-nofc-windows-x64": "1.15.10",
14
+ "opencode-ai-nofc-linux-arm64": "1.15.10",
15
+ "opencode-ai-nofc-linux-x64": "1.15.10",
16
+ "opencode-ai-nofc-darwin-x64": "1.15.10",
17
+ "opencode-ai-nofc-windows-arm64": "1.15.10"
18
18
  }
19
19
  }
package/postinstall.mjs CHANGED
@@ -1,102 +1,189 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import childProcess from "child_process"
3
4
  import fs from "fs"
4
- import path from "path"
5
5
  import os from "os"
6
- import { fileURLToPath } from "url"
6
+ import path from "path"
7
7
  import { createRequire } from "module"
8
+ import { fileURLToPath } from "url"
8
9
 
9
10
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
10
11
  const require = createRequire(import.meta.url)
12
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"))
13
+
14
+ const platformMap = {
15
+ darwin: "darwin",
16
+ linux: "linux",
17
+ win32: "windows",
18
+ }
19
+ const archMap = {
20
+ x64: "x64",
21
+ arm64: "arm64",
22
+ arm: "arm",
23
+ }
24
+
25
+ const platform = platformMap[os.platform()] ?? os.platform()
26
+ const arch = archMap[os.arch()] ?? os.arch()
27
+ const base = `opencode-ai-nofc-${platform}-${arch}`
28
+ const sourceBinary = platform === "windows" ? "opencode.exe" : "opencode"
29
+ const targetBinary = path.join(__dirname, "bin", "opencode.exe")
30
+
31
+ function supportsAvx2() {
32
+ if (arch !== "x64") return false
33
+
34
+ if (platform === "linux") {
35
+ try {
36
+ return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
37
+ } catch {
38
+ return false
39
+ }
40
+ }
11
41
 
12
- function detectPlatformAndArch() {
13
- // Map platform names
14
- let platform
15
- switch (os.platform()) {
16
- case "darwin":
17
- platform = "darwin"
18
- break
19
- case "linux":
20
- platform = "linux"
21
- break
22
- case "win32":
23
- platform = "windows"
24
- break
25
- default:
26
- platform = os.platform()
27
- break
42
+ if (platform === "darwin") {
43
+ try {
44
+ const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
45
+ encoding: "utf8",
46
+ timeout: 1500,
47
+ })
48
+ if (result.status !== 0) return false
49
+ return (result.stdout || "").trim() === "1"
50
+ } catch {
51
+ return false
52
+ }
28
53
  }
29
54
 
30
- // Map architecture names
31
- let arch
32
- switch (os.arch()) {
33
- case "x64":
34
- arch = "x64"
35
- break
36
- case "arm64":
37
- arch = "arm64"
38
- break
39
- case "arm":
40
- arch = "arm"
41
- break
42
- default:
43
- arch = os.arch()
44
- break
55
+ if (platform === "windows") {
56
+ const command =
57
+ '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
58
+
59
+ for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
60
+ try {
61
+ const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
62
+ encoding: "utf8",
63
+ timeout: 3000,
64
+ windowsHide: true,
65
+ })
66
+ if (result.status !== 0) continue
67
+ const output = (result.stdout || "").trim().toLowerCase()
68
+ if (output === "true" || output === "1") return true
69
+ if (output === "false" || output === "0") return false
70
+ } catch {
71
+ continue
72
+ }
73
+ }
45
74
  }
46
75
 
47
- return { platform, arch }
76
+ return false
48
77
  }
49
78
 
50
- function findBinary() {
51
- const { platform, arch } = detectPlatformAndArch()
52
- const packageName = `opencode-ai-nofc-${platform}-${arch}`
53
- const binaryName = platform === "windows" ? "opencode.exe" : "opencode"
79
+ function isMusl() {
80
+ if (platform !== "linux") return false
54
81
 
55
82
  try {
56
- // Use require.resolve to find the package
57
- const packageJsonPath = require.resolve(`${packageName}/package.json`)
58
- const packageDir = path.dirname(packageJsonPath)
59
- const binaryPath = path.join(packageDir, "bin", binaryName)
83
+ if (fs.existsSync("/etc/alpine-release")) return true
84
+ } catch {
85
+ // Ignore filesystem probes that are blocked by the host.
86
+ }
60
87
 
61
- if (!fs.existsSync(binaryPath)) {
62
- throw new Error(`Binary not found at ${binaryPath}`)
88
+ try {
89
+ const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
90
+ return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl")
91
+ } catch {
92
+ return false
93
+ }
94
+ }
95
+
96
+ function packageNames() {
97
+ const baseline = arch === "x64" && !supportsAvx2()
98
+
99
+ if (platform === "linux") {
100
+ if (isMusl()) {
101
+ if (arch === "x64")
102
+ return baseline
103
+ ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
104
+ : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
105
+ return [`${base}-musl`, base]
63
106
  }
64
107
 
65
- return { binaryPath, binaryName }
66
- } catch (error) {
67
- throw new Error(`Could not find package ${packageName}: ${error.message}`, { cause: error })
108
+ if (arch === "x64")
109
+ return baseline
110
+ ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
111
+ : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
112
+ return [base, `${base}-musl`]
68
113
  }
114
+
115
+ if (arch === "x64") return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]
116
+ return [base]
117
+ }
118
+
119
+ function resolveBinary(name) {
120
+ const packageJsonPath = require.resolve(`${name}/package.json`)
121
+ const binaryPath = path.join(path.dirname(packageJsonPath), "bin", sourceBinary)
122
+ if (!fs.existsSync(binaryPath)) throw new Error(`Binary not found at ${binaryPath}`)
123
+ return binaryPath
69
124
  }
70
125
 
71
- async function main() {
126
+ function installPackage(name) {
127
+ const version = packageJson.optionalDependencies?.[name]
128
+ if (!version) return
129
+
130
+ const temp = fs.mkdtempSync(path.join(os.tmpdir(), "opencode-install-"))
72
131
  try {
73
- if (os.platform() === "win32") {
74
- // On Windows, the .exe is already included in the package and bin field points to it
75
- // No postinstall setup needed
76
- console.log("Windows detected: binary setup not needed (using packaged .exe)")
77
- return
78
- }
132
+ const result = childProcess.spawnSync(
133
+ "npm",
134
+ ["install", "--ignore-scripts", "--no-save", "--loglevel=error", "--prefix", temp, `${name}@${version}`],
135
+ { stdio: "inherit", windowsHide: true },
136
+ )
137
+ if (result.status !== 0) return
138
+ const packageDir = path.join(temp, "node_modules", name)
139
+ copyBinary(path.join(packageDir, "bin", sourceBinary), targetBinary)
140
+ return true
141
+ } finally {
142
+ fs.rmSync(temp, { recursive: true, force: true })
143
+ }
144
+ }
79
145
 
80
- // On non-Windows platforms, just verify the binary package exists
81
- // Don't replace the wrapper script - it handles binary execution
82
- const { binaryPath } = findBinary()
83
- const target = path.join(__dirname, "bin", ".opencode")
84
- if (fs.existsSync(target)) fs.unlinkSync(target)
146
+ function copyBinary(source, target) {
147
+ if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
148
+ fs.mkdirSync(path.dirname(target), { recursive: true })
149
+ if (fs.existsSync(target)) fs.unlinkSync(target)
150
+ try {
151
+ fs.linkSync(source, target)
152
+ } catch {
153
+ fs.copyFileSync(source, target)
154
+ }
155
+ fs.chmodSync(target, 0o755)
156
+ }
157
+
158
+ function verifyBinary() {
159
+ const result = childProcess.spawnSync(targetBinary, ["--version"], {
160
+ encoding: "utf8",
161
+ stdio: "ignore",
162
+ windowsHide: true,
163
+ })
164
+ return result.status === 0
165
+ }
166
+
167
+ function main() {
168
+ for (const name of packageNames()) {
85
169
  try {
86
- fs.linkSync(binaryPath, target)
170
+ copyBinary(resolveBinary(name), targetBinary)
171
+ if (verifyBinary()) return
87
172
  } catch {
88
- fs.copyFileSync(binaryPath, target)
173
+ if (installPackage(name) && verifyBinary()) return
89
174
  }
90
- fs.chmodSync(target, 0o755)
91
- } catch (error) {
92
- console.error("Failed to setup opencode binary:", error.message)
93
- process.exit(1)
94
175
  }
176
+
177
+ throw new Error(
178
+ `It seems your package manager failed to install the right opencode CLI package. Try manually installing ${packageNames()
179
+ .map((name) => JSON.stringify(name))
180
+ .join(" or ")}.`,
181
+ )
95
182
  }
96
183
 
97
184
  try {
98
- void main()
185
+ main()
99
186
  } catch (error) {
100
- console.error("Postinstall script error:", error.message)
101
- process.exit(0)
187
+ console.error(error.message)
188
+ process.exit(1)
102
189
  }