package services import ( "fmt" "strings" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" ) // CompletarTextoIA hace una llamada simple (sin tools, sin streaming) al // proveedor configurado para el servicio dado y devuelve el texto. // // Reusa callAI, que es el mismo despachador del bot de Telegram: sabe hablar // Anthropic y OpenAI-compatible, y completa la URL base cuando la config la // tiene vacía. Escribir una segunda implementación acá fue un error: no // soportaba Anthropic y armaba una URL relativa cuando faltaba la base, así // que fallaba con la config que ya estaba en producción. func CompletarTextoIA(servicio, sistema, usuario string) (string, error) { config, err := models.GetAiConfigForService(servicio) if err != nil { return "", fmt.Errorf("no hay configuración de IA activa; configurá una en /app/ai-config") } if strings.TrimSpace(config.ModelName) == "" { return "", fmt.Errorf("la configuración de IA %q no tiene modelo definido (/app/ai-config)", config.Nombre) } msg, _, err := callAI(config, []agentMessage{ {Role: "system", Content: sistema}, {Role: "user", Content: usuario}, }, nil) if err != nil { return "", fmt.Errorf("%s (%s): %w", config.Nombre, config.Provider, err) } texto, _ := msg.Content.(string) if strings.TrimSpace(texto) == "" { return "", fmt.Errorf("%s no devolvió texto", config.Nombre) } return texto, nil } // ProbarAiConfig manda una consulta mínima a una configuración concreta y // devuelve lo que contestó. // // A diferencia de CompletarTextoIA, no resuelve la config por módulo: recibe la // que hay que probar. Es lo que necesita alguien que acaba de cargar su cuenta // y quiere saber si la clave sirve, antes de que lo descubra un cliente real. func ProbarAiConfig(cfg *models.AiConfig) (string, error) { if cfg == nil { return "", fmt.Errorf("no hay configuración que probar") } if strings.TrimSpace(cfg.ModelName) == "" { return "", fmt.Errorf("falta el modelo en esta configuración") } msg, _, err := callAI(cfg, []agentMessage{ {Role: "system", Content: "Respondé con una sola palabra."}, {Role: "user", Content: "Decí \"listo\" si me estás leyendo."}, }, nil) if err != nil { return "", fmt.Errorf("%s rechazó la consulta: %w", cfg.Provider, err) } texto, _ := msg.Content.(string) if strings.TrimSpace(texto) == "" { return "", fmt.Errorf("%s respondió, pero sin texto: revisá el modelo", cfg.Provider) } return strings.TrimSpace(texto), nil }