@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 CHANGED
@@ -1,39 +1,75 @@
1
- # @nemoobc/opencode-termux
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
- Paket ini menjembatani masalah: `opencode-ai` resmi tidak punya target `android`,
6
- sehingga postinstall gagal di Termux. Solusinya: paket ini mengunduh binary
7
- resmi `opencode-linux-arm64-musl` + **loader musl & libstdc++/libgcc dari Alpine**,
8
- lalu menjalankannya lewat loader tersebut β€” murni userspace.
5
+ [![npm](https://img.shields.io/npm/v/@nemoobc/opencode-termux?color=cb3837&logo=npm)](https://www.npmjs.com/package/@nemoobc/opencode-termux)
6
+ [![platform](https://img.shields.io/badge/platform-Android%20%7C%20Termux-3DDC84)](#)
7
+ [![arch](https://img.shields.io/badge/arch-arm64-blue)](#)
9
8
 
10
- ## Install
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
- Default model gratis: `opencode/x-preview-f-free` (Ox Alpha Free).
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
- Tidak ada file sistem Android yang disentuh. Semua ada di `$PREFIX/lib/node_modules/@nemoobc/opencode-termux/vendor`.
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
- ## Batasan
73
+ ## πŸ“œ Lisensi
36
74
 
37
- - Arsitektur: **arm64** (hampir semua HP sekarang). x86_64 bisa dipaksa utk uji: `OCX_ARCH=x64 OCX_FORCE=1 npm rebuild ...`
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
- // Diagnosa awal: Android sering tidak punya /etc/resolv.conf yang dibaca musl.
29
+ // DNS fix: musl hasil build kita membaca config dari prefix Termux β€”
30
+ // pastikan filenya ada (bisa ditulis tanpa root).
30
31
  try {
31
- if (!fs.existsSync("/etc/resolv.conf")) {
32
- console.error("[opencode-termux] ⚠️ /etc/resolv.conf tidak ada di device ini;")
33
- console.error(" kalau perintah jaringan (models/login) gagal/gantung, itu sebabnya.")
34
- console.error(" Solusi sementara (butuh akses root):")
35
- console.error(' su -c \'mkdir -p /etc && echo "nameserver 8.8.8.8" > /etc/resolv.conf\'')
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) loader+libc musl dari Alpine minirootfs
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
- // 4) rakit vendor/
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 = (from, name) => fs.copyFileSync(path.join(from, name), path.join(vendor, name))
78
- cp(`${work}/ap/lib`, `ld-musl-${A}.so.1`); fs.renameSync(path.join(vendor, `ld-musl-${A}.so.1`), path.join(vendor, "ld-musl.so"))
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.23",
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
  }