feat(ml): auto-commit con 14 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
package ml
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SdcliBinary describe el binario sd resuelto: su path absoluto, version detectada
|
||||
// y como fue localizado.
|
||||
type SdcliBinary struct {
|
||||
Path string `json:"path"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Source string `json:"source"` // "config" | "path"
|
||||
}
|
||||
|
||||
// SdcliResolveBinary localiza el binario sd / sd-cli de stable-diffusion.cpp.
|
||||
//
|
||||
// Orden de busqueda:
|
||||
// 1. Si hint != "" y el archivo existe y es ejecutable: usar como "config".
|
||||
// 2. exec.LookPath("sd"): primer candidato en PATH.
|
||||
// 3. exec.LookPath("sd-cli"): segundo candidato en PATH.
|
||||
// 4. Error descriptivo si no se encuentra ninguno.
|
||||
//
|
||||
// Tras localizar el binario, intenta obtener la version ejecutando
|
||||
// `<bin> --version` con timeout de 3 segundos. Si el comando falla
|
||||
// o no produce output, Version queda vacia (no es error fatal).
|
||||
func SdcliResolveBinary(hint string) (SdcliBinary, error) {
|
||||
var binPath string
|
||||
var source string
|
||||
|
||||
if hint != "" {
|
||||
info, err := os.Stat(hint)
|
||||
if err != nil {
|
||||
return SdcliBinary{}, fmt.Errorf("sdcli hint %q: %w", hint, err)
|
||||
}
|
||||
if info.Mode()&0o111 == 0 {
|
||||
return SdcliBinary{}, fmt.Errorf("sdcli hint %q: file exists but is not executable", hint)
|
||||
}
|
||||
binPath = hint
|
||||
source = "config"
|
||||
}
|
||||
|
||||
if binPath == "" {
|
||||
if p, err := exec.LookPath("sd"); err == nil {
|
||||
binPath = p
|
||||
source = "path"
|
||||
}
|
||||
}
|
||||
|
||||
if binPath == "" {
|
||||
if p, err := exec.LookPath("sd-cli"); err == nil {
|
||||
binPath = p
|
||||
source = "path"
|
||||
}
|
||||
}
|
||||
|
||||
if binPath == "" {
|
||||
return SdcliBinary{}, fmt.Errorf(
|
||||
"sd binary not found in PATH (hint: install from leejet/stable-diffusion.cpp)",
|
||||
)
|
||||
}
|
||||
|
||||
version := sdcliProbeVersion(binPath)
|
||||
return SdcliBinary{
|
||||
Path: binPath,
|
||||
Version: version,
|
||||
Source: source,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// sdcliProbeVersion ejecuta `<bin> --version` con timeout 3s y retorna
|
||||
// la primera linea de la salida. Retorna "" si el comando falla o no
|
||||
// produce output; no propaga el error (version es best-effort).
|
||||
func sdcliProbeVersion(binPath string) string {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
out, err := exec.CommandContext(ctx, binPath, "--version").Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
line := strings.TrimSpace(strings.SplitN(string(out), "\n", 2)[0])
|
||||
return line
|
||||
}
|
||||
Reference in New Issue
Block a user