From 6471075cc598a6e4271df52410900fafb6a33557 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Thu, 16 Apr 2026 12:48:36 -0400 Subject: [PATCH] feat: Robust interactive prompts and error handling in installer --- scripts/onboard-baremetal.sh | 58 +++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/scripts/onboard-baremetal.sh b/scripts/onboard-baremetal.sh index 3092ef0..908e20e 100755 --- a/scripts/onboard-baremetal.sh +++ b/scripts/onboard-baremetal.sh @@ -1,8 +1,31 @@ #!/bin/bash set -e -RED='\033[0;31m'; GREEN='\033[0;32m'; BLUE='\033[0;34m'; NC='\033[0m' +RED='\033[0;31m'; GREEN='\033[0;32m'; BLUE='\033[0;34m'; YELLOW='\033[0;33m'; NC='\033[0m' -echo -e "${BLUE}=== opencortex: Baremetal Power-User Setup ===${NC}" +echo -e "${BLUE}=== OpenCortex: Baremetal Power-User Setup ===${NC}" + +# Helper for robust input +prompt_user() { + local prompt="$1" + local default="$2" + local var_name="$3" + local result="" + + # Try reading from /dev/tty, fallback to stdin, fallback to default + if [ -t 0 ]; then + read -p "$prompt (default: $default): " result + else + # If piped, try /dev/tty explicitly + if read -p "$prompt (default: $default): " result < /dev/tty 2>/dev/null; then + : + else + result="" + fi + fi + + val=${result:-$default} + eval "$var_name=\"$val\"" +} # 1. Dependency Management install_deps() { @@ -22,8 +45,8 @@ install_deps() { if ! command -v sbcl >/dev/null 2>&1 || ! command -v emacs >/dev/null 2>&1; then echo -e "${YELLOW}! Missing dependencies (SBCL/Emacs).${NC}" - read -p "Should I attempt to install them for you? [Y/n]: " INSTALL_CHOICE < /dev/tty - if [[ ! "$INSTALL_CHOICE" =~ ^[Nn]$ ]]; then + prompt_user "Should I attempt to install them for you? [Y/n]" "y" "DO_INSTALL" + if [[ ! "$DO_INSTALL" =~ ^[Nn]$ ]]; then install_deps else echo -e "${RED}✗ Dependencies required. Exiting.${NC}" @@ -34,8 +57,8 @@ fi # 2. Quicklisp Installation if [ ! -d "$HOME/quicklisp" ] && [ ! -d "$HOME/.quicklisp" ]; then echo -e "${YELLOW}! Quicklisp not found.${NC}" - read -p "Install Quicklisp now? [Y/n]: " QL_CHOICE < /dev/tty - if [[ ! "$QL_CHOICE" =~ ^[Nn]$ ]]; then + prompt_user "Install Quicklisp now? [Y/n]" "y" "DO_QL" + if [[ ! "$DO_QL" =~ ^[Nn]$ ]]; then curl -O https://beta.quicklisp.org/quicklisp.lisp sbcl --non-interactive --load quicklisp.lisp \ --eval "(quicklisp-quickstart:install)" \ @@ -47,8 +70,7 @@ fi # 3. Literate Tangling echo -e "${BLUE}Tangling Literate Org files into source code...${NC}" -# Use || true because Emacs might return non-zero on warnings, but we only care if src/ actually gets populated -emacs --batch --eval "(require 'org)" --eval "(mapc 'org-babel-tangle-file (file-expand-wildcards \"literate/*.org\"))" || echo -e "${YELLOW}! Emacs finished with warnings.${NC}" +emacs --batch --eval "(require 'org)" --eval "(mapc 'org-babel-tangle-file (file-expand-wildcards \"literate/*.org\"))" || true if [ ! -f "src/package.lisp" ]; then echo -e "${RED}✗ Tangling failed. Source files not generated.${NC}" @@ -59,23 +81,25 @@ echo -e "${GREEN}✓ Core tangled.${NC}" # 4. Environment Configuration if [ ! -f .env ]; then cp .env.example .env; fi -read -p "What is your name? (default: User): " USER_NAME < /dev/tty -USER_NAME=${USER_NAME:-User} +# Disable exit-on-error for the interactive part to ensure we don't crash +set +e +prompt_user "What is your name?" "User" "USER_NAME" sed -i "s/MEMEX_USER=.*/MEMEX_USER=\"$USER_NAME\"/g" .env -read -p "What shall we name your Assistant? (default: OpenCortex): " AGENT_NAME < /dev/tty -AGENT_NAME=${AGENT_NAME:-OpenCortex} +prompt_user "What shall we name your Assistant?" "OpenCortex" "AGENT_NAME" sed -i "s/MEMEX_ASSISTANT=.*/MEMEX_ASSISTANT=\"$AGENT_NAME\"/g" .env echo -e "\nSelect primary neural provider:" echo "1) Gemini (Free/Official)"; echo "2) OpenRouter"; echo "3) Anthropic"; echo "4) OpenAI" -read -p "Choice [1-4]: " LLM_CHOICE < /dev/tty +prompt_user "Choice [1-4]" "1" "LLM_CHOICE" + case $LLM_CHOICE in - 2) read -p "Enter OpenRouter Key: " INPUT < /dev/tty; sed -i "s/OPENROUTER_API_KEY=.*/OPENROUTER_API_KEY=\"$INPUT\"/g" .env ;; - 3) read -p "Enter Anthropic Key: " INPUT < /dev/tty; sed -i "s/ANTHROPIC_API_KEY=.*/ANTHROPIC_API_KEY=\"$INPUT\"/g" .env ;; - 4) read -p "Enter OpenAI Key: " INPUT < /dev/tty; sed -i "s/OPENAI_API_KEY=.*/OPENAI_API_KEY=\"$INPUT\"/g" .env ;; - *) read -p "Enter Gemini Key: " INPUT < /dev/tty; sed -i "s/GEMINI_API_KEY=.*/GEMINI_API_KEY=\"$INPUT\"/g" .env ;; + 2) prompt_user "Enter OpenRouter Key" "" "INPUT"; sed -i "s/OPENROUTER_API_KEY=.*/OPENROUTER_API_KEY=\"$INPUT\"/g" .env ;; + 3) prompt_user "Enter Anthropic Key" "" "INPUT"; sed -i "s/ANTHROPIC_API_KEY=.*/ANTHROPIC_API_KEY=\"$INPUT\"/g" .env ;; + 4) prompt_user "Enter OpenAI Key" "" "INPUT"; sed -i "s/OPENAI_API_KEY=.*/OPENAI_API_KEY=\"$INPUT\"/g" .env ;; + *) prompt_user "Enter Gemini Key" "" "INPUT"; sed -i "s/GEMINI_API_KEY=.*/GEMINI_API_KEY=\"$INPUT\"/g" .env ;; esac +set -e # 5. Path Alignment PROJECT_ROOT=$(pwd)