#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 "" 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 -- env // FN_REGISTRY_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 #include #include 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 -- env FN_REGISTRY_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/". // - 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& argv, int timeout_ms = 60000); // Helper: ejecuta un script inline via `python -c ""` con args extra. PyResult py_run_inline(const std::string& code, const std::vector& 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& argv, int timeout_ms, std::function on_done); } // namespace navegator