opencode-node 0.0.0-next-15778 → 0.0.0-next-15781

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.
@@ -0,0 +1,5 @@
1
+ echo "Error: opencode-node's postinstall script was not run." >&2
2
+ echo "" >&2
3
+ echo "This occurs when installation scripts are disabled." >&2
4
+ echo "Run the package postinstall script or reinstall with scripts enabled." >&2
5
+ exit 1
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "opencode-node",
3
3
  "bin": {
4
- "opencode2-node": "./bin/opencode2-node"
4
+ "opencode2-node": "./bin/opencode2-node.exe"
5
5
  },
6
- "version": "0.0.0-next-15778",
6
+ "scripts": {
7
+ "postinstall": "node ./postinstall.mjs"
8
+ },
9
+ "version": "0.0.0-next-15781",
7
10
  "license": "MIT",
8
11
  "repository": {
9
12
  "type": "git",
@@ -19,10 +22,10 @@
19
22
  "x64"
20
23
  ],
21
24
  "optionalDependencies": {
22
- "@opencode-ai/cli-node-linux-x64": "0.0.0-next-15778",
23
- "@opencode-ai/cli-node-linux-arm64": "0.0.0-next-15778",
24
- "@opencode-ai/cli-node-windows-x64": "0.0.0-next-15778",
25
- "@opencode-ai/cli-node-windows-arm64": "0.0.0-next-15778",
26
- "@opencode-ai/cli-node-darwin-arm64": "0.0.0-next-15778"
25
+ "@opencode-ai/cli-node-darwin-arm64": "0.0.0-next-15781",
26
+ "@opencode-ai/cli-node-windows-x64": "0.0.0-next-15781",
27
+ "@opencode-ai/cli-node-windows-arm64": "0.0.0-next-15781",
28
+ "@opencode-ai/cli-node-linux-x64": "0.0.0-next-15781",
29
+ "@opencode-ai/cli-node-linux-arm64": "0.0.0-next-15781"
27
30
  }
