mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-31 06:12:26 +00:00
feat: roolbac
This commit is contained in:
222
scripts/install-tfcode.sh
Normal file
222
scripts/install-tfcode.sh
Normal file
@@ -0,0 +1,222 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
APP=tfcode
|
||||
GITEA_HOST="${TFCODE_GITEA_HOST:-gitea.toothfairyai.com}"
|
||||
GITEA_REPO="${TFCODE_GITEA_REPO:-ToothFairyAI/tfcode}"
|
||||
|
||||
MUTED='\033[0;2m'
|
||||
RED='\033[0;31m'
|
||||
ORANGE='\033[38;5;214m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
tfcode Installer - ToothFairyAI's official coding agent
|
||||
|
||||
Usage: install.sh [options]
|
||||
|
||||
Options:
|
||||
-h, --help Display this help message
|
||||
-v, --version <version> Install a specific version (e.g., 1.0.0)
|
||||
--no-modify-path Don't modify shell config files
|
||||
|
||||
Examples:
|
||||
curl -fsSL https://toothfairyai.com/install/tfcode | bash
|
||||
curl -fsSL https://toothfairyai.com/install/tfcode | bash -s -- --version 1.0.0
|
||||
EOF
|
||||
}
|
||||
|
||||
requested_version=${VERSION:-}
|
||||
no_modify_path=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-v|--version)
|
||||
if [[ -n "${2:-}" ]]; then
|
||||
requested_version="$2"
|
||||
shift 2
|
||||
else
|
||||
echo -e "${RED}Error: --version requires a version argument${NC}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--no-modify-path)
|
||||
no_modify_path=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo -e "${ORANGE}Warning: Unknown option '$1'${NC}" >&2
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
INSTALL_DIR=$HOME/.tfcode/bin
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
|
||||
# Detect platform
|
||||
raw_os=$(uname -s)
|
||||
os=$(echo "$raw_os" | tr '[:upper:]' '[:lower:]')
|
||||
case "$raw_os" in
|
||||
Darwin*) os="darwin" ;;
|
||||
Linux*) os="linux" ;;
|
||||
MINGW*|MSYS*|CYGWIN*) os="windows" ;;
|
||||
esac
|
||||
|
||||
arch=$(uname -m)
|
||||
if [[ "$arch" == "aarch64" ]]; then arch="arm64"; fi
|
||||
if [[ "$arch" == "x86_64" ]]; then arch="x64"; fi
|
||||
|
||||
# Check Rosetta on macOS
|
||||
if [ "$os" = "darwin" ] && [ "$arch" = "x64" ]; then
|
||||
rosetta_flag=$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)
|
||||
if [ "$rosetta_flag" = "1" ]; then arch="arm64"; fi
|
||||
fi
|
||||
|
||||
# Check AVX2 on x64
|
||||
needs_baseline=false
|
||||
if [ "$arch" = "x64" ]; then
|
||||
if [ "$os" = "linux" ]; then
|
||||
if ! grep -qwi avx2 /proc/cpuinfo 2>/dev/null; then
|
||||
needs_baseline=true
|
||||
fi
|
||||
fi
|
||||
if [ "$os" = "darwin" ]; then
|
||||
avx2=$(sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0)
|
||||
if [ "$avx2" != "1" ]; then needs_baseline=true; fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check musl on Linux
|
||||
is_musl=false
|
||||
if [ "$os" = "linux" ]; then
|
||||
if [ -f /etc/alpine-release ]; then is_musl=true; fi
|
||||
if command -v ldd >/dev/null 2>&1; then
|
||||
if ldd --version 2>&1 | grep -qi musl; then is_musl=true; fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Build target
|
||||
target="$os-$arch"
|
||||
if [ "$needs_baseline" = "true" ]; then target="$target-baseline"; fi
|
||||
if [ "$is_musl" = "true" ]; then target="$target-musl"; fi
|
||||
|
||||
archive_ext=".zip"
|
||||
if [ "$os" = "linux" ]; then archive_ext=".tar.gz"; fi
|
||||
|
||||
filename="$APP-$target$archive_ext"
|
||||
|
||||
# Check tools
|
||||
if [ "$os" = "linux" ]; then
|
||||
if ! command -v tar >/dev/null 2>&1; then
|
||||
echo -e "${RED}Error: 'tar' is required but not installed.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if ! command -v unzip >/dev/null 2>&1; then
|
||||
echo -e "${RED}Error: 'unzip' is required but not installed.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get version
|
||||
if [ -z "$requested_version" ]; then
|
||||
# Get latest version from Gitea API
|
||||
api_url="https://$GITEA_HOST/api/v1/repos/$GITEA_REPO/releases/latest"
|
||||
specific_version=$(curl -s "$api_url" | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
|
||||
|
||||
if [[ $? -ne 0 || -z "$specific_version" ]]; then
|
||||
echo -e "${RED}Failed to fetch version information${NC}"
|
||||
exit 1
|
||||
fi
|
||||
url="https://$GITEA_HOST/$GITEA_REPO/releases/download/v${specific_version}/$filename"
|
||||
else
|
||||
requested_version="${requested_version#v}"
|
||||
url="https://$GITEA_HOST/$GITEA_REPO/releases/download/v${requested_version}/$filename"
|
||||
specific_version=$requested_version
|
||||
fi
|
||||
|
||||
# Download
|
||||
echo -e "${MUTED}Installing ${NC}tfcode ${MUTED}version: ${NC}$specific_version"
|
||||
tmp_dir="${TMPDIR:-/tmp}/tfcode_install_$$"
|
||||
mkdir -p "$tmp_dir"
|
||||
|
||||
echo -e "${MUTED}Downloading ${NC}$filename"
|
||||
curl -# -L -o "$tmp_dir/$filename" "$url"
|
||||
|
||||
# Extract
|
||||
echo -e "${MUTED}Extracting...${NC}"
|
||||
if [ "$os" = "linux" ]; then
|
||||
tar -xzf "$tmp_dir/$filename" -C "$tmp_dir"
|
||||
else
|
||||
unzip -q "$tmp_dir/$filename" -d "$tmp_dir"
|
||||
fi
|
||||
|
||||
# Install
|
||||
mv "$tmp_dir/tfcode" "$INSTALL_DIR"
|
||||
chmod 755 "${INSTALL_DIR}/tfcode"
|
||||
rm -rf "$tmp_dir"
|
||||
|
||||
# Add to PATH
|
||||
add_to_path() {
|
||||
local config_file=$1
|
||||
local command=$2
|
||||
|
||||
if grep -Fxq "$command" "$config_file" 2>/dev/null; then
|
||||
return
|
||||
elif [[ -w $config_file ]]; then
|
||||
echo -e "\n# tfcode" >> "$config_file"
|
||||
echo "$command" >> "$config_file"
|
||||
echo -e "${MUTED}Added tfcode to \$PATH in ${NC}$config_file"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$no_modify_path" != "true" ]]; then
|
||||
current_shell=$(basename "$SHELL")
|
||||
case $current_shell in
|
||||
fish) config_files="$HOME/.config/fish/config.fish" ;;
|
||||
zsh) config_files="$HOME/.zshrc $HOME/.zshenv" ;;
|
||||
bash) config_files="$HOME/.bashrc $HOME/.bash_profile $HOME/.profile" ;;
|
||||
*) config_files="$HOME/.profile" ;;
|
||||
esac
|
||||
|
||||
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
|
||||
for file in $config_files; do
|
||||
if [[ -f $file ]]; then
|
||||
add_to_path "$file" "export PATH=$INSTALL_DIR:\$PATH"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install Python SDK
|
||||
echo ""
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
echo -e "${MUTED}Installing ToothFairyAI Python SDK...${NC}"
|
||||
python3 -m pip install --user --break-system-packages toothfairyai pydantic httpx rich 2>/dev/null || \
|
||||
python3 -m pip install --user toothfairyai pydantic httpx rich 2>/dev/null || \
|
||||
echo -e "${ORANGE}Could not install Python SDK. Run manually:${NC}"
|
||||
echo -e " ${MUTED}pip install toothfairyai pydantic httpx rich${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo -e "${GREEN}✓ tfcode installed successfully!${NC}"
|
||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||
echo ""
|
||||
echo -e "${MUTED}Quick Start:${NC}"
|
||||
echo ""
|
||||
echo -e " ${ORANGE}tfcode setup${NC} ${MUTED}Interactive credential setup${NC}"
|
||||
echo -e " ${ORANGE}tfcode validate${NC} ${MUTED}Test your credentials${NC}"
|
||||
echo -e " ${ORANGE}tfcode sync${NC} ${MUTED}Sync tools from workspace${NC}"
|
||||
echo -e " ${ORANGE}tfcode${NC} ${MUTED}Start coding assistant${NC}"
|
||||
echo ""
|
||||
echo -e "${MUTED}Documentation: https://toothfairyai.com/developers/tfcode${NC}"
|
||||
echo ""
|
||||
Reference in New Issue
Block a user