Files
navegator_dashboard/py_subprocess.h
T

68 lines
3.3 KiB
C++

#pragma once
// py_subprocess — spawn Python con args y capturar stdout. Lo usan los paneles
// AutoExtract y Recipes para invocar funciones del registry (cdp_open_url_and_wait,
// cdp_get_ax_tree, llm_propose_scraping_schema, cdp_extract_recipe, infer_json_rows_schema).
//
// Decisiones:
// - Heredoc inline: el script Python se pasa via -c "<inline>" para evitar archivos temporales.
// - PATH: prioridad del interprete:
// Windows: (1) ${FN_REGISTRY_ROOT}\python\.venv\Scripts\python.exe si existe,
// (2) wsl.exe sentinel si FN_REGISTRY_ROOT_WSL esta seteado (invoca
// el python del venv WSL con: wsl.exe --cd <linux_root> -- env
// FN_REGISTRY_ROOT=<linux_root> python/.venv/bin/python3 ...),
// (3) "python" en PATH (sistema).
// POSIX: ${FN_REGISTRY_ROOT}/python/.venv/bin/python3, luego "python3".
// - Cuando se usa el sentinel wsl.exe, py_run reescribe el argv completo para que
// el script Python reciba FN_REGISTRY_ROOT como path Linux, pueda importar
// funciones del registry y use el venv WSL con todas las deps.
// - FN_REGISTRY_ROOT y FN_REGISTRY_ROOT_WSL se propagan via launch_cpp_app_windows
// (bash/functions/infra/launch_cpp_app_windows.sh v1.1.0).
// - Stdout: capturado completo. El llamante parsea JSON.
// - Stderr: redirigido a stdout para facilitar diagnostico (logs visibles).
// - Sin consola visible en Windows (CREATE_NO_WINDOW).
// - Async wrapper opcional: lanzar en thread y publicar resultado via callback.
#include <functional>
#include <string>
#include <vector>
namespace navegator {
struct PyResult {
int exit_code = -1;
std::string stdout_data;
std::string error; // mensaje propio si CreateProcess/popen fallo
};
// Devuelve la ruta al interprete python a usar. Prioridad (Windows):
// 1. ${FN_REGISTRY_ROOT}\python\.venv\Scripts\python.exe — venv Windows nativo
// 2. "wsl.exe" (sentinel) — cuando FN_REGISTRY_ROOT_WSL esta seteado.
// py_run() lo expande a: wsl.exe --cd <linux_root> -- env FN_REGISTRY_ROOT=<linux_root>
// <linux_root>/python/.venv/bin/python3 ...
// 3. "python" — fallback PATH (python.exe del sistema, sin deps del registry)
// Prioridad (POSIX):
// 1. ${FN_REGISTRY_ROOT}/python/.venv/bin/python3
// 2. "python3" en PATH
std::string py_resolve_interpreter();
// Devuelve FN_REGISTRY_ROOT. Si no esta seteada, intenta deducirla:
// - Working dir del exe ".../fn_registry/projects/navegator/apps/<app>".
// - Subiendo 4 niveles desde exe_dir.
std::string py_resolve_registry_root();
// Lanza python con argv. argv[0] DEBE ser el interprete (de py_resolve_interpreter()).
// Hereda env. Timeout en ms (0 = sin timeout). Devuelve PyResult con stdout + exit.
PyResult py_run(const std::vector<std::string>& argv, int timeout_ms = 60000);
// Helper: ejecuta un script inline via `python -c "<code>"` con args extra.
PyResult py_run_inline(const std::string& code, const std::vector<std::string>& extra_args,
int timeout_ms = 60000);
// Async: ejecuta en thread y llama on_done en el thread del worker.
// Captura args por valor; el caller debe sincronizar acceso compartido.
void py_run_async(const std::vector<std::string>& argv, int timeout_ms,
std::function<void(PyResult)> on_done);
} // namespace navegator