@nemoobc/opencode-termux 1.18.23 β 1.18.26
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/README.md +55 -19
- package/bin/opencode.js +9 -7
- package/install.mjs +30 -9
- package/package.json +9 -2
- package/prebuilt/ld-musl-aarch64-termux.so +0 -0
package/README.md
CHANGED
|
@@ -1,39 +1,75 @@
|
|
|
1
|
-
#
|
|
1
|
+
# π± opencode-termux
|
|
2
2
|
|
|
3
|
-
**opencode CLI native di Termux/Android β TANPA proot.**
|
|
3
|
+
**[opencode](https://opencode.ai) CLI native di Termux/Android β TANPA proot, TANPA root.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
lalu menjalankannya lewat loader tersebut β murni userspace.
|
|
5
|
+
[](https://www.npmjs.com/package/@nemoobc/opencode-termux)
|
|
6
|
+
[](#)
|
|
7
|
+
[](#)
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Kenapa paket ini ada?
|
|
12
|
+
|
|
13
|
+
Installer resmi `opencode-ai` gagal di Termux karena tidak mengenali
|
|
14
|
+
`process.platform === "android"` dan tidak menyediakan build untuk Bionic libc.
|
|
15
|
+
|
|
16
|
+
Paket ini menjembatani tanpa trik aneh:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
opencode-termux (shim Node)
|
|
20
|
+
ββ vendor/ld-musl.so β musl libc hasil build khusus Termux*
|
|
21
|
+
ββ vendor/opencode β binary resmi opencode-linux-arm64-musl
|
|
22
|
+
β€³ LD_LIBRARY_PATH β libstdc++ / libgcc_s (dari Alpine)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
\* path `/etc/resolv.conf` & `/etc/hosts` dipatch saat kompilasi menuju
|
|
26
|
+
`$PREFIX/etc/` sehingga DNS jalan tanpa root.
|
|
27
|
+
|
|
28
|
+
## π Install
|
|
11
29
|
|
|
12
30
|
```bash
|
|
13
31
|
pkg update && pkg install nodejs-lts
|
|
14
32
|
npm i -g @nemoobc/opencode-termux
|
|
15
|
-
opencode-termux --version
|
|
16
33
|
```
|
|
17
34
|
|
|
35
|
+
> Jika muncul warning `install-scripts`, izinkan sekali:
|
|
36
|
+
> ```bash
|
|
37
|
+
> npm config set allow-scripts=@nemoobc/opencode-termux --location=user
|
|
38
|
+
> npm rebuild -g @nemoobc/opencode-termux
|
|
39
|
+
> ```
|
|
40
|
+
> (atau abaikan β shim akan memasang bundle otomatis saat pertama dijalankan)
|
|
41
|
+
|
|
18
42
|
Alias biar terasa asli:
|
|
19
43
|
|
|
20
44
|
```bash
|
|
21
45
|
ln -sf $PREFIX/bin/opencode-termux $PREFIX/bin/opencode
|
|
22
46
|
```
|
|
23
47
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## Cara kerja
|
|
48
|
+
## β
Verifikasi
|
|
27
49
|
|
|
50
|
+
```bash
|
|
51
|
+
opencode-termux --version # versi upstream opencode
|
|
52
|
+
opencode-termux models # katalog model (tes jaringan/DNS)
|
|
28
53
|
```
|
|
29
|
-
opencode-termux β ld-musl-aarch64.so.1 (dibundel) β opencode (musl, dibundel)
|
|
30
|
-
β LD_LIBRARY_PATH: libstdc++/libgcc (dibundel)
|
|
31
|
-
```
|
|
32
54
|
|
|
33
|
-
|
|
55
|
+
Model gratis default: **`opencode/x-preview-f-free`** (Ox Alpha Free Β· Unlimited).
|
|
56
|
+
|
|
57
|
+
## π§ Troubleshooting
|
|
58
|
+
|
|
59
|
+
| Masalah | Solusi |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `Permission denied` saat menjalankan | `chmod +x $PREFIX/lib/node_modules/@nemoobc/opencode-termux/bin/opencode.js` |
|
|
62
|
+
| Warning `install-scripts` | lihat bagian Install |
|
|
63
|
+
| Perintah jaringan gantung | pastikan `$PREFIX/etc/resolv.conf` ada β installer/shim membuatnya otomatis |
|
|
64
|
+
| Versi upstream lama | `npm i -g @nemoobc/opencode-termux@latest` β installer selalu tarik rilis terbaru |
|
|
65
|
+
|
|
66
|
+
## βοΈ Variabel lingkungan
|
|
67
|
+
|
|
68
|
+
| Var | Fungsi |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `OCX_UPSTREAM` | paksa versi upstream tertentu (default: terbaru) |
|
|
71
|
+
| `OCX_ARCH` / `OCX_FORCE` | uji bundle di non-Android (`x64`) |
|
|
34
72
|
|
|
35
|
-
##
|
|
73
|
+
## π Lisensi
|
|
36
74
|
|
|
37
|
-
|
|
38
|
-
- Butuh koneksi internet saat `npm install` (mengunduh ~200 MB binary)
|
|
39
|
-
- Jika upstream opencode rilis versi baru, paket ini perlu bump versi mengikuti
|
|
75
|
+
MIT. Binary opencode adalah milik proyek [opencode](https://github.com/sst/opencode) (MIT).
|
package/bin/opencode.js
CHANGED
|
@@ -26,14 +26,16 @@ if (!ready()) {
|
|
|
26
26
|
|
|
27
27
|
if (!ready()) process.exit(1)
|
|
28
28
|
|
|
29
|
-
//
|
|
29
|
+
// DNS fix: musl hasil build kita membaca config dari prefix Termux β
|
|
30
|
+
// pastikan filenya ada (bisa ditulis tanpa root).
|
|
30
31
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const PREFIX = process.env.TERMUX_PREFIX || "/data/data/com.termux/files/usr"
|
|
33
|
+
const etc = path.join(PREFIX, "etc")
|
|
34
|
+
fs.mkdirSync(etc, { recursive: true })
|
|
35
|
+
const rc = path.join(etc, "resolv.conf")
|
|
36
|
+
if (!fs.existsSync(rc)) fs.writeFileSync(rc, "nameserver 1.1.1.1\nnameserver 8.8.8.8\n")
|
|
37
|
+
const hh = path.join(etc, "hosts")
|
|
38
|
+
if (!fs.existsSync(hh)) fs.writeFileSync(hh, "127.0.0.1 localhost\n")
|
|
37
39
|
} catch {}
|
|
38
40
|
|
|
39
41
|
// LD_PRELOAD bawaan Termux (libtermux-exec) dibuat untuk Bionic dan akan
|
package/install.mjs
CHANGED
|
@@ -54,32 +54,53 @@ const untar = (tgz, dest, members = []) => {
|
|
|
54
54
|
const work = path.join(__dirname, ".build")
|
|
55
55
|
fs.rmSync(work, { recursive: true, force: true })
|
|
56
56
|
fs.mkdirSync(work, { recursive: true })
|
|
57
|
+
const AV = "v3.21", AL = "3.21.3"
|
|
57
58
|
|
|
58
59
|
// 1) binary opencode (musl) dari npm resmi
|
|
59
60
|
await dl(`https://registry.npmjs.org/opencode-linux-${ARCH}-musl/-/opencode-linux-${ARCH}-musl-${V}.tgz`, `${work}/oc.tgz`)
|
|
60
61
|
untar(`${work}/oc.tgz`, `${work}/oc`)
|
|
61
62
|
|
|
62
|
-
// 2)
|
|
63
|
-
const AV = "v3.21", AL = "3.21.3"
|
|
64
|
-
await dl(`https://dl-cdn.alpinelinux.org/alpine/${AV}/releases/${A}/alpine-minirootfs-${AL}-${A}.tar.gz`, `${work}/ap.tgz`)
|
|
65
|
-
untar(`${work}/ap.tgz`, `${work}/ap`, ["lib"])
|
|
66
|
-
|
|
67
|
-
// 3) libgcc + libstdc++
|
|
63
|
+
// 2) libgcc + libstdc++
|
|
68
64
|
const apkDir = `${work}/apk`; fs.mkdirSync(apkDir, { recursive: true })
|
|
69
65
|
for (const f of [`libgcc-14.2.0-r4.apk`, `libstdc%2B%2B-14.2.0-r4.apk`]) {
|
|
70
66
|
await dl(`https://dl-cdn.alpinelinux.org/alpine/${AV}/main/${A}/${f}`, `${apkDir}/${f}`)
|
|
71
67
|
untar(`${apkDir}/${f}`, apkDir)
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
//
|
|
70
|
+
// 3) rakit vendor/
|
|
75
71
|
const vendor = path.join(__dirname, "vendor")
|
|
76
72
|
fs.rmSync(vendor, { recursive: true, force: true }); fs.mkdirSync(vendor)
|
|
77
|
-
const cp = (
|
|
78
|
-
|
|
73
|
+
const cp = (dir, name) => fs.copyFileSync(path.join(dir, name), path.join(vendor, name))
|
|
74
|
+
if (A === "aarch64") {
|
|
75
|
+
// loader hasil build khusus: resolv.conf & hosts menunjuk ke prefix Termux
|
|
76
|
+
cp(path.join(__dirname, "prebuilt"), "ld-musl-aarch64-termux.so")
|
|
77
|
+
fs.renameSync(path.join(vendor, "ld-musl-aarch64-termux.so"), path.join(vendor, "ld-musl.so"))
|
|
78
|
+
} else {
|
|
79
|
+
const mini = `${work}/ap`; await dl(
|
|
80
|
+
`https://dl-cdn.alpinelinux.org/alpine/${AV}/releases/${A}/alpine-minirootfs-${AL}-${A}.tar.gz`, `${work}/ap.tgz`)
|
|
81
|
+
untar(`${work}/ap.tgz`, mini, ["lib"])
|
|
82
|
+
cp(`${mini}/lib`, `ld-musl-${A}.so.1`); fs.renameSync(path.join(vendor, `ld-musl-${A}.so.1`), path.join(vendor, "ld-musl.so"))
|
|
83
|
+
}
|
|
79
84
|
cp(`${work}/oc/package/bin`, "opencode")
|
|
80
85
|
cp(`${apkDir}/usr/lib`, "libstdc++.so.6"); cp(`${apkDir}/usr/lib`, "libstdc++.so.6.0.33"); cp(`${apkDir}/usr/lib`, "libgcc_s.so.1")
|
|
81
86
|
for (const f of fs.readdirSync(vendor)) fs.chmodSync(path.join(vendor, f), 0o755)
|
|
82
87
|
|
|
88
|
+
// 4) siapkan DNS config di prefix Termux (bisa ditulis TANPA root)
|
|
89
|
+
function ensureEtc() {
|
|
90
|
+
try {
|
|
91
|
+
const PREFIX = process.env.TERMUX_PREFIX || "/data/data/com.termux/files/usr"
|
|
92
|
+
const etc = path.join(PREFIX, "etc")
|
|
93
|
+
fs.mkdirSync(etc, { recursive: true })
|
|
94
|
+
const rc = path.join(etc, "resolv.conf")
|
|
95
|
+
if (!fs.existsSync(rc)) fs.writeFileSync(rc, "nameserver 1.1.1.1\nnameserver 8.8.8.8\n")
|
|
96
|
+
const hh = path.join(etc, "hosts")
|
|
97
|
+
if (!fs.existsSync(hh)) fs.writeFileSync(hh, "127.0.0.1 localhost\n")
|
|
98
|
+
} catch (e) {
|
|
99
|
+
if (!FORCE && IS_ANDROID) throw e
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
ensureEtc()
|
|
103
|
+
|
|
83
104
|
// 5) smoke test (LD_PRELOAD termux-exec dibuang: tidak kompatibel dengan musl)
|
|
84
105
|
console.log("[opencode-termux] smoke testβ¦")
|
|
85
106
|
const { LD_PRELOAD, LD_PRELOAD_32BIT, ...cleanEnv } = process.env
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nemoobc/opencode-termux",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.26",
|
|
4
4
|
"description": "opencode CLI native untuk Termux/Android tanpa proot β membundel loader musl + binary opencode resmi (upstream opencode-ai)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"opencode-termux": "./bin/opencode.js"
|
|
@@ -22,6 +22,13 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
"bin",
|
|
24
24
|
"install.mjs",
|
|
25
|
+
"prebuilt",
|
|
25
26
|
"README.md"
|
|
26
|
-
]
|
|
27
|
+
],
|
|
28
|
+
"opencodeUpstream": "1.18.21",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/nemoobc/opencode-termux.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/nemoobc/opencode-termux#readme"
|
|
27
34
|
}
|
|
Binary file
|