Files
2026-06-04 23:44:39 +02:00

5.1 KiB
Raw Permalink Blame History

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
pty_capture_idle function go infra 1.0.0 impure func PTYCaptureIdle(ctx context.Context, name string, args []string, warmup time.Duration, inputs []string, stepDelay, idle, maxDur time.Duration) (string, error) Lanza un comando dentro de un pseudo-terminal (PTY) en memoria y captura todo su output hasta que el terminal permanece idle durante al menos `idle`, o se alcanza `maxDur`. Soporta envío de inputs interactivos tras el warmup inicial. Devuelve el output RAW con secuencias ANSI intactas.
terminal
pty
tui
capture
automation
terminal-capture
false error_go_core
context
time
github.com/creack/pty
true
captura output de echo hola
input interactivo con cat
timeout duro con sleep 10
functions/infra/pty_capture_idle_test.go functions/infra/pty_capture_idle.go
name desc
ctx Contexto de cancelación. Si se cancela, la función aborta la captura y retorna el output acumulado hasta ese momento.
name desc
name Nombre o path del ejecutable a lanzar (debe existir en PATH o ser un path absoluto).
name desc
args Argumentos posicionales para el ejecutable. Puede ser nil o vacío.
name desc
warmup Tiempo que la función espera después de arrancar el proceso antes de enviar inputs. Permite que la TUI inicialice su render. Típico: 500ms2s para CLIs lentas.
name desc
inputs Lista de strings a escribir al PTY en secuencia, uno por vez. Incluir '\r' al final de cada string para simular Enter. Puede ser nil si solo se quiere observar la salida sin interactuar.
name desc
stepDelay Espera entre cada input enviado. Permite que la TUI procese y renderice la respuesta de cada paso antes de enviar el siguiente.
name desc
idle Tiempo sin nuevos bytes en el PTY que se considera 'respuesta terminada'. Cuando el terminal lleva idle sin actividad, la función retorna. Típico: 500ms2s.
name desc
maxDur Timeout duro desde el inicio de la función. Garantiza que la función retorna aunque la TUI siga emitiendo output indefinidamente (spinners, relojes). Típico: 30s120s.
String con el output completo del terminal desde el arranque hasta la captura, incluyendo secuencias de escape ANSI. Vacío string si el proceso no produjo nada. Error si el PTY no pudo arrancar o el contexto fue cancelado durante warmup.

Ejemplo

// Capturar una sesión de claude con un prompt automático
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()

raw, err := PTYCaptureIdle(
    ctx,
    "claude", nil,
    2*time.Second,                    // warmup: esperar que claude cargue
    []string{"hola, responde PONG\r"}, // inputs: enviar mensaje + Enter
    300*time.Millisecond,             // stepDelay entre inputs
    2*time.Second,                    // idle: cortar cuando lleve 2s sin output
    120*time.Second,                  // maxDur: timeout duro
)
if err != nil {
    log.Fatal(err)
}
// raw contiene el render completo con ANSI; limpiar antes de procesar texto:
// clean := StripANSI(raw)   // strip_ansi_go_tui
fmt.Println(raw)

Cuando usarla

Cuando necesites automatizar o scriptear una CLI interactiva que solo entra en modo interactivo si detecta un TTY real (como claude, vim, fzf, htop, python REPL, psql). El PTY hace creer al proceso que habla con un terminal real, sin abrir ninguna ventana gráfica.

Gotchas

  • Linux/Unix only. Usa PTY POSIX (creack/pty). No funciona en Windows.
  • Output RAW con ANSI. El string devuelto contiene secuencias de escape (\x1b[...m, cursor moves, etc.). Para convertirlo a texto plano: usa vt_render_go_tui (reconstruye el layout 2D — correcto para TUIs con posicionamiento absoluto como claude o htop) o strip_ansi_go_core (para output secuencial tipo log). strip_ansi sobre una TUI con layout absoluto deja las palabras pegadas porque los espacios entre columnas eran movimientos de cursor.
  • Idle es heurístico. Si la TUI hace render periódico (spinners, relojes en pantalla, progress bars continuas), el idle nunca se dispara y la función esperará hasta maxDur. Aumentar maxDur o matar el spinner antes de capturar.
  • El binario debe existir en PATH (o usar path absoluto en name). La función devuelve error si pty.Start falla.
  • EIO/EOF al cerrar PTY es normal en Linux. El goroutine lector lo absorbe silenciosamente; no se propaga como error.
  • SIGTERM → SIGKILL. Al terminar la captura, la función envía SIGTERM al proceso y espera 2s antes de SIGKILL. Procesos que ignoran SIGTERM (como sleep) se matan limpiamente.
  • Tamaño de terminal fijado a 40×120. Suficiente para la mayoría de TUIs. Si el render se ve truncado, el llamador puede hacer pty.Setsize adicional después de obtener el ptmx (no expuesto por esta función; para casos avanzados, reimplementar con acceso directo al ptmx).