omni-catalyst 1.0.0
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 +1137 -0
- package/core/bin/core +85 -0
- package/core/bin/omni +21 -0
- package/core/cli/commands/--version.sh +8 -0
- package/core/cli/commands/brain.sh +1549 -0
- package/core/cli/commands/doctor.sh +834 -0
- package/core/cli/commands/env.sh +226 -0
- package/core/cli/commands/init.sh +1266 -0
- package/core/cli/commands/install.sh +759 -0
- package/core/cli/commands/list.sh +397 -0
- package/core/cli/commands/open.sh +71 -0
- package/core/cli/commands/pg.sh +761 -0
- package/core/cli/commands/reinstall.sh +694 -0
- package/core/cli/commands/show.sh +90 -0
- package/core/cli/commands/uninstall.sh +700 -0
- package/core/cli/commands/update.sh +754 -0
- package/core/cli/commands/voice.sh +170 -0
- package/core/cli/core.sh +82 -0
- package/core/cli/omni.sh +634 -0
- package/core/modules/ai.sh +152 -0
- package/core/modules/auto.sh +90 -0
- package/core/modules/db.sh +94 -0
- package/core/modules/deploy.sh +50 -0
- package/core/modules/dev.sh +126 -0
- package/core/modules/editor.sh +101 -0
- package/core/modules/lang.sh +100 -0
- package/core/modules/npm.sh +122 -0
- package/core/modules/shell.sh +312 -0
- package/core/modules/ui.sh +115 -0
- package/core/tools/ai/all.sh +63 -0
- package/core/tools/ai/antigravity-cli/README.md +45 -0
- package/core/tools/ai/antigravity-cli/bin/agy +28 -0
- package/core/tools/ai/antigravity-cli/helper/agy_helper.c +39 -0
- package/core/tools/ai/antigravity-cli/install.sh +469 -0
- package/core/tools/ai/claude-code/README.md +45 -0
- package/core/tools/ai/claude-code/bin/claude +29 -0
- package/core/tools/ai/claude-code/helper/claude_helper.c +42 -0
- package/core/tools/ai/claude-code/install.sh +278 -0
- package/core/tools/ai/codegraph/README.md +43 -0
- package/core/tools/ai/codegraph/bin/codegraph +3 -0
- package/core/tools/ai/codegraph/install.sh +149 -0
- package/core/tools/ai/codex/README.md +44 -0
- package/core/tools/ai/codex/install.sh +104 -0
- package/core/tools/ai/command-code/README.md +62 -0
- package/core/tools/ai/command-code/install.sh +136 -0
- package/core/tools/ai/engram/README.md +44 -0
- package/core/tools/ai/engram/install.sh +127 -0
- package/core/tools/ai/freebuff/README.md +52 -0
- package/core/tools/ai/freebuff/bin/freebuff +28 -0
- package/core/tools/ai/freebuff/helper/freebuff_helper.c +47 -0
- package/core/tools/ai/freebuff/install.sh +301 -0
- package/core/tools/ai/gemini-cli/README.md +46 -0
- package/core/tools/ai/gemini-cli/install.sh +111 -0
- package/core/tools/ai/gentle-ai/README.md +42 -0
- package/core/tools/ai/gentle-ai/install.sh +253 -0
- package/core/tools/ai/gentle-ai/termux-patches.go +256 -0
- package/core/tools/ai/gga/README.md +49 -0
- package/core/tools/ai/gga/install.sh +134 -0
- package/core/tools/ai/hermes-agent/README.md +50 -0
- package/core/tools/ai/hermes-agent/install.sh +80 -0
- package/core/tools/ai/heygen/README.md +24 -0
- package/core/tools/ai/heygen/install.sh +126 -0
- package/core/tools/ai/kilocode-cli/README.md +45 -0
- package/core/tools/ai/kilocode-cli/bin/kilocode +21 -0
- package/core/tools/ai/kilocode-cli/helper/kilocode_helper.c +47 -0
- package/core/tools/ai/kilocode-cli/install.sh +179 -0
- package/core/tools/ai/kimchi-code/README.md +8 -0
- package/core/tools/ai/kimchi-code/install.sh +120 -0
- package/core/tools/ai/kimi-code/README.md +45 -0
- package/core/tools/ai/kimi-code/install.sh +111 -0
- package/core/tools/ai/kiro-cli/README.md +23 -0
- package/core/tools/ai/kiro-cli/install.sh +127 -0
- package/core/tools/ai/mimocode/README.md +43 -0
- package/core/tools/ai/mimocode/bin/mimo +28 -0
- package/core/tools/ai/mimocode/helper/mimocode_helper.c +47 -0
- package/core/tools/ai/mimocode/install.sh +287 -0
- package/core/tools/ai/minimax-cli/README.md +45 -0
- package/core/tools/ai/minimax-cli/install.sh +111 -0
- package/core/tools/ai/mistral-vibe/README.md +46 -0
- package/core/tools/ai/mistral-vibe/install.sh +119 -0
- package/core/tools/ai/odysseus/README.md +35 -0
- package/core/tools/ai/odysseus/install.sh +163 -0
- package/core/tools/ai/ollama/README.md +44 -0
- package/core/tools/ai/ollama/install.sh +78 -0
- package/core/tools/ai/openclaude/README.md +46 -0
- package/core/tools/ai/openclaude/install.sh +110 -0
- package/core/tools/ai/openclaw/README.md +47 -0
- package/core/tools/ai/openclaw/install.sh +112 -0
- package/core/tools/ai/opencode/README.md +51 -0
- package/core/tools/ai/opencode/bin/opencode +28 -0
- package/core/tools/ai/opencode/helper/opencode_helper.c +57 -0
- package/core/tools/ai/opencode/install.sh +290 -0
- package/core/tools/ai/pi/README.md +46 -0
- package/core/tools/ai/pi/install.sh +104 -0
- package/core/tools/ai/qwen-code/README.md +45 -0
- package/core/tools/ai/qwen-code/install.sh +111 -0
- package/core/tools/ai/seedance/README.md +22 -0
- package/core/tools/ai/seedance/install.sh +134 -0
- package/core/tools/ai/veo3/README.md +36 -0
- package/core/tools/ai/veo3/install.sh +151 -0
- package/core/tools/auto/all.sh +57 -0
- package/core/tools/auto/n8n/README.md +47 -0
- package/core/tools/auto/n8n/install.sh +102 -0
- package/core/tools/db/all.sh +60 -0
- package/core/tools/db/mariadb/README.md +43 -0
- package/core/tools/db/mariadb/install.sh +65 -0
- package/core/tools/db/mongodb/README.md +42 -0
- package/core/tools/db/mongodb/install.sh +73 -0
- package/core/tools/db/postgresql/README.md +45 -0
- package/core/tools/db/postgresql/install.sh +65 -0
- package/core/tools/db/sqlite/README.md +44 -0
- package/core/tools/db/sqlite/install.sh +65 -0
- package/core/tools/deploy/all.sh +39 -0
- package/core/tools/deploy/netlify/install.sh +41 -0
- package/core/tools/deploy/railway/install.sh +47 -0
- package/core/tools/deploy/vercel/install.sh +43 -0
- package/core/tools/dev/all.sh +75 -0
- package/core/tools/dev/bat/README.md +44 -0
- package/core/tools/dev/bat/install.sh +82 -0
- package/core/tools/dev/bc/README.md +44 -0
- package/core/tools/dev/bc/install.sh +82 -0
- package/core/tools/dev/cloudflared/README.md +43 -0
- package/core/tools/dev/cloudflared/install.sh +82 -0
- package/core/tools/dev/curl/README.md +43 -0
- package/core/tools/dev/curl/install.sh +82 -0
- package/core/tools/dev/fzf/README.md +44 -0
- package/core/tools/dev/fzf/install.sh +82 -0
- package/core/tools/dev/gh/README.md +43 -0
- package/core/tools/dev/gh/install.sh +82 -0
- package/core/tools/dev/html2text/README.md +44 -0
- package/core/tools/dev/html2text/install.sh +82 -0
- package/core/tools/dev/imagemagick/README.md +44 -0
- package/core/tools/dev/imagemagick/install.sh +82 -0
- package/core/tools/dev/jq/README.md +44 -0
- package/core/tools/dev/jq/install.sh +82 -0
- package/core/tools/dev/lsd/README.md +44 -0
- package/core/tools/dev/lsd/install.sh +82 -0
- package/core/tools/dev/make/README.md +44 -0
- package/core/tools/dev/make/install.sh +82 -0
- package/core/tools/dev/ncurses/README.md +42 -0
- package/core/tools/dev/ncurses/install.sh +82 -0
- package/core/tools/dev/proot/README.md +43 -0
- package/core/tools/dev/proot/install.sh +82 -0
- package/core/tools/dev/shfmt/README.md +44 -0
- package/core/tools/dev/shfmt/install.sh +82 -0
- package/core/tools/dev/tmate/README.md +44 -0
- package/core/tools/dev/tmate/install.sh +82 -0
- package/core/tools/dev/translate/README.md +44 -0
- package/core/tools/dev/translate/install.sh +82 -0
- package/core/tools/dev/tree/README.md +44 -0
- package/core/tools/dev/tree/install.sh +82 -0
- package/core/tools/dev/udocker/README.md +44 -0
- package/core/tools/dev/udocker/install.sh +82 -0
- package/core/tools/dev/wget/README.md +44 -0
- package/core/tools/dev/wget/install.sh +82 -0
- package/core/tools/editor/all.sh +58 -0
- package/core/tools/editor/neovim/README.md +43 -0
- package/core/tools/editor/neovim/install.sh +66 -0
- package/core/tools/editor/nvchad/README.md +45 -0
- package/core/tools/editor/nvchad/install.sh +110 -0
- package/core/tools/lang/all.sh +63 -0
- package/core/tools/lang/clang/README.md +43 -0
- package/core/tools/lang/clang/install.sh +79 -0
- package/core/tools/lang/golang/README.md +43 -0
- package/core/tools/lang/golang/install.sh +79 -0
- package/core/tools/lang/nodejs/README.md +43 -0
- package/core/tools/lang/nodejs/install.sh +79 -0
- package/core/tools/lang/perl/README.md +43 -0
- package/core/tools/lang/perl/install.sh +79 -0
- package/core/tools/lang/php/README.md +43 -0
- package/core/tools/lang/php/install.sh +79 -0
- package/core/tools/lang/python/README.md +43 -0
- package/core/tools/lang/python/install.sh +79 -0
- package/core/tools/lang/rust/README.md +43 -0
- package/core/tools/lang/rust/install.sh +79 -0
- package/core/tools/npm/all.sh +67 -0
- package/core/tools/npm/live-server/README.md +43 -0
- package/core/tools/npm/live-server/install.sh +95 -0
- package/core/tools/npm/localtunnel/README.md +43 -0
- package/core/tools/npm/localtunnel/install.sh +111 -0
- package/core/tools/npm/markserv/README.md +43 -0
- package/core/tools/npm/markserv/install.sh +94 -0
- package/core/tools/npm/ncu/README.md +43 -0
- package/core/tools/npm/ncu/install.sh +94 -0
- package/core/tools/npm/nestjs/README.md +43 -0
- package/core/tools/npm/nestjs/install.sh +94 -0
- package/core/tools/npm/ngrok/README.md +44 -0
- package/core/tools/npm/ngrok/install.sh +94 -0
- package/core/tools/npm/prettier/README.md +43 -0
- package/core/tools/npm/prettier/install.sh +94 -0
- package/core/tools/npm/psqlformat/README.md +43 -0
- package/core/tools/npm/psqlformat/install.sh +94 -0
- package/core/tools/npm/turbopack/README.md +8 -0
- package/core/tools/npm/turbopack/install.sh +41 -0
- package/core/tools/npm/typescript/README.md +43 -0
- package/core/tools/npm/typescript/install.sh +94 -0
- package/core/tools/npm/vercel/README.md +43 -0
- package/core/tools/npm/vercel/install.sh +94 -0
- package/core/tools/shell/all.sh +67 -0
- package/core/tools/shell/better-npm/README.md +43 -0
- package/core/tools/shell/better-npm/install.sh +85 -0
- package/core/tools/shell/fzf-tab/README.md +44 -0
- package/core/tools/shell/fzf-tab/install.sh +85 -0
- package/core/tools/shell/history-substring/README.md +43 -0
- package/core/tools/shell/history-substring/install.sh +85 -0
- package/core/tools/shell/powerlevel10k/README.md +43 -0
- package/core/tools/shell/powerlevel10k/install.sh +85 -0
- package/core/tools/shell/you-should-use/README.md +43 -0
- package/core/tools/shell/you-should-use/install.sh +85 -0
- package/core/tools/shell/zsh-autopair/README.md +44 -0
- package/core/tools/shell/zsh-autopair/install.sh +85 -0
- package/core/tools/shell/zsh-autosuggestions/README.md +43 -0
- package/core/tools/shell/zsh-autosuggestions/install.sh +85 -0
- package/core/tools/shell/zsh-completions/README.md +43 -0
- package/core/tools/shell/zsh-completions/install.sh +85 -0
- package/core/tools/shell/zsh-defer/README.md +43 -0
- package/core/tools/shell/zsh-defer/install.sh +85 -0
- package/core/tools/shell/zsh-syntax-highlighting/README.md +43 -0
- package/core/tools/shell/zsh-syntax-highlighting/install.sh +72 -0
- package/core/tools/ui/all.sh +61 -0
- package/core/tools/ui/banner/README.md +42 -0
- package/core/tools/ui/banner/install.sh +151 -0
- package/core/tools/ui/cursor/README.md +42 -0
- package/core/tools/ui/cursor/install.sh +58 -0
- package/core/tools/ui/extra-keys/README.md +43 -0
- package/core/tools/ui/extra-keys/install.sh +62 -0
- package/core/tools/ui/font/README.md +43 -0
- package/core/tools/ui/font/install.sh +63 -0
- package/core/utils/banner.sh +519 -0
- package/core/utils/bootstrap.sh +25 -0
- package/core/utils/colors.sh +31 -0
- package/core/utils/dialogrc +30 -0
- package/core/utils/env.sh +53 -0
- package/core/utils/log.sh +598 -0
- package/install.sh +272 -0
- package/package.json +43 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
import "@/utils/log"
|
|
4
|
+
import "@/utils/colors"
|
|
5
|
+
|
|
6
|
+
: "${OMNI_CACHE:=$HOME/.cache/omni}"
|
|
7
|
+
: "${OMNI_PATH:=$HOME/omni/core}"
|
|
8
|
+
: "${PREFIX:=$PREFIX}"
|
|
9
|
+
|
|
10
|
+
LOG_FILE="$OMNI_CACHE/install_ai.log"
|
|
11
|
+
GENTLE_AI_DATA_DIR="${GENTLE_AI_DATA_DIR:-$HOME/.local/share/omni-data/gentle-ai}"
|
|
12
|
+
|
|
13
|
+
_gentle_ai_dependencies() {
|
|
14
|
+
loading "Installing dependencies" _gentle_ai_dependencies_impl
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_gentle_ai_dependencies_impl() {
|
|
18
|
+
declare -A DEPS=(
|
|
19
|
+
["golang"]="go"
|
|
20
|
+
["git"]="git"
|
|
21
|
+
["curl"]="curl"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
local pkg_name bin_name
|
|
25
|
+
for pkg_name in "${!DEPS[@]}"; do
|
|
26
|
+
bin_name="${DEPS[$pkg_name]}"
|
|
27
|
+
if ! command -v "$bin_name" &>/dev/null; then
|
|
28
|
+
if ! pkg install "$pkg_name" -y &>>"$LOG_FILE"; then
|
|
29
|
+
log_error "Failed to install $pkg_name"
|
|
30
|
+
return 1
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
done
|
|
34
|
+
|
|
35
|
+
return 0
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_gentle_ai_ensure_go() {
|
|
39
|
+
loading "Checking Go version" _gentle_ai_ensure_go_impl
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_gentle_ai_ensure_go_impl() {
|
|
43
|
+
if ! command -v go &>/dev/null; then
|
|
44
|
+
log_error "Go is required but not installed"
|
|
45
|
+
return 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
local go_installed
|
|
49
|
+
go_installed=$(go version | sed 's/.*go\([0-9.]*\).*/\1/')
|
|
50
|
+
|
|
51
|
+
local go_required
|
|
52
|
+
if [ -f "$GENTLE_AI_DATA_DIR/go.mod" ]; then
|
|
53
|
+
go_required=$(sed -n 's/^go \([0-9.]*\)/\1/p' "$GENTLE_AI_DATA_DIR/go.mod" | head -1)
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ -z "$go_required" ]; then
|
|
57
|
+
go_required="1.25.0"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if ! _version_ge "$go_installed" "$go_required"; then
|
|
61
|
+
log_error "Go $go_required+ required (detected $go_installed). Run: pkg upgrade golang"
|
|
62
|
+
return 1
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
return 0
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_version_ge() {
|
|
69
|
+
local v1="$1" v2="$2"
|
|
70
|
+
local highest
|
|
71
|
+
highest=$(printf '%s\n%s\n' "$v1" "$v2" | sort -V | tail -1)
|
|
72
|
+
[ "$highest" = "$v1" ]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_clone_or_update_repo() {
|
|
76
|
+
loading "Cloning or updating gentle-ai repo" _clone_or_update_repo_impl
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_clone_or_update_repo_impl() {
|
|
80
|
+
local repo_url="https://github.com/Gentleman-Programming/gentle-ai.git"
|
|
81
|
+
|
|
82
|
+
if [ -d "$GENTLE_AI_DATA_DIR/.git" ]; then
|
|
83
|
+
git -C "$GENTLE_AI_DATA_DIR" remote set-url origin "$repo_url" &>>"$LOG_FILE"
|
|
84
|
+
git -C "$GENTLE_AI_DATA_DIR" stash --include-untracked &>>"$LOG_FILE" || true
|
|
85
|
+
if ! git -C "$GENTLE_AI_DATA_DIR" fetch origin &>>"$LOG_FILE"; then
|
|
86
|
+
log_error "Failed to fetch from remote"
|
|
87
|
+
return 1
|
|
88
|
+
fi
|
|
89
|
+
if ! git -C "$GENTLE_AI_DATA_DIR" reset --hard origin/main &>>"$LOG_FILE"; then
|
|
90
|
+
log_error "Failed to reset to origin/main"
|
|
91
|
+
return 1
|
|
92
|
+
fi
|
|
93
|
+
else
|
|
94
|
+
if [ -d "$GENTLE_AI_DATA_DIR" ]; then
|
|
95
|
+
rm -rf "$GENTLE_AI_DATA_DIR"
|
|
96
|
+
fi
|
|
97
|
+
if ! git clone "$repo_url" "$GENTLE_AI_DATA_DIR" &>>"$LOG_FILE"; then
|
|
98
|
+
log_error "Failed to clone gentle-ai repo"
|
|
99
|
+
return 1
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
return 0
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_build_and_apply_patches() {
|
|
107
|
+
loading "Applying Termux patches" _build_and_apply_patches_impl
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_build_and_apply_patches_impl() {
|
|
111
|
+
local patcher_src="$OMNI_PATH/tools/ai/gentle-ai/termux-patches.go"
|
|
112
|
+
local patcher_bin="$OMNI_CACHE/termux-patcher"
|
|
113
|
+
|
|
114
|
+
mkdir -p "$OMNI_CACHE"
|
|
115
|
+
|
|
116
|
+
if [ ! -f "$patcher_bin" ] || [ "$patcher_src" -nt "$patcher_bin" ]; then
|
|
117
|
+
if ! go build -o "$patcher_bin" "$patcher_src" &>>"$LOG_FILE"; then
|
|
118
|
+
log_error "Failed to compile patcher"
|
|
119
|
+
return 1
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
pushd "$GENTLE_AI_DATA_DIR" &>/dev/null || return 1
|
|
124
|
+
|
|
125
|
+
local patch_out patch_rc
|
|
126
|
+
patch_out=$("$patcher_bin" "$GENTLE_AI_DATA_DIR" 2>&1)
|
|
127
|
+
patch_rc=$?
|
|
128
|
+
|
|
129
|
+
echo "$patch_out" >>"$LOG_FILE"
|
|
130
|
+
|
|
131
|
+
if [ $patch_rc -ne 0 ]; then
|
|
132
|
+
popd &>/dev/null || true
|
|
133
|
+
echo ""
|
|
134
|
+
log_error "Termux patches failed. Output:"
|
|
135
|
+
echo "$patch_out"
|
|
136
|
+
return 1
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
popd &>/dev/null || true
|
|
140
|
+
return 0
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_compile() {
|
|
144
|
+
loading "Compiling gentle-ai" _compile_impl
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
_compile_impl() {
|
|
148
|
+
if ! command -v gcc &>/dev/null && ! command -v clang &>/dev/null; then
|
|
149
|
+
export CGO_ENABLED=0
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
local build_dir="$GENTLE_AI_DATA_DIR/cmd/gentle-ai"
|
|
153
|
+
if [ ! -d "$build_dir" ]; then
|
|
154
|
+
log_error "Entry point not found at cmd/gentle-ai"
|
|
155
|
+
return 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
pushd "$GENTLE_AI_DATA_DIR" &>/dev/null || return 1
|
|
159
|
+
|
|
160
|
+
if ! go mod download &>>"$LOG_FILE"; then
|
|
161
|
+
popd &>/dev/null || true
|
|
162
|
+
log_error "Failed to download Go dependencies"
|
|
163
|
+
return 1
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
if ! go build -trimpath -ldflags="-s -w" -o gentle-ai ./cmd/gentle-ai/ &>>"$LOG_FILE"; then
|
|
167
|
+
popd &>/dev/null || true
|
|
168
|
+
log_error "Failed to compile gentle-ai"
|
|
169
|
+
return 1
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
popd &>/dev/null || true
|
|
173
|
+
|
|
174
|
+
if [ ! -f "$GENTLE_AI_DATA_DIR/gentle-ai" ]; then
|
|
175
|
+
log_error "Compilation succeeded but binary not found"
|
|
176
|
+
return 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
return 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
_install_binary() {
|
|
183
|
+
loading "Installing binary" _install_binary_impl
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
_install_binary_impl() {
|
|
187
|
+
if ! cp "$GENTLE_AI_DATA_DIR/gentle-ai" "$PREFIX/bin/gentle-ai" &>>"$LOG_FILE"; then
|
|
188
|
+
log_error "Failed to install binary to $PREFIX/bin/gentle-ai"
|
|
189
|
+
return 1
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
chmod +x "$PREFIX/bin/gentle-ai"
|
|
193
|
+
return 0
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
install_gentle_ai() {
|
|
197
|
+
if command -v gentle-ai &>/dev/null; then
|
|
198
|
+
log_info "gentle-ai is already installed"
|
|
199
|
+
return 2
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
log_info "Installing gentle-ai..."
|
|
203
|
+
mkdir -p "$(dirname "$LOG_FILE")" "$OMNI_CACHE"
|
|
204
|
+
|
|
205
|
+
_gentle_ai_dependencies || return 1
|
|
206
|
+
_clone_or_update_repo || return 1
|
|
207
|
+
_gentle_ai_ensure_go || return 1
|
|
208
|
+
_build_and_apply_patches || return 1
|
|
209
|
+
_compile || return 1
|
|
210
|
+
_install_binary || return 1
|
|
211
|
+
|
|
212
|
+
log_success "gentle-ai installed"
|
|
213
|
+
return 0
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
uninstall_gentle_ai() {
|
|
217
|
+
if ! command -v gentle-ai &>/dev/null; then
|
|
218
|
+
log_info "gentle-ai is not installed"
|
|
219
|
+
return 2
|
|
220
|
+
fi
|
|
221
|
+
log_info "Uninstalling gentle-ai..."
|
|
222
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
223
|
+
|
|
224
|
+
rm -f "$PREFIX/bin/gentle-ai"
|
|
225
|
+
rm -rf "$GENTLE_AI_DATA_DIR"
|
|
226
|
+
|
|
227
|
+
if [ ! -f "$PREFIX/bin/gentle-ai" ] && [ ! -d "$GENTLE_AI_DATA_DIR" ]; then
|
|
228
|
+
log_success "gentle-ai uninstalled"
|
|
229
|
+
return 0
|
|
230
|
+
else
|
|
231
|
+
log_error "Failed to uninstall gentle-ai"
|
|
232
|
+
return 1
|
|
233
|
+
fi
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
update_gentle_ai() {
|
|
237
|
+
log_info "Updating gentle-ai..."
|
|
238
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
239
|
+
|
|
240
|
+
_clone_or_update_repo || return 1
|
|
241
|
+
_gentle_ai_ensure_go || return 1
|
|
242
|
+
_build_and_apply_patches || return 1
|
|
243
|
+
_compile || return 1
|
|
244
|
+
_install_binary || return 1
|
|
245
|
+
|
|
246
|
+
log_success "gentle-ai updated"
|
|
247
|
+
return 0
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
reinstall_gentle_ai() {
|
|
251
|
+
uninstall_gentle_ai
|
|
252
|
+
install_gentle_ai
|
|
253
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// termux-patches applies the necessary source-code changes to compile and run
|
|
2
|
+
// gentle-ai on Android/Termux.
|
|
3
|
+
//
|
|
4
|
+
// Unlike a sed-based approach, this program uses exact Go source patterns so
|
|
5
|
+
// that upstream changes that break the patch are DETECTED (non-zero exit)
|
|
6
|
+
// rather than silently skipped.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
//
|
|
10
|
+
// go run termux-patches.go [source-directory]
|
|
11
|
+
//
|
|
12
|
+
// Default source-directory is "." (current directory).
|
|
13
|
+
// The program modifies files in-place.
|
|
14
|
+
package main
|
|
15
|
+
|
|
16
|
+
import (
|
|
17
|
+
"fmt"
|
|
18
|
+
"os"
|
|
19
|
+
"path/filepath"
|
|
20
|
+
"strings"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
func main() {
|
|
24
|
+
srcDir := "."
|
|
25
|
+
if len(os.Args) > 1 {
|
|
26
|
+
srcDir = os.Args[1]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type patchDef struct {
|
|
30
|
+
path string
|
|
31
|
+
patchFn func(string) (string, error)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
patches := []patchDef{
|
|
35
|
+
{filepath.Join(srcDir, "internal/system/detect.go"), patchDetectGo},
|
|
36
|
+
{filepath.Join(srcDir, "internal/system/guard.go"), patchGuardGo},
|
|
37
|
+
{filepath.Join(srcDir, "internal/update/upgrade/download.go"), patchDownloadGo},
|
|
38
|
+
{filepath.Join(srcDir, "internal/tui/model.go"), patchModelGo},
|
|
39
|
+
{filepath.Join(srcDir, "internal/components/engram/download.go"), patchEngramDownloadGo},
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
anyFailed := false
|
|
43
|
+
for _, p := range patches {
|
|
44
|
+
content, err := os.ReadFile(p.path)
|
|
45
|
+
if err != nil {
|
|
46
|
+
fmt.Fprintf(os.Stderr, "ERROR reading %s: %v\n", p.path, err)
|
|
47
|
+
anyFailed = true
|
|
48
|
+
continue
|
|
49
|
+
}
|
|
50
|
+
result, err := p.patchFn(string(content))
|
|
51
|
+
if err != nil {
|
|
52
|
+
fmt.Fprintf(os.Stderr, "ERROR patching %s: %v\n", p.path, err)
|
|
53
|
+
anyFailed = true
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
if result != string(content) {
|
|
57
|
+
if err := os.WriteFile(p.path, []byte(result), 0o644); err != nil {
|
|
58
|
+
fmt.Fprintf(os.Stderr, "ERROR writing %s: %v\n", p.path, err)
|
|
59
|
+
anyFailed = true
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
fmt.Printf("PATCHED %s\n", p.path)
|
|
63
|
+
} else {
|
|
64
|
+
fmt.Printf("ALREADY PATCHED %s\n", p.path)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if anyFailed {
|
|
69
|
+
os.Exit(1)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// helpers
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
func tab(n int) string {
|
|
78
|
+
return strings.Repeat("\t", n)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// assertReplace replaces old with new in src once.
|
|
82
|
+
// If old is not found, it checks whether new is already present (idempotent).
|
|
83
|
+
// If neither is found, it returns an error with a descriptive message.
|
|
84
|
+
func assertReplace(src, old, new, desc string) (string, error) {
|
|
85
|
+
if strings.Contains(src, old) {
|
|
86
|
+
return strings.Replace(src, old, new, 1), nil
|
|
87
|
+
}
|
|
88
|
+
if strings.Contains(src, new) {
|
|
89
|
+
return src, nil
|
|
90
|
+
}
|
|
91
|
+
return src, fmt.Errorf("%s: pattern not found in source", desc)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// 1. internal/system/detect.go
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
func patchDetectGo(src string) (string, error) {
|
|
99
|
+
var err error
|
|
100
|
+
|
|
101
|
+
// 1a. IsSupportedOS: add android to the list.
|
|
102
|
+
old1 := tab(1) + `return goos == "darwin" || goos == "linux" || goos == "windows"` + "\n}"
|
|
103
|
+
new1 := tab(1) + `return goos == "darwin" || goos == "linux" || goos == "windows" || goos == "android"` + "\n}"
|
|
104
|
+
src, err = assertReplace(src, old1, new1, "IsSupportedOS return")
|
|
105
|
+
if err != nil {
|
|
106
|
+
return src, err
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 1b. resolvePlatformProfile: add case "android" before default.
|
|
110
|
+
old2 := "" +
|
|
111
|
+
tab(1) + `case "windows":` + "\n" +
|
|
112
|
+
tab(2) + `profile.PackageManager = "winget"` + "\n" +
|
|
113
|
+
tab(2) + `profile.Supported = true` + "\n" +
|
|
114
|
+
tab(2) + `return profile` + "\n" +
|
|
115
|
+
tab(1) + `default:`
|
|
116
|
+
new2 := "" +
|
|
117
|
+
tab(1) + `case "windows":` + "\n" +
|
|
118
|
+
tab(2) + `profile.PackageManager = "winget"` + "\n" +
|
|
119
|
+
tab(2) + `profile.Supported = true` + "\n" +
|
|
120
|
+
tab(2) + `return profile` + "\n" +
|
|
121
|
+
tab(1) + `case "android":` + "\n" +
|
|
122
|
+
tab(2) + `profile.PackageManager = "pkg"` + "\n" +
|
|
123
|
+
tab(2) + `profile.Supported = true` + "\n" +
|
|
124
|
+
tab(2) + `distro := detectLinuxDistro(linuxOSRelease)` + "\n" +
|
|
125
|
+
tab(2) + `if distro != LinuxDistroUnknown {` + "\n" +
|
|
126
|
+
tab(3) + `profile.LinuxDistro = distro` + "\n" +
|
|
127
|
+
tab(2) + `}` + "\n" +
|
|
128
|
+
tab(2) + `return profile` + "\n" +
|
|
129
|
+
tab(1) + `default:`
|
|
130
|
+
src, err = assertReplace(src, old2, new2, "resolvePlatformProfile android case")
|
|
131
|
+
if err != nil {
|
|
132
|
+
return src, err
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 1c. osReleaseContent: read $PREFIX/etc/os-release on android.
|
|
136
|
+
old3 := "" +
|
|
137
|
+
`func osReleaseContent(goos string) (string, error) {` + "\n" +
|
|
138
|
+
tab(1) + `if goos != "linux" {` + "\n" +
|
|
139
|
+
tab(2) + `return "", nil` + "\n" +
|
|
140
|
+
tab(1) + `}`
|
|
141
|
+
new3 := "" +
|
|
142
|
+
`func osReleaseContent(goos string) (string, error) {` + "\n" +
|
|
143
|
+
tab(1) + `if goos == "android" {` + "\n" +
|
|
144
|
+
tab(2) + `prefix := os.Getenv("PREFIX")` + "\n" +
|
|
145
|
+
tab(2) + `if prefix != "" {` + "\n" +
|
|
146
|
+
tab(3) + `if data, err := os.ReadFile(prefix + "/etc/os-release"); err == nil {` + "\n" +
|
|
147
|
+
tab(4) + `return string(data), nil` + "\n" +
|
|
148
|
+
tab(3) + `}` + "\n" +
|
|
149
|
+
tab(2) + `}` + "\n" +
|
|
150
|
+
tab(2) + `return "", nil` + "\n" +
|
|
151
|
+
tab(1) + `}` + "\n" +
|
|
152
|
+
tab(1) + `if goos != "linux" {` + "\n" +
|
|
153
|
+
tab(2) + `return "", nil` + "\n" +
|
|
154
|
+
tab(1) + `}`
|
|
155
|
+
src, err = assertReplace(src, old3, new3, "osReleaseContent android PREFIX")
|
|
156
|
+
if err != nil {
|
|
157
|
+
return src, err
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return src, nil
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
// 2. internal/system/guard.go
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
func patchGuardGo(src string) (string, error) {
|
|
168
|
+
// EnsureSupportedOS error message: mention Android.
|
|
169
|
+
old1 := `return fmt.Errorf("%w: only macOS, Linux, and Windows are supported (detected %s)", ErrUnsupportedOS, goos)`
|
|
170
|
+
new1 := `return fmt.Errorf("%w: only macOS, Linux, Windows, and Android are supported (detected %s)", ErrUnsupportedOS, goos)`
|
|
171
|
+
return assertReplace(src, old1, new1, "EnsureSupportedOS error message Android")
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
// 3. internal/update/upgrade/download.go
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
|
|
178
|
+
func patchDownloadGo(src string) (string, error) {
|
|
179
|
+
// On Android/Termux, download linux binaries (no android releases on
|
|
180
|
+
// GitHub). profile is passed by value so the modification is local.
|
|
181
|
+
old1 := `func Download(ctx context.Context, r update.UpdateResult, profile system.PlatformProfile) error {` + "\n" +
|
|
182
|
+
tab(1) + `if profile.OS == "windows" {`
|
|
183
|
+
new1 := `func Download(ctx context.Context, r update.UpdateResult, profile system.PlatformProfile) error {` + "\n" +
|
|
184
|
+
tab(1) + `if profile.OS == "android" {` + "\n" +
|
|
185
|
+
tab(2) + `profile.OS = "linux"` + "\n" +
|
|
186
|
+
tab(1) + `}` + "\n" +
|
|
187
|
+
"\n" +
|
|
188
|
+
tab(1) + `if profile.OS == "windows" {`
|
|
189
|
+
return assertReplace(src, old1, new1, "Download android->linux redirect")
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// 4. internal/tui/model.go
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
func patchModelGo(src string) (string, error) {
|
|
197
|
+
// openBrowserCmd: use termux-open-url on android.
|
|
198
|
+
old1 := "" +
|
|
199
|
+
tab(2) + `case "windows":` + "\n" +
|
|
200
|
+
tab(3) + `cmd = execCommandFn("rundll32", "url.dll,FileProtocolHandler", url)` + "\n" +
|
|
201
|
+
tab(2) + `default:` + "\n" +
|
|
202
|
+
tab(3) + `cmd = execCommandFn("xdg-open", url)`
|
|
203
|
+
new1 := "" +
|
|
204
|
+
tab(2) + `case "windows":` + "\n" +
|
|
205
|
+
tab(3) + `cmd = execCommandFn("rundll32", "url.dll,FileProtocolHandler", url)` + "\n" +
|
|
206
|
+
tab(2) + `case "android":` + "\n" +
|
|
207
|
+
tab(3) + `cmd = execCommandFn("termux-open-url", url)` + "\n" +
|
|
208
|
+
tab(2) + `default:` + "\n" +
|
|
209
|
+
tab(3) + `cmd = execCommandFn("xdg-open", url)`
|
|
210
|
+
return assertReplace(src, old1, new1, "openBrowserCmd android case")
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// 5. internal/components/engram/download.go
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
func patchEngramDownloadGo(src string) (string, error) {
|
|
218
|
+
var err error
|
|
219
|
+
|
|
220
|
+
// 5a. DownloadLatestBinary: redirect android -> linux for asset URLs.
|
|
221
|
+
old1 := "" +
|
|
222
|
+
tab(1) + `goos := profile.OS` + "\n" +
|
|
223
|
+
tab(1) + `goarch := normalizeArch(runtime.GOARCH)`
|
|
224
|
+
new1 := "" +
|
|
225
|
+
tab(1) + `goos := profile.OS` + "\n" +
|
|
226
|
+
tab(1) + `if goos == "android" {` + "\n" +
|
|
227
|
+
tab(2) + `goos = "linux"` + "\n" +
|
|
228
|
+
tab(1) + `}` + "\n" +
|
|
229
|
+
tab(1) + `goarch := normalizeArch(runtime.GOARCH)`
|
|
230
|
+
src, err = assertReplace(src, old1, new1, "engram DownloadLatestBinary android->linux")
|
|
231
|
+
if err != nil {
|
|
232
|
+
return src, err
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 5b. engramInstallDir: use $PREFIX/bin on Termux.
|
|
236
|
+
old2 := "" +
|
|
237
|
+
`func engramInstallDir(goos string) string {` + "\n" +
|
|
238
|
+
tab(1) + `if goos == "windows" {`
|
|
239
|
+
new2 := "" +
|
|
240
|
+
`func engramInstallDir(goos string) string {` + "\n" +
|
|
241
|
+
tab(1) + `if goos == "android" {` + "\n" +
|
|
242
|
+
tab(2) + `prefix := os.Getenv("PREFIX")` + "\n" +
|
|
243
|
+
tab(2) + `if prefix != "" {` + "\n" +
|
|
244
|
+
tab(3) + `return filepath.Join(prefix, "bin")` + "\n" +
|
|
245
|
+
tab(2) + `}` + "\n" +
|
|
246
|
+
tab(2) + `return "/data/data/com.termux/files/usr/bin"` + "\n" +
|
|
247
|
+
tab(1) + `}` + "\n" +
|
|
248
|
+
"\n" +
|
|
249
|
+
tab(1) + `if goos == "windows" {`
|
|
250
|
+
src, err = assertReplace(src, old2, new2, "engramInstallDir android PREFIX")
|
|
251
|
+
if err != nil {
|
|
252
|
+
return src, err
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return src, nil
|
|
256
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Gentleman Guardian Angel
|
|
2
|
+
|
|
3
|
+
Provider-agnostic AI code review on every commit
|
|
4
|
+
|
|
5
|
+
**Package:** gga
|
|
6
|
+
**Author:** Gentleman-Programming
|
|
7
|
+
**Repository:** https://github.com/israel676767/omni
|
|
8
|
+
**Official:** https://github.com/Gentleman-Programming/gentleman-guardian-angel
|
|
9
|
+
**Termux fork:** https://github.com/israel676767/gga-termux
|
|
10
|
+
**Type:** AI code review CLI (Pure Bash)
|
|
11
|
+
**License:** MIT
|
|
12
|
+
|
|
13
|
+
## Description
|
|
14
|
+
|
|
15
|
+
GGA (Gentleman Guardian Angel) is a provider-agnostic AI code review tool that runs on every commit. It validates staged files against your `AGENTS.md` rules using any LLM provider (Claude, Gemini, Codex, OpenCode, Ollama, LM Studio, GitHub Models). Pure Bash, zero dependencies, works as a standard pre-commit git hook.
|
|
16
|
+
|
|
17
|
+
The Termux fork adapts the installer/uninstaller for Android environments (Termux detects `$PREFIX` and installs to `$PREFIX/bin` and `$PREFIX/share/gga/lib`).
|
|
18
|
+
|
|
19
|
+
## Dependencies
|
|
20
|
+
|
|
21
|
+
- git, curl
|
|
22
|
+
- bash 5.0+
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
core install ai --gga
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Uninstall
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
core uninstall ai --gga
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Update
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
core update ai --gga
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Source cloned to `$OMNI_DATA/gga-termux/` (`~/.local/share/omni-data/gga-termux/`)
|
|
45
|
+
- Binary installed to `$PREFIX/bin/gga`
|
|
46
|
+
- Libraries installed to `$PREFIX/share/gga/lib/`
|
|
47
|
+
- Clones the Termux-compatible fork and runs its bundled `install.sh` / `uninstall.sh`
|
|
48
|
+
- Repository is updated via `git pull` on `core update ai --gga`
|
|
49
|
+
- Requires the gga repo to be present at runtime only during install/update (can be safely removed afterward)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
import "@/utils/log"
|
|
4
|
+
import "@/utils/colors"
|
|
5
|
+
|
|
6
|
+
LOG_FILE="$OMNI_CACHE/install_ai.log"
|
|
7
|
+
GGA_DATA_DIR="$OMNI_DATA/gga-termux"
|
|
8
|
+
|
|
9
|
+
_gga_dependencies() {
|
|
10
|
+
loading "Installing dependencies" _gga_dependencies_impl
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
_gga_dependencies_impl() {
|
|
14
|
+
declare -A DEPS=(
|
|
15
|
+
["git"]="git"
|
|
16
|
+
["curl"]="curl"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
local pkg_name bin_name
|
|
20
|
+
for pkg_name in "${!DEPS[@]}"; do
|
|
21
|
+
bin_name="${DEPS[$pkg_name]}"
|
|
22
|
+
if ! command -v "$bin_name" &>/dev/null; then
|
|
23
|
+
if ! pkg install "$pkg_name" -y &>>"$LOG_FILE"; then
|
|
24
|
+
log_error "Failed to install $pkg_name"
|
|
25
|
+
return 1
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
return 0
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_gga_clone_or_update_repo() {
|
|
34
|
+
loading "Cloning or updating gga-termux repo" _gga_clone_or_update_repo_impl
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_gga_clone_or_update_repo_impl() {
|
|
38
|
+
local repo_url="https://github.com/israel676767/gga-termux.git"
|
|
39
|
+
|
|
40
|
+
if [ -d "$GGA_DATA_DIR/.git" ]; then
|
|
41
|
+
if ! git -C "$GGA_DATA_DIR" pull --ff-only &>>"$LOG_FILE"; then
|
|
42
|
+
log_error "Failed to update gga-termux repo"
|
|
43
|
+
return 1
|
|
44
|
+
fi
|
|
45
|
+
else
|
|
46
|
+
mkdir -p "$(dirname "$GGA_DATA_DIR")"
|
|
47
|
+
if ! git clone "$repo_url" "$GGA_DATA_DIR" &>>"$LOG_FILE"; then
|
|
48
|
+
log_error "Failed to clone gga-termux repo"
|
|
49
|
+
return 1
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
return 0
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_gga_run_installer() {
|
|
57
|
+
loading "Running gga-termux installer" _gga_run_installer_impl
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_gga_run_installer_impl() {
|
|
61
|
+
if [ ! -d "$GGA_DATA_DIR" ] || [ ! -f "$GGA_DATA_DIR/install.sh" ]; then
|
|
62
|
+
log_error "gga-termux repo not found at $GGA_DATA_DIR"
|
|
63
|
+
return 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if ! (cd "$GGA_DATA_DIR" && bash ./install.sh < /dev/null) &>>"$LOG_FILE"; then
|
|
67
|
+
log_error "gga-termux install.sh failed (see $LOG_FILE)"
|
|
68
|
+
return 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
return 0
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
install_gga() {
|
|
75
|
+
if command -v gga &>/dev/null; then
|
|
76
|
+
log_info "GGA is already installed"
|
|
77
|
+
return 2
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
log_info "Installing GGA..."
|
|
81
|
+
|
|
82
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
83
|
+
|
|
84
|
+
_gga_dependencies || return 1
|
|
85
|
+
_gga_clone_or_update_repo || return 1
|
|
86
|
+
_gga_run_installer || return 1
|
|
87
|
+
|
|
88
|
+
log_success "GGA installed"
|
|
89
|
+
return 0
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
uninstall_gga() {
|
|
93
|
+
if ! command -v gga &>/dev/null; then
|
|
94
|
+
log_info "GGA is not installed"
|
|
95
|
+
return 2
|
|
96
|
+
fi
|
|
97
|
+
log_info "Uninstalling GGA..."
|
|
98
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
99
|
+
|
|
100
|
+
if [ -d "$GGA_DATA_DIR" ] && [ -f "$GGA_DATA_DIR/uninstall.sh" ]; then
|
|
101
|
+
log_info "Running gga-termux uninstaller..."
|
|
102
|
+
if ! (cd "$GGA_DATA_DIR" && printf "n\n" | bash ./uninstall.sh) &>>"$LOG_FILE"; then
|
|
103
|
+
log_warn "gga-termux uninstall.sh failed, falling back to manual cleanup"
|
|
104
|
+
fi
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
rm -f "$PREFIX/bin/gga"
|
|
108
|
+
rm -rf "$PREFIX/share/gga"
|
|
109
|
+
rm -rf "$GGA_DATA_DIR"
|
|
110
|
+
|
|
111
|
+
if [ ! -f "$PREFIX/bin/gga" ] && [ ! -d "$GGA_DATA_DIR" ]; then
|
|
112
|
+
log_success "GGA uninstalled"
|
|
113
|
+
return 0
|
|
114
|
+
else
|
|
115
|
+
log_error "Failed to uninstall GGA"
|
|
116
|
+
return 1
|
|
117
|
+
fi
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
update_gga() {
|
|
121
|
+
log_info "Updating GGA..."
|
|
122
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
123
|
+
|
|
124
|
+
_gga_clone_or_update_repo || return 1
|
|
125
|
+
_gga_run_installer || return 1
|
|
126
|
+
|
|
127
|
+
log_success "GGA updated"
|
|
128
|
+
return 0
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
reinstall_gga() {
|
|
132
|
+
uninstall_gga
|
|
133
|
+
install_gga
|
|
134
|
+
}
|