[IMPROVED] Refactorizado sora.sh para seguir estándares del proyecto

- Modificado formato de header según convenciones del proyecto

- Implementada estructura modular con funciones bien definidas

- Mejorado manejo de errores y validaciones

- Añadida documentación interna siguiendo guías de estilo

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Mauro Rosero P. 2025-04-07 20:35:31 -05:00
parent 97a965417e
commit 9ef1dd4c25
Signed by: mrosero
GPG key ID: 83BD2A5F674B7E26

View file

@ -1,104 +1,232 @@
#!/bin/bash
# [Author] Cortana Rosero One <cortana@rosero.one>
# [Generated] Created by Claude Code (claude-3-7-sonnet-20250219)
# Modified Date: 2025-04-07
# Version $(cat "$(dirname "$0")/config/version" 2>/dev/null || echo "1.0.0")
#Script : sora.sh
#Apps : MRDEVS TOOLS
#Description : Ejecuta aider con configuración de OpenRouter/Ollama
#Author : Sora Rosero One <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 : $(cat "$(dirname "$0")/config/version" 2>/dev/null || echo "1.0.0")
#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. <mauro@rosero.one>]
#==============================================================================
# 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.
#
# Description: Script para ejecutar aider con la configuración adecuada de OpenRouter
# Usage: ./sora.sh [parámetros para aider]
# 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 <https://www.gnu.org/licenses/>.
# Verifica si aider está instalado
if ! command -v aider &> /dev/null; then
echo "Error: aider no está instalado."
echo "Instálelo ejecutando: bin/sora_install.sh"
# 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
# Obtiene la ruta base de tokens desde el archivo de configuración
TOKENS_BASE_PATH=$(cat "$(dirname "$0")/config/ai_tokens.path" 2>/dev/null)
if [ -z "$TOKENS_BASE_PATH" ]; then
echo "Error: No se pudo obtener la ruta base de tokens."
exit 1
fi
# Mensaje de bienvenida
echo "=== Sora - Asistente de Desarrollo Colaborativo ==="
echo "Versión: $VERSION"
echo ""
# Expande la ruta si comienza con ~
if [[ "$TOKENS_BASE_PATH" == "~"* ]]; then
TOKENS_BASE_PATH="${TOKENS_BASE_PATH/#\~/$HOME}"
fi
# 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
}
# Define el archivo de tokens de OpenRouter
OPENROUTER_TOKEN_FILE="${TOKENS_BASE_PATH}/router.sops.yaml"
# Verifica si el archivo de token existe
if [ ! -f "$OPENROUTER_TOKEN_FILE" ]; then
echo "Error: Archivo de token no encontrado: $OPENROUTER_TOKEN_FILE"
echo "Registre su token usando ai_token.sh o solicite el token al administrador del proyecto."
exit 1
fi
# Desencripta y obtiene el token de OpenRouter (decodificando base64)
OPENROUTER_API_KEY=$(sops -d "$OPENROUTER_TOKEN_FILE" | cut -d\| -f2 | tr -d '[:space:]' | base64 -d)
if [ -z "$OPENROUTER_API_KEY" ]; then
echo "Error: No se pudo desencriptar el token de OpenRouter."
exit 1
fi
# Lee o crea el archivo de configuración de la API base
API_BASE_CONFIG_FILE="$(dirname "$0")/config/sora_api_base.cfg"
if [ ! -f "$API_BASE_CONFIG_FILE" ]; then
echo "https://openrouter.ai/api/v1" > "$API_BASE_CONFIG_FILE"
fi
OPENAI_API_BASE=$(cat "$API_BASE_CONFIG_FILE" 2>/dev/null || echo "https://openrouter.ai/api/v1")
# Lee o crea el archivo de configuración del modelo
MODEL_CONFIG_FILE="$(dirname "$0")/config/sora_model.cfg"
if [ ! -f "$MODEL_CONFIG_FILE" ]; then
echo "deepseek/deepseek-r1-distill-llama-70b:free" > "$MODEL_CONFIG_FILE"
fi
AIDER_MODEL=$(cat "$MODEL_CONFIG_FILE" 2>/dev/null || echo "deepseek/deepseek-r1-distill-llama-70b:free")
# Pregunta al usuario si desea usar modelo remoto o local (ollama)
MODE=$(gum choose "Remoto (OpenRouter)" "Local (Ollama)")
if [[ "$MODE" == "Local (Ollama)" ]]; then
# Muestra 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."
# Obtener ruta de tokens
get_tokens_path() {
local tokens_path_file="$SCRIPT_DIR/$BIN_CFGS/ai_tokens.path"
local tokens_path
# Evalúa el hardware de la máquina
CPU_CORES=$(nproc)
RAM_TOTAL_GB=$(free -g | awk '/^Mem:/{print $2}')
RAM_AVAILABLE_GB=$(free -g | awk '/^Mem:/{print $7}')
HAS_GPU=$(lspci | grep -i nvidia | grep -v "Audio\|USB" || echo "")
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
# Determina nivel de rendimiento
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"
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
# Muestra estado del hardware
echo ""
echo "Evaluación de hardware:"
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")"
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
# Muestra barra de rendimiento con gum
echo ""
echo -n "Rendimiento esperado: "
case "$PERFORMANCE_LEVEL" in
case "$level" in
"Muy Malo")
gum style --foreground 255 --background 1 " Muy Malo "
;;
@ -122,76 +250,94 @@ if [[ "$MODE" == "Local (Ollama)" ]]; then
;;
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"
# Pregunta si desea continuar
# 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
# 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..."
"$(dirname "$0")/ollama_up.sh"
# Espera hasta 30 segundos para que Ollama se inicie completamente
WAIT_TIME=0
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."
exit 1
fi
echo "Esperando que Ollama responda... ($WAIT_TIME/$MAX_WAIT)"
sleep 1
WAIT_TIME=$((WAIT_TIME + 1))
done
OLLAMA_STARTED=true
fi
# Iniciar Ollama si es necesario
start_ollama
OLLAMA_STARTED=$?
# Verifica que Ollama funcione correctamente haciendo una solicitud simple
# 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
# Configura para usar Ollama
OLLAMA_API_BASE=$(cat "$(dirname "$0")/config/ollama.local" 2>/dev/null)
# 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"
# Lista y permite seleccionar modelos disponibles en Ollama
echo "Consultando modelos disponibles en Ollama..."
OLLAMA_MODELS=$(curl -s http://127.0.0.1:11434/api/tags | jq -r '.models[].name')
if [ -z "$OLLAMA_MODELS" ]; then
echo "Error: No se encontraron modelos en Ollama."
exit 1
fi
# Permite seleccionar un modelo utilizando gum
echo "Seleccione un modelo:"
SELECTED_MODEL=$(echo "$OLLAMA_MODELS" | gum filter --placeholder="Buscar modelo...")
# Seleccionar modelo
SELECTED_MODEL=$(select_ollama_model)
if [ -z "$SELECTED_MODEL" ]; then
echo "No se seleccionó ningún modelo. Saliendo."
exit 1
fi
echo "Modelo seleccionado: $SELECTED_MODEL"
# Añade el prefijo al modelo de Ollama
# Añadir prefijo
OLLAMA_FULL_MODEL="ollama_chat/$SELECTED_MODEL"
echo "Modelo con prefijo: $OLLAMA_FULL_MODEL"
# Ejecuta aider con la configuración de Ollama
# 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" = true ]; then
if [ "$OLLAMA_STARTED" -eq 0 ]; then
echo "Deteniendo Ollama..."
"$(dirname "$0")/ollama_down.sh"
"$SCRIPT_DIR/ollama_down.sh"
fi
}
# Ejecución principal según el modo seleccionado
if [[ "$MODE" == "Local (Ollama)" ]]; then
run_local_aider "$@"
else
# Ejecuta aider con la configuración de OpenRouter
OPENAI_API_BASE="$OPENAI_API_BASE" OPENROUTER_API_KEY="$OPENROUTER_API_KEY" AIDER_MODEL="$AIDER_MODEL" aider --no-git --no-show-model-warnings "$@"
run_remote_aider "$@"
fi