diff --git a/chat.cpp b/chat.cpp index 935950e..1e6cac3 100644 --- a/chat.cpp +++ b/chat.cpp @@ -1,5 +1,6 @@ #include "chat.h" +#include "app_base.h" #include "imgui.h" #include "core/icons_tabler.h" #include "core/selectable_text.h" @@ -16,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -808,10 +810,25 @@ std::string write_mcp_config() { config_path_for_claude = config_path_native; #endif - // El "command" que claude ejecutara es gx-cli con shebang python3. En - // WSL esto es la ruta Linux dentro de fn_registry. + // gx-cli vive en /assets/ tras el deploy con la + // convencion assets/. Fallback al app_dir del repo en modo dev. std::string app_dir_linux = to_linux_path(g_st->app_dir); - std::string gxcli_path = app_dir_linux + "/gx-cli"; + std::string gxcli_path; + { + std::string assets_gx = fn::asset_path( +#ifdef _WIN32 + "gx-cli.exe" +#else + "gx-cli" +#endif + ); + std::error_code _ec; + if (std::filesystem::exists(assets_gx, _ec)) { + gxcli_path = to_linux_path(assets_gx); + } else { + gxcli_path = app_dir_linux + "/gx-cli"; + } + } // No metemos env: en el config para que herede del proceso padre // (claude, que ya tiene GX_OPS_DB/GX_APP_DB/GX_APP_DIR via WSLENV). diff --git a/jobs.cpp b/jobs.cpp index c531f40..184a764 100644 --- a/jobs.cpp +++ b/jobs.cpp @@ -119,25 +119,32 @@ bool file_exists(const std::string& p) { } // Cadena de fallback (logged una sola vez al primer uso): -// 1. /runtime/python/{python.exe|bin/python3} -> kind=embedded -// 2. $FN_PYTHON -> kind=env -// 3. /python/.venv/bin/python3 -> kind=registry_venv -// 4. python3 del PATH -> kind=system +// 1. /assets/runtime/python/{python.exe|bin/python3} -> kind=embedded +// 2. /runtime/python/... (legacy, pre-assets/) -> kind=embedded +// 3. $FN_PYTHON -> kind=env +// 4. /python/.venv/bin/python3 -> kind=registry_venv +// 5. python3 del PATH -> kind=system PyRuntime resolve_python_runtime() { PyRuntime r; std::string exe = get_exe_dir(); #ifdef _WIN32 - if (!exe.empty()) { - std::string p = exe + "\\runtime\\python\\python.exe"; - if (file_exists(p)) { r.path = p; r.kind = "embedded"; return r; } - } + const char* embed_rel[] = { + "\\assets\\runtime\\python\\python.exe", + "\\runtime\\python\\python.exe", // legacy + }; #else - if (!exe.empty()) { - std::string p = exe + "/runtime/python/bin/python3"; - if (file_exists(p)) { r.path = p; r.kind = "embedded"; return r; } - } + const char* embed_rel[] = { + "/assets/runtime/python/bin/python3", + "/runtime/python/bin/python3", // legacy + }; #endif + if (!exe.empty()) { + for (const char* rel : embed_rel) { + std::string p = exe + rel; + if (file_exists(p)) { r.path = p; r.kind = "embedded"; return r; } + } + } if (const char* env = std::getenv("FN_PYTHON"); env && *env) { if (file_exists(env)) { r.path = env; r.kind = "env"; return r; } diff --git a/main.cpp b/main.cpp index 96ea875..0f44ba5 100644 --- a/main.cpp +++ b/main.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #ifndef _WIN32 @@ -1968,7 +1969,21 @@ int main(int argc, char** argv) { std::string app_dir = registry_root.empty() ? "." : registry_root + "/projects/osint_graph/apps/graph_explorer"; - std::string enrichers_dir = app_dir + "/enrichers"; + + // Convencion assets/: enrichers vienen empaquetados en + // /assets/enrichers/. Fallback al app_dir del repo + // para modo dev local cuando se ejecuta desde build/. + std::string enrichers_dir; + { + std::string assets_enrichers = fn::asset_path("enrichers"); + struct stat st{}; + if (::stat(assets_enrichers.c_str(), &st) == 0 && + S_ISDIR(st.st_mode)) { + enrichers_dir = assets_enrichers; + } else { + enrichers_dir = app_dir + "/enrichers"; + } + } // graph_explorer.db es el mismo SQLite usado por layout_store. // Default a /graph_explorer.db si no hay proyecto.