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.
Files changed (258) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +454 -0
  3. package/install.sh +272 -0
  4. package/karnel/bin/karnel +77 -0
  5. package/karnel/cli/commands/brain.sh +1553 -0
  6. package/karnel/cli/commands/cleanup.sh +66 -0
  7. package/karnel/cli/commands/doctor.sh +1528 -0
  8. package/karnel/cli/commands/env.sh +233 -0
  9. package/karnel/cli/commands/help.sh +8 -0
  10. package/karnel/cli/commands/ia.sh +502 -0
  11. package/karnel/cli/commands/init.sh +1274 -0
  12. package/karnel/cli/commands/install.sh +718 -0
  13. package/karnel/cli/commands/list.sh +399 -0
  14. package/karnel/cli/commands/open.sh +106 -0
  15. package/karnel/cli/commands/pg.sh +719 -0
  16. package/karnel/cli/commands/reinstall.sh +663 -0
  17. package/karnel/cli/commands/show.sh +90 -0
  18. package/karnel/cli/commands/start.sh +54 -0
  19. package/karnel/cli/commands/status.sh +96 -0
  20. package/karnel/cli/commands/uninstall.sh +668 -0
  21. package/karnel/cli/commands/update.sh +723 -0
  22. package/karnel/cli/commands/upgrade.sh +40 -0
  23. package/karnel/cli/commands/version.sh +3 -0
  24. package/karnel/cli/commands/voice.sh +230 -0
  25. package/karnel/cli/karnel.sh +706 -0
  26. package/karnel/modules/ai.sh +135 -0
  27. package/karnel/modules/auto.sh +114 -0
  28. package/karnel/modules/db.sh +132 -0
  29. package/karnel/modules/deploy.sh +74 -0
  30. package/karnel/modules/dev.sh +148 -0
  31. package/karnel/modules/editor.sh +115 -0
  32. package/karnel/modules/lang.sh +124 -0
  33. package/karnel/modules/npm.sh +146 -0
  34. package/karnel/modules/shell.sh +338 -0
  35. package/karnel/modules/ui.sh +139 -0
  36. package/karnel/modules/voice.sh +118 -0
  37. package/karnel/tools/ai/all.sh +209 -0
  38. package/karnel/tools/ai/antigravity-cli/README.md +45 -0
  39. package/karnel/tools/ai/antigravity-cli/bin/agy +28 -0
  40. package/karnel/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
  41. package/karnel/tools/ai/antigravity-cli/install.sh +469 -0
  42. package/karnel/tools/ai/claude-code/README.md +45 -0
  43. package/karnel/tools/ai/claude-code/bin/claude +29 -0
  44. package/karnel/tools/ai/claude-code/helper/claude_helper.c +42 -0
  45. package/karnel/tools/ai/claude-code/install.sh +278 -0
  46. package/karnel/tools/ai/cline/install.sh +160 -0
  47. package/karnel/tools/ai/codegraph/README.md +43 -0
  48. package/karnel/tools/ai/codegraph/bin/codegraph +5 -0
  49. package/karnel/tools/ai/codegraph/install.sh +160 -0
  50. package/karnel/tools/ai/codex/README.md +44 -0
  51. package/karnel/tools/ai/codex/install.sh +104 -0
  52. package/karnel/tools/ai/command-code/README.md +62 -0
  53. package/karnel/tools/ai/command-code/install.sh +136 -0
  54. package/karnel/tools/ai/crush/README.md +17 -0
  55. package/karnel/tools/ai/crush/install.sh +89 -0
  56. package/karnel/tools/ai/ctx7/README.md +26 -0
  57. package/karnel/tools/ai/ctx7/install.sh +61 -0
  58. package/karnel/tools/ai/engram/README.md +44 -0
  59. package/karnel/tools/ai/engram/install.sh +127 -0
  60. package/karnel/tools/ai/freebuff/README.md +52 -0
  61. package/karnel/tools/ai/freebuff/bin/freebuff +28 -0
  62. package/karnel/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
  63. package/karnel/tools/ai/freebuff/install.sh +303 -0
  64. package/karnel/tools/ai/gemini-cli/README.md +46 -0
  65. package/karnel/tools/ai/gemini-cli/install.sh +111 -0
  66. package/karnel/tools/ai/gentle-ai/README.md +42 -0
  67. package/karnel/tools/ai/gentle-ai/install.sh +253 -0
  68. package/karnel/tools/ai/gentle-ai/termux-patches.go +256 -0
  69. package/karnel/tools/ai/gga/README.md +49 -0
  70. package/karnel/tools/ai/gga/install.sh +134 -0
  71. package/karnel/tools/ai/hermes-agent/README.md +50 -0
  72. package/karnel/tools/ai/hermes-agent/install.sh +120 -0
  73. package/karnel/tools/ai/kilocode-cli/README.md +45 -0
  74. package/karnel/tools/ai/kilocode-cli/bin/kilocode +21 -0
  75. package/karnel/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
  76. package/karnel/tools/ai/kilocode-cli/install.sh +179 -0
  77. package/karnel/tools/ai/kimchi-code/README.md +53 -0
  78. package/karnel/tools/ai/kimchi-code/install.sh +221 -0
  79. package/karnel/tools/ai/kimi-code/README.md +45 -0
  80. package/karnel/tools/ai/kimi-code/install.sh +111 -0
  81. package/karnel/tools/ai/kiro/README.md +17 -0
  82. package/karnel/tools/ai/kiro/install.sh +134 -0
  83. package/karnel/tools/ai/mimocode/README.md +43 -0
  84. package/karnel/tools/ai/mimocode/bin/mimo +28 -0
  85. package/karnel/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
  86. package/karnel/tools/ai/mimocode/install.sh +287 -0
  87. package/karnel/tools/ai/minimax-cli/README.md +45 -0
  88. package/karnel/tools/ai/minimax-cli/install.sh +111 -0
  89. package/karnel/tools/ai/mistral-vibe/README.md +46 -0
  90. package/karnel/tools/ai/mistral-vibe/install.sh +119 -0
  91. package/karnel/tools/ai/odysseus/README.md +35 -0
  92. package/karnel/tools/ai/odysseus/install.sh +198 -0
  93. package/karnel/tools/ai/ollama/README.md +44 -0
  94. package/karnel/tools/ai/ollama/install.sh +78 -0
  95. package/karnel/tools/ai/omni-route/README.md +111 -0
  96. package/karnel/tools/ai/omni-route/install.sh +165 -0
  97. package/karnel/tools/ai/openclaude/README.md +46 -0
  98. package/karnel/tools/ai/openclaude/install.sh +110 -0
  99. package/karnel/tools/ai/openclaw/README.md +47 -0
  100. package/karnel/tools/ai/openclaw/install.sh +112 -0
  101. package/karnel/tools/ai/opencode/README.md +51 -0
  102. package/karnel/tools/ai/opencode/bin/opencode +28 -0
  103. package/karnel/tools/ai/opencode/helper/opencode_helper.c +57 -0
  104. package/karnel/tools/ai/opencode/install.sh +290 -0
  105. package/karnel/tools/ai/openspec/README.md +34 -0
  106. package/karnel/tools/ai/openspec/install.sh +61 -0
  107. package/karnel/tools/ai/pi/README.md +46 -0
  108. package/karnel/tools/ai/pi/install.sh +104 -0
  109. package/karnel/tools/ai/qwen-code/README.md +45 -0
  110. package/karnel/tools/ai/qwen-code/install.sh +111 -0
  111. package/karnel/tools/auto/all.sh +57 -0
  112. package/karnel/tools/auto/n8n/README.md +47 -0
  113. package/karnel/tools/auto/n8n/install.sh +102 -0
  114. package/karnel/tools/db/all.sh +61 -0
  115. package/karnel/tools/db/mariadb/README.md +43 -0
  116. package/karnel/tools/db/mariadb/install.sh +65 -0
  117. package/karnel/tools/db/mongodb/README.md +42 -0
  118. package/karnel/tools/db/mongodb/install.sh +73 -0
  119. package/karnel/tools/db/postgresql/README.md +45 -0
  120. package/karnel/tools/db/postgresql/install.sh +65 -0
  121. package/karnel/tools/db/redis/README.md +46 -0
  122. package/karnel/tools/db/redis/install.sh +64 -0
  123. package/karnel/tools/db/sqlite/README.md +44 -0
  124. package/karnel/tools/db/sqlite/install.sh +65 -0
  125. package/karnel/tools/deploy/all.sh +43 -0
  126. package/karnel/tools/deploy/netlify/install.sh +41 -0
  127. package/karnel/tools/deploy/railway/install.sh +109 -0
  128. package/karnel/tools/deploy/vercel/install.sh +43 -0
  129. package/karnel/tools/dev/all.sh +77 -0
  130. package/karnel/tools/dev/bat/README.md +44 -0
  131. package/karnel/tools/dev/bat/install.sh +82 -0
  132. package/karnel/tools/dev/bc/README.md +44 -0
  133. package/karnel/tools/dev/bc/install.sh +82 -0
  134. package/karnel/tools/dev/cloudflared/README.md +43 -0
  135. package/karnel/tools/dev/cloudflared/install.sh +82 -0
  136. package/karnel/tools/dev/curl/README.md +43 -0
  137. package/karnel/tools/dev/curl/install.sh +82 -0
  138. package/karnel/tools/dev/fzf/README.md +44 -0
  139. package/karnel/tools/dev/fzf/install.sh +82 -0
  140. package/karnel/tools/dev/gh/README.md +43 -0
  141. package/karnel/tools/dev/gh/install.sh +82 -0
  142. package/karnel/tools/dev/html2text/README.md +44 -0
  143. package/karnel/tools/dev/html2text/install.sh +82 -0
  144. package/karnel/tools/dev/imagemagick/README.md +44 -0
  145. package/karnel/tools/dev/imagemagick/install.sh +82 -0
  146. package/karnel/tools/dev/jq/README.md +44 -0
  147. package/karnel/tools/dev/jq/install.sh +82 -0
  148. package/karnel/tools/dev/lsd/README.md +44 -0
  149. package/karnel/tools/dev/lsd/install.sh +82 -0
  150. package/karnel/tools/dev/make/README.md +44 -0
  151. package/karnel/tools/dev/make/install.sh +82 -0
  152. package/karnel/tools/dev/ncurses/README.md +42 -0
  153. package/karnel/tools/dev/ncurses/install.sh +82 -0
  154. package/karnel/tools/dev/openssh/README.md +43 -0
  155. package/karnel/tools/dev/openssh/install.sh +75 -0
  156. package/karnel/tools/dev/proot/README.md +43 -0
  157. package/karnel/tools/dev/proot/install.sh +82 -0
  158. package/karnel/tools/dev/shfmt/README.md +44 -0
  159. package/karnel/tools/dev/shfmt/install.sh +82 -0
  160. package/karnel/tools/dev/tmate/README.md +44 -0
  161. package/karnel/tools/dev/tmate/install.sh +82 -0
  162. package/karnel/tools/dev/tmux/README.md +43 -0
  163. package/karnel/tools/dev/tmux/install.sh +75 -0
  164. package/karnel/tools/dev/translate/README.md +44 -0
  165. package/karnel/tools/dev/translate/install.sh +82 -0
  166. package/karnel/tools/dev/tree/README.md +44 -0
  167. package/karnel/tools/dev/tree/install.sh +82 -0
  168. package/karnel/tools/dev/udocker/README.md +44 -0
  169. package/karnel/tools/dev/udocker/install.sh +82 -0
  170. package/karnel/tools/dev/wget/README.md +44 -0
  171. package/karnel/tools/dev/wget/install.sh +82 -0
  172. package/karnel/tools/editor/all.sh +59 -0
  173. package/karnel/tools/editor/code-server/README.md +42 -0
  174. package/karnel/tools/editor/code-server/install.sh +74 -0
  175. package/karnel/tools/editor/neovim/README.md +43 -0
  176. package/karnel/tools/editor/neovim/install.sh +64 -0
  177. package/karnel/tools/editor/nvchad/README.md +45 -0
  178. package/karnel/tools/editor/nvchad/install.sh +105 -0
  179. package/karnel/tools/lang/all.sh +63 -0
  180. package/karnel/tools/lang/clang/README.md +43 -0
  181. package/karnel/tools/lang/clang/install.sh +79 -0
  182. package/karnel/tools/lang/golang/README.md +43 -0
  183. package/karnel/tools/lang/golang/install.sh +79 -0
  184. package/karnel/tools/lang/nodejs/README.md +43 -0
  185. package/karnel/tools/lang/nodejs/install.sh +79 -0
  186. package/karnel/tools/lang/perl/README.md +43 -0
  187. package/karnel/tools/lang/perl/install.sh +79 -0
  188. package/karnel/tools/lang/php/README.md +43 -0
  189. package/karnel/tools/lang/php/install.sh +79 -0
  190. package/karnel/tools/lang/python/README.md +43 -0
  191. package/karnel/tools/lang/python/install.sh +79 -0
  192. package/karnel/tools/lang/rust/README.md +43 -0
  193. package/karnel/tools/lang/rust/install.sh +79 -0
  194. package/karnel/tools/npm/all.sh +90 -0
  195. package/karnel/tools/npm/live-server/README.md +43 -0
  196. package/karnel/tools/npm/live-server/install.sh +96 -0
  197. package/karnel/tools/npm/localtunnel/README.md +43 -0
  198. package/karnel/tools/npm/localtunnel/install.sh +112 -0
  199. package/karnel/tools/npm/markserv/README.md +43 -0
  200. package/karnel/tools/npm/markserv/install.sh +95 -0
  201. package/karnel/tools/npm/ncu/README.md +43 -0
  202. package/karnel/tools/npm/ncu/install.sh +95 -0
  203. package/karnel/tools/npm/nestjs/README.md +43 -0
  204. package/karnel/tools/npm/nestjs/install.sh +95 -0
  205. package/karnel/tools/npm/ngrok/README.md +44 -0
  206. package/karnel/tools/npm/ngrok/install.sh +95 -0
  207. package/karnel/tools/npm/prettier/README.md +43 -0
  208. package/karnel/tools/npm/prettier/install.sh +95 -0
  209. package/karnel/tools/npm/psqlformat/README.md +43 -0
  210. package/karnel/tools/npm/psqlformat/install.sh +95 -0
  211. package/karnel/tools/npm/turbopack/README.md +8 -0
  212. package/karnel/tools/npm/turbopack/install.sh +42 -0
  213. package/karnel/tools/npm/typescript/README.md +43 -0
  214. package/karnel/tools/npm/typescript/install.sh +95 -0
  215. package/karnel/tools/npm/vercel/README.md +43 -0
  216. package/karnel/tools/npm/vercel/install.sh +95 -0
  217. package/karnel/tools/shell/all.sh +67 -0
  218. package/karnel/tools/shell/better-npm/README.md +43 -0
  219. package/karnel/tools/shell/better-npm/install.sh +85 -0
  220. package/karnel/tools/shell/fzf-tab/README.md +44 -0
  221. package/karnel/tools/shell/fzf-tab/install.sh +85 -0
  222. package/karnel/tools/shell/history-substring/README.md +43 -0
  223. package/karnel/tools/shell/history-substring/install.sh +85 -0
  224. package/karnel/tools/shell/powerlevel10k/README.md +43 -0
  225. package/karnel/tools/shell/powerlevel10k/install.sh +85 -0
  226. package/karnel/tools/shell/you-should-use/README.md +43 -0
  227. package/karnel/tools/shell/you-should-use/install.sh +85 -0
  228. package/karnel/tools/shell/zsh-autopair/README.md +44 -0
  229. package/karnel/tools/shell/zsh-autopair/install.sh +85 -0
  230. package/karnel/tools/shell/zsh-autosuggestions/README.md +43 -0
  231. package/karnel/tools/shell/zsh-autosuggestions/install.sh +85 -0
  232. package/karnel/tools/shell/zsh-completions/README.md +43 -0
  233. package/karnel/tools/shell/zsh-completions/install.sh +85 -0
  234. package/karnel/tools/shell/zsh-defer/README.md +43 -0
  235. package/karnel/tools/shell/zsh-defer/install.sh +85 -0
  236. package/karnel/tools/shell/zsh-syntax-highlighting/README.md +43 -0
  237. package/karnel/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
  238. package/karnel/tools/ui/all.sh +61 -0
  239. package/karnel/tools/ui/banner/README.md +42 -0
  240. package/karnel/tools/ui/banner/install.sh +160 -0
  241. package/karnel/tools/ui/cursor/README.md +42 -0
  242. package/karnel/tools/ui/cursor/install.sh +58 -0
  243. package/karnel/tools/ui/extra-keys/README.md +43 -0
  244. package/karnel/tools/ui/extra-keys/install.sh +62 -0
  245. package/karnel/tools/ui/font/README.md +43 -0
  246. package/karnel/tools/ui/font/install.sh +63 -0
  247. package/karnel/tools/voice/all.sh +27 -0
  248. package/karnel/tools/voice/install.sh +10 -0
  249. package/karnel/tools/voice/uninstall.sh +8 -0
  250. package/karnel/utils/banner.sh +492 -0
  251. package/karnel/utils/bootstrap.sh +25 -0
  252. package/karnel/utils/colors.sh +33 -0
  253. package/karnel/utils/dialogrc +30 -0
  254. package/karnel/utils/env.sh +53 -0
  255. package/karnel/utils/log.sh +567 -0
  256. package/karnel/utils/version.sh +205 -0
  257. package/package.json +42 -0
  258. 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
+ }