-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathinstall-opencode.sh
More file actions
245 lines (207 loc) Β· 7.81 KB
/
Copy pathinstall-opencode.sh
File metadata and controls
245 lines (207 loc) Β· 7.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/usr/bin/env bash
# install-opencode.sh - Install OpenCode on Termux
# Uses proot + ld.so concatenation for Bun standalone binaries.
#
# This script is NON-CRITICAL: failure does not affect OpenClaw.
#
# Why proot + ld.so concatenation?
# 1. Bun uses raw syscalls (LD_PRELOAD shims don't work)
# 2. patchelf causes SIGSEGV on Android (seccomp)
# 3. Bun standalone reads embedded JS via /proc/self/exe offset
# β grun makes /proc/self/exe point to ld.so, breaking this
# β concatenating ld.so + binary data fixes the offset math
set -euo pipefail
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
OPENCLAW_DIR="$HOME/.oca"
GLIBC_LDSO="$PREFIX/glibc/lib/ld-linux-aarch64.so.1"
PROOT_ROOT="$OPENCLAW_DIR/proot-root"
fail_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
exit 0
}
echo "=== RTXβ‘3 β Installing OpenCode ==="
echo ""
# ββ Pre-checks βββββββββββββββββββββββββββββββ
if [ ! -f "$OPENCLAW_DIR/.glibc-arch" ]; then
fail_warn "glibc environment not installed β skipping OpenCode install"
fi
if [ ! -x "$GLIBC_LDSO" ]; then
fail_warn "glibc dynamic linker not found β skipping OpenCode install"
fi
if ! command -v proot &>/dev/null; then
echo "Installing proot..."
if ! pkg install -y proot; then
fail_warn "Failed to install proot β skipping OpenCode install"
fi
fi
# ββ Helper: Create ld.so concatenation βββββββ
# Bun standalone binaries store embedded JS at the end of the file.
# The last 8 bytes contain the original file size as a LE u64.
# Bun calculates: embedded_offset = current_file_size - stored_size
# By prepending ld.so, current_file_size increases, and the offset
# shifts correctly to find the embedded data after ld.so.
create_ldso_concat() {
local bin_path="$1"
local output_path="$2"
local name="$3"
if [ ! -f "$bin_path" ]; then
echo -e "${RED}[FAIL]${NC} $name binary not found at $bin_path"
return 1
fi
echo " Creating ld.so concatenation for $name..."
echo " (Copying large binary files β this may take a minute)"
cp "$GLIBC_LDSO" "$output_path"
cat "$bin_path" >> "$output_path"
chmod +x "$output_path"
# Verify the Bun magic marker exists at the end
local marker
marker=$(tail -c 32 "$output_path" | strings 2>/dev/null | grep -o "Bun" || true)
if [ -n "$marker" ]; then
echo -e "${GREEN}[OK]${NC} $name ld.so concatenation created ($(du -h "$output_path" | cut -f1))"
else
echo -e "${YELLOW}[WARN]${NC} $name ld.so concatenation created but Bun marker not found"
fi
}
# ββ Helper: Create proot wrapper script ββββββ
create_proot_wrapper() {
local wrapper_path="$1"
local ldso_path="$2"
local bin_path="$3"
local name="$4"
cat > "$wrapper_path" << WRAPPER
#!/data/data/com.termux/files/usr/bin/bash
# $name wrapper β proot + ld.so concatenation
# proot: intercepts raw syscalls (Bun uses inline asm, not glibc calls)
# ld.so concat: fixes /proc/self/exe offset for embedded JS
# unset LD_PRELOAD: prevents Bionic libtermux-exec.so version mismatch
unset LD_PRELOAD
exec proot \\
-R "$PROOT_ROOT" \\
-b "\$PREFIX:\$PREFIX" \\
-b /system:/system \\
-b /apex:/apex \\
-w "\$(pwd)" \\
"$ldso_path" "$bin_path" "\$@"
WRAPPER
chmod +x "$wrapper_path"
echo -e "${GREEN}[OK]${NC} $name wrapper script created"
}
# ββ Step 1: Create minimal proot rootfs ββββββ
echo "Setting up proot minimal rootfs..."
mkdir -p "$PROOT_ROOT/data/data/com.termux/files"
echo -e "${GREEN}[OK]${NC} proot rootfs created at $PROOT_ROOT"
# ββ Step 2: Install Bun (package manager) ββββ
echo ""
echo "Installing Bun..."
echo " (Downloading and installing Bun runtime β this may take a few minutes)"
BUN_BIN="$HOME/.bun/bin/bun"
if [ -x "$BUN_BIN" ]; then
echo -e "${GREEN}[OK]${NC} Bun already installed"
else
# Install bun via the official installer
# Bun is needed to download the opencode package
BUN_INSTALLED=false
for _attempt in 1 2 3; do
if curl -fsSL --max-time 60 https://bun.sh/install | bash 2>/dev/null; then
echo -e "${GREEN}[OK]${NC} Bun installed"
BUN_INSTALLED=true
break
fi
echo -e "${YELLOW}[WARN]${NC} Bun install attempt ${_attempt}/3 failed, retrying in 5s..."
sleep 5
done
if [ "$BUN_INSTALLED" = false ]; then
fail_warn "Failed to install Bun after 3 attempts β cannot install OpenCode"
fi
BUN_BIN="$HOME/.bun/bin/bun"
fi
# Bun itself needs grun to run (it's a glibc binary)
# Create a temporary wrapper for bun
BUN_WRAPPER=$(mktemp "$PREFIX/tmp/bun-wrapper.XXXXXX")
cat > "$BUN_WRAPPER" << WRAPPER
#!/data/data/com.termux/files/usr/bin/bash
unset LD_PRELOAD
exec "$GLIBC_LDSO" "$BUN_BIN" "\$@"
WRAPPER
chmod +x "$BUN_WRAPPER"
# Verify bun works
BUN_VER=$("$BUN_WRAPPER" --version 2>/dev/null) || {
rm -f "$BUN_WRAPPER"
fail_warn "Bun verification failed"
}
echo -e "${GREEN}[OK]${NC} Bun $BUN_VER verified"
# ββ Step 3: Install OpenCode ββββββββββββββββ
echo ""
echo "Installing OpenCode..."
echo " (Downloading package β this may take a few minutes)"
# Use bun to install opencode-ai package
# Note: bun may exit non-zero due to optional platform packages (windows, darwin)
# failing to install, but the linux-arm64 binary is still installed successfully.
"$BUN_WRAPPER" install -g opencode-ai 2>&1 || true
echo -e "${GREEN}[OK]${NC} opencode-ai package install attempted"
# Remove bun's global shim β it tries to spawnSync the native binary directly,
# which fails on Termux (missing /lib/ld-linux-aarch64.so.1).
# Our proot wrapper at $PREFIX/bin/opencode will be used instead.
rm -f "$HOME/.bun/bin/opencode"
# Find the OpenCode binary
OPENCODE_BIN=""
for pattern in \
"$HOME/.bun/install/cache/opencode-linux-arm64@*/bin/opencode" \
"$HOME/.bun/install/global/node_modules/opencode-linux-arm64/bin/opencode"; do
# shellcheck disable=SC2012,SC2086
FOUND=$(ls $pattern 2>/dev/null | sort -V | tail -1 || true)
if [ -n "$FOUND" ] && [ -f "$FOUND" ]; then
OPENCODE_BIN="$FOUND"
break
fi
done
if [ -z "$OPENCODE_BIN" ]; then
rm -f "$BUN_WRAPPER"
fail_warn "OpenCode binary not found after installation"
fi
echo -e "${GREEN}[OK]${NC} OpenCode binary found: $OPENCODE_BIN"
# Create ld.so concatenation
mkdir -p "$OPENCLAW_DIR/bin"
LDSO_OPENCODE="$OPENCLAW_DIR/bin/ld.so.opencode"
create_ldso_concat "$OPENCODE_BIN" "$LDSO_OPENCODE" "OpenCode" || {
rm -f "$BUN_WRAPPER"
fail_warn "Failed to create OpenCode ld.so concatenation"
}
# Create wrapper script
create_proot_wrapper "$PREFIX/bin/opencode" "$LDSO_OPENCODE" "$OPENCODE_BIN" "OpenCode"
# Verify
echo ""
echo "Verifying OpenCode..."
OC_VER=$("$PREFIX/bin/opencode" --version 2>/dev/null) || true
if [ -n "$OC_VER" ]; then
echo -e "${GREEN}[OK]${NC} OpenCode v$OC_VER verified"
else
echo -e "${YELLOW}[WARN]${NC} OpenCode --version check failed (may work in interactive mode)"
fi
# ββ Step 4: Create OpenCode config βββββββββββ
echo ""
echo "Setting up OpenCode configuration..."
OPENCODE_CONFIG_DIR="$HOME/.config/opencode"
OPENCODE_CONFIG="$OPENCODE_CONFIG_DIR/opencode.json"
mkdir -p "$OPENCODE_CONFIG_DIR"
if [ ! -f "$OPENCODE_CONFIG" ]; then
cat > "$OPENCODE_CONFIG" << 'CONFIG'
{
"$schema": "https://opencode.ai/config.json"
}
CONFIG
echo -e "${GREEN}[OK]${NC} OpenCode config created"
else
echo -e "${GREEN}[OK]${NC} OpenCode config already exists"
fi
# ββ Cleanup ββββββββββββββββββββββββββββββββββ
rm -f "$BUN_WRAPPER"
echo ""
echo -e "${GREEN}OpenCode installation complete.${NC}"
if [ -n "${OC_VER:-}" ]; then
echo " OpenCode: v$OC_VER"
fi
echo " Run: opencode"