feat(graph_explorer): adopta layout assets/ via fn::asset_path
Junto con el cambio del framework (commit 81d8a7c9), graph_explorer
ahora resuelve enrichers/, runtime Python y gx-cli desde
<exe_dir>/assets/ con fallback a las rutas dev legacy.
- main.cpp: enrichers_dir busca primero <exe_dir>/assets/enrichers/
(deploy con /compile). Fallback a <app_dir>/enrichers/ del repo
cuando se ejecuta desde build/ (modo dev).
- jobs.cpp::resolve_python_runtime: incluye
<exe_dir>/assets/runtime/python/{python.exe|bin/python3} como
primera opcion de la cadena de fallback. La opcion legacy sin
assets/ queda como segundo intento.
- chat.cpp: gxcli_path busca <exe_dir>/assets/gx-cli{.exe} con
fallback a <app_dir>/gx-cli para modo dev.
Tests: 32/32 verde. Build Linux + Windows OK. Deploy fresco a
Desktop con todas las 6 apps confirma layout limpio:
<app>.exe + (duckdb.dll si aplica) + assets/ + local_files/
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 <cstring>
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
@@ -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 <exe_dir>/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).
|
||||
|
||||
@@ -119,25 +119,32 @@ bool file_exists(const std::string& p) {
|
||||
}
|
||||
|
||||
// Cadena de fallback (logged una sola vez al primer uso):
|
||||
// 1. <exe_dir>/runtime/python/{python.exe|bin/python3} -> kind=embedded
|
||||
// 2. $FN_PYTHON -> kind=env
|
||||
// 3. <registry_root>/python/.venv/bin/python3 -> kind=registry_venv
|
||||
// 4. python3 del PATH -> kind=system
|
||||
// 1. <exe_dir>/assets/runtime/python/{python.exe|bin/python3} -> kind=embedded
|
||||
// 2. <exe_dir>/runtime/python/... (legacy, pre-assets/) -> kind=embedded
|
||||
// 3. $FN_PYTHON -> kind=env
|
||||
// 4. <registry_root>/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; }
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
// <exe_dir>/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 <local_files>/graph_explorer.db si no hay proyecto.
|
||||
|
||||
Reference in New Issue
Block a user