nikcli-ai 1.6.0
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.
- package/bin/nikcli +84 -0
- package/package.json +24 -0
- package/postinstall.mjs +144 -0
package/bin/nikcli
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
function run(target) {
|
|
9
|
+
const result = childProcess.spawnSync(target, process.argv.slice(2), {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
})
|
|
12
|
+
if (result.error) {
|
|
13
|
+
console.error(result.error.message)
|
|
14
|
+
process.exit(1)
|
|
15
|
+
}
|
|
16
|
+
const code = typeof result.status === "number" ? result.status : 0
|
|
17
|
+
process.exit(code)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const envPath = process.env.NIKCLI_BIN_PATH
|
|
21
|
+
if (envPath) {
|
|
22
|
+
run(envPath)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const scriptPath = fs.realpathSync(__filename)
|
|
26
|
+
const scriptDir = path.dirname(scriptPath)
|
|
27
|
+
|
|
28
|
+
const platformMap = {
|
|
29
|
+
darwin: "darwin",
|
|
30
|
+
linux: "linux",
|
|
31
|
+
win32: "windows",
|
|
32
|
+
}
|
|
33
|
+
const archMap = {
|
|
34
|
+
x64: "x64",
|
|
35
|
+
arm64: "arm64",
|
|
36
|
+
arm: "arm",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let platform = platformMap[os.platform()]
|
|
40
|
+
if (!platform) {
|
|
41
|
+
platform = os.platform()
|
|
42
|
+
}
|
|
43
|
+
let arch = archMap[os.arch()]
|
|
44
|
+
if (!arch) {
|
|
45
|
+
arch = os.arch()
|
|
46
|
+
}
|
|
47
|
+
const base = "nikcli-ai-" + platform + "-" + arch
|
|
48
|
+
const binary = platform === "windows" ? "nikcli.exe" : "nikcli"
|
|
49
|
+
|
|
50
|
+
function findBinary(startDir) {
|
|
51
|
+
let current = startDir
|
|
52
|
+
for (;;) {
|
|
53
|
+
const modules = path.join(current, "node_modules")
|
|
54
|
+
if (fs.existsSync(modules)) {
|
|
55
|
+
const entries = fs.readdirSync(modules)
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
if (!entry.startsWith(base)) {
|
|
58
|
+
continue
|
|
59
|
+
}
|
|
60
|
+
const candidate = path.join(modules, entry, "bin", binary)
|
|
61
|
+
if (fs.existsSync(candidate)) {
|
|
62
|
+
return candidate
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const parent = path.dirname(current)
|
|
67
|
+
if (parent === current) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
current = parent
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const resolved = findBinary(scriptDir)
|
|
75
|
+
if (!resolved) {
|
|
76
|
+
console.error(
|
|
77
|
+
'It seems that your package manager failed to install the right version of the nikcli CLI for your platform. You can try manually installing the "' +
|
|
78
|
+
base +
|
|
79
|
+
'" package',
|
|
80
|
+
)
|
|
81
|
+
process.exit(1)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
run(resolved)
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nikcli-ai",
|
|
3
|
+
"bin": {
|
|
4
|
+
"nikcli": "./bin/nikcli"
|
|
5
|
+
},
|
|
6
|
+
"scripts": {
|
|
7
|
+
"postinstall": "bun ./postinstall.mjs || node ./postinstall.mjs"
|
|
8
|
+
},
|
|
9
|
+
"version": "1.6.0",
|
|
10
|
+
"optionalDependencies": {
|
|
11
|
+
"nikcli-ai-linux-arm64": "1.6.0",
|
|
12
|
+
"nikcli-ai-linux-x64": "1.6.0",
|
|
13
|
+
"nikcli-ai-linux-x64-baseline": "1.6.0",
|
|
14
|
+
"nikcli-ai-linux-arm64-musl": "1.6.0",
|
|
15
|
+
"nikcli-ai-linux-x64-musl": "1.6.0",
|
|
16
|
+
"nikcli-ai-linux-x64-baseline-musl": "1.6.0",
|
|
17
|
+
"nikcli-ai-darwin-arm64": "1.6.0",
|
|
18
|
+
"nikcli-ai-darwin-x64": "1.6.0",
|
|
19
|
+
"nikcli-ai-darwin-x64-baseline": "1.6.0",
|
|
20
|
+
"nikcli-ai-windows-arm64": "1.6.0",
|
|
21
|
+
"nikcli-ai-windows-x64": "1.6.0",
|
|
22
|
+
"nikcli-ai-windows-x64-baseline": "1.6.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/postinstall.mjs
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs"
|
|
4
|
+
import path from "path"
|
|
5
|
+
import os from "os"
|
|
6
|
+
import { execSync } from "child_process"
|
|
7
|
+
import { fileURLToPath } from "url"
|
|
8
|
+
import { createRequire } from "module"
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
11
|
+
const require = createRequire(import.meta.url)
|
|
12
|
+
|
|
13
|
+
function detectPlatformAndArch() {
|
|
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
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let arch
|
|
31
|
+
switch (os.arch()) {
|
|
32
|
+
case "x64":
|
|
33
|
+
arch = "x64"
|
|
34
|
+
break
|
|
35
|
+
case "arm64":
|
|
36
|
+
arch = "arm64"
|
|
37
|
+
break
|
|
38
|
+
default:
|
|
39
|
+
arch = os.arch()
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return { platform, arch }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function detectMusl() {
|
|
47
|
+
if (os.platform() !== "linux") return false
|
|
48
|
+
try {
|
|
49
|
+
const ldd = execSync("ldd --version 2>&1", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
|
|
50
|
+
if (ldd.toLowerCase().includes("musl")) return true
|
|
51
|
+
} catch {}
|
|
52
|
+
return fs.existsSync("/etc/alpine-release")
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function detectBaseline() {
|
|
56
|
+
if (os.platform() === "linux") {
|
|
57
|
+
try {
|
|
58
|
+
const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8")
|
|
59
|
+
return !cpuinfo.includes("avx2")
|
|
60
|
+
} catch {}
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
if (os.platform() === "darwin") {
|
|
64
|
+
try {
|
|
65
|
+
const avx2 = execSync("sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0", { encoding: "utf8" }).trim()
|
|
66
|
+
return avx2 !== "1"
|
|
67
|
+
} catch {}
|
|
68
|
+
}
|
|
69
|
+
return false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function tryResolvePackage(packageName, binaryName) {
|
|
73
|
+
try {
|
|
74
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`)
|
|
75
|
+
const packageDir = path.dirname(packageJsonPath)
|
|
76
|
+
const binaryPath = path.join(packageDir, "bin", binaryName)
|
|
77
|
+
if (!fs.existsSync(binaryPath)) return null
|
|
78
|
+
return binaryPath
|
|
79
|
+
} catch {
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function findBinary() {
|
|
85
|
+
const { platform, arch } = detectPlatformAndArch()
|
|
86
|
+
const binaryName = platform === "windows" ? "nikcli.exe" : "nikcli"
|
|
87
|
+
const isMusl = platform === "linux" ? detectMusl() : false
|
|
88
|
+
const isBaseline = arch === "x64" ? detectBaseline() : false
|
|
89
|
+
|
|
90
|
+
// Try in order: most specific → least specific
|
|
91
|
+
const candidates = []
|
|
92
|
+
|
|
93
|
+
if (isBaseline && isMusl) candidates.push(`nikcli-ai-${platform}-${arch}-baseline-musl`)
|
|
94
|
+
if (isBaseline && !isMusl) candidates.push(`nikcli-ai-${platform}-${arch}-baseline`)
|
|
95
|
+
if (!isBaseline && isMusl) candidates.push(`nikcli-ai-${platform}-${arch}-musl`)
|
|
96
|
+
candidates.push(`nikcli-ai-${platform}-${arch}`)
|
|
97
|
+
// Final fallbacks (skip musl/baseline restriction)
|
|
98
|
+
if (isMusl) candidates.push(`nikcli-ai-${platform}-${arch}`)
|
|
99
|
+
if (isBaseline) candidates.push(`nikcli-ai-${platform}-${arch}`)
|
|
100
|
+
|
|
101
|
+
for (const name of candidates) {
|
|
102
|
+
const found = tryResolvePackage(name, binaryName)
|
|
103
|
+
if (found) {
|
|
104
|
+
console.log(`nikcli: resolved binary from ${name}`)
|
|
105
|
+
return { binaryPath: found, binaryName }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Could not find nikcli binary for ${platform}-${arch}${isMusl ? " (musl)" : ""}${isBaseline ? " (baseline)" : ""}.\n` +
|
|
111
|
+
`Tried: ${candidates.join(", ")}\n` +
|
|
112
|
+
`Install manually: https://nikcli.store/install`,
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function prepareBinDirectory(binaryName) {
|
|
117
|
+
const binDir = path.join(__dirname, "..", "bin")
|
|
118
|
+
const targetPath = path.join(binDir, binaryName)
|
|
119
|
+
if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true })
|
|
120
|
+
if (fs.existsSync(targetPath)) fs.unlinkSync(targetPath)
|
|
121
|
+
return { binDir, targetPath }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function symlinkBinary(sourcePath, binaryName) {
|
|
125
|
+
const { targetPath } = prepareBinDirectory(binaryName)
|
|
126
|
+
fs.symlinkSync(sourcePath, targetPath)
|
|
127
|
+
if (!fs.existsSync(targetPath)) throw new Error(`Failed to symlink binary to ${targetPath}`)
|
|
128
|
+
console.log(`nikcli: ${targetPath} -> ${sourcePath}`)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function main() {
|
|
132
|
+
if (os.platform() === "win32") {
|
|
133
|
+
console.log("nikcli: Windows detected, skipping postinstall symlink")
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const { binaryPath, binaryName } = findBinary()
|
|
138
|
+
symlinkBinary(binaryPath, binaryName)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
main().catch((error) => {
|
|
142
|
+
console.error("nikcli postinstall failed:", error.message)
|
|
143
|
+
process.exit(1)
|
|
144
|
+
})
|