#!/bin/bash #Script : sora.sh #Apps : MRDEVS TOOLS #Description : Ejecuta aider con configuración de OpenRouter/Ollama #Author : Sora Rosero One #Generated by : Claude Code (claude-3-7-sonnet-20250219) #Created : 2025/04/07 10:23:45 #Modified : 2025/04/07 12:10:30 #Version : 1.3.1 #Use Notes : # Conecta con modelos de IA remotos (OpenRouter) o locales (Ollama) # Evalúa el hardware para ejecución local y muestra diagnóstico # Permite selección interactiva de modelos con gum #============================================================================== # Derechos de Autor [2025] [Mauro Rosero P. ] #============================================================================== # Este programa es software libre: usted puede redistribuirlo y/o modificarlo # bajo los términos de la Licencia Pública Affero General de GNU tal como # lo publica la Free Software Foundation, ya sea la versión 3 de la licencia, # o (a su elección) cualquier versión posterior. # # Este programa se distribuye con la esperanza de que sea útil, # pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de # COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la # Licencia Pública Affero General de GNU para obtener más detalles. # # Debería haber recibido una copia de la Licencia Pública Affero General # junto con este programa. Si no la recibió, consulte . # Configuración inicial SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BIN_BASE="bin" BIN_LIBS="lib" BIN_MESG="msg" BIN_CFGS="config" BIN_SOPS="sops" # Cargar bibliotecas if [ -f "$SCRIPT_DIR/../$BIN_LIBS/base.lib" ]; then source "$SCRIPT_DIR/../$BIN_LIBS/base.lib" else echo "Error: No se pudo cargar la biblioteca base." exit 1 fi # Mensaje de bienvenida echo "=== Sora - Asistente de Desarrollo Colaborativo ===" echo "Versión: $VERSION" echo "" # Verificar si aider está instalado check_aider() { if ! command -v aider &> /dev/null; then echo "Error: aider no está instalado." echo "Instálelo ejecutando: $BIN_BASE/sora_install.sh" exit 1 fi } # Obtener ruta de tokens get_tokens_path() { local tokens_path_file="$SCRIPT_DIR/$BIN_CFGS/ai_tokens.path" local tokens_path if [ -f "$tokens_path_file" ]; then tokens_path=$(cat "$tokens_path_file" 2>/dev/null) if [ -z "$tokens_path" ]; then echo "Error: Archivo de configuración de ruta de tokens vacío." exit 1 fi # Expandir ruta si comienza con ~ if [[ "$tokens_path" == "~"* ]]; then tokens_path="${tokens_path/#\~/$HOME}" fi echo "$tokens_path" else echo "Error: No se pudo encontrar el archivo de configuración de ruta de tokens." exit 1 fi } # Ejecutar verificaciones iniciales check_aider TOKENS_BASE_PATH=$(get_tokens_path) # Función para verificar y obtener tokens check_token() { local token_file=$1 local provider=$2 if [ ! -f "$token_file" ]; then echo "Error: Archivo de token no encontrado: $token_file" echo "Registre su token usando $BIN_BASE/ai_token.sh o solicite el token al administrador del proyecto." exit 1 fi local api_key api_key=$(sops -d "$token_file" | cut -d\| -f2 | tr -d '[:space:]' | base64 -d) if [ -z "$api_key" ]; then echo "Error: No se pudo desencriptar el token de $provider." exit 1 fi echo "$api_key" } # Función para cargar o crear configuración load_config() { local config_file=$1 local default_value=$2 local description=$3 if [ ! -f "$config_file" ]; then echo "Creando archivo de configuración para $description..." echo "$default_value" > "$config_file" fi local config_value config_value=$(cat "$config_file" 2>/dev/null || echo "$default_value") echo "$config_value" } # Función para evaluar hardware evaluate_hardware() { local cpu_cores=$(nproc) local ram_total_gb=$(free -g | awk '/^Mem:/{print $2}') local ram_available_gb=$(free -g | awk '/^Mem:/{print $7}') local has_gpu=$(lspci | grep -i nvidia | grep -v "Audio\|USB" || echo "") echo "CPU Cores: $cpu_cores" echo "RAM Total: $ram_total_gb GB" echo "RAM Disponible: $ram_available_gb GB" echo "GPU NVIDIA: $([ -n "$has_gpu" ] && echo "Detectada" || echo "No detectada")" # Determinar nivel de rendimiento local performance_level="Muy Malo" if [ -n "$has_gpu" ] && [ $cpu_cores -ge 8 ] && [ $ram_available_gb -ge 16 ]; then performance_level="Excelente" elif [ -n "$has_gpu" ] && [ $cpu_cores -ge 6 ] && [ $ram_available_gb -ge 12 ]; then performance_level="Muy Bueno" elif [ $cpu_cores -ge 8 ] && [ $ram_available_gb -ge 12 ]; then performance_level="Bueno" elif [ $cpu_cores -ge 6 ] && [ $ram_available_gb -ge 8 ]; then performance_level="Intermedio" elif [ $cpu_cores -ge 4 ] && [ $ram_available_gb -ge 6 ]; then performance_level="Pobre" elif [ $cpu_cores -ge 2 ] && [ $ram_available_gb -ge 4 ]; then performance_level="Malo" fi echo "$performance_level" } # Definir archivos de configuración OPENROUTER_TOKEN_FILE="${TOKENS_BASE_PATH}/router.sops.yaml" API_BASE_CONFIG_FILE="$SCRIPT_DIR/$BIN_CFGS/sora_api_base.cfg" MODEL_CONFIG_FILE="$SCRIPT_DIR/$BIN_CFGS/sora_model.cfg" # Cargar configuraciones OPENAI_API_BASE=$(load_config "$API_BASE_CONFIG_FILE" "https://openrouter.ai/api/v1" "API base") AIDER_MODEL=$(load_config "$MODEL_CONFIG_FILE" "deepseek/deepseek-r1-distill-llama-70b:free" "modelo predeterminado") # Verificar si gum está instalado if ! command -v gum &> /dev/null; then echo "Error: gum no está instalado." echo "Instálelo ejecutando: $BIN_BASE/bootstrap.sh" exit 1 fi # Preguntar al usuario por el modo a usar MODE=$(gum choose "Remoto (OpenRouter)" "Local (Ollama)") # Función para iniciar y comprobar Ollama start_ollama() { # Verifica si ollama está activo if ! curl -s http://127.0.0.1:11434/api/tags >/dev/null 2>&1; then echo "Ollama no está activo. Iniciando..." "$SCRIPT_DIR/ollama_up.sh" # Espera hasta 30 segundos para que Ollama se inicie completamente local wait_time=0 local max_wait=30 while ! curl -s http://127.0.0.1:11434/api/tags >/dev/null 2>&1; do if [ $wait_time -ge $max_wait ]; then echo "Error: No se pudo iniciar Ollama después de $max_wait segundos." return 1 fi echo "Esperando que Ollama responda... ($wait_time/$max_wait)" sleep 1 wait_time=$((wait_time + 1)) done return 0 fi return 2 # Ya estaba activo } # Función para seleccionar modelo de Ollama select_ollama_model() { echo "Consultando modelos disponibles en Ollama..." local models models=$(curl -s http://127.0.0.1:11434/api/tags | jq -r '.models[].name') if [ -z "$models" ]; then echo "Error: No se encontraron modelos en Ollama." return 1 fi echo "Seleccione un modelo:" local selected selected=$(echo "$models" | gum filter --placeholder="Buscar modelo...") if [ -z "$selected" ]; then echo "No se seleccionó ningún modelo." return 1 fi echo "$selected" } # Función para mostrar valoración de rendimiento show_performance_rating() { local level=$1 echo -n "Rendimiento esperado: " case "$level" in "Muy Malo") gum style --foreground 255 --background 1 " Muy Malo " ;; "Malo") gum style --foreground 255 --background 1 " Malo " ;; "Pobre") gum style --foreground 255 --background 202 " Pobre " ;; "Intermedio") gum style --foreground 255 --background 3 " Intermedio " ;; "Bueno") gum style --foreground 255 --background 35 " Bueno " ;; "Muy Bueno") gum style --foreground 255 --background 2 " Muy Bueno " ;; "Excelente") gum style --foreground 255 --background 5 " Excelente " ;; esac echo "" } # Función para ejecutar aider en modo remoto run_remote_aider() { echo "Modo: Remoto (OpenRouter)" echo "Modelo: $AIDER_MODEL" echo "API Base: $OPENAI_API_BASE" # Verificar y obtener token de OpenRouter OPENROUTER_API_KEY=$(check_token "$OPENROUTER_TOKEN_FILE" "OpenRouter") # Ejecutar aider OPENAI_API_BASE="$OPENAI_API_BASE" OPENROUTER_API_KEY="$OPENROUTER_API_KEY" AIDER_MODEL="$AIDER_MODEL" aider --no-git --no-show-model-warnings "$@" } # Función para ejecutar aider en modo local run_local_aider() { echo "Modo: Local (Ollama)" # Mostrar advertencia sobre rendimiento echo "⚠️ ADVERTENCIA: El uso de modelos locales requiere hardware adecuado." echo " Si su hardware no es suficiente, las respuestas pueden ser extremadamente lentas." # Evaluar hardware y mostrar información echo "" echo "Evaluación de hardware:" # Obtener datos de rendimiento HARDWARE_INFO=$(evaluate_hardware) # Extraer líneas individuales readarray -t hardware_lines <<< "$HARDWARE_INFO" # Mostrar información de hardware for ((i=0; i<${#hardware_lines[@]}-1; i++)); do echo "- ${hardware_lines[i]}" done # Mostrar valoración de rendimiento (última línea) echo "" show_performance_rating "${hardware_lines[${#hardware_lines[@]}-1]}" # Confirmar si desea continuar if ! gum confirm "¿Desea continuar con el modo local?"; then echo "Operación cancelada por el usuario." exit 0 fi # Iniciar Ollama si es necesario start_ollama OLLAMA_STARTED=$? # Verificar que Ollama funcione correctamente echo "Verificando que Ollama responda correctamente..." if ! curl -s http://127.0.0.1:11434/api/tags | jq -e '.models' >/dev/null 2>&1; then echo "Error: Ollama está iniciado pero no responde correctamente." exit 1 fi # Cargar API base OLLAMA_CONFIG_FILE="$SCRIPT_DIR/$BIN_CFGS/ollama.local" OLLAMA_API_BASE=$(cat "$OLLAMA_CONFIG_FILE" 2>/dev/null) echo "Usando Ollama con API base: $OLLAMA_API_BASE" # Seleccionar modelo SELECTED_MODEL=$(select_ollama_model) if [ -z "$SELECTED_MODEL" ]; then exit 1 fi echo "Modelo seleccionado: $SELECTED_MODEL" # Añadir prefijo OLLAMA_FULL_MODEL="ollama_chat/$SELECTED_MODEL" echo "Modelo con prefijo: $OLLAMA_FULL_MODEL" # Ejecutar aider OLLAMA_API_BASE="$OLLAMA_API_BASE" AIDER_MODEL="$OLLAMA_FULL_MODEL" aider --no-git --no-show-model-warnings "$@" # Si iniciamos Ollama, lo detenemos al finalizar if [ "$OLLAMA_STARTED" -eq 0 ]; then echo "Deteniendo Ollama..." "$SCRIPT_DIR/ollama_down.sh" fi } # Ejecución principal según el modo seleccionado if [[ "$MODE" == "Local (Ollama)" ]]; then run_local_aider "$@" else run_remote_aider "$@" fi