28
31
  }
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+
3
+ import childProcess from "node:child_process"
4
+ import fs from "node:fs"
5
+ import os from "node:os"
6
+ import path from "node:path"
7
+ import { createRequire } from "node:module"
8
+ import { fileURLToPath } from "node:url"
9
+
10
+ const directory = path.dirname(fileURLToPath(import.meta.url))
11
+ const require = createRequire(import.meta.url)
12
+ const packageJson = JSON.parse(fs.readFileSync(path.join(directory, "package.json"), "utf8"))
13
+ const command = Object.keys(packageJson.bin ?? {})[0]
14
+ if (!command) throw new Error("OpenCode package does not declare a binary")
15
+
16
+ const platform = { darwin: "darwin", linux: "linux", win32: "windows" }[os.platform()] ?? os.platform()
17
+ const arch = { x64: "x64", arm64: "arm64", arm: "arm" }[os.arch()] ?? os.arch()
18
+ const sourceBinary = platform === "windows" ? `${command}.exe` : command
19
+ const targetBinary = path.resolve(directory, packageJson.bin[command])
20
+ const dependencies = packageJson.optionalDependencies ?? {}
21
+ const base = Object.keys(dependencies).find((name) => name.endsWith(`-${platform}-${arch}`))
22
+ if (!base) throw new Error(`OpenCode does not provide a binary for ${platform}-${arch}`)
23
+
24
+ function supportsAvx2() {
25
+ if (arch !== "x64") return false
26
+ if (platform === "linux") {
27
+ try {
28
+ return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
29
+ } catch {
30
+ return false
31
+ }
32
+ }
33
+ if (platform === "darwin") {
34
+ try {
35
+ const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
36
+ encoding: "utf8",
37
+ timeout: 1500,
38
+ })
39
+ return result.status === 0 && (result.stdout || "").trim() === "1"
40
+ } catch {
41
+ return false
42
+ }
43
+ }
44
+ if (platform === "windows") {
45
+ const script =
46
+ '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
47
+ for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
48
+ try {
49
+ const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", script], {
50
+ encoding: "utf8",
51
+ timeout: 3000,
52
+ windowsHide: true,
53
+ })
54
+ if (result.status !== 0) continue
55
+ const output = (result.stdout || "").trim().toLowerCase()
56
+ if (output === "true" || output === "1") return true
57
+ if (output === "false" || output === "0") return false
58
+ } catch {
59
+ continue
60
+ }
61
+ }
62
+ }
63
+ return false
64
+ }
65
+
66
+ function isMusl() {
67
+ if (platform !== "linux") return false
68
+ try {
69
+ if (fs.existsSync("/etc/alpine-release")) return true
70
+ const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
71
+ return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl")
72
+ } catch {
73
+ return false
74
+ }
75
+ }
76
+
77
+ function packageNames() {
78
+ const baseline = arch === "x64" && !supportsAvx2()
79
+ const names =
80
+ platform === "linux"
81
+ ? isMusl()
82
+ ? arch === "x64"
83
+ ? baseline
84
+ ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
85
+ : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
86
+ : [`${base}-musl`, base]
87
+ : arch === "x64"
88
+ ? baseline
89
+ ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
90
+ : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
91
+ : [base, `${base}-musl`]
92
+ : arch === "x64"
93
+ ? baseline
94
+ ? [`${base}-baseline`, base]
95
+ : [base, `${base}-baseline`]
96
+ : [base]
97
+ return names.filter((name) => dependencies[name])
98
+ }
99
+
100
+ function copyBinary(source) {
101
+ if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
102
+ fs.mkdirSync(path.dirname(targetBinary), { recursive: true })
103
+ if (fs.existsSync(targetBinary)) fs.unlinkSync(targetBinary)
104
+ try {
105
+ fs.linkSync(source, targetBinary)
106
+ } catch {
107
+ fs.copyFileSync(source, targetBinary)
108
+ }
109
+ fs.chmodSync(targetBinary, 0o755)
110
+ }
111
+
112
+ function resolveBinary(name) {
113
+ const packagePath = require.resolve(`${name}/package.json`)
114
+ return path.join(path.dirname(packagePath), "bin", sourceBinary)
115
+ }
116
+
117
+ function installPackage(name) {
118
+ const temp = fs.mkdtempSync(path.join(os.tmpdir(), "opencode-install-"))
119
+ try {
120
+ const result = childProcess.spawnSync(
121
+ "npm",
122
+ ["install", "--ignore-scripts", "--no-save", "--loglevel=error", "--prefix", temp, `${name}@${dependencies[name]}`],
123
+ { stdio: "inherit", windowsHide: true },
124
+ )
125
+ if (result.status !== 0) return false
126
+ copyBinary(path.join(temp, "node_modules", name, "bin", sourceBinary))
127
+ return true
128
+ } finally {
129
+ fs.rmSync(temp, { recursive: true, force: true })
130
+ }
131
+ }
132
+
133
+ function verifyBinary() {
134
+ return (
135
+ childProcess.spawnSync(targetBinary, ["--version"], {
136
+ stdio: "ignore",
137
+ windowsHide: true,
138
+ }).status === 0
139
+ )
140
+ }
141
+
142
+ function main() {
143
+ const names = packageNames()
144
+ for (const name of names) {
145
+ try {
146
+ copyBinary(resolveBinary(name))
147
+ if (verifyBinary()) return
148
+ } catch {
149
+ if (installPackage(name) && verifyBinary()) return
150
+ }
151
+ }
152
+
153
+ throw new Error(`Failed to install OpenCode. Try manually installing ${names.map((name) => JSON.stringify(name)).join(" or ")}.`)
154
+ }
155
+
156
+ try {
157
+ main()
158
+ } catch (error) {
159
+ console.error(error instanceof Error ? error.message : String(error))
160
+ process.exit(1)
161
+ }
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const childProcess = require("child_process")
4
- const fs = require("fs")
5
- const path = require("path")
6
- const os = require("os")
7
-
8
- const forwardedSignals = ["SIGINT", "SIGTERM", "SIGHUP"]
9
-
10
- function run(target) {
11
- const child = childProcess.spawn(target, process.argv.slice(2), { stdio: "inherit" })
12
- child.on("error", (error) => {
13
- console.error(error.message)
14
- process.exit(1)
15
- })
16
- const forwarders = {}
17
- for (const signal of forwardedSignals) {
18
- forwarders[signal] = () => {
19
- try {
20
- child.kill(signal)
21
- } catch {}
22
- }
23
- process.on(signal, forwarders[signal])
24
- }
25
- child.on("exit", (code, signal) => {
26
- for (const forwardedSignal of forwardedSignals) process.removeListener(forwardedSignal, forwarders[forwardedSignal])
27
- if (signal) return process.kill(process.pid, signal)
28
- process.exit(typeof code === "number" ? code : 0)
29
- })
30
- }
31
-
32
- const envPath = process.env.OPENCODE_BIN_PATH
33
- const scriptDir = path.dirname(fs.realpathSync(__filename))
34
- const command = path.basename(__filename).replace(/\.cjs$/, "")
35
- const nodeBuild = command === "opencode2-node"
36
- const cached = path.join(scriptDir, `.${command}`)
37
- const platform = { darwin: "darwin", linux: "linux", win32: "windows" }[os.platform()] || os.platform()
38
- const arch = { x64: "x64", arm64: "arm64", arm: "arm" }[os.arch()] || os.arch()
39
- const base = `@opencode-ai/cli${nodeBuild ? "-node" : ""}-` + platform + "-" + arch
40
- const binary = platform === "windows" ? `${command}.exe` : command
41
-
42
- function supportsAvx2() {
43
- if (arch !== "x64") return false
44
- if (platform === "linux") {
45
- try {
46
- return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
47
- } catch {
48
- return false
49
- }
50
- }
51
- if (platform === "darwin") {
52
- try {
53
- const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], { encoding: "utf8", timeout: 1500 })
54
- return result.status === 0 && (result.stdout || "").trim() === "1"
55
- } catch {
56
- return false
57
- }
58
- }
59
- if (platform === "windows") {
60
- const command =
61
- '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
62
- for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
63
- try {
64
- const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
65
- encoding: "utf8",
66
- timeout: 3000,
67
- windowsHide: true,
68
- })
69
- if (result.status !== 0) continue
70
- const output = (result.stdout || "").trim().toLowerCase()
71
- if (output === "true" || output === "1") return true
72
- if (output === "false" || output === "0") return false
73
- } catch {
74
- continue
75
- }
76
- }
77
- }
78
- return false
79
- }
80
-
81
- const names = (() => {
82
- if (nodeBuild) return [base]
83
- const baseline = arch === "x64" && !supportsAvx2()
84
- if (platform === "linux") {
85
- const musl = (() => {
86
- try {
87
- if (fs.existsSync("/etc/alpine-release")) return true
88
- const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
89
- return ((result.stdout || "") + (result.stderr || "")).toLowerCase().includes("musl")
90
- } catch {
91
- return false
92
- }
93
- })()
94
- if (musl)
95
- return arch === "x64"
96
- ? baseline
97
- ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
98
- : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
99
- : [`${base}-musl`, base]
100
- return arch === "x64"
101
- ? baseline
102
- ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
103
- : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
104
- : [base, `${base}-musl`]
105
- }
106
- return arch === "x64" ? (baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]) : [base]
107
- })()
108
-
109
- function findBinary(startDir) {
110
- let current = startDir
111
- for (;;) {
112
- const modules = path.join(current, "node_modules")
113
- if (fs.existsSync(modules))
114
- for (const name of names) {
115
- const candidate = path.join(modules, name, "bin", binary)
116
- if (fs.existsSync(candidate)) return candidate
117
- }
118
- const parent = path.dirname(current)
119
- if (parent === current) return
120
- current = parent
121
- }
122
- }
123
-
124
- const resolved = envPath || (fs.existsSync(cached) ? cached : findBinary(scriptDir))
125
- if (!resolved) {
126
- console.error(
127
- `It seems that your package manager failed to install the right ${command} CLI package. Try manually installing ` +
128
- names.map((name) => `"${name}"`).join(" or ") +
129
- " package",
130
- )
131
- process.exit(1)
132
- }
133
- run(resolved)