karnel-termux 0.0.1
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/LICENSE +21 -0
- package/README.md +454 -0
- package/install.sh +272 -0
- package/karnel/bin/karnel +77 -0
- package/karnel/cli/commands/brain.sh +1553 -0
- package/karnel/cli/commands/cleanup.sh +66 -0
- package/karnel/cli/commands/doctor.sh +1528 -0
- package/karnel/cli/commands/env.sh +233 -0
- package/karnel/cli/commands/help.sh +8 -0
- package/karnel/cli/commands/ia.sh +502 -0
- package/karnel/cli/commands/init.sh +1274 -0
- package/karnel/cli/commands/install.sh +718 -0
- package/karnel/cli/commands/list.sh +399 -0
- package/karnel/cli/commands/open.sh +106 -0
- package/karnel/cli/commands/pg.sh +719 -0
- package/karnel/cli/commands/reinstall.sh +663 -0
- package/karnel/cli/commands/show.sh +90 -0
- package/karnel/cli/commands/start.sh +54 -0
- package/karnel/cli/commands/status.sh +96 -0
- package/karnel/cli/commands/uninstall.sh +668 -0
- package/karnel/cli/commands/update.sh +723 -0
- package/karnel/cli/commands/upgrade.sh +40 -0
- package/karnel/cli/commands/version.sh +3 -0
- package/karnel/cli/commands/voice.sh +230 -0
- package/karnel/cli/karnel.sh +706 -0
- package/karnel/modules/ai.sh +135 -0
- package/karnel/modules/auto.sh +114 -0
- package/karnel/modules/db.sh +132 -0
- package/karnel/modules/deploy.sh +74 -0
- package/karnel/modules/dev.sh +148 -0
- package/karnel/modules/editor.sh +115 -0
- package/karnel/modules/lang.sh +124 -0
- package/karnel/modules/npm.sh +146 -0
- package/karnel/modules/shell.sh +338 -0
- package/karnel/modules/ui.sh +139 -0
- package/karnel/modules/voice.sh +118 -0
- package/karnel/tools/ai/all.sh +209 -0
- package/karnel/tools/ai/antigravity-cli/README.md +45 -0
- package/karnel/tools/ai/antigravity-cli/bin/agy +28 -0
- package/karnel/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
- package/karnel/tools/ai/antigravity-cli/install.sh +469 -0
- package/karnel/tools/ai/claude-code/README.md +45 -0
- package/karnel/tools/ai/claude-code/bin/claude +29 -0
- package/karnel/tools/ai/claude-code/helper/claude_helper.c +42 -0
- package/karnel/tools/ai/claude-code/install.sh +278 -0
- package/karnel/tools/ai/cline/install.sh +160 -0
- package/karnel/tools/ai/codegraph/README.md +43 -0
- package/karnel/tools/ai/codegraph/bin/codegraph +5 -0
- package/karnel/tools/ai/codegraph/install.sh +160 -0
- package/karnel/tools/ai/codex/README.md +44 -0
- package/karnel/tools/ai/codex/install.sh +104 -0
- package/karnel/tools/ai/command-code/README.md +62 -0
- package/karnel/tools/ai/command-code/install.sh +136 -0
- package/karnel/tools/ai/crush/README.md +17 -0
- package/karnel/tools/ai/crush/install.sh +89 -0
- package/karnel/tools/ai/ctx7/README.md +26 -0
- package/karnel/tools/ai/ctx7/install.sh +61 -0
- package/karnel/tools/ai/engram/README.md +44 -0
- package/karnel/tools/ai/engram/install.sh +127 -0
- package/karnel/tools/ai/freebuff/README.md +52 -0
- package/karnel/tools/ai/freebuff/bin/freebuff +28 -0
- package/karnel/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
- package/karnel/tools/ai/freebuff/install.sh +303 -0
- package/karnel/tools/ai/gemini-cli/README.md +46 -0
- package/karnel/tools/ai/gemini-cli/install.sh +111 -0
- package/karnel/tools/ai/gentle-ai/README.md +42 -0
- package/karnel/tools/ai/gentle-ai/install.sh +253 -0
- package/karnel/tools/ai/gentle-ai/termux-patches.go +256 -0
- package/karnel/tools/ai/gga/README.md +49 -0
- package/karnel/tools/ai/gga/install.sh +134 -0
- package/karnel/tools/ai/hermes-agent/README.md +50 -0
- package/karnel/tools/ai/hermes-agent/install.sh +120 -0
- package/karnel/tools/ai/kilocode-cli/README.md +45 -0
- package/karnel/tools/ai/kilocode-cli/bin/kilocode +21 -0
- package/karnel/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
- package/karnel/tools/ai/kilocode-cli/install.sh +179 -0
- package/karnel/tools/ai/kimchi-code/README.md +53 -0
- package/karnel/tools/ai/kimchi-code/install.sh +221 -0
- package/karnel/tools/ai/kimi-code/README.md +45 -0
- package/karnel/tools/ai/kimi-code/install.sh +111 -0
- package/karnel/tools/ai/kiro/README.md +17 -0
- package/karnel/tools/ai/kiro/install.sh +134 -0
- package/karnel/tools/ai/mimocode/README.md +43 -0
- package/karnel/tools/ai/mimocode/bin/mimo +28 -0
- package/karnel/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
- package/karnel/tools/ai/mimocode/install.sh +287 -0
- package/karnel/tools/ai/minimax-cli/README.md +45 -0
- package/karnel/tools/ai/minimax-cli/install.sh +111 -0
- package/karnel/tools/ai/mistral-vibe/README.md +46 -0
- package/karnel/tools/ai/mistral-vibe/install.sh +119 -0
- package/karnel/tools/ai/odysseus/README.md +35 -0
- package/karnel/tools/ai/odysseus/install.sh +198 -0
- package/karnel/tools/ai/ollama/README.md +44 -0
- package/karnel/tools/ai/ollama/install.sh +78 -0
- package/karnel/tools/ai/omni-route/README.md +111 -0
- package/karnel/tools/ai/omni-route/install.sh +165 -0
- package/karnel/tools/ai/openclaude/README.md +46 -0
- package/karnel/tools/ai/openclaude/install.sh +110 -0
- package/karnel/tools/ai/openclaw/README.md +47 -0
- package/karnel/tools/ai/openclaw/install.sh +112 -0
- package/karnel/tools/ai/opencode/README.md +51 -0
- package/karnel/tools/ai/opencode/bin/opencode +28 -0
- package/karnel/tools/ai/opencode/helper/opencode_helper.c +57 -0
- package/karnel/tools/ai/opencode/install.sh +290 -0
- package/karnel/tools/ai/openspec/README.md +34 -0
- package/karnel/tools/ai/openspec/install.sh +61 -0
- package/karnel/tools/ai/pi/README.md +46 -0
- package/karnel/tools/ai/pi/install.sh +104 -0
- package/karnel/tools/ai/qwen-code/README.md +45 -0
- package/karnel/tools/ai/qwen-code/install.sh +111 -0
- package/karnel/tools/auto/all.sh +57 -0
- package/karnel/tools/auto/n8n/README.md +47 -0
- package/karnel/tools/auto/n8n/install.sh +102 -0
- package/karnel/tools/db/all.sh +61 -0
- package/karnel/tools/db/mariadb/README.md +43 -0
- package/karnel/tools/db/mariadb/install.sh +65 -0
- package/karnel/tools/db/mongodb/README.md +42 -0
- package/karnel/tools/db/mongodb/install.sh +73 -0
- package/karnel/tools/db/postgresql/README.md +45 -0
- package/karnel/tools/db/postgresql/install.sh +65 -0
- package/karnel/tools/db/redis/README.md +46 -0
- package/karnel/tools/db/redis/install.sh +64 -0
- package/karnel/tools/db/sqlite/README.md +44 -0
- package/karnel/tools/db/sqlite/install.sh +65 -0
- package/karnel/tools/deploy/all.sh +43 -0
- package/karnel/tools/deploy/netlify/install.sh +41 -0
- package/karnel/tools/deploy/railway/install.sh +109 -0
- package/karnel/tools/deploy/vercel/install.sh +43 -0
- package/karnel/tools/dev/all.sh +77 -0
- package/karnel/tools/dev/bat/README.md +44 -0
- package/karnel/tools/dev/bat/install.sh +82 -0
- package/karnel/tools/dev/bc/README.md +44 -0
- package/karnel/tools/dev/bc/install.sh +82 -0
- package/karnel/tools/dev/cloudflared/README.md +43 -0
- package/karnel/tools/dev/cloudflared/install.sh +82 -0
- package/karnel/tools/dev/curl/README.md +43 -0
- package/karnel/tools/dev/curl/install.sh +82 -0
- package/karnel/tools/dev/fzf/README.md +44 -0
- package/karnel/tools/dev/fzf/install.sh +82 -0
- package/karnel/tools/dev/gh/README.md +43 -0
- package/karnel/tools/dev/gh/install.sh +82 -0
- package/karnel/tools/dev/html2text/README.md +44 -0
- package/karnel/tools/dev/html2text/install.sh +82 -0
- package/karnel/tools/dev/imagemagick/README.md +44 -0
- package/karnel/tools/dev/imagemagick/install.sh +82 -0
- package/karnel/tools/dev/jq/README.md +44 -0
- package/karnel/tools/dev/jq/install.sh +82 -0
- package/karnel/tools/dev/lsd/README.md +44 -0
- package/karnel/tools/dev/lsd/install.sh +82 -0
- package/karnel/tools/dev/make/README.md +44 -0
- package/karnel/tools/dev/make/install.sh +82 -0
- package/karnel/tools/dev/ncurses/README.md +42 -0
- package/karnel/tools/dev/ncurses/install.sh +82 -0
- package/karnel/tools/dev/openssh/README.md +43 -0
- package/karnel/tools/dev/openssh/install.sh +75 -0
- package/karnel/tools/dev/proot/README.md +43 -0
- package/karnel/tools/dev/proot/install.sh +82 -0
- package/karnel/tools/dev/shfmt/README.md +44 -0
- package/karnel/tools/dev/shfmt/install.sh +82 -0
- package/karnel/tools/dev/tmate/README.md +44 -0
- package/karnel/tools/dev/tmate/install.sh +82 -0
- package/karnel/tools/dev/tmux/README.md +43 -0
- package/karnel/tools/dev/tmux/install.sh +75 -0
- package/karnel/tools/dev/translate/README.md +44 -0
- package/karnel/tools/dev/translate/install.sh +82 -0
- package/karnel/tools/dev/tree/README.md +44 -0
- package/karnel/tools/dev/tree/install.sh +82 -0
- package/karnel/tools/dev/udocker/README.md +44 -0
- package/karnel/tools/dev/udocker/install.sh +82 -0
- package/karnel/tools/dev/wget/README.md +44 -0
- package/karnel/tools/dev/wget/install.sh +82 -0
- package/karnel/tools/editor/all.sh +59 -0
- package/karnel/tools/editor/code-server/README.md +42 -0
- package/karnel/tools/editor/code-server/install.sh +74 -0
- package/karnel/tools/editor/neovim/README.md +43 -0
- package/karnel/tools/editor/neovim/install.sh +64 -0
- package/karnel/tools/editor/nvchad/README.md +45 -0
- package/karnel/tools/editor/nvchad/install.sh +105 -0
- package/karnel/tools/lang/all.sh +63 -0
- package/karnel/tools/lang/clang/README.md +43 -0
- package/karnel/tools/lang/clang/install.sh +79 -0
- package/karnel/tools/lang/golang/README.md +43 -0
- package/karnel/tools/lang/golang/install.sh +79 -0
- package/karnel/tools/lang/nodejs/README.md +43 -0
- package/karnel/tools/lang/nodejs/install.sh +79 -0
- package/karnel/tools/lang/perl/README.md +43 -0
- package/karnel/tools/lang/perl/install.sh +79 -0
- package/karnel/tools/lang/php/README.md +43 -0
- package/karnel/tools/lang/php/install.sh +79 -0
- package/karnel/tools/lang/python/README.md +43 -0
- package/karnel/tools/lang/python/install.sh +79 -0
- package/karnel/tools/lang/rust/README.md +43 -0
- package/karnel/tools/lang/rust/install.sh +79 -0
- package/karnel/tools/npm/all.sh +90 -0
- package/karnel/tools/npm/live-server/README.md +43 -0
- package/karnel/tools/npm/live-server/install.sh +96 -0
- package/karnel/tools/npm/localtunnel/README.md +43 -0
- package/karnel/tools/npm/localtunnel/install.sh +112 -0
- package/karnel/tools/npm/markserv/README.md +43 -0
- package/karnel/tools/npm/markserv/install.sh +95 -0
- package/karnel/tools/npm/ncu/README.md +43 -0
- package/karnel/tools/npm/ncu/install.sh +95 -0
- package/karnel/tools/npm/nestjs/README.md +43 -0
- package/karnel/tools/npm/nestjs/install.sh +95 -0
- package/karnel/tools/npm/ngrok/README.md +44 -0
- package/karnel/tools/npm/ngrok/install.sh +95 -0
- package/karnel/tools/npm/prettier/README.md +43 -0
- package/karnel/tools/npm/prettier/install.sh +95 -0
- package/karnel/tools/npm/psqlformat/README.md +43 -0
- package/karnel/tools/npm/psqlformat/install.sh +95 -0
- package/karnel/tools/npm/turbopack/README.md +8 -0
- package/karnel/tools/npm/turbopack/install.sh +42 -0
- package/karnel/tools/npm/typescript/README.md +43 -0
- package/karnel/tools/npm/typescript/install.sh +95 -0
- package/karnel/tools/npm/vercel/README.md +43 -0
- package/karnel/tools/npm/vercel/install.sh +95 -0
- package/karnel/tools/shell/all.sh +67 -0
- package/karnel/tools/shell/better-npm/README.md +43 -0
- package/karnel/tools/shell/better-npm/install.sh +85 -0
- package/karnel/tools/shell/fzf-tab/README.md +44 -0
- package/karnel/tools/shell/fzf-tab/install.sh +85 -0
- package/karnel/tools/shell/history-substring/README.md +43 -0
- package/karnel/tools/shell/history-substring/install.sh +85 -0
- package/karnel/tools/shell/powerlevel10k/README.md +43 -0
- package/karnel/tools/shell/powerlevel10k/install.sh +85 -0
- package/karnel/tools/shell/you-should-use/README.md +43 -0
- package/karnel/tools/shell/you-should-use/install.sh +85 -0
- package/karnel/tools/shell/zsh-autopair/README.md +44 -0
- package/karnel/tools/shell/zsh-autopair/install.sh +85 -0
- package/karnel/tools/shell/zsh-autosuggestions/README.md +43 -0
- package/karnel/tools/shell/zsh-autosuggestions/install.sh +85 -0
- package/karnel/tools/shell/zsh-completions/README.md +43 -0
- package/karnel/tools/shell/zsh-completions/install.sh +85 -0
- package/karnel/tools/shell/zsh-defer/README.md +43 -0
- package/karnel/tools/shell/zsh-defer/install.sh +85 -0
- package/karnel/tools/shell/zsh-syntax-highlighting/README.md +43 -0
- package/karnel/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
- package/karnel/tools/ui/all.sh +61 -0
- package/karnel/tools/ui/banner/README.md +42 -0
- package/karnel/tools/ui/banner/install.sh +160 -0
- package/karnel/tools/ui/cursor/README.md +42 -0
- package/karnel/tools/ui/cursor/install.sh +58 -0
- package/karnel/tools/ui/extra-keys/README.md +43 -0
- package/karnel/tools/ui/extra-keys/install.sh +62 -0
- package/karnel/tools/ui/font/README.md +43 -0
- package/karnel/tools/ui/font/install.sh +63 -0
- package/karnel/tools/voice/all.sh +27 -0
- package/karnel/tools/voice/install.sh +10 -0
- package/karnel/tools/voice/uninstall.sh +8 -0
- package/karnel/utils/banner.sh +492 -0
- package/karnel/utils/bootstrap.sh +25 -0
- package/karnel/utils/colors.sh +33 -0
- package/karnel/utils/dialogrc +30 -0
- package/karnel/utils/env.sh +53 -0
- package/karnel/utils/log.sh +567 -0
- package/karnel/utils/version.sh +205 -0
- package/package.json +42 -0
- package/scripts/npm-install.js +60 -0
|
@@ -0,0 +1,1528 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
import "@/utils/log"
|
|
4
|
+
import "@/utils/colors"
|
|
5
|
+
|
|
6
|
+
doctor_main() {
|
|
7
|
+
local QUICK_MODE=false
|
|
8
|
+
for arg in "$@"; do
|
|
9
|
+
[[ "$arg" == "--quick" || "$arg" == "-q" ]] && QUICK_MODE=true
|
|
10
|
+
done
|
|
11
|
+
|
|
12
|
+
echo
|
|
13
|
+
box "◈ KARNEL DOCTOR ◈"
|
|
14
|
+
echo
|
|
15
|
+
if $QUICK_MODE; then
|
|
16
|
+
log_info "Quick mode — skipping slow checks"
|
|
17
|
+
fi
|
|
18
|
+
log_info "Diagnosing your Termux and Karnel environment..."
|
|
19
|
+
echo
|
|
20
|
+
|
|
21
|
+
local warnings=0
|
|
22
|
+
local errors=0
|
|
23
|
+
local fixed=0
|
|
24
|
+
local -a fix_commands=()
|
|
25
|
+
local -a fix_descriptions=()
|
|
26
|
+
local -a fix_callbacks=()
|
|
27
|
+
|
|
28
|
+
# ===== 1. SYSTEM INFO =====
|
|
29
|
+
local arch
|
|
30
|
+
arch=$(uname -m)
|
|
31
|
+
|
|
32
|
+
local android_ver
|
|
33
|
+
android_ver=$(getprop ro.build.version.release 2>/dev/null)
|
|
34
|
+
android_ver="${android_ver:-Unknown}"
|
|
35
|
+
|
|
36
|
+
local termux_ver=""
|
|
37
|
+
if command -v termux-info &>/dev/null; then
|
|
38
|
+
termux_ver=$(timeout 5 termux-info 2>/dev/null | grep -i "termux_version" | head -n1 | cut -d'=' -f2)
|
|
39
|
+
fi
|
|
40
|
+
if [[ -z "$termux_ver" ]]; then
|
|
41
|
+
termux_ver=$(dpkg -s termux-tools 2>/dev/null | grep -i version | awk '{print $2}')
|
|
42
|
+
fi
|
|
43
|
+
termux_ver="${termux_ver:-Unknown}"
|
|
44
|
+
|
|
45
|
+
log_success "Android Version: $android_ver"
|
|
46
|
+
log_success "Termux Version: $termux_ver"
|
|
47
|
+
log_success "CPU Architecture: $arch"
|
|
48
|
+
|
|
49
|
+
# ===== 2. DISK SPACE & RAM =====
|
|
50
|
+
echo
|
|
51
|
+
separator_section "System Resources"
|
|
52
|
+
echo
|
|
53
|
+
|
|
54
|
+
local free_space
|
|
55
|
+
free_space=$(df -h "$HOME" | awk 'NR==2 {print $4}')
|
|
56
|
+
log_success "Available disk space: $free_space"
|
|
57
|
+
|
|
58
|
+
local ram_total="Unknown"
|
|
59
|
+
local ram_free="Unknown"
|
|
60
|
+
if [[ -f /proc/meminfo ]]; then
|
|
61
|
+
local total_kb free_kb
|
|
62
|
+
total_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
|
63
|
+
ram_total="$((total_kb / 1024)) MB"
|
|
64
|
+
free_kb=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
|
|
65
|
+
ram_free="$((free_kb / 1024)) MB"
|
|
66
|
+
log_success "RAM: Total: $ram_total | Available: $ram_free"
|
|
67
|
+
|
|
68
|
+
# Warn if low memory
|
|
69
|
+
local free_mb=$((free_kb / 1024))
|
|
70
|
+
if (( free_mb < 200 )); then
|
|
71
|
+
log_warn "Low available memory (${ram_free}). Some tools may fail."
|
|
72
|
+
((warnings++))
|
|
73
|
+
fi
|
|
74
|
+
else
|
|
75
|
+
log_warn "Could not read RAM details"
|
|
76
|
+
((warnings++))
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# ===== 3. STORAGE & PERMISSIONS =====
|
|
80
|
+
echo
|
|
81
|
+
separator_section "Storage & Permissions"
|
|
82
|
+
echo
|
|
83
|
+
|
|
84
|
+
local storage_status="Accessible"
|
|
85
|
+
if ls /sdcard &>/dev/null || [ -d "$HOME/storage" ]; then
|
|
86
|
+
log_success "Shared storage is accessible"
|
|
87
|
+
else
|
|
88
|
+
log_warn "Shared storage is not linked"
|
|
89
|
+
storage_status="Not Linked"
|
|
90
|
+
((warnings++))
|
|
91
|
+
fix_commands+=("termux-setup-storage")
|
|
92
|
+
fix_descriptions+=("Link shared storage for file access")
|
|
93
|
+
fix_callbacks+=("_fix_storage")
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if [ -w "$KARNEL_PATH" ]; then
|
|
97
|
+
log_success "Write permission in Karnel path: $KARNEL_PATH"
|
|
98
|
+
else
|
|
99
|
+
log_error "No write permission in Karnel path!"
|
|
100
|
+
((errors++))
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
local dirs=("$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA")
|
|
104
|
+
for dir in "${dirs[@]}"; do
|
|
105
|
+
if [ -d "$dir" ] && [ -w "$dir" ]; then
|
|
106
|
+
log_success "Directory OK: $(basename "$dir")"
|
|
107
|
+
else
|
|
108
|
+
log_warn "Directory missing or read-only: $(basename "$dir")"
|
|
109
|
+
((warnings++))
|
|
110
|
+
fix_commands+=("mkdir -p \"$dir\" && chmod 755 \"$dir\"")
|
|
111
|
+
fix_descriptions+=("Recreate directory: $(basename "$dir")")
|
|
112
|
+
fix_callbacks+=("_fix_mkdir")
|
|
113
|
+
fi
|
|
114
|
+
done
|
|
115
|
+
|
|
116
|
+
# ===== 4. LANGUAGES & CRITICAL TOOLS =====
|
|
117
|
+
echo
|
|
118
|
+
separator_section "Languages & Critical Tools"
|
|
119
|
+
echo
|
|
120
|
+
|
|
121
|
+
local -a critical_deps=("git" "rg" "jq" "curl" "tar" "node" "python" "rustc" "go" "clang" "make")
|
|
122
|
+
for dep in "${critical_deps[@]}"; do
|
|
123
|
+
if command -v "$dep" &>/dev/null; then
|
|
124
|
+
local version=""
|
|
125
|
+
case "$dep" in
|
|
126
|
+
git) version=$(git --version | awk '{print $3}') ;;
|
|
127
|
+
node) version=$(node --version) ;;
|
|
128
|
+
python) version=$(python3 --version 2>/dev/null || python --version 2>/dev/null | awk '{print $2}') ;;
|
|
129
|
+
rustc) version=$(rustc --version | awk '{print $2}') ;;
|
|
130
|
+
go) version=$(go version | awk '{print $3}') ;;
|
|
131
|
+
clang) version=$(clang --version | head -1 | awk '{print $3}') ;;
|
|
132
|
+
*) version="installed" ;;
|
|
133
|
+
esac
|
|
134
|
+
log_success "$dep: $version"
|
|
135
|
+
else
|
|
136
|
+
log_warn "$dep is not installed"
|
|
137
|
+
((warnings++))
|
|
138
|
+
local pkg_to_install="$dep"
|
|
139
|
+
[[ "$dep" == "rg" ]] && pkg_to_install="ripgrep"
|
|
140
|
+
[[ "$dep" == "rustc" ]] && pkg_to_install="rust"
|
|
141
|
+
[[ "$dep" == "go" ]] && pkg_to_install="golang"
|
|
142
|
+
[[ "$dep" == "python" ]] && pkg_to_install="python"
|
|
143
|
+
fix_commands+=("pkg install -y $pkg_to_install")
|
|
144
|
+
fix_descriptions+=("Install missing: $pkg_to_install")
|
|
145
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
146
|
+
fi
|
|
147
|
+
done
|
|
148
|
+
|
|
149
|
+
# ===== 5. PACKAGE MANAGER HEALTH =====
|
|
150
|
+
echo
|
|
151
|
+
separator_section "Package Manager & System Health"
|
|
152
|
+
echo
|
|
153
|
+
|
|
154
|
+
if dpkg --audit &>/dev/null; then
|
|
155
|
+
log_success "dpkg package manager is healthy"
|
|
156
|
+
else
|
|
157
|
+
log_error "dpkg has interrupted installations!"
|
|
158
|
+
((errors++))
|
|
159
|
+
fix_commands+=("dpkg --configure -a && apt-get -f install -y")
|
|
160
|
+
fix_descriptions+=("Fix broken dpkg/apt state")
|
|
161
|
+
fix_callbacks+=("_fix_dpkg")
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# Check for held packages
|
|
165
|
+
local held_pkgs
|
|
166
|
+
held_pkgs=$(dpkg --get-selections 2>/dev/null | grep -c "hold" || true)
|
|
167
|
+
if (( held_pkgs > 0 )); then
|
|
168
|
+
log_warn "$held_pkgs package(s) are held back"
|
|
169
|
+
((warnings++))
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# Check apt sources
|
|
173
|
+
if [[ -f "$PREFIX/etc/apt/sources.list" ]]; then
|
|
174
|
+
local source_lines
|
|
175
|
+
source_lines=$(wc -l < "$PREFIX/etc/apt/sources.list")
|
|
176
|
+
if (( source_lines == 0 )); then
|
|
177
|
+
log_error "APT sources list is empty!"
|
|
178
|
+
((errors++))
|
|
179
|
+
fix_commands+=("pkg update -y")
|
|
180
|
+
fix_descriptions+=("Refresh APT sources")
|
|
181
|
+
fix_callbacks+=("_fix_apt_update")
|
|
182
|
+
else
|
|
183
|
+
log_success "APT sources configured ($source_lines entries)"
|
|
184
|
+
fi
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
if $QUICK_MODE; then
|
|
188
|
+
echo
|
|
189
|
+
log_info "Quick mode: skipping Node.js, Python, PostgreSQL, AI tools, binary health, I/O, and network checks"
|
|
190
|
+
echo
|
|
191
|
+
else
|
|
192
|
+
|
|
193
|
+
# ===== 6. NODE.JS / NPM =====
|
|
194
|
+
echo
|
|
195
|
+
separator_section "Node.js & NPM"
|
|
196
|
+
echo
|
|
197
|
+
|
|
198
|
+
if command -v node &>/dev/null; then
|
|
199
|
+
local node_ver
|
|
200
|
+
node_ver=$(node --version)
|
|
201
|
+
log_success "Node.js: $node_ver"
|
|
202
|
+
|
|
203
|
+
if command -v npm &>/dev/null; then
|
|
204
|
+
local npm_ver
|
|
205
|
+
npm_ver=$(npm --version)
|
|
206
|
+
log_success "NPM: $npm_ver"
|
|
207
|
+
|
|
208
|
+
# Check npm global prefix permissions
|
|
209
|
+
local npm_prefix
|
|
210
|
+
npm_prefix=$(npm config get prefix 2>/dev/null)
|
|
211
|
+
if [[ -n "$npm_prefix" ]] && [[ -d "$npm_prefix" ]]; then
|
|
212
|
+
if [[ -w "$npm_prefix" ]]; then
|
|
213
|
+
log_success "NPM global directory is writable"
|
|
214
|
+
else
|
|
215
|
+
log_warn "NPM global directory is not writable: $npm_prefix"
|
|
216
|
+
((warnings++))
|
|
217
|
+
fix_commands+=("mkdir -p \"\$HOME/.npm-global\" && npm config set prefix \"\$HOME/.npm-global\"")
|
|
218
|
+
fix_descriptions+=("Fix NPM global directory permissions")
|
|
219
|
+
fix_callbacks+=("_fix_npm_prefix")
|
|
220
|
+
fi
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
# Check for npm cache bloat
|
|
224
|
+
local npm_cache_size
|
|
225
|
+
npm_cache_size=$(timeout 15 du -sh "$(npm config get cache 2>/dev/null)" 2>/dev/null | awk '{print $1}')
|
|
226
|
+
if [[ -n "$npm_cache_size" ]]; then
|
|
227
|
+
log_info "NPM cache size: $npm_cache_size"
|
|
228
|
+
fi
|
|
229
|
+
else
|
|
230
|
+
log_warn "NPM is not installed"
|
|
231
|
+
((warnings++))
|
|
232
|
+
fix_commands+=("pkg install -y nodejs-lts")
|
|
233
|
+
fix_descriptions+=("Install Node.js with NPM")
|
|
234
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
235
|
+
fi
|
|
236
|
+
else
|
|
237
|
+
log_warn "Node.js is not installed"
|
|
238
|
+
((warnings++))
|
|
239
|
+
fix_commands+=("pkg install -y nodejs-lts")
|
|
240
|
+
fix_descriptions+=("Install Node.js LTS")
|
|
241
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# ===== 7. PYTHON =====
|
|
245
|
+
echo
|
|
246
|
+
separator_section "Python Environment"
|
|
247
|
+
echo
|
|
248
|
+
|
|
249
|
+
local py_cmd=""
|
|
250
|
+
for py in python3.12 python3.11 python3.10 python3.9 python3 python; do
|
|
251
|
+
if command -v "$py" &>/dev/null; then
|
|
252
|
+
py_cmd="$py"
|
|
253
|
+
break
|
|
254
|
+
fi
|
|
255
|
+
done
|
|
256
|
+
|
|
257
|
+
if [[ -n "$py_cmd" ]]; then
|
|
258
|
+
local py_ver
|
|
259
|
+
py_ver=$("$py_cmd" --version 2>&1 | awk '{print $2}')
|
|
260
|
+
log_success "Python: $py_cmd ($py_ver)"
|
|
261
|
+
|
|
262
|
+
# Check pip
|
|
263
|
+
if "$py_cmd" -m pip --version &>/dev/null; then
|
|
264
|
+
local pip_ver
|
|
265
|
+
pip_ver=$("$py_cmd" -m pip --version | awk '{print $2}')
|
|
266
|
+
log_success "Pip: $pip_ver"
|
|
267
|
+
else
|
|
268
|
+
log_warn "Pip is not installed for $py_cmd"
|
|
269
|
+
((warnings++))
|
|
270
|
+
fix_commands+=("$py_cmd -m ensurepip && $py_cmd -m pip install --upgrade pip")
|
|
271
|
+
fix_descriptions+=("Install/upgrade pip for $py_cmd")
|
|
272
|
+
fix_callbacks+=("_fix_pip")
|
|
273
|
+
fi
|
|
274
|
+
|
|
275
|
+
# Check venv module
|
|
276
|
+
if "$py_cmd" -m venv --help &>/dev/null; then
|
|
277
|
+
log_success "Python venv module available"
|
|
278
|
+
else
|
|
279
|
+
log_warn "Python venv module not available"
|
|
280
|
+
((warnings++))
|
|
281
|
+
local venv_pkg="python-venv"
|
|
282
|
+
[[ "$py_cmd" == "python3.11" ]] && venv_pkg="python3.11-venv"
|
|
283
|
+
[[ "$py_cmd" == "python3.10" ]] && venv_pkg="python3.10-venv"
|
|
284
|
+
fix_commands+=("pkg install -y $venv_pkg")
|
|
285
|
+
fix_descriptions+=("Install venv module for $py_cmd")
|
|
286
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
287
|
+
fi
|
|
288
|
+
else
|
|
289
|
+
log_warn "Python is not installed"
|
|
290
|
+
((warnings++))
|
|
291
|
+
fix_commands+=("pkg install -y python")
|
|
292
|
+
fix_descriptions+=("Install Python")
|
|
293
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
# ===== 8. POSTGRESQL =====
|
|
297
|
+
echo
|
|
298
|
+
separator_section "PostgreSQL Database"
|
|
299
|
+
echo
|
|
300
|
+
|
|
301
|
+
local pg_installed=false
|
|
302
|
+
if command -v pg_ctl &>/dev/null; then
|
|
303
|
+
pg_installed=true
|
|
304
|
+
local pg_ver
|
|
305
|
+
pg_ver=$(postgres --version 2>/dev/null | awk '{print $3}')
|
|
306
|
+
log_success "PostgreSQL installed: $pg_ver"
|
|
307
|
+
|
|
308
|
+
# Check if data directory exists
|
|
309
|
+
local pg_data_found=false
|
|
310
|
+
local pg_data_dirs=(
|
|
311
|
+
"$PREFIX/var/lib/postgresql/data"
|
|
312
|
+
"$PREFIX/var/lib/postgresql"
|
|
313
|
+
"$HOME/.termux/postgresql/data"
|
|
314
|
+
"$HOME/.termux/postgresql"
|
|
315
|
+
)
|
|
316
|
+
for dir in "${pg_data_dirs[@]}"; do
|
|
317
|
+
if [[ -d "$dir" ]] && [[ -f "$dir/PG_VERSION" ]]; then
|
|
318
|
+
pg_data_found=true
|
|
319
|
+
log_success "Data directory found: $dir"
|
|
320
|
+
break
|
|
321
|
+
fi
|
|
322
|
+
done
|
|
323
|
+
|
|
324
|
+
if [[ "$pg_data_found" == "false" ]]; then
|
|
325
|
+
log_warn "PostgreSQL not initialized (no data directory)"
|
|
326
|
+
((warnings++))
|
|
327
|
+
fix_commands+=("karnel pg init && karnel pg start")
|
|
328
|
+
fix_descriptions+=("Initialize and start PostgreSQL")
|
|
329
|
+
fix_callbacks+=("_fix_pg_init")
|
|
330
|
+
else
|
|
331
|
+
# Check if running
|
|
332
|
+
if pg_ctl -D "$dir" status &>/dev/null; then
|
|
333
|
+
log_success "PostgreSQL: RUNNING"
|
|
334
|
+
else
|
|
335
|
+
log_warn "PostgreSQL: STOPPED"
|
|
336
|
+
((warnings++))
|
|
337
|
+
fix_commands+=("karnel pg start")
|
|
338
|
+
fix_descriptions+=("Start PostgreSQL server")
|
|
339
|
+
fix_callbacks+=("_fix_pg_start")
|
|
340
|
+
fi
|
|
341
|
+
fi
|
|
342
|
+
else
|
|
343
|
+
log_warn "PostgreSQL is not installed"
|
|
344
|
+
((warnings++))
|
|
345
|
+
fix_commands+=("karnel install db --postgresql")
|
|
346
|
+
fix_descriptions+=("Install PostgreSQL")
|
|
347
|
+
fix_callbacks+=("_fix_pg_install")
|
|
348
|
+
fi
|
|
349
|
+
|
|
350
|
+
# ===== 9. PYTHON COMPATIBILITY CHECKS =====
|
|
351
|
+
echo
|
|
352
|
+
separator_section "Python Compatibility (Termux patches)"
|
|
353
|
+
echo
|
|
354
|
+
|
|
355
|
+
# psutil Android check
|
|
356
|
+
if python3 -c "import psutil; print(psutil.__version__)" &>/dev/null; then
|
|
357
|
+
log_success "psutil: $(python3 -c 'import psutil; print(psutil.__version__)') — Android patch OK"
|
|
358
|
+
else
|
|
359
|
+
log_warn "psutil not installed — needed by hermes-agent and other AI tools"
|
|
360
|
+
((warnings++))
|
|
361
|
+
fix_commands+=("pip install psutil==7.2.2")
|
|
362
|
+
fix_descriptions+=("Install psutil for Python process monitoring")
|
|
363
|
+
fix_callbacks+=("_fix_psutil")
|
|
364
|
+
fi
|
|
365
|
+
|
|
366
|
+
# Python version constraint check (pyproject.toml files)
|
|
367
|
+
local constraint_issues=0
|
|
368
|
+
while IFS= read -r -d '' pyproject; do
|
|
369
|
+
local require_py
|
|
370
|
+
require_py=$(grep -E 'requires-python\s*=' "$pyproject" 2>/dev/null | grep -oP '>=3\.\d+,<3\.\d+')
|
|
371
|
+
if [[ -n "$require_py" ]]; then
|
|
372
|
+
local max_ver
|
|
373
|
+
max_ver=$(echo "$require_py" | grep -oP '<3\.\K\d+')
|
|
374
|
+
if [[ -n "$max_ver" ]] && (( max_ver <= 14 )); then
|
|
375
|
+
log_warn "Constraint in $(basename "$(dirname "$pyproject")"): $require_py may block Python 3.14"
|
|
376
|
+
((constraint_issues++))
|
|
377
|
+
fi
|
|
378
|
+
fi
|
|
379
|
+
done < <(timeout 10 find "$HOME/.hermes" "$HOME/karnel" -name "pyproject.toml" -maxdepth 3 -print0 2>/dev/null || true)
|
|
380
|
+
if (( constraint_issues == 0 )); then
|
|
381
|
+
log_success "No Python version constraints blocking 3.14"
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
# C extension build capability
|
|
385
|
+
local cc_test="$PREFIX/tmp/cext_test.c"
|
|
386
|
+
echo '#include <Python.h>' > "$cc_test"
|
|
387
|
+
if python3-config --includes &>/dev/null && \
|
|
388
|
+
clang $(python3-config --includes) -shared -fPIC -o /dev/null -x c - <<<'#include <Python.h>' &>/dev/null; then
|
|
389
|
+
log_success "C extensions can be compiled (Python.h + clang OK)"
|
|
390
|
+
else
|
|
391
|
+
log_warn "C extension build may fail — clang or Python headers issue"
|
|
392
|
+
((warnings++))
|
|
393
|
+
fix_commands+=("pkg install -y clang python-dev")
|
|
394
|
+
fix_descriptions+=("Install C build dependencies for Python extensions")
|
|
395
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
396
|
+
fi
|
|
397
|
+
rm -f "$cc_test"
|
|
398
|
+
|
|
399
|
+
# uv availability (used by hermes-agent installer)
|
|
400
|
+
if command -v uv &>/dev/null; then
|
|
401
|
+
log_success "uv package manager: available"
|
|
402
|
+
else
|
|
403
|
+
log_info "uv not installed (used by hermes-agent, optional)"
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
# pip check — detect broken dependencies
|
|
407
|
+
local pip_check_output
|
|
408
|
+
pip_check_output=$(timeout 15 pip check 2>&1 | grep -i "broken\|missing\|conflict\|incompatible" || true)
|
|
409
|
+
if [[ -z "$pip_check_output" ]]; then
|
|
410
|
+
log_success "pip dependencies: consistent"
|
|
411
|
+
else
|
|
412
|
+
log_warn "pip dependency issues detected"
|
|
413
|
+
echo "$pip_check_output" | while IFS= read -r line; do
|
|
414
|
+
list_item "$line"
|
|
415
|
+
done
|
|
416
|
+
((warnings++))
|
|
417
|
+
local broken_pkgs
|
|
418
|
+
broken_pkgs=$(timeout 10 pip check 2>&1 | grep -oP '^\S+' | head -3 | tr '\n' ' ')
|
|
419
|
+
if [[ -n "$broken_pkgs" ]]; then
|
|
420
|
+
fix_commands+=("pip install --upgrade --force-reinstall $broken_pkgs")
|
|
421
|
+
fix_descriptions+=("Fix pip dependency conflicts: $broken_pkgs")
|
|
422
|
+
fix_callbacks+=("_fix_pip_check")
|
|
423
|
+
fi
|
|
424
|
+
fi
|
|
425
|
+
|
|
426
|
+
# ===== 10. KARNEL FRAMEWORK =====
|
|
427
|
+
echo
|
|
428
|
+
separator_section "Karnel Framework"
|
|
429
|
+
echo
|
|
430
|
+
|
|
431
|
+
# Check Karnel version
|
|
432
|
+
local karnel_ver="unknown"
|
|
433
|
+
if [[ -n "${KARNEL_VERSION:-}" ]]; then
|
|
434
|
+
karnel_ver="$KARNEL_VERSION"
|
|
435
|
+
fi
|
|
436
|
+
log_success "Karnel version: $karnel_ver"
|
|
437
|
+
|
|
438
|
+
# Check symlinks
|
|
439
|
+
if [[ -L "$PREFIX/bin/karnel" ]]; then
|
|
440
|
+
log_success "CLI symlink: karnel"
|
|
441
|
+
else
|
|
442
|
+
log_warn "CLI symlinks missing"
|
|
443
|
+
((warnings++))
|
|
444
|
+
fix_commands+=("ln -sf \"$KARNEL_PATH/bin/karnel\" \"$PREFIX/bin/karnel\"")
|
|
445
|
+
fix_descriptions+=("Recreate CLI symlinks")
|
|
446
|
+
fix_callbacks+=("_fix_symlinks")
|
|
447
|
+
fi
|
|
448
|
+
|
|
449
|
+
# Check if banner is installed in shell config
|
|
450
|
+
local shell_config=""
|
|
451
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
452
|
+
shell_config="$HOME/.zshrc"
|
|
453
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
454
|
+
shell_config="$HOME/.bashrc"
|
|
455
|
+
fi
|
|
456
|
+
|
|
457
|
+
if [[ -n "$shell_config" ]]; then
|
|
458
|
+
if grep -qF "# ===== Karnel Banner =====" "$shell_config" 2>/dev/null; then
|
|
459
|
+
log_success "Banner installed in $(basename "$shell_config")"
|
|
460
|
+
else
|
|
461
|
+
log_warn "Banner not installed in $(basename "$shell_config")"
|
|
462
|
+
((warnings++))
|
|
463
|
+
fix_commands+=("karnel install ui --banner")
|
|
464
|
+
fix_descriptions+=("Install Karnel banner in shell")
|
|
465
|
+
fix_callbacks+=("_fix_banner")
|
|
466
|
+
fi
|
|
467
|
+
fi
|
|
468
|
+
fi # end QUICK_MODE skip
|
|
469
|
+
|
|
470
|
+
# ===== 10. AI TOOLS STATUS =====
|
|
471
|
+
echo
|
|
472
|
+
separator_section "AI Tools Installed"
|
|
473
|
+
echo
|
|
474
|
+
|
|
475
|
+
local -a ai_cmds=("opencode" "claude" "gemini" "codex" "qwen" "vibe" "mimo" "hermes" "kimi" "ollama" "freebuff" "pi" "agy" "mmx" "gentle-ai" "gga" "engram" "codegraph" "kilocode" "kiro" "crush" "odysseus" "openclaude" "openclaw" "command-code" "kimchi" "cline" "omni-route" "ctx7" "openspec")
|
|
476
|
+
local ai_count=0
|
|
477
|
+
|
|
478
|
+
for cmd in "${ai_cmds[@]}"; do
|
|
479
|
+
if command -v "$cmd" &>/dev/null; then
|
|
480
|
+
log_success "$cmd: installed"
|
|
481
|
+
((ai_count++))
|
|
482
|
+
fi
|
|
483
|
+
done
|
|
484
|
+
|
|
485
|
+
if (( ai_count == 0 )); then
|
|
486
|
+
log_warn "No AI tools installed"
|
|
487
|
+
((warnings++))
|
|
488
|
+
fix_commands+=("karnel install ai")
|
|
489
|
+
fix_descriptions+=("Install all AI tools")
|
|
490
|
+
fix_callbacks+=("_fix_ai_install")
|
|
491
|
+
else
|
|
492
|
+
log_info "$ai_count AI tool(s) installed"
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
# Registry consistency check
|
|
496
|
+
local registry_file="$KARNEL_PATH/tools/ai/all.sh"
|
|
497
|
+
if [[ -f "$registry_file" ]]; then
|
|
498
|
+
local registered_tools
|
|
499
|
+
registered_tools=$(grep -cE '^[[:space:]]*"[^:]+:[^:]+:[^"]+"' "$registry_file" 2>/dev/null || echo 0)
|
|
500
|
+
local installed_ai
|
|
501
|
+
installed_ai=0
|
|
502
|
+
for cmd in "${ai_cmds[@]}"; do
|
|
503
|
+
command -v "$cmd" &>/dev/null && ((installed_ai++))
|
|
504
|
+
done
|
|
505
|
+
log_info "AI registry: $registered_tools tools | Installed: $installed_ai"
|
|
506
|
+
fi
|
|
507
|
+
|
|
508
|
+
# Check for discontinued tools still referenced in active installers
|
|
509
|
+
local -a removed_tools=()
|
|
510
|
+
for tool_dir in "$KARNEL_PATH/tools/ai/"*/; do
|
|
511
|
+
local tool_name
|
|
512
|
+
tool_name=$(basename "${tool_dir%/}")
|
|
513
|
+
if [[ ! -f "$tool_dir/install.sh" && ! -f "$tool_dir/all.sh" ]]; then
|
|
514
|
+
removed_tools+=("$tool_name")
|
|
515
|
+
fi
|
|
516
|
+
done
|
|
517
|
+
if [[ ${#removed_tools[@]} -gt 0 ]]; then
|
|
518
|
+
log_warn "Orphaned tool directories (no installer): ${removed_tools[*]}"
|
|
519
|
+
((warnings++))
|
|
520
|
+
fi
|
|
521
|
+
|
|
522
|
+
# ===== SHEBANG & BINARY HEALTH =====
|
|
523
|
+
echo
|
|
524
|
+
separator_section "Binary & Shebang Health"
|
|
525
|
+
echo
|
|
526
|
+
|
|
527
|
+
# Check for bad shebangs (#!/usr/bin/env) in PREFIX/bin (fast grep)
|
|
528
|
+
local bad_shebangs=0
|
|
529
|
+
local bad_files
|
|
530
|
+
bad_files=$(timeout 10 rg -l "^#!/usr/bin/env" "$PREFIX/bin/" 2>/dev/null || true)
|
|
531
|
+
if [[ -n "$bad_files" ]]; then
|
|
532
|
+
bad_shebangs=$(echo "$bad_files" | wc -l)
|
|
533
|
+
log_warn "$bad_shebangs binary(s) with #!/usr/bin/env — will fail on Termux"
|
|
534
|
+
echo "$bad_files" | while IFS= read -r f; do
|
|
535
|
+
list_item "$(basename "$f")"
|
|
536
|
+
done
|
|
537
|
+
((warnings++))
|
|
538
|
+
fix_commands+=("karnel install npm --all 2>/dev/null || true")
|
|
539
|
+
fix_descriptions+=("Reinstall npm tools to fix shebangs")
|
|
540
|
+
fix_callbacks+=("_fix_npm_shebangs")
|
|
541
|
+
else
|
|
542
|
+
log_success "All binaries have valid shebangs"
|
|
543
|
+
fi
|
|
544
|
+
|
|
545
|
+
# Check for broken symlinks in PREFIX/bin
|
|
546
|
+
local broken_symlinks=0
|
|
547
|
+
broken_symlinks=$(timeout 10 find "$PREFIX/bin" -type l ! -exec test -e {} \; -print 2>/dev/null | wc -l)
|
|
548
|
+
if (( broken_symlinks > 0 )); then
|
|
549
|
+
log_warn "$broken_symlinks broken symlink(s) in $PREFIX/bin"
|
|
550
|
+
((warnings++))
|
|
551
|
+
fix_commands+=("find $PREFIX/bin -type l ! -exec test -e {} \; -delete")
|
|
552
|
+
fix_descriptions+=("Remove broken symlinks from PREFIX/bin")
|
|
553
|
+
fix_callbacks+=("_fix_broken_symlinks")
|
|
554
|
+
else
|
|
555
|
+
log_success "No broken symlinks in $PREFIX/bin"
|
|
556
|
+
fi
|
|
557
|
+
|
|
558
|
+
# Detect glibc-dependent binaries (need proot)
|
|
559
|
+
local glibc_bins=0
|
|
560
|
+
local -a glibc_dependent=("kimchi")
|
|
561
|
+
for cmd in "${glibc_dependent[@]}"; do
|
|
562
|
+
local path
|
|
563
|
+
path=$(command -v "$cmd" 2>/dev/null)
|
|
564
|
+
if [[ -n "$path" ]]; then
|
|
565
|
+
if file "$path" 2>/dev/null | grep -qi "ELF\|executable" && \
|
|
566
|
+
! ldd "$path" &>/dev/null 2>&1; then
|
|
567
|
+
log_info "$cmd: glibc binary (needs proot)"
|
|
568
|
+
if command -v proot-distro &>/dev/null; then
|
|
569
|
+
log_success " proot-distro available as fallback"
|
|
570
|
+
else
|
|
571
|
+
log_warn " $cmd needs proot but proot-distro not installed"
|
|
572
|
+
((warnings++))
|
|
573
|
+
fi
|
|
574
|
+
((glibc_bins++))
|
|
575
|
+
fi
|
|
576
|
+
fi
|
|
577
|
+
done
|
|
578
|
+
if (( glibc_bins == 0 )); then
|
|
579
|
+
log_success "No glibc-dependent binaries detected"
|
|
580
|
+
fi
|
|
581
|
+
|
|
582
|
+
# ===== SHELL CONFIGURATION =====
|
|
583
|
+
echo
|
|
584
|
+
separator_section "Shell Configuration"
|
|
585
|
+
echo
|
|
586
|
+
|
|
587
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
588
|
+
log_success "ZSH config: .zshrc exists"
|
|
589
|
+
|
|
590
|
+
# Check for syntax errors
|
|
591
|
+
if zsh -n "$HOME/.zshrc" 2>/dev/null; then
|
|
592
|
+
log_success ".zshrc syntax: OK"
|
|
593
|
+
else
|
|
594
|
+
log_error ".zshrc has syntax errors!"
|
|
595
|
+
((errors++))
|
|
596
|
+
fix_commands+=("cp \"$HOME/.zshrc\" \"$HOME/.zshrc.bak\" && karnel install shell")
|
|
597
|
+
fix_descriptions+=("Backup and reinstall shell config")
|
|
598
|
+
fix_callbacks+=("_fix_shell_syntax")
|
|
599
|
+
fi
|
|
600
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
601
|
+
log_success "Bash config: .bashrc exists"
|
|
602
|
+
else
|
|
603
|
+
log_warn "No shell config found"
|
|
604
|
+
((warnings++))
|
|
605
|
+
fi
|
|
606
|
+
|
|
607
|
+
# ===== CACHE & BUILD ARTIFACTS =====
|
|
608
|
+
echo
|
|
609
|
+
separator_section "Cache & Build Artifacts"
|
|
610
|
+
echo
|
|
611
|
+
|
|
612
|
+
# npm cache
|
|
613
|
+
local npm_cache_dir
|
|
614
|
+
npm_cache_dir=$(npm config get cache 2>/dev/null)
|
|
615
|
+
if [[ -n "$npm_cache_dir" ]] && [[ -d "$npm_cache_dir" ]]; then
|
|
616
|
+
local npm_cache_size
|
|
617
|
+
npm_cache_size=$(du -sh "$npm_cache_dir" 2>/dev/null | awk '{print $1}')
|
|
618
|
+
log_info "npm cache: $npm_cache_size"
|
|
619
|
+
if [[ "$npm_cache_size" =~ [0-9]+G ]]; then
|
|
620
|
+
log_warn "npm cache is large (${npm_cache_size}) — consider cleaning"
|
|
621
|
+
((warnings++))
|
|
622
|
+
fix_commands+=("npm cache clean --force 2>/dev/null")
|
|
623
|
+
fix_descriptions+=("Clean npm cache")
|
|
624
|
+
fix_callbacks+=("_fix_npm_cache")
|
|
625
|
+
fi
|
|
626
|
+
fi
|
|
627
|
+
|
|
628
|
+
# pip cache
|
|
629
|
+
local pip_cache_dir
|
|
630
|
+
pip_cache_dir=$(pip cache dir 2>/dev/null)
|
|
631
|
+
if [[ -n "$pip_cache_dir" ]] && [[ -d "$pip_cache_dir" ]]; then
|
|
632
|
+
local pip_cache_size
|
|
633
|
+
pip_cache_size=$(du -sh "$pip_cache_dir" 2>/dev/null | awk '{print $1}')
|
|
634
|
+
log_info "pip cache: $pip_cache_size"
|
|
635
|
+
if [[ "$pip_cache_size" =~ [0-9]+G ]]; then
|
|
636
|
+
log_warn "pip cache is large (${pip_cache_size})"
|
|
637
|
+
((warnings++))
|
|
638
|
+
fix_commands+=("pip cache purge 2>/dev/null")
|
|
639
|
+
fix_descriptions+=("Clean pip cache")
|
|
640
|
+
fix_callbacks+=("_fix_pip_cache")
|
|
641
|
+
fi
|
|
642
|
+
fi
|
|
643
|
+
|
|
644
|
+
# Python __pycache__ bloat
|
|
645
|
+
local pycache_size
|
|
646
|
+
pycache_size=$(find "$PREFIX/lib/python3.*" -name "__pycache__" -type d -exec du -sk {} + 2>/dev/null | awk '{s+=$1}END{printf "%.0f", s/1024}')
|
|
647
|
+
if [[ -n "$pycache_size" ]] && (( pycache_size > 50 )); then
|
|
648
|
+
log_info "Python __pycache__: ${pycache_size}MB"
|
|
649
|
+
if (( pycache_size > 200 )); then
|
|
650
|
+
log_warn "Large Python cache (${pycache_size}MB) — may slow imports"
|
|
651
|
+
fix_commands+=("find $PREFIX/lib/python3.* -name __pycache__ -exec rm -rf {} + 2>/dev/null")
|
|
652
|
+
fix_descriptions+=("Clean Python __pycache__ directories")
|
|
653
|
+
fix_callbacks+=("_fix_pycache")
|
|
654
|
+
fi
|
|
655
|
+
fi
|
|
656
|
+
|
|
657
|
+
# cargo cache (if rust installed)
|
|
658
|
+
if [[ -d "$HOME/.cargo/registry" ]]; then
|
|
659
|
+
local cargo_size
|
|
660
|
+
cargo_size=$(du -sh "$HOME/.cargo/registry" 2>/dev/null | awk '{print $1}')
|
|
661
|
+
log_info "cargo registry: $cargo_size"
|
|
662
|
+
fi
|
|
663
|
+
|
|
664
|
+
# karnel cache
|
|
665
|
+
if [[ -d "$KARNEL_CACHE" ]]; then
|
|
666
|
+
local karnel_cache_size
|
|
667
|
+
karnel_cache_size=$(du -sh "$KARNEL_CACHE" 2>/dev/null | awk '{print $1}')
|
|
668
|
+
log_info "karnel cache: $karnel_cache_size"
|
|
669
|
+
fi
|
|
670
|
+
|
|
671
|
+
# Zombie/stale build processes
|
|
672
|
+
local stale_builds
|
|
673
|
+
stale_builds=$(pgrep -f "pip.*install\|npm.*install\|cargo.*build" 2>/dev/null | wc -l)
|
|
674
|
+
if (( stale_builds > 0 )); then
|
|
675
|
+
log_warn "$stale_builds build process(es) still running"
|
|
676
|
+
list_item "Run 'kill \$(pgrep -f \"pip.*install\")' to clean up"
|
|
677
|
+
fi
|
|
678
|
+
|
|
679
|
+
# ===== PHANTOM PROCESS KILLER =====
|
|
680
|
+
echo
|
|
681
|
+
separator_section "Android Compatibility"
|
|
682
|
+
echo
|
|
683
|
+
|
|
684
|
+
if [[ "$android_ver" =~ ^(12|13|14|15|16) ]]; then
|
|
685
|
+
log_warn "Android $android_ver: Phantom Process Killer may kill Termux processes"
|
|
686
|
+
log_info "Fix: Run via ADB:"
|
|
687
|
+
list_item "adb shell device_config put activity_manager max_phantom_processes 2147483647"
|
|
688
|
+
((warnings++))
|
|
689
|
+
else
|
|
690
|
+
log_success "No phantom killer warnings apply"
|
|
691
|
+
fi
|
|
692
|
+
|
|
693
|
+
# ===== PROOT / GLIBC ENVIRONMENT =====
|
|
694
|
+
echo
|
|
695
|
+
separator_section "Proot & glibc Environment"
|
|
696
|
+
echo
|
|
697
|
+
|
|
698
|
+
if command -v proot-distro &>/dev/null; then
|
|
699
|
+
log_success "proot-distro: available"
|
|
700
|
+
local ubuntu_installed=false
|
|
701
|
+
if proot-distro list 2>/dev/null | grep -qi ubuntu; then
|
|
702
|
+
ubuntu_installed=true
|
|
703
|
+
log_success "Ubuntu proot container: installed"
|
|
704
|
+
else
|
|
705
|
+
log_info "Ubuntu proot container: not installed (needed by kimchi)"
|
|
706
|
+
fix_commands+=("proot-distro install ubuntu 2>/dev/null")
|
|
707
|
+
fix_descriptions+=("Install Ubuntu proot container for glibc tools")
|
|
708
|
+
fix_callbacks+=("_fix_proot_ubuntu")
|
|
709
|
+
fi
|
|
710
|
+
else
|
|
711
|
+
log_info "proot-distro not installed (optional, needed for kimchi)"
|
|
712
|
+
fix_commands+=("pkg install -y proot-distro")
|
|
713
|
+
fix_descriptions+=("Install proot-distro for glibc compatibility")
|
|
714
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
715
|
+
fi
|
|
716
|
+
|
|
717
|
+
if command -v proot &>/dev/null; then
|
|
718
|
+
log_success "proot: available"
|
|
719
|
+
else
|
|
720
|
+
log_info "proot not installed (optional)"
|
|
721
|
+
fi
|
|
722
|
+
|
|
723
|
+
# ===== TERMUX:API =====
|
|
724
|
+
echo
|
|
725
|
+
separator_section "Termux:API"
|
|
726
|
+
echo
|
|
727
|
+
|
|
728
|
+
if command -v termux-info &>/dev/null; then
|
|
729
|
+
log_success "Termux:API is installed"
|
|
730
|
+
else
|
|
731
|
+
log_warn "Termux:API not installed (needed for voice commands)"
|
|
732
|
+
((warnings++))
|
|
733
|
+
fix_commands+=("pkg install -y termux-api")
|
|
734
|
+
fix_descriptions+=("Install Termux:API for voice features")
|
|
735
|
+
fix_callbacks+=("_fix_pkg_install")
|
|
736
|
+
fi
|
|
737
|
+
|
|
738
|
+
# ===== 14. GIT CONFIGURATION =====
|
|
739
|
+
echo
|
|
740
|
+
separator_section "Git Configuration"
|
|
741
|
+
echo
|
|
742
|
+
|
|
743
|
+
if command -v git &>/dev/null; then
|
|
744
|
+
local git_user git_email
|
|
745
|
+
git_user=$(git config --global user.name 2>/dev/null)
|
|
746
|
+
git_email=$(git config --global user.email 2>/dev/null)
|
|
747
|
+
if [[ -n "$git_user" ]] && [[ -n "$git_email" ]]; then
|
|
748
|
+
log_success "Git user: $git_user <$git_email>"
|
|
749
|
+
else
|
|
750
|
+
log_warn "Git user.name or user.email not configured"
|
|
751
|
+
((warnings++))
|
|
752
|
+
fi
|
|
753
|
+
fi
|
|
754
|
+
|
|
755
|
+
# ===== 15. SSH KEYS =====
|
|
756
|
+
echo
|
|
757
|
+
separator_section "SSH Keys"
|
|
758
|
+
echo
|
|
759
|
+
|
|
760
|
+
if [[ -f "$HOME/.ssh/id_ed25519" ]] || [[ -f "$HOME/.ssh/id_rsa" ]]; then
|
|
761
|
+
log_success "SSH key found"
|
|
762
|
+
else
|
|
763
|
+
log_warn "No SSH key found (needed for GitHub)"
|
|
764
|
+
((warnings++))
|
|
765
|
+
fix_commands+=("ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''")
|
|
766
|
+
fix_descriptions+=("Generate SSH key for GitHub")
|
|
767
|
+
fix_callbacks+=("_fix_ssh_key")
|
|
768
|
+
fi
|
|
769
|
+
|
|
770
|
+
# ===== 16. NETWORK CONNECTIVITY =====
|
|
771
|
+
echo
|
|
772
|
+
separator_section "Network"
|
|
773
|
+
echo
|
|
774
|
+
|
|
775
|
+
# DNS resolution
|
|
776
|
+
if nslookup github.com &>/dev/null || host github.com &>/dev/null; then
|
|
777
|
+
log_success "DNS resolution: OK"
|
|
778
|
+
else
|
|
779
|
+
log_warn "DNS resolution failed"
|
|
780
|
+
((warnings++))
|
|
781
|
+
fix_commands+=("echo 'nameserver 8.8.8.8' > $PREFIX/etc/resolv.conf")
|
|
782
|
+
fix_descriptions+=("Set Google DNS (8.8.8.8) for Termux")
|
|
783
|
+
fix_callbacks+=("_fix_dns")
|
|
784
|
+
fi
|
|
785
|
+
|
|
786
|
+
if curl -fsSL --max-time 5 https://github.com &>/dev/null; then
|
|
787
|
+
log_success "HTTPS connectivity: OK"
|
|
788
|
+
else
|
|
789
|
+
log_warn "Network connectivity issue detected"
|
|
790
|
+
((warnings++))
|
|
791
|
+
fi
|
|
792
|
+
|
|
793
|
+
# Termux mirror speed
|
|
794
|
+
local active_mirror=""
|
|
795
|
+
if [[ -f "$PREFIX/etc/apt/sources.list" ]]; then
|
|
796
|
+
active_mirror=$(grep -oP 'https?://[^ ]+' "$PREFIX/etc/apt/sources.list" 2>/dev/null | head -1)
|
|
797
|
+
fi
|
|
798
|
+
if [[ -n "$active_mirror" ]]; then
|
|
799
|
+
local mirror_host
|
|
800
|
+
mirror_host=$(echo "$active_mirror" | awk -F/ '{print $3}')
|
|
801
|
+
local ping_time
|
|
802
|
+
ping_time=$(timeout 5 ping -c 1 -W 3 "$mirror_host" 2>/dev/null | grep -oP 'time=\K[0-9.]+' || echo "slow")
|
|
803
|
+
log_info "Termux mirror: $mirror_host (${ping_time}ms)"
|
|
804
|
+
if [[ "$ping_time" == "slow" ]]; then
|
|
805
|
+
log_warn "Termux mirror is slow — consider switching"
|
|
806
|
+
fix_commands+=("termux-change-repo")
|
|
807
|
+
fix_descriptions+=("Switch to a faster Termux mirror")
|
|
808
|
+
fix_callbacks+=("_fix_mirror")
|
|
809
|
+
fi
|
|
810
|
+
fi
|
|
811
|
+
|
|
812
|
+
# ===== 17. OPENSSH =====
|
|
813
|
+
if command -v sshd &>/dev/null; then
|
|
814
|
+
log_success "OpenSSH server available"
|
|
815
|
+
else
|
|
816
|
+
log_info "OpenSSH server not installed (optional)"
|
|
817
|
+
fi
|
|
818
|
+
|
|
819
|
+
# ===== 18. DISK SPACE CHECK =====
|
|
820
|
+
echo
|
|
821
|
+
separator_section "Disk Health"
|
|
822
|
+
echo
|
|
823
|
+
|
|
824
|
+
local free_space_kb
|
|
825
|
+
free_space_kb=$(df "$HOME" | awk 'NR==2 {print $4}')
|
|
826
|
+
if [[ -n "$free_space_kb" ]]; then
|
|
827
|
+
local free_mb=$((free_space_kb / 1024))
|
|
828
|
+
if (( free_mb < 500 )); then
|
|
829
|
+
log_warn "Low disk space: ${free_mb}MB free. Consider cleaning cache."
|
|
830
|
+
((warnings++))
|
|
831
|
+
fix_commands+=("rm -rf ~/.cache/karnel/install_*.log 2>/dev/null; pkg clean -y 2>/dev/null")
|
|
832
|
+
fix_descriptions+=("Clean cache and unused packages")
|
|
833
|
+
fix_callbacks+=("_fix_disk_cleanup")
|
|
834
|
+
else
|
|
835
|
+
log_success "Disk space: OK (${free_mb}MB free)"
|
|
836
|
+
fi
|
|
837
|
+
fi
|
|
838
|
+
|
|
839
|
+
# ===== 19. KARNEL DATA DIRS =====
|
|
840
|
+
echo
|
|
841
|
+
separator_section "Karnel Data Integrity"
|
|
842
|
+
echo
|
|
843
|
+
|
|
844
|
+
local karnel_dirs=("$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA" "$HOME/.local/share/karnel-data")
|
|
845
|
+
for dir in "${karnel_dirs[@]}"; do
|
|
846
|
+
if [[ -d "$dir" ]]; then
|
|
847
|
+
local size
|
|
848
|
+
size=$(du -sh "$dir" 2>/dev/null | awk '{print $1}')
|
|
849
|
+
log_success "$(basename "$dir"): ${size:-0}"
|
|
850
|
+
else
|
|
851
|
+
log_warn "Missing: $(basename "$dir")"
|
|
852
|
+
((warnings++))
|
|
853
|
+
fix_commands+=("mkdir -p \"$dir\"")
|
|
854
|
+
fix_descriptions+=("Create missing dir: $(basename "$dir")")
|
|
855
|
+
fix_callbacks+=("_fix_mkdir_single")
|
|
856
|
+
fi
|
|
857
|
+
done
|
|
858
|
+
|
|
859
|
+
# ===== ZSH PLUGINS & KARNEL INTEGRATION =====
|
|
860
|
+
echo
|
|
861
|
+
separator_section "Zsh Plugins & Karnel Integration"
|
|
862
|
+
echo
|
|
863
|
+
|
|
864
|
+
local zsh_plugins_dir="$HOME/.oh-my-zsh/custom/plugins"
|
|
865
|
+
if [[ -d "$zsh_plugins_dir" ]]; then
|
|
866
|
+
local -a needed_plugins=("history-substring-search" "you-should-use")
|
|
867
|
+
for plugin in "${needed_plugins[@]}"; do
|
|
868
|
+
if [[ -d "$zsh_plugins_dir/$plugin" ]]; then
|
|
869
|
+
log_success "zsh plugin: $plugin"
|
|
870
|
+
else
|
|
871
|
+
log_info "zsh plugin: $plugin not found (optional)"
|
|
872
|
+
fi
|
|
873
|
+
done
|
|
874
|
+
else
|
|
875
|
+
local zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
|
876
|
+
if [[ ! -d "$zsh_custom" ]]; then
|
|
877
|
+
log_info "Oh My Zsh not installed (optional)"
|
|
878
|
+
fi
|
|
879
|
+
fi
|
|
880
|
+
|
|
881
|
+
# Check karnel module loading
|
|
882
|
+
if [[ -f "$HOME/.zshrc" ]] && grep -q "karnel" "$HOME/.zshrc" 2>/dev/null; then
|
|
883
|
+
log_success "Karnel integration in .zshrc"
|
|
884
|
+
fi
|
|
885
|
+
|
|
886
|
+
# Check url-quote-magic for parse errors (Termux zsh bug)
|
|
887
|
+
local uqm_file="$PREFIX/share/zsh/functions/Zle/url-quote-magic"
|
|
888
|
+
if [[ -f "$uqm_file" ]] && grep -q '((${~localschema})' "$uqm_file" 2>/dev/null; then
|
|
889
|
+
log_warn "url-quote-magic: double-paren parse error found (zsh 5.9 bug)"
|
|
890
|
+
log_warn "url-quote-magic has known double-paren syntax error"
|
|
891
|
+
fix_commands+=("true")
|
|
892
|
+
fix_descriptions+=("Patch url-quote-magic double-paren parse error")
|
|
893
|
+
fix_callbacks+=("_fix_url_quote_magic")
|
|
894
|
+
fi
|
|
895
|
+
|
|
896
|
+
# ===== GPU / OPENGL INFO =====
|
|
897
|
+
echo
|
|
898
|
+
separator_section "GPU & Hardware Acceleration"
|
|
899
|
+
echo
|
|
900
|
+
|
|
901
|
+
if command -v termux-info &>/dev/null; then
|
|
902
|
+
local gpu_info
|
|
903
|
+
gpu_info=$(termux-info 2>/dev/null | grep -i "gpu\|render\|opengl" | head -3)
|
|
904
|
+
if [[ -n "$gpu_info" ]]; then
|
|
905
|
+
log_success "GPU: $(echo "$gpu_info" | tr -s ' ')"
|
|
906
|
+
fi
|
|
907
|
+
fi
|
|
908
|
+
|
|
909
|
+
# Check /dev/dri or /dev/ Mali for GPU acceleration
|
|
910
|
+
if [[ -e /dev/dri/renderD128 ]] || [[ -e /dev/mali0 ]]; then
|
|
911
|
+
log_success "GPU render node accessible"
|
|
912
|
+
fi
|
|
913
|
+
|
|
914
|
+
# ===== ENCODING & LOCALE =====
|
|
915
|
+
echo
|
|
916
|
+
separator_section "Locale & Encoding"
|
|
917
|
+
echo
|
|
918
|
+
|
|
919
|
+
if locale 2>/dev/null | grep -qi "utf8\|utf-8"; then
|
|
920
|
+
log_success "UTF-8 locale: OK"
|
|
921
|
+
else
|
|
922
|
+
log_warn "UTF-8 locale not set — may cause encoding issues"
|
|
923
|
+
((warnings++))
|
|
924
|
+
fix_commands+=("echo 'export LANG=en_US.UTF-8' >> $HOME/.zshrc")
|
|
925
|
+
fix_descriptions+=("Set UTF-8 locale in shell config")
|
|
926
|
+
fix_callbacks+=("_fix_locale")
|
|
927
|
+
fi
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
# ===== BATTERY & POWER MANAGEMENT =====
|
|
931
|
+
echo
|
|
932
|
+
separator_section "Battery & Power Management"
|
|
933
|
+
echo
|
|
934
|
+
|
|
935
|
+
if command -v termux-battery-status &>/dev/null; then
|
|
936
|
+
local battery_info
|
|
937
|
+
battery_info=$(termux-battery-status 2>/dev/null)
|
|
938
|
+
if [[ -n "$battery_info" ]]; then
|
|
939
|
+
local battery_pct
|
|
940
|
+
battery_pct=$(echo "$battery_info" | python3 -c "import json,sys; print(json.load(sys.stdin).get('percentage',0))" 2>/dev/null || echo "?")
|
|
941
|
+
log_success "Battery: ${battery_pct}%"
|
|
942
|
+
|
|
943
|
+
# Check if battery is critically low
|
|
944
|
+
if [[ "$battery_pct" =~ ^[0-9]+$ ]] && (( battery_pct < 15 )); then
|
|
945
|
+
log_warn "Battery critically low (${battery_pct}%) — processes may be killed"
|
|
946
|
+
((warnings++))
|
|
947
|
+
fi
|
|
948
|
+
|
|
949
|
+
# Check charging status
|
|
950
|
+
local charging
|
|
951
|
+
charging=$(echo "$battery_info" | python3 -c "import json,sys; print(json.load(sys.stdin).get('status','Unknown'))" 2>/dev/null || echo "?")
|
|
952
|
+
log_info "Charging status: $charging"
|
|
953
|
+
fi
|
|
954
|
+
else
|
|
955
|
+
log_info "termux-battery-status not available (install termux-api)"
|
|
956
|
+
fi
|
|
957
|
+
|
|
958
|
+
# Check battery optimization exemption
|
|
959
|
+
if command -v termux-wake-lock &>/dev/null; then
|
|
960
|
+
log_success "termux-wake-lock available (prevents sleep)"
|
|
961
|
+
else
|
|
962
|
+
log_info "termux-wake-lock not installed (optional, prevents background killing)"
|
|
963
|
+
fi
|
|
964
|
+
|
|
965
|
+
# ===== API KEYS VALIDATION =====
|
|
966
|
+
echo
|
|
967
|
+
separator_section "API Keys & Environment"
|
|
968
|
+
echo
|
|
969
|
+
|
|
970
|
+
local -a api_keys=("OPENAI_API_KEY" "ANTHROPIC_API_KEY" "GOOGLE_API_KEY" "GEMINI_API_KEY" "OPENROUTER_API_KEY" "DEEPSEEK_API_KEY" "MISTRAL_API_KEY")
|
|
971
|
+
local keys_found=0
|
|
972
|
+
|
|
973
|
+
for key in "${api_keys[@]}"; do
|
|
974
|
+
if [[ -n "${!key:-}" ]]; then
|
|
975
|
+
local val="${!key}"
|
|
976
|
+
local masked="${val:0:8}****${val: -4}"
|
|
977
|
+
log_success "$key: $masked"
|
|
978
|
+
((keys_found++))
|
|
979
|
+
fi
|
|
980
|
+
done
|
|
981
|
+
|
|
982
|
+
if [[ $keys_found -eq 0 ]]; then
|
|
983
|
+
log_info "No API keys found in environment"
|
|
984
|
+
log_info "Set keys with: ${D_CYAN}karnel env set${NC}"
|
|
985
|
+
else
|
|
986
|
+
log_info "$keys_found API key(s) configured"
|
|
987
|
+
fi
|
|
988
|
+
|
|
989
|
+
# Check for .env files with leaked keys
|
|
990
|
+
local leaked_keys=0
|
|
991
|
+
while IFS= read -r -d '' envfile; do
|
|
992
|
+
if grep -qE '(sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|xoxb-[0-9])' "$envfile" 2>/dev/null; then
|
|
993
|
+
log_warn "Potential API key found in: $envfile"
|
|
994
|
+
((leaked_keys++))
|
|
995
|
+
fi
|
|
996
|
+
done < <(find "$HOME" -maxdepth 3 -name '.env' -not -path '*/node_modules/*' -not -path '*/.git/*' -print0 2>/dev/null || true)
|
|
997
|
+
|
|
998
|
+
if (( leaked_keys > 0 )); then
|
|
999
|
+
log_warn "$leaked_keys file(s) with potential API keys in tracked directories"
|
|
1000
|
+
((warnings++))
|
|
1001
|
+
fi
|
|
1002
|
+
|
|
1003
|
+
# ===== PROCESS HEALTH =====
|
|
1004
|
+
echo
|
|
1005
|
+
separator_section "Process Health"
|
|
1006
|
+
echo
|
|
1007
|
+
|
|
1008
|
+
# Check for zombie processes
|
|
1009
|
+
local zombies
|
|
1010
|
+
zombies=$(ps aux 2>/dev/null | awk '$8 ~ /^Z/ {count++} END {print count+0}')
|
|
1011
|
+
if (( zombies > 0 )); then
|
|
1012
|
+
log_warn "$zombies zombie process(es) detected"
|
|
1013
|
+
((warnings++))
|
|
1014
|
+
fix_commands+=("kill -9 \$(ps aux | awk '\\$8 ~ /^Z/ {print \\$2}') 2>/dev/null")
|
|
1015
|
+
fix_descriptions+=("Kill zombie processes")
|
|
1016
|
+
fix_callbacks+=("_fix_zombies")
|
|
1017
|
+
else
|
|
1018
|
+
log_success "No zombie processes"
|
|
1019
|
+
fi
|
|
1020
|
+
|
|
1021
|
+
# Check for orphaned node/python processes
|
|
1022
|
+
local orphan_count=0
|
|
1023
|
+
orphan_count=$(pgrep -c -f 'node.*karnel\|python.*karnel' 2>/dev/null || echo 0)
|
|
1024
|
+
if (( orphan_count > 2 )); then
|
|
1025
|
+
log_warn "$orphan_count Karnel-related processes running (may be stale)"
|
|
1026
|
+
((warnings++))
|
|
1027
|
+
fi
|
|
1028
|
+
|
|
1029
|
+
# ===== STORAGE I/O HEALTH =====
|
|
1030
|
+
echo
|
|
1031
|
+
separator_section "Storage I/O Health"
|
|
1032
|
+
echo
|
|
1033
|
+
|
|
1034
|
+
local io_test_file="$HOME/.cache/karnel_io_test"
|
|
1035
|
+
mkdir -p "$(dirname "$io_test_file")" 2>/dev/null
|
|
1036
|
+
local io_start io_end io_time
|
|
1037
|
+
io_start=$(date +%s%N 2>/dev/null || echo 0)
|
|
1038
|
+
dd if=/dev/zero of="$io_test_file" bs=4096 count=100 2>/dev/null
|
|
1039
|
+
io_end=$(date +%s%N 2>/dev/null || echo 0)
|
|
1040
|
+
rm -f "$io_test_file" 2>/dev/null
|
|
1041
|
+
|
|
1042
|
+
if [[ $io_start -gt 0 ]] && [[ $io_end -gt 0 ]]; then
|
|
1043
|
+
io_time=$(( (io_end - io_start) / 1000000 ))
|
|
1044
|
+
if (( io_time < 100 )); then
|
|
1045
|
+
log_success "Storage I/O: fast (${io_time}ms for 400KB)"
|
|
1046
|
+
elif (( io_time < 500 )); then
|
|
1047
|
+
log_info "Storage I/O: moderate (${io_time}ms for 400KB)"
|
|
1048
|
+
else
|
|
1049
|
+
log_warn "Storage I/O: slow (${io_time}ms for 400KB) — may affect performance"
|
|
1050
|
+
((warnings++))
|
|
1051
|
+
fi
|
|
1052
|
+
fi
|
|
1053
|
+
|
|
1054
|
+
# ===== WIFI / NETWORK QUALITY =====
|
|
1055
|
+
echo
|
|
1056
|
+
separator_section "Network Quality"
|
|
1057
|
+
echo
|
|
1058
|
+
|
|
1059
|
+
if command -v ping &>/dev/null; then
|
|
1060
|
+
local ping_result
|
|
1061
|
+
ping_result=$(timeout 10 ping -c 3 -W 5 8.8.8.8 2>/dev/null)
|
|
1062
|
+
if [[ -n "$ping_result" ]]; then
|
|
1063
|
+
local avg_ping
|
|
1064
|
+
avg_ping=$(echo "$ping_result" | grep 'avg' | awk -F'/' '{print $5}')
|
|
1065
|
+
if [[ -n "$avg_ping" ]]; then
|
|
1066
|
+
local ping_int=${avg_ping%.*}
|
|
1067
|
+
if (( ping_int < 50 )); then
|
|
1068
|
+
log_success "Network latency: excellent (${avg_ping}ms)"
|
|
1069
|
+
elif (( ping_int < 150 )); then
|
|
1070
|
+
log_info "Network latency: good (${avg_ping}ms)"
|
|
1071
|
+
else
|
|
1072
|
+
log_warn "Network latency: high (${avg_ping}ms)"
|
|
1073
|
+
((warnings++))
|
|
1074
|
+
fi
|
|
1075
|
+
fi
|
|
1076
|
+
fi
|
|
1077
|
+
fi
|
|
1078
|
+
|
|
1079
|
+
# ===== SHELL HISTORY & PRIVACY =====
|
|
1080
|
+
echo
|
|
1081
|
+
separator_section "Shell Privacy"
|
|
1082
|
+
echo
|
|
1083
|
+
|
|
1084
|
+
local histfiles=("$HOME/.zsh_history" "$HOME/.bash_history" "$HOME/.local/share/zsh/history")
|
|
1085
|
+
for histfile in "${histfiles[@]}"; do
|
|
1086
|
+
if [[ -f "$histfile" ]]; then
|
|
1087
|
+
local hist_size
|
|
1088
|
+
hist_size=$(du -sh "$histfile" 2>/dev/null | awk '{print $1}')
|
|
1089
|
+
local hist_lines
|
|
1090
|
+
hist_lines=$(wc -l < "$histfile" 2>/dev/null || echo 0)
|
|
1091
|
+
log_info "History: $(basename "$histfile") ($hist_size, $hist_lines lines)"
|
|
1092
|
+
|
|
1093
|
+
# Check for sensitive patterns in recent history
|
|
1094
|
+
if grep -qiE '(password=|secret=|token=|api_key=)' "$histfile" 2>/dev/null; then
|
|
1095
|
+
log_warn "Potential secrets found in shell history"
|
|
1096
|
+
((warnings++))
|
|
1097
|
+
log_info "Run: ${D_CYAN}karnel brain save${NC} to protect sensitive data"
|
|
1098
|
+
fi
|
|
1099
|
+
fi
|
|
1100
|
+
done
|
|
1101
|
+
|
|
1102
|
+
# ===== USB & EXTERNAL STORAGE =====
|
|
1103
|
+
echo
|
|
1104
|
+
separator_section "USB & External"
|
|
1105
|
+
echo
|
|
1106
|
+
|
|
1107
|
+
if [[ -d /storage ]]; then
|
|
1108
|
+
local storage_count
|
|
1109
|
+
storage_count=$(ls -1 /storage 2>/dev/null | grep -v '^emulated$\|^self$' | wc -l)
|
|
1110
|
+
if (( storage_count > 0 )); then
|
|
1111
|
+
log_success "External storage: $storage_count volume(s) mounted"
|
|
1112
|
+
else
|
|
1113
|
+
log_info "No external storage mounted"
|
|
1114
|
+
fi
|
|
1115
|
+
fi
|
|
1116
|
+
|
|
1117
|
+
# Check USB devices
|
|
1118
|
+
if [[ -d /dev/bus/usb ]]; then
|
|
1119
|
+
local usb_count
|
|
1120
|
+
usb_count=$(ls /dev/bus/usb/ 2>/dev/null | wc -l)
|
|
1121
|
+
if (( usb_count > 0 )); then
|
|
1122
|
+
log_info "USB: $usb_count bus(es) detected"
|
|
1123
|
+
fi
|
|
1124
|
+
fi
|
|
1125
|
+
|
|
1126
|
+
# ===== GENERATE REPORT =====
|
|
1127
|
+
local report_dir="$KARNEL_DATA/doctor_reports"
|
|
1128
|
+
mkdir -p "$report_dir"
|
|
1129
|
+
local report_file="$report_dir/doctor_report_latest.md"
|
|
1130
|
+
|
|
1131
|
+
cat >"$report_file" <<EOF
|
|
1132
|
+
# Karnel Doctor Diagnostic Report
|
|
1133
|
+
Generated: $(date)
|
|
1134
|
+
|
|
1135
|
+
## System Info
|
|
1136
|
+
- **Android**: $android_ver
|
|
1137
|
+
- **Termux**: $termux_ver
|
|
1138
|
+
- **Architecture**: $arch
|
|
1139
|
+
- **Karnel Version**: $karnel_ver
|
|
1140
|
+
|
|
1141
|
+
## Resources
|
|
1142
|
+
- **Disk Free**: $free_space
|
|
1143
|
+
- **RAM Total**: $ram_total
|
|
1144
|
+
- **RAM Free**: $ram_free
|
|
1145
|
+
|
|
1146
|
+
## Storage & Permissions
|
|
1147
|
+
- **Shared Storage**: $storage_status
|
|
1148
|
+
- **Karnel Write Access**: $([ -w "$KARNEL_PATH" ] && echo "Yes" || echo "No")
|
|
1149
|
+
|
|
1150
|
+
## PostgreSQL
|
|
1151
|
+
- **Installed**: $pg_installed
|
|
1152
|
+
- **Data Found**: ${pg_data_found:-unknown}
|
|
1153
|
+
|
|
1154
|
+
## AI Tools
|
|
1155
|
+
- **Count**: $ai_count
|
|
1156
|
+
|
|
1157
|
+
## Summary
|
|
1158
|
+
- **Errors**: $errors
|
|
1159
|
+
- **Warnings**: $warnings
|
|
1160
|
+
- **Fixed**: $fixed
|
|
1161
|
+
EOF
|
|
1162
|
+
|
|
1163
|
+
# ===== RESULTS =====
|
|
1164
|
+
echo
|
|
1165
|
+
separator
|
|
1166
|
+
log_success "Diagnostics completed!"
|
|
1167
|
+
list_item "Report saved: ${D_CYAN}$report_file${D_NC}"
|
|
1168
|
+
|
|
1169
|
+
if [[ $errors -gt 0 ]]; then
|
|
1170
|
+
log_error "Found $errors error(s) and $warnings warning(s)."
|
|
1171
|
+
elif [[ $warnings -gt 0 ]]; then
|
|
1172
|
+
log_warn "Found $warnings warning(s). System is functional but can be optimized."
|
|
1173
|
+
else
|
|
1174
|
+
log_success "All systems healthy!"
|
|
1175
|
+
fi
|
|
1176
|
+
|
|
1177
|
+
# ===== AUTO-FIX =====
|
|
1178
|
+
if [[ ${#fix_commands[@]} -gt 0 ]]; then
|
|
1179
|
+
echo
|
|
1180
|
+
separator_section "Auto-Fix Options"
|
|
1181
|
+
echo
|
|
1182
|
+
log_info "Detected $(( ${#fix_commands[@]} )) issue(s) that can be automatically fixed:"
|
|
1183
|
+
echo
|
|
1184
|
+
for ((i=0; i<${#fix_commands[@]}; i++)); do
|
|
1185
|
+
printf " ${D_YELLOW}%2d.${D_NC} %s\n" $((i + 1)) "${fix_descriptions[$i]}"
|
|
1186
|
+
done
|
|
1187
|
+
echo
|
|
1188
|
+
|
|
1189
|
+
local confirm
|
|
1190
|
+
read_confirm "Apply all auto-corrections?" confirm
|
|
1191
|
+
if [[ "$confirm" == "y" ]]; then
|
|
1192
|
+
echo
|
|
1193
|
+
for ((i=0; i<${#fix_commands[@]}; i++)); do
|
|
1194
|
+
log_info "Fixing: ${fix_descriptions[$i]}..."
|
|
1195
|
+
local callback="${fix_callbacks[$i]:-}"
|
|
1196
|
+
local success=false
|
|
1197
|
+
|
|
1198
|
+
if [[ -n "$callback" ]] && type "$callback" &>/dev/null 2>&1; then
|
|
1199
|
+
"$callback" && success=true
|
|
1200
|
+
elif [[ -n "${fix_commands[$i]}" ]]; then
|
|
1201
|
+
eval "${fix_commands[$i]}" 2>/dev/null && success=true
|
|
1202
|
+
fi
|
|
1203
|
+
|
|
1204
|
+
if [[ "$success" == "true" ]]; then
|
|
1205
|
+
((fixed++))
|
|
1206
|
+
log_success "Fixed: ${fix_descriptions[$i]}"
|
|
1207
|
+
else
|
|
1208
|
+
log_warn "Could not fix: ${fix_descriptions[$i]}"
|
|
1209
|
+
fi
|
|
1210
|
+
done
|
|
1211
|
+
echo
|
|
1212
|
+
if (( fixed > 0 )); then
|
|
1213
|
+
log_success "Fixed $fixed issue(s)! Run 'karnel doctor' again to verify."
|
|
1214
|
+
else
|
|
1215
|
+
log_warn "Some fixes could not be applied. Check errors above."
|
|
1216
|
+
fi
|
|
1217
|
+
fi
|
|
1218
|
+
fi
|
|
1219
|
+
echo
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
# ===== FIX CALLBACK FUNCTIONS =====
|
|
1223
|
+
|
|
1224
|
+
_fix_storage() {
|
|
1225
|
+
termux-setup-storage 2>/dev/null
|
|
1226
|
+
return $?
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
_fix_mkdir() {
|
|
1230
|
+
for dir in "$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA"; do
|
|
1231
|
+
mkdir -p "$dir" 2>/dev/null
|
|
1232
|
+
chmod 755 "$dir" 2>/dev/null
|
|
1233
|
+
done
|
|
1234
|
+
return 0
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
_fix_pkg_install() {
|
|
1238
|
+
local pkg_to_install=""
|
|
1239
|
+
case "$1" in
|
|
1240
|
+
pkg) pkg_to_install="$2" ;;
|
|
1241
|
+
*) pkg_to_install="${fix_commands[$i]:-}" ;;
|
|
1242
|
+
esac
|
|
1243
|
+
local pkg_name=""
|
|
1244
|
+
if [[ "$pkg_to_install" =~ pkg\ install\ -y\ (.+) ]]; then
|
|
1245
|
+
pkg_name="${BASH_REMATCH[1]}"
|
|
1246
|
+
fi
|
|
1247
|
+
if [[ -n "$pkg_name" ]]; then
|
|
1248
|
+
pkg install -y "$pkg_name" 2>/dev/null
|
|
1249
|
+
return $?
|
|
1250
|
+
fi
|
|
1251
|
+
return 1
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
_fix_dpkg() {
|
|
1255
|
+
dpkg --configure -a 2>/dev/null
|
|
1256
|
+
apt-get -f install -y 2>/dev/null
|
|
1257
|
+
return $?
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
_fix_apt_update() {
|
|
1261
|
+
pkg update -y 2>/dev/null
|
|
1262
|
+
return $?
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
_fix_npm_prefix() {
|
|
1266
|
+
mkdir -p "$HOME/.npm-global"
|
|
1267
|
+
npm config set prefix "$HOME/.npm-global" 2>/dev/null
|
|
1268
|
+
return $?
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
_fix_pip() {
|
|
1272
|
+
local py_cmd=""
|
|
1273
|
+
for py in python3.12 python3.11 python3.10 python3.9 python3 python; do
|
|
1274
|
+
if command -v "$py" &>/dev/null; then py_cmd="$py"; break; fi
|
|
1275
|
+
done
|
|
1276
|
+
if [[ -n "$py_cmd" ]]; then
|
|
1277
|
+
"$py_cmd" -m ensurepip 2>/dev/null
|
|
1278
|
+
"$py_cmd" -m pip install --upgrade pip 2>/dev/null
|
|
1279
|
+
return $?
|
|
1280
|
+
fi
|
|
1281
|
+
return 1
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
_fix_pg_init() {
|
|
1285
|
+
source "$KARNEL_PATH/utils/env.sh" 2>/dev/null
|
|
1286
|
+
import "@/modules/db" 2>/dev/null
|
|
1287
|
+
if type pg_init &>/dev/null; then
|
|
1288
|
+
pg_init 2>/dev/null
|
|
1289
|
+
pg_start 2>/dev/null
|
|
1290
|
+
return $?
|
|
1291
|
+
fi
|
|
1292
|
+
local pg_data="$HOME/.local/share/postgresql/data"
|
|
1293
|
+
mkdir -p "$pg_data" 2>/dev/null
|
|
1294
|
+
if command -v initdb &>/dev/null; then
|
|
1295
|
+
initdb -D "$pg_data" 2>/dev/null
|
|
1296
|
+
pg_ctl -D "$pg_data" -l "$HOME/.cache/karnel/postgresql.log" start 2>/dev/null
|
|
1297
|
+
return $?
|
|
1298
|
+
fi
|
|
1299
|
+
return 1
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
_fix_pg_start() {
|
|
1303
|
+
local pg_data=""
|
|
1304
|
+
for dir in "$PREFIX/var/lib/postgresql/data" "$PREFIX/var/lib/postgresql" "$HOME/.termux/postgresql/data" "$HOME/.termux/postgresql" "$HOME/.local/share/postgresql/data"; do
|
|
1305
|
+
if [[ -d "$dir" ]] && [[ -f "$dir/PG_VERSION" ]]; then
|
|
1306
|
+
pg_data="$dir"
|
|
1307
|
+
break
|
|
1308
|
+
fi
|
|
1309
|
+
done
|
|
1310
|
+
if [[ -n "$pg_data" ]] && command -v pg_ctl &>/dev/null; then
|
|
1311
|
+
pg_ctl -D "$pg_data" -l "$HOME/.cache/karnel/postgresql.log" start 2>/dev/null
|
|
1312
|
+
return $?
|
|
1313
|
+
fi
|
|
1314
|
+
return 1
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
_fix_pg_install() {
|
|
1318
|
+
source "$KARNEL_PATH/utils/env.sh" 2>/dev/null
|
|
1319
|
+
import "@/modules/db" 2>/dev/null
|
|
1320
|
+
if type install_db &>/dev/null; then
|
|
1321
|
+
install_db 2>/dev/null
|
|
1322
|
+
return $?
|
|
1323
|
+
fi
|
|
1324
|
+
pkg install -y postgresql 2>/dev/null
|
|
1325
|
+
return $?
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
_fix_symlinks() {
|
|
1329
|
+
ln -sf "$KARNEL_PATH/bin/karnel" "$PREFIX/bin/karnel" 2>/dev/null
|
|
1330
|
+
[[ -L "$PREFIX/bin/karnel" ]]
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
_fix_banner() {
|
|
1334
|
+
local shell_config=""
|
|
1335
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
1336
|
+
shell_config="$HOME/.zshrc"
|
|
1337
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
1338
|
+
shell_config="$HOME/.bashrc"
|
|
1339
|
+
fi
|
|
1340
|
+
if [[ -z "$shell_config" ]]; then
|
|
1341
|
+
shell_config="$HOME/.zshrc"
|
|
1342
|
+
touch "$shell_config"
|
|
1343
|
+
fi
|
|
1344
|
+
local marker="# ===== Karnel Banner ====="
|
|
1345
|
+
if ! grep -qF "$marker" "$shell_config" 2>/dev/null; then
|
|
1346
|
+
cat >>"$shell_config" <<EOF
|
|
1347
|
+
|
|
1348
|
+
$marker
|
|
1349
|
+
source "$KARNEL_UTILS/banner.sh"
|
|
1350
|
+
EOF
|
|
1351
|
+
return 0
|
|
1352
|
+
fi
|
|
1353
|
+
return 0
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
_fix_ai_install() {
|
|
1357
|
+
log_info "Installing AI tools (this may take a while)..."
|
|
1358
|
+
source "$KARNEL_PATH/utils/env.sh" 2>/dev/null
|
|
1359
|
+
import "@/modules/ai" 2>/dev/null
|
|
1360
|
+
if type install_ai &>/dev/null; then
|
|
1361
|
+
install_ai 2>/dev/null
|
|
1362
|
+
return $?
|
|
1363
|
+
fi
|
|
1364
|
+
return 1
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
_fix_shell_syntax() {
|
|
1368
|
+
local config=""
|
|
1369
|
+
if [[ -f "$HOME/.zshrc" ]]; then
|
|
1370
|
+
config="$HOME/.zshrc"
|
|
1371
|
+
elif [[ -f "$HOME/.bashrc" ]]; then
|
|
1372
|
+
config="$HOME/.bashrc"
|
|
1373
|
+
fi
|
|
1374
|
+
if [[ -n "$config" ]]; then
|
|
1375
|
+
cp "$config" "${config}.bak" 2>/dev/null
|
|
1376
|
+
local marker="# ===== Karnel Banner ====="
|
|
1377
|
+
local banner_block=""
|
|
1378
|
+
if grep -qF "$marker" "$config" 2>/dev/null; then
|
|
1379
|
+
local marker_line
|
|
1380
|
+
marker_line=$(grep -nF "$marker" "$config" | head -1 | cut -d: -f1)
|
|
1381
|
+
if [[ -n "$marker_line" ]]; then
|
|
1382
|
+
banner_block=$(sed -n "$((marker_line - 1)),\$p" "$config" 2>/dev/null)
|
|
1383
|
+
fi
|
|
1384
|
+
fi
|
|
1385
|
+
local tmpconfig
|
|
1386
|
+
tmpconfig=$(mktemp)
|
|
1387
|
+
sed '/^source.*\/dev\/null$/d; /^#.*syntax error/d' "$config" > "$tmpconfig" 2>/dev/null
|
|
1388
|
+
if [[ -n "$banner_block" ]]; then
|
|
1389
|
+
echo "" >> "$tmpconfig"
|
|
1390
|
+
echo "$banner_block" >> "$tmpconfig"
|
|
1391
|
+
fi
|
|
1392
|
+
cp "$tmpconfig" "$config" 2>/dev/null
|
|
1393
|
+
rm -f "$tmpconfig"
|
|
1394
|
+
return 0
|
|
1395
|
+
fi
|
|
1396
|
+
return 1
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
_fix_ssh_key() {
|
|
1400
|
+
mkdir -p "$HOME/.ssh"
|
|
1401
|
+
chmod 700 "$HOME/.ssh"
|
|
1402
|
+
ssh-keygen -t ed25519 -f "$HOME/.ssh/id_ed25519" -N '' 2>/dev/null
|
|
1403
|
+
return $?
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
_fix_disk_cleanup() {
|
|
1407
|
+
rm -rf ~/.cache/karnel/install_*.log 2>/dev/null
|
|
1408
|
+
if command -v pkg &>/dev/null; then
|
|
1409
|
+
pkg clean -y 2>/dev/null
|
|
1410
|
+
fi
|
|
1411
|
+
return $?
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
_fix_mkdir_single() {
|
|
1415
|
+
for dir in "$KARNEL_CONFIG" "$KARNEL_CACHE" "$KARNEL_DATA" "$HOME/.local/share/karnel-data"; do
|
|
1416
|
+
[[ -d "$dir" ]] || mkdir -p "$dir" 2>/dev/null
|
|
1417
|
+
done
|
|
1418
|
+
return 0
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
# ===== NEW FIX CALLBACKS =====
|
|
1422
|
+
|
|
1423
|
+
_fix_psutil() {
|
|
1424
|
+
local tmp="$PREFIX/tmp/psutil_patch"
|
|
1425
|
+
mkdir -p "$tmp"
|
|
1426
|
+
pip download psutil==7.2.2 --no-binary :all: --no-deps -d "$tmp" 2>/dev/null || return 1
|
|
1427
|
+
tar xzf "$tmp/psutil-7.2.2.tar.gz" -C "$tmp"
|
|
1428
|
+
sed -i 's/LINUX = sys.platform.startswith("linux")/LINUX = sys.platform.startswith(("linux", "android"))/' "$tmp/psutil-7.2.2/psutil/_common.py"
|
|
1429
|
+
pip install "$tmp/psutil-7.2.2" 2>/dev/null
|
|
1430
|
+
local rc=$?
|
|
1431
|
+
rm -rf "$tmp"
|
|
1432
|
+
return $rc
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
_fix_pip_check() {
|
|
1436
|
+
local broken
|
|
1437
|
+
broken=$(pip check 2>&1 | grep -oP '^\S+' | head -3)
|
|
1438
|
+
if [[ -n "$broken" ]]; then
|
|
1439
|
+
pip install --upgrade --force-reinstall $broken 2>/dev/null
|
|
1440
|
+
fi
|
|
1441
|
+
return 0
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
_fix_npm_shebangs() {
|
|
1445
|
+
local fixed=0
|
|
1446
|
+
for f in "$PREFIX/bin/"*; do
|
|
1447
|
+
[[ -f "$f" ]] || continue
|
|
1448
|
+
local shebang
|
|
1449
|
+
shebang=$(head -1 "$f" 2>/dev/null | tr -d '\0')
|
|
1450
|
+
if [[ "$shebang" == "#!/usr/bin/env node" ]]; then
|
|
1451
|
+
sed -i "1s|^.*$|#!$PREFIX/bin/node|" "$f"
|
|
1452
|
+
((fixed++))
|
|
1453
|
+
elif [[ "$shebang" == "#!/usr/bin/env bash" ]] || [[ "$shebang" == "#!/usr/bin/env sh" ]]; then
|
|
1454
|
+
sed -i "1s|^.*$|#!$PREFIX/bin/bash|" "$f"
|
|
1455
|
+
((fixed++))
|
|
1456
|
+
fi
|
|
1457
|
+
done
|
|
1458
|
+
return 0
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
_fix_broken_symlinks() {
|
|
1462
|
+
find "$PREFIX/bin" -type l ! -exec test -e {} \; -delete 2>/dev/null
|
|
1463
|
+
return 0
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
_fix_npm_cache() {
|
|
1467
|
+
npm cache clean --force 2>/dev/null
|
|
1468
|
+
return $?
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
_fix_pip_cache() {
|
|
1472
|
+
pip cache purge 2>/dev/null
|
|
1473
|
+
return $?
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
_fix_pycache() {
|
|
1477
|
+
find "$PREFIX/lib/python3.*" -name "__pycache__" -exec rm -rf {} + 2>/dev/null
|
|
1478
|
+
return 0
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
_fix_proot_ubuntu() {
|
|
1482
|
+
if command -v proot-distro &>/dev/null; then
|
|
1483
|
+
proot-distro install ubuntu 2>/dev/null
|
|
1484
|
+
return $?
|
|
1485
|
+
fi
|
|
1486
|
+
return 1
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
_fix_dns() {
|
|
1490
|
+
echo 'nameserver 8.8.8.8' > "$PREFIX/etc/resolv.conf" 2>/dev/null
|
|
1491
|
+
return $?
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
_fix_mirror() {
|
|
1495
|
+
if command -v termux-change-repo &>/dev/null; then
|
|
1496
|
+
termux-change-repo 2>/dev/null
|
|
1497
|
+
return $?
|
|
1498
|
+
fi
|
|
1499
|
+
return 1
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
_fix_locale() {
|
|
1503
|
+
local config="$HOME/.zshrc"
|
|
1504
|
+
if [[ ! -f "$config" ]] && [[ -f "$HOME/.bashrc" ]]; then
|
|
1505
|
+
config="$HOME/.bashrc"
|
|
1506
|
+
fi
|
|
1507
|
+
echo 'export LANG=en_US.UTF-8' >> "$config" 2>/dev/null
|
|
1508
|
+
return $?
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
_fix_zombies() {
|
|
1513
|
+
ps aux 2>/dev/null | awk '$8 ~ /^Z/ {print $2}' | xargs kill -9 2>/dev/null
|
|
1514
|
+
return 0
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
_fix_url_quote_magic() {
|
|
1518
|
+
local uqm_file="$PREFIX/share/zsh/functions/Zle/url-quote-magic"
|
|
1519
|
+
if [[ ! -f "$uqm_file" ]]; then
|
|
1520
|
+
return 1
|
|
1521
|
+
fi
|
|
1522
|
+
# Fix double-paren case patterns: (( -> ( for localschema and otherschema
|
|
1523
|
+
sed -i \
|
|
1524
|
+
-e 's/((${~localschema})/(${~localschema})/g' \
|
|
1525
|
+
-e 's/((${~otherschema})/(${~otherschema})/g' \
|
|
1526
|
+
"$uqm_file" 2>/dev/null
|
|
1527
|
+
return $?
|
|
1528
|
+
}
|