| 1 | #!/bin/bash |
| 2 | # Parrot post-installation setup script |
| 3 | # This script provides guided setup for backend configuration |
| 4 | |
| 5 | set -e |
| 6 | |
| 7 | # Colors for output |
| 8 | RED='\033[0;31m' |
| 9 | GREEN='\033[0;32m' |
| 10 | YELLOW='\033[1;33m' |
| 11 | BLUE='\033[0;34m' |
| 12 | PURPLE='\033[0;35m' |
| 13 | NC='\033[0m' # No Color |
| 14 | |
| 15 | # Configuration |
| 16 | PARROT_BIN="/usr/bin/parrot" |
| 17 | CONFIG_DIR="$HOME/.config/parrot" |
| 18 | CONFIG_FILE="$CONFIG_DIR/parrot.toml" |
| 19 | EXAMPLE_CONFIG="/etc/parrot/parrot.toml.example" |
| 20 | |
| 21 | # Helper functions |
| 22 | print_header() { |
| 23 | echo -e "${BLUE}🦜 Parrot Setup Assistant${NC}" |
| 24 | echo -e "${BLUE}=========================${NC}" |
| 25 | echo |
| 26 | } |
| 27 | |
| 28 | print_success() { |
| 29 | echo -e "${GREEN}✓${NC} $1" |
| 30 | } |
| 31 | |
| 32 | print_warning() { |
| 33 | echo -e "${YELLOW}⚠${NC} $1" |
| 34 | } |
| 35 | |
| 36 | print_error() { |
| 37 | echo -e "${RED}✗${NC} $1" |
| 38 | } |
| 39 | |
| 40 | print_info() { |
| 41 | echo -e "${BLUE}ℹ${NC} $1" |
| 42 | } |
| 43 | |
| 44 | check_command() { |
| 45 | command -v "$1" >/dev/null 2>&1 |
| 46 | } |
| 47 | |
| 48 | detect_backends() { |
| 49 | local backends=() |
| 50 | |
| 51 | # Check for Ollama |
| 52 | if check_command ollama && ollama list >/dev/null 2>&1; then |
| 53 | backends+=("local") |
| 54 | print_success "Ollama detected and running" |
| 55 | else |
| 56 | print_warning "Ollama not found or not running" |
| 57 | fi |
| 58 | |
| 59 | # Check for API key environment variable |
| 60 | if [[ -n "${PARROT_API_KEY:-}" ]] || [[ -n "${OPENAI_API_KEY:-}" ]]; then |
| 61 | backends+=("api") |
| 62 | print_success "API key detected in environment" |
| 63 | else |
| 64 | print_warning "No API keys found in environment" |
| 65 | fi |
| 66 | |
| 67 | # Fallback is always available |
| 68 | backends+=("fallback") |
| 69 | print_success "Fallback backend available" |
| 70 | |
| 71 | echo "${backends[@]}" |
| 72 | } |
| 73 | |
| 74 | setup_config_dir() { |
| 75 | if [[ ! -d "$CONFIG_DIR" ]]; then |
| 76 | mkdir -p "$CONFIG_DIR" |
| 77 | print_success "Created configuration directory: $CONFIG_DIR" |
| 78 | fi |
| 79 | } |
| 80 | |
| 81 | create_basic_config() { |
| 82 | local backend_priority="$1" |
| 83 | local personality="${2:-sarcastic}" |
| 84 | |
| 85 | cat > "$CONFIG_FILE" << EOF |
| 86 | # Parrot Configuration |
| 87 | # Generated by post-install setup |
| 88 | |
| 89 | backend_priority = ["$backend_priority"] |
| 90 | personality = "$personality" |
| 91 | colors = true |
| 92 | |
| 93 | [shell] |
| 94 | enabled = true |
| 95 | |
| 96 | [advanced] |
| 97 | debug = false |
| 98 | cache_enabled = true |
| 99 | EOF |
| 100 | |
| 101 | print_success "Created basic configuration: $CONFIG_FILE" |
| 102 | } |
| 103 | |
| 104 | setup_ollama() { |
| 105 | print_info "Setting up Ollama backend..." |
| 106 | |
| 107 | if ! check_command ollama; then |
| 108 | print_error "Ollama is not installed" |
| 109 | echo "To install Ollama:" |
| 110 | echo " curl -fsSL https://ollama.com/install.sh | sh" |
| 111 | echo |
| 112 | return 1 |
| 113 | fi |
| 114 | |
| 115 | if ! ollama list >/dev/null 2>&1; then |
| 116 | print_warning "Ollama service is not running" |
| 117 | echo "To start Ollama:" |
| 118 | echo " systemctl --user enable ollama" |
| 119 | echo " systemctl --user start ollama" |
| 120 | echo |
| 121 | return 1 |
| 122 | fi |
| 123 | |
| 124 | # Check if phi3.5 model is available |
| 125 | if ! ollama list | grep -q "phi3.5:3.8b"; then |
| 126 | print_info "Downloading phi3.5:3.8b model (this may take a few minutes)..." |
| 127 | if ollama pull phi3.5:3.8b; then |
| 128 | print_success "Downloaded phi3.5:3.8b model" |
| 129 | else |
| 130 | print_error "Failed to download model" |
| 131 | return 1 |
| 132 | fi |
| 133 | else |
| 134 | print_success "phi3.5:3.8b model already available" |
| 135 | fi |
| 136 | |
| 137 | return 0 |
| 138 | } |
| 139 | |
| 140 | setup_api_backend() { |
| 141 | print_info "Setting up API backend..." |
| 142 | |
| 143 | if [[ -n "${PARROT_API_KEY:-}" ]]; then |
| 144 | print_success "Using PARROT_API_KEY from environment" |
| 145 | return 0 |
| 146 | elif [[ -n "${OPENAI_API_KEY:-}" ]]; then |
| 147 | print_success "Using OPENAI_API_KEY from environment" |
| 148 | return 0 |
| 149 | else |
| 150 | print_warning "No API key found in environment" |
| 151 | echo "To use API backend, set one of:" |
| 152 | echo " export PARROT_API_KEY='your-api-key'" |
| 153 | echo " export OPENAI_API_KEY='your-api-key'" |
| 154 | echo |
| 155 | echo "Or configure it in: $CONFIG_FILE" |
| 156 | return 1 |
| 157 | fi |
| 158 | } |
| 159 | |
| 160 | setup_shell_integration() { |
| 161 | print_info "Shell integration will be configured when you run 'parrot setup'" |
| 162 | print_info "This enables automatic command failure detection" |
| 163 | } |
| 164 | |
| 165 | interactive_setup() { |
| 166 | print_header |
| 167 | |
| 168 | echo "Welcome to Parrot! Let's set up your intelligent CLI assistant." |
| 169 | echo |
| 170 | |
| 171 | # Detect available backends |
| 172 | print_info "Detecting available backends..." |
| 173 | local available_backends |
| 174 | available_backends=($(detect_backends)) |
| 175 | echo |
| 176 | |
| 177 | # Choose personality |
| 178 | echo "Choose your parrot's personality:" |
| 179 | echo " 1) mild - Gentle and helpful" |
| 180 | echo " 2) sarcastic - Witty with attitude (recommended)" |
| 181 | echo " 3) savage - Brutally honest" |
| 182 | echo |
| 183 | read -p "Select personality [1-3, default: 2]: " personality_choice |
| 184 | |
| 185 | local personality="sarcastic" |
| 186 | case ${personality_choice:-2} in |
| 187 | 1) personality="mild" ;; |
| 188 | 2) personality="sarcastic" ;; |
| 189 | 3) personality="savage" ;; |
| 190 | *) personality="sarcastic" ;; |
| 191 | esac |
| 192 | |
| 193 | # Choose backend |
| 194 | echo |
| 195 | echo "Choose your preferred backend:" |
| 196 | local backend_options=() |
| 197 | local backend_descriptions=() |
| 198 | |
| 199 | if [[ " ${available_backends[@]} " =~ " local " ]]; then |
| 200 | backend_options+=("local") |
| 201 | backend_descriptions+=("Local AI (Ollama) - Private and fast") |
| 202 | fi |
| 203 | |
| 204 | if [[ " ${available_backends[@]} " =~ " api " ]]; then |
| 205 | backend_options+=("api") |
| 206 | backend_descriptions+=("API Backend - Requires API key, highest quality") |
| 207 | fi |
| 208 | |
| 209 | backend_options+=("fallback") |
| 210 | backend_descriptions+=("Fallback - Built-in responses, no setup required") |
| 211 | |
| 212 | for i in "${!backend_options[@]}"; do |
| 213 | echo " $((i+1))) ${backend_descriptions[i]}" |
| 214 | done |
| 215 | |
| 216 | echo |
| 217 | read -p "Select backend [1-${#backend_options[@]}, default: 1]: " backend_choice |
| 218 | |
| 219 | local selected_backend="${backend_options[$((${backend_choice:-1}-1))]}" |
| 220 | |
| 221 | # Set up configuration |
| 222 | setup_config_dir |
| 223 | create_basic_config "$selected_backend" "$personality" |
| 224 | |
| 225 | # Backend-specific setup |
| 226 | case "$selected_backend" in |
| 227 | "local") |
| 228 | if ! setup_ollama; then |
| 229 | print_warning "Ollama setup incomplete, falling back to basic responses" |
| 230 | create_basic_config "fallback" "$personality" |
| 231 | fi |
| 232 | ;; |
| 233 | "api") |
| 234 | if ! setup_api_backend; then |
| 235 | print_warning "API setup incomplete, you'll need to configure it manually" |
| 236 | fi |
| 237 | ;; |
| 238 | "fallback") |
| 239 | print_success "Fallback backend configured - no additional setup required" |
| 240 | ;; |
| 241 | esac |
| 242 | |
| 243 | # Shell integration |
| 244 | echo |
| 245 | setup_shell_integration |
| 246 | |
| 247 | echo |
| 248 | print_success "Parrot setup complete!" |
| 249 | echo |
| 250 | echo "Next steps:" |
| 251 | echo " 1. Run 'parrot setup' to enable shell integration" |
| 252 | echo " 2. Try 'parrot mock \"git push\" 1' to test it out" |
| 253 | echo " 3. Run 'parrot configure' to adjust settings" |
| 254 | echo |
| 255 | echo "For help: parrot --help" |
| 256 | print_info "Configuration file: $CONFIG_FILE" |
| 257 | } |
| 258 | |
| 259 | # Main execution |
| 260 | main() { |
| 261 | # Check if running interactively |
| 262 | if [[ -t 0 && -t 1 ]]; then |
| 263 | # Interactive mode |
| 264 | interactive_setup |
| 265 | else |
| 266 | # Non-interactive mode (RPM post-install) |
| 267 | print_header |
| 268 | echo "Parrot has been installed successfully!" |
| 269 | echo |
| 270 | echo "To complete setup, run:" |
| 271 | echo " parrot setup" |
| 272 | echo |
| 273 | echo "This will guide you through backend configuration and shell integration." |
| 274 | echo |
| 275 | print_info "For manual configuration, see: $EXAMPLE_CONFIG" |
| 276 | fi |
| 277 | } |
| 278 | |
| 279 | # Run main function |
| 280 | main "$@" |