diff --git a/README.md b/README.md index 14219bf..ca3d9b6 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,16 @@ dotnet run -- --mcp - Sensitive data (code, events, files) encrypted at rest in SQLite - Non-sensitive metadata (timestamps, types) stored in plaintext +### 3. `copilot-termux/` — Copilot CLI Fix for Termux + +Fixes GitHub Copilot CLI (v1.0.60+) to run natively on Termux (Android ARM64). Solves the `Native addon "runtime" not found for android-arm64` error and all related glibc/seccomp issues. + +```bash +cd copilot-termux && ./install.sh +``` + +**See [copilot-termux/README.md](copilot-termux/README.md) for full documentation.** + ## Requirements - Termux (Android ARM64) or proot-distro Ubuntu diff --git a/copilot-termux/README.md b/copilot-termux/README.md new file mode 100644 index 0000000..6317cc5 --- /dev/null +++ b/copilot-termux/README.md @@ -0,0 +1,206 @@ +# Copilot CLI on Termux — Complete Fix + +> تشغيل GitHub Copilot CLI (v1.0.60+) مباشرة على Termux (Android ARM64) بدون الحاجة للدخول إلى proot-distro + +## المشكلة + +عند تثبيت Copilot CLI على Termux بالطريقة العادية (`npm install -g @github/copilot`)، يفشل التشغيل بالخطأ: + +``` +Error: Native addon "runtime" not found for android-arm64 +``` + +### تسلسل المشكلة وجذرها + +Copilot CLI v1.0.60 يعتمد على native addon مُترجم مسبقاً (`runtime.node`) وهو ملف ELF مبني لنظام Linux القياسي. عند تشغيله على Termux تظهر سلسلة من المشاكل المتتابعة: + +``` +المشكلة 1: كشف المنصة +├─ process.platform يُرجع "android" بدلاً من "linux" +├─ الكود يبحث عن prebuilds/android-arm64/ وهو غير موجود +└─ الحل: ترقيع app.js لمعاملة android كـ linux + +المشكلة 2: المكتبات الأصلية (Native Libraries) +├─ runtime.node مبني ضد glibc (GNU C Library) +├─ Termux يستخدم Bionic (Android C Library) +├─ لا يمكن خلط glibc و Bionic في نفس العملية +└─ الحل: استخدام Node.js مبني ضد glibc مع Ubuntu rootfs libraries + +المشكلة 3: libc.so Linker Scripts +├─ Ubuntu يستخدم usrmerge (/lib → /usr/lib) +├─ libc.so ملف نصي (linker script) وليس مكتبة ELF +├─ Dynamic linker يفشل عند محاولة تحميله +└─ الحل: تخطّيه - المكتبات الحقيقية هي .so.6 + +المشكلة 4: LD_PRELOAD التعارض +├─ Termux يحقن libtermux-exec-ld-preload.so عبر LD_PRELOAD +├─ هذه المكتبة مبنية ضد Bionic وتتعارض مع glibc +└─ الحل: إلغاء LD_PRELOAD عند التشغيل + +المشكلة 5: Seccomp و Syscalls +├─ Android يحجب بعض system calls عبر seccomp filters +├─ glibc Node.js يستخدم syscalls محجوبة → Signal 31 (SIGSYS) +└─ الحل: استخدام proot لاعتراض syscalls المحجوبة +``` + +### الحل الجذري + +استخدام **proot خفيف** (بدون proot-distro الكامل) لتشغيل Node.js 22 المبني لـ Linux مع مكتبات Ubuntu، مع ربط مجلد Termux الرئيسي لإبقاء الملفات والجلسات متاحة: + +``` +Termux Shell + └─ copilot (wrapper script) + └─ proot (syscall interception فقط) + └─ Ubuntu rootfs (مكتبات glibc) + └─ Node.js 22 linux-arm64 + └─ Copilot CLI app.js (مُرقّع) + └─ runtime.node (يعمل بنجاح) +``` + +## المتطلبات + +| المتطلب | الأمر | +|---------|-------| +| Termux (Android ARM64) | — | +| proot-distro مع Ubuntu | `pkg install proot-distro && proot-distro install ubuntu` | +| Node.js على Termux | `pkg install nodejs` | +| GitHub CLI | `pkg install gh` | + +## التثبيت السريع + +```bash +# تثبيت بخطوة واحدة +bash <(curl -sL https://raw.githubusercontent.com/sbay-dev/dotnet-termux/main/copilot-termux/install.sh) +``` + +### أو تثبيت يدوي + +```bash +git clone https://github.com/sbay-dev/dotnet-termux.git +cd dotnet-termux/copilot-termux +chmod +x install.sh +./install.sh +``` + +## ماذا يفعل سكربت التثبيت + +1. **يتحقق** من المتطلبات (proot-distro، Ubuntu rootfs) +2. **يُثبّت Copilot CLI** داخل Ubuntu rootfs عبر npm +3. **يُرقّع `app.js`** لدعم منصة Android (4 ترقيعات) +4. **يُنزّل Node.js 22** (linux-arm64) لدعم `node:sqlite` +5. **يُنشئ wrapper script** في `$PREFIX/bin/copilot` +6. **يختبر** التثبيت تلقائياً + +## البنية + +``` +copilot-termux/ +├── README.md # هذا الملف - التوثيق الكامل +├── install.sh # سكربت التثبيت الرئيسي +├── patch-app.sh # ترقيع app.js لمنصة Android +├── fix-session.sh # إصلاح الجلسات التالفة (tokensRemoved سالب) +└── wrapper-template.sh # قالب wrapper script +``` + +## استكشاف الأخطاء + +### الخطأ: `Session file is corrupted (tokensRemoved: Number must be >= 0)` + +**رسالة الخطأ الكاملة:** +``` +Error: Session '1e3b7178-...' was found but could not be loaded. +Error: Session file is corrupted (line 89198: data.tokensRemoved: Number must be greater than or equal to 0) +``` + +**السبب الجذري:** + +Copilot CLI يُجري عملية **ضغط (compaction)** دورية على الجلسات الطويلة لتقليل استهلاك الـ tokens. العملية تسجّل حدث `session.compaction_complete` في ملف `events.jsonl` يحتوي: +- `preCompactionTokens`: عدد الـ tokens قبل الضغط +- `postCompactionTokens`: عدد الـ tokens بعد الضغط +- `tokensRemoved`: الفرق بينهما (المفترض أن يكون ≥ 0) + +في بعض الحالات — خاصة مع الجلسات الطويلة جداً أو عند استخدام أدوات كثيرة — يحدث أن `postCompactionTokens > preCompactionTokens` (الملخص أكبر من الأصل)، فتكون النتيجة **قيمة سالبة**. هذا سلوك طبيعي من الـ compaction لكن مُخالف لقواعد التحقق (validation schema) التي تشترط `tokensRemoved >= 0`. + +**التأثير:** +- الجلسة **موجودة وسليمة** لكن لا يمكن تحميلها بسبب فشل التحقق +- البيانات **غير تالفة** فعلياً — فقط قيمة إحصائية خاطئة +- يمكن أن يتأثر أكثر من حدث compaction في نفس الجلسة (في حالتنا: 19 حدث) + +**الإصلاح التلقائي:** +```bash +# سكربت إصلاح مضمّن +./fix-session.sh + +# مثال +./fix-session.sh 1e3b7178-cb31-419a-a73b-1ef5f6a0c09d +``` + +**الإصلاح اليدوي:** +```bash +# 1. العثور على ملف الأحداث +EVENTS="$HOME/.copilot/session-state//events.jsonl" + +# 2. فحص القيم السالبة +grep -c '"tokensRemoved":-' "$EVENTS" + +# 3. نسخة احتياطية +cp "$EVENTS" "${EVENTS}.bak" + +# 4. تصفير جميع القيم السالبة +sed -i 's/"tokensRemoved":-[0-9]\+/"tokensRemoved":0/g' "$EVENTS" + +# 5. استئناف الجلسة +copilot --resume= +``` + +**لماذا التصفير آمن:** +- `tokensRemoved` قيمة **إحصائية بحتة** تُستخدم فقط لتسجيل ما حدث +- لا تؤثر على محتوى المحادثة أو سياقها أو سلوك النموذج +- الضغط نفسه تمّ بنجاح — فقط القيمة المسجّلة غير صحيحة + +--- + +### الخطأ: `Native addon "runtime" not found for android-arm64` +**السبب:** app.js غير مُرقّع +**الحل:** +```bash +cd dotnet-termux/copilot-termux && ./patch-app.sh +``` + +### الخطأ: `libc.so: invalid ELF header` +**السبب:** LD_LIBRARY_PATH يشير لمجلد يحتوي linker scripts +**الحل:** السكربت يتعامل مع هذا تلقائياً عبر proot + +### الخطأ: `Unknown signal 31` +**السبب:** Android seccomp يحجب syscalls +**الحل:** استخدام proot (مُضمّن في wrapper) + +### الخطأ: `ERR_UNKNOWN_BUILTIN_MODULE: node:sqlite` +**السبب:** إصدار Node.js قديم (أقل من 22) +**الحل:** السكربت ينزّل Node.js 22 تلقائياً + +## التحديث + +عند تحديث Copilot CLI، أعد تشغيل سكربت التثبيت: + +```bash +cd dotnet-termux/copilot-termux && ./install.sh +``` + +## المعلومات التقنية + +| المكون | التفاصيل | +|--------|----------| +| Copilot CLI | v1.0.60 | +| Node.js | v22.x (linux-arm64, glibc) | +| نظام الملفات | Ubuntu rootfs عبر proot | +| المنصة | Android ARM64 (Termux) | +| Syscall Interception | proot | + +## المؤلف + +[@sultanaalyami](https://github.com/sultanaalyami) / [sbay-dev](https://github.com/sbay-dev) + +## الترخيص + +MIT diff --git a/copilot-termux/fix-session.sh b/copilot-termux/fix-session.sh new file mode 100755 index 0000000..3e36638 --- /dev/null +++ b/copilot-termux/fix-session.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# fix-session.sh — إصلاح جلسات Copilot CLI التالفة +# يُعالج خطأ: Session file is corrupted (tokensRemoved: Number must be >= 0) +# +# الاستخدام: +# ./fix-session.sh +# ./fix-session.sh 1e3b7178-cb31-419a-a73b-1ef5f6a0c09d +# +# يبحث في المسارات التالية بالترتيب: +# 1. ~/.copilot/session-state//events.jsonl +# 2. $COPILOT_SESSION_DIR (إذا كان مُعيّناً) + +set -euo pipefail + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +info() { echo -e "${CYAN}ℹ️ $1${NC}"; } +ok() { echo -e "${GREEN}✅ $1${NC}"; } +warn() { echo -e "${YELLOW}⚠️ $1${NC}"; } +err() { echo -e "${RED}❌ $1${NC}"; } + +if [ $# -lt 1 ]; then + echo "الاستخدام: $0 " + echo "مثال: $0 1e3b7178-cb31-419a-a73b-1ef5f6a0c09d" + exit 1 +fi + +SESSION_ID="$1" + +# البحث عن ملف الأحداث +EVENTS="" +SEARCH_PATHS=( + "$HOME/.copilot/session-state/$SESSION_ID/events.jsonl" + "${COPILOT_SESSION_DIR:-/nonexistent}/$SESSION_ID/events.jsonl" +) + +for path in "${SEARCH_PATHS[@]}"; do + if [ -f "$path" ]; then + EVENTS="$path" + break + fi +done + +if [ -z "$EVENTS" ]; then + err "لم يتم العثور على الجلسة: $SESSION_ID" + echo " المسارات التي تم البحث فيها:" + for path in "${SEARCH_PATHS[@]}"; do + echo " - $path" + done + exit 1 +fi + +info "ملف الأحداث: $EVENTS" +info "حجم الملف: $(du -h "$EVENTS" | cut -f1)" +info "عدد الأسطر: $(wc -l < "$EVENTS")" + +# فحص القيم السالبة +NEGATIVE_COUNT=$(grep -c '"tokensRemoved":-' "$EVENTS" 2>/dev/null || echo "0") + +if [ "$NEGATIVE_COUNT" -eq 0 ]; then + ok "لا توجد قيم tokensRemoved سالبة. الملف سليم." + exit 0 +fi + +warn "وُجدت $NEGATIVE_COUNT قيمة سالبة في tokensRemoved" +echo "" + +# عرض القيم التالفة +info "القيم التالفة:" +grep -n '"tokensRemoved":-' "$EVENTS" | while IFS= read -r match; do + LINE_NUM=$(echo "$match" | cut -d: -f1) + VALUE=$(echo "$match" | grep -o '"tokensRemoved":-[0-9]*' | head -1) + echo " السطر $LINE_NUM: $VALUE" +done +echo "" + +# نسخة احتياطية +BACKUP="${EVENTS}.bak-$(date +%Y%m%d%H%M%S)" +cp "$EVENTS" "$BACKUP" +ok "نسخة احتياطية: $BACKUP" + +# الإصلاح: تصفير جميع القيم السالبة +sed -i 's/"tokensRemoved":-[0-9]\+/"tokensRemoved":0/g' "$EVENTS" + +# التحقق +REMAINING=$(grep -c '"tokensRemoved":-' "$EVENTS" 2>/dev/null || echo "0") + +if [ "$REMAINING" -eq 0 ]; then + ok "تم إصلاح $NEGATIVE_COUNT قيمة بنجاح!" + echo "" + info "جرّب الآن:" + echo " copilot --resume=$SESSION_ID" +else + err "لا تزال هناك $REMAINING قيمة سالبة. الرجاء الإصلاح يدوياً." + exit 1 +fi diff --git a/copilot-termux/install.sh b/copilot-termux/install.sh new file mode 100755 index 0000000..3b6e8ee --- /dev/null +++ b/copilot-termux/install.sh @@ -0,0 +1,204 @@ +#!/data/data/com.termux/files/usr/bin/bash +# install.sh — تثبيت GitHub Copilot CLI على Termux (Android ARM64) +# +# يُثبّت Copilot CLI ويُهيّئه للعمل مباشرة من Termux +# عبر proot + glibc Node.js + Ubuntu rootfs libraries +# +# الاستخدام: ./install.sh +# أو: bash <(curl -sL https://raw.githubusercontent.com/sbay-dev/dotnet-termux/main/copilot-termux/install.sh) + +set -e + +# ─── ألوان ─── +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' + +log() { echo -e "${GREEN}✅ $1${NC}"; } +info() { echo -e "${BLUE}ℹ️ $1${NC}"; } +warn() { echo -e "${YELLOW}⚠️ $1${NC}"; } +error() { echo -e "${RED}❌ $1${NC}"; exit 1; } +step() { echo -e "\n${CYAN}═══ $1 ═══${NC}"; } + +# ─── ثوابت ─── +UBUNTU_ROOT="/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu" +COPILOT_DIR="$UBUNTU_ROOT/usr/local/lib/node_modules/@github/copilot" +COPILOT_APP="$COPILOT_DIR/app.js" +NODE_DIR="$HOME/.copilot-node" +NODE_VERSION="v22.16.0" +NODE_URL="https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.xz" +WRAPPER_PATH="$PREFIX/bin/copilot" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo -e "${CYAN}" +echo "╔═══════════════════════════════════════════════════╗" +echo "║ GitHub Copilot CLI — Termux Installer ║" +echo "║ تثبيت كوبايلوت على تيرموكس ║" +echo "╚═══════════════════════════════════════════════════╝" +echo -e "${NC}" + +# ─── الخطوة 0: فحص المتطلبات ─── +step "الخطوة 0/5: فحص المتطلبات" + +# التحقق من Termux +if [ -z "$PREFIX" ] || [[ "$PREFIX" != *"com.termux"* ]]; then + error "هذا السكربت مُصمّم لـ Termux فقط" +fi +log "بيئة Termux" + +# التحقق من proot +if ! command -v proot &>/dev/null; then + info "تثبيت proot..." + pkg install -y proot >/dev/null 2>&1 +fi +log "proot متوفر" + +# التحقق من proot-distro +if ! command -v proot-distro &>/dev/null; then + info "تثبيت proot-distro..." + pkg install -y proot-distro >/dev/null 2>&1 +fi +log "proot-distro متوفر" + +# التحقق من Ubuntu rootfs +if [ ! -d "$UBUNTU_ROOT" ]; then + info "تثبيت Ubuntu عبر proot-distro (قد يستغرق وقتاً)..." + proot-distro install ubuntu +fi +log "Ubuntu rootfs موجود" + +# التحقق من Node.js على Termux +if ! command -v node &>/dev/null; then + info "تثبيت Node.js..." + pkg install -y nodejs >/dev/null 2>&1 +fi +log "Node.js (Termux): $(node --version 2>/dev/null)" + +# التحقق من gh CLI +if ! command -v gh &>/dev/null; then + warn "gh CLI غير مُثبّت — ثبّته لاحقاً: pkg install gh" +fi + +# ─── الخطوة 1: تثبيت Copilot CLI في Ubuntu rootfs ─── +step "الخطوة 1/5: تثبيت Copilot CLI" + +# تثبيت Node.js داخل Ubuntu إن لم يكن موجوداً +if [ ! -f "$UBUNTU_ROOT/usr/bin/node" ]; then + info "تثبيت Node.js داخل Ubuntu rootfs..." + proot-distro login ubuntu -- bash -c "apt update -qq && apt install -y -qq nodejs npm" 2>/dev/null +fi + +# تثبيت/تحديث Copilot CLI +info "تثبيت @github/copilot داخل Ubuntu rootfs..." +proot-distro login ubuntu -- bash -c "npm install -g @github/copilot --force 2>&1" | tail -3 +log "Copilot CLI مُثبّت" + +# ─── الخطوة 2: ترقيع app.js ─── +step "الخطوة 2/5: ترقيع app.js لدعم Android" + +COPILOT_APP="$UBUNTU_ROOT/usr/local/lib/node_modules/@github/copilot/app.js" + +if [ ! -f "$COPILOT_APP" ]; then + error "لم يتم العثور على app.js في: $COPILOT_APP" +fi + +if [ -f "$SCRIPT_DIR/patch-app.sh" ]; then + bash "$SCRIPT_DIR/patch-app.sh" "$COPILOT_APP" +else + # ترقيع مُضمّن في حال التشغيل بدون المستودع + info "تطبيق الترقيعات مباشرة..." + + [ ! -f "$COPILOT_APP.bak-android" ] && cp "$COPILOT_APP" "$COPILOT_APP.bak-android" + + # Patch 1: oVo() — case switch للمنصة + grep -q 'case"android":case"linux"' "$COPILOT_APP" 2>/dev/null || \ + sed -i 's/case"linux":return`linux-${e}-${OVe()}`/case"android":case"linux":return`linux-${e}-${OVe()}`/' "$COPILOT_APP" + + # Patch 2: BVe() — بادئة المنصة + grep -q 't==="android"?"linux":t}' "$COPILOT_APP" 2>/dev/null || \ + sed -i 's/t==="linux"\&\&r==="musl"?"linuxmusl":t}/t==="linux"\&\&r==="musl"?"linuxmusl":t==="android"?"linux":t}/' "$COPILOT_APP" + + # Patch 3: OVe() — كشف libc + grep -q '!=="android"?"gnu"' "$COPILOT_APP" 2>/dev/null || \ + sed -i 's/(t.platform??process.platform)!=="linux"?"gnu"/(t.platform??process.platform)!=="linux"\&\&(t.platform??process.platform)!=="android"?"gnu"/' "$COPILOT_APP" + + # Patch 4: pme() — كشف musl + grep -q 'process.platform==="android"' "$COPILOT_APP" 2>/dev/null || \ + sed -i 's/process.platform==="linux"\&\&OVe()==="musl"/(process.platform==="linux"||process.platform==="android")\&\&OVe()==="musl"/' "$COPILOT_APP" + + log "تم تطبيق الترقيعات" +fi + +# ─── الخطوة 3: تنزيل Node.js 22 (linux-arm64) ─── +step "الخطوة 3/5: تنزيل Node.js 22 (linux-arm64)" + +if [ -f "$NODE_DIR/bin/node" ]; then + CURRENT_NODE_VER=$("$UBUNTU_ROOT/lib/ld-linux-aarch64.so.1" "$NODE_DIR/bin/node" -e "console.log(process.version)" 2>/dev/null || echo "unknown") + if [[ "$CURRENT_NODE_VER" == v22.* ]] || [[ "$CURRENT_NODE_VER" == v24.* ]]; then + log "Node.js $CURRENT_NODE_VER موجود مسبقاً" + else + info "تحديث Node.js إلى $NODE_VERSION..." + rm -rf "$NODE_DIR" + fi +fi + +if [ ! -f "$NODE_DIR/bin/node" ]; then + info "تنزيل Node.js $NODE_VERSION..." + mkdir -p "$NODE_DIR" + curl -sL "$NODE_URL" -o /tmp/node-arm64.tar.xz + tar xf /tmp/node-arm64.tar.xz -C "$NODE_DIR" --strip-components=1 + rm -f /tmp/node-arm64.tar.xz + log "Node.js $NODE_VERSION مُثبّت في $NODE_DIR" +fi + +# ─── الخطوة 4: إنشاء wrapper script ─── +step "الخطوة 4/5: إنشاء wrapper script" + +cat > "$WRAPPER_PATH" << 'COPILOT_WRAPPER' +#!/data/data/com.termux/files/usr/bin/bash +# GitHub Copilot CLI — Termux Wrapper +# Generated by copilot-termux installer +# https://github.com/sbay-dev/dotnet-termux/tree/main/copilot-termux + +UBUNTU_ROOT="/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu" +NODE22="/data/data/com.termux/files/home/.copilot-node/bin/node" +COPILOT_APP="/usr/local/lib/node_modules/@github/copilot/app.js" +TERMUX_HOME="/data/data/com.termux/files/home" + +export LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu:/lib/aarch64-linux-gnu +exec proot \ + -r "$UBUNTU_ROOT" \ + -b "$TERMUX_HOME":/root \ + -b "$TERMUX_HOME":"$TERMUX_HOME" \ + -b /dev:/dev \ + -b /proc:/proc \ + -b /sys:/sys \ + -w /root \ + "$NODE22" "$COPILOT_APP" "$@" +COPILOT_WRAPPER + +chmod +x "$WRAPPER_PATH" +log "wrapper مُثبّت في $WRAPPER_PATH" + +# ─── الخطوة 5: اختبار ─── +step "الخطوة 5/5: اختبار التثبيت" + +VERSION_OUTPUT=$(copilot --version 2>&1) +if echo "$VERSION_OUTPUT" | grep -q "GitHub Copilot CLI"; then + log "$(echo "$VERSION_OUTPUT" | head -1)" + echo "" + echo -e "${GREEN}╔═══════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}║ 🎉 تم التثبيت بنجاح! ║${NC}" + echo -e "${GREEN}║ ║${NC}" + echo -e "${GREEN}║ شغّل: copilot ║${NC}" + echo -e "${GREEN}║ أو: copilot -p \"سؤالك هنا\" ║${NC}" + echo -e "${GREEN}╚═══════════════════════════════════════════════════╝${NC}" +else + warn "التثبيت قد لا يكون مكتملاً. المخرجات:" + echo "$VERSION_OUTPUT" + echo "" + info "جرّب تشغيل: copilot --version" +fi diff --git a/copilot-termux/patch-app.sh b/copilot-termux/patch-app.sh new file mode 100755 index 0000000..10ec21a --- /dev/null +++ b/copilot-termux/patch-app.sh @@ -0,0 +1,106 @@ +#!/data/data/com.termux/files/usr/bin/bash +# patch-app.sh — ترقيع Copilot CLI app.js لدعم Android/Termux +# +# يُعالج 4 دوال في app.js تفحص process.platform: +# 1. oVo() — تحويل المنصة لاسم ملف (case switch) +# 2. BVe() — بادئة المنصة (linux/linuxmusl) +# 3. OVe() — كشف عائلة libc (gnu/musl) +# 4. pme() — كشف musl +# +# الاستخدام: ./patch-app.sh [مسار app.js] + +set -e + +APP_JS="${1:-}" + +if [ -z "$APP_JS" ]; then + # محاولة العثور على app.js تلقائياً + UBUNTU_ROOT="/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu" + for path in \ + "$UBUNTU_ROOT/usr/local/lib/node_modules/@github/copilot/app.js" \ + "$PREFIX/lib/node_modules/@github/copilot/app.js" \ + "$HOME/node_modules/@github/copilot/app.js"; do + if [ -f "$path" ]; then + APP_JS="$path" + break + fi + done +fi + +if [ -z "$APP_JS" ] || [ ! -f "$APP_JS" ]; then + echo "❌ لم يتم العثور على app.js" + echo " الاستخدام: $0 [مسار app.js]" + exit 1 +fi + +echo "📄 ملف: $APP_JS" + +# نسخة احتياطية +if [ ! -f "$APP_JS.bak-android" ]; then + cp "$APP_JS" "$APP_JS.bak-android" + echo "📋 نسخة احتياطية: app.js.bak-android" +fi + +PATCHED=0 + +# ─── Patch 1: oVo() — إضافة case "android" قبل case "linux" ─── +if grep -q 'case"android":case"linux"' "$APP_JS" 2>/dev/null; then + echo "✅ [1/4] oVo() مُرقّع مسبقاً" +else + sed -i 's/case"linux":return`linux-${e}-${OVe()}`/case"android":case"linux":return`linux-${e}-${OVe()}`/' "$APP_JS" + if grep -q 'case"android":case"linux"' "$APP_JS"; then + echo "✅ [1/4] oVo() — تم الترقيع" + PATCHED=$((PATCHED + 1)) + else + echo "⚠️ [1/4] oVo() — فشل الترقيع" + fi +fi + +# ─── Patch 2: BVe() — معاملة android كـ linux ─── +if grep -q 't==="android"?"linux":t}' "$APP_JS" 2>/dev/null; then + echo "✅ [2/4] BVe() مُرقّع مسبقاً" +else + sed -i 's/t==="linux"\&\&r==="musl"?"linuxmusl":t}/t==="linux"\&\&r==="musl"?"linuxmusl":t==="android"?"linux":t}/' "$APP_JS" + if grep -q 't==="android"?"linux":t}' "$APP_JS"; then + echo "✅ [2/4] BVe() — تم الترقيع" + PATCHED=$((PATCHED + 1)) + else + echo "⚠️ [2/4] BVe() — فشل الترقيع" + fi +fi + +# ─── Patch 3: OVe() — كشف libc لمنصة Android ─── +if grep -q '!=="android"?"gnu"' "$APP_JS" 2>/dev/null; then + echo "✅ [3/4] OVe() مُرقّع مسبقاً" +else + sed -i 's/(t.platform??process.platform)!=="linux"?"gnu"/(t.platform??process.platform)!=="linux"\&\&(t.platform??process.platform)!=="android"?"gnu"/' "$APP_JS" + if grep -q '!=="android"?"gnu"' "$APP_JS"; then + echo "✅ [3/4] OVe() — تم الترقيع" + PATCHED=$((PATCHED + 1)) + else + echo "⚠️ [3/4] OVe() — فشل الترقيع" + fi +fi + +# ─── Patch 4: pme() — كشف musl لمنصة Android ─── +if grep -q '(process.platform==="linux"||process.platform==="android")&&OVe()==="musl"' "$APP_JS" 2>/dev/null; then + echo "✅ [4/4] pme() مُرقّع مسبقاً" +else + sed -i 's/process.platform==="linux"\&\&OVe()==="musl"/(process.platform==="linux"||process.platform==="android")\&\&OVe()==="musl"/' "$APP_JS" + if grep -q 'process.platform==="android"' "$APP_JS"; then + echo "✅ [4/4] pme() — تم الترقيع" + PATCHED=$((PATCHED + 1)) + else + echo "⚠️ [4/4] pme() — فشل الترقيع" + fi +fi + +echo "" +if [ "$PATCHED" -gt 0 ]; then + echo "🎉 تم تطبيق $PATCHED ترقيع(ات) جديدة" +else + echo "ℹ️ جميع الترقيعات مُطبّقة مسبقاً" +fi +echo "" +echo "💡 لاستعادة النسخة الأصلية:" +echo " cp $APP_JS.bak-android $APP_JS" diff --git a/copilot-termux/wrapper-template.sh b/copilot-termux/wrapper-template.sh new file mode 100755 index 0000000..f28742a --- /dev/null +++ b/copilot-termux/wrapper-template.sh @@ -0,0 +1,23 @@ +#!/data/data/com.termux/files/usr/bin/bash +# wrapper-template.sh — قالب wrapper لتشغيل Copilot CLI على Termux +# +# يستخدم proot لاعتراض syscalls المحجوبة من Android +# مع ربط مجلد Termux الرئيسي للوصول للملفات والجلسات +# +# يُنسخ إلى $PREFIX/bin/copilot أثناء التثبيت + +UBUNTU_ROOT="/data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/ubuntu" +NODE22="/data/data/com.termux/files/home/.copilot-node/bin/node" +COPILOT_APP="/usr/local/lib/node_modules/@github/copilot/app.js" +TERMUX_HOME="/data/data/com.termux/files/home" + +export LD_LIBRARY_PATH=/usr/lib/aarch64-linux-gnu:/lib/aarch64-linux-gnu +exec proot \ + -r "$UBUNTU_ROOT" \ + -b "$TERMUX_HOME":/root \ + -b "$TERMUX_HOME":"$TERMUX_HOME" \ + -b /dev:/dev \ + -b /proc:/proc \ + -b /sys:/sys \ + -w /root \ + "$NODE22" "$COPILOT_APP" "$@"