feat: docking host + add-node toolbar + node context menu
- Dockspace host (PassthruCentralNode) bajo la toolbar para que las
ventanas Viewport/Legend/Inspector/Stats puedan dockearse dentro de la
app principal.
- Toolbar: input "Add node" con auto-deteccion de tipo (text/email/
ip_address/url/domain/phone). Insert en operations.db + reload.
- Context menu (right-click sobre nodo): Change type, Duplicate, Delete,
submenu "Run enricher" (placeholder hasta issues 0001-0003).
- Inspector: vecinos ahora muestran etiqueta de relacion ("-> employs",
"<- owns") usando rel_types[].name como label de arista.
- Default relation label k_default_relation_name="RELATED_TO" para
relaciones creadas sin nombre semantico explicito.
- Indice EntityIndex (FNV1a hash -> sql id) reconstruido tras cada load
para resolver mutaciones desde el grafo en memoria.
Issues planteadas para iteraciones siguientes:
- 0001: chat con Claude sobre el grafo (HTTP + tool-use)
- 0002: enricher GLiNER+GLiREL desde nodo texto
- 0003: enricher web (fetch URL/dominio + extract text)
- 0004: vista tabla por tipo de entidad
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
// Operaciones CRUD sobre operations.db (entities + relations) y deteccion
|
||||
// heuristica de tipo a partir de texto libre. Pensado para que la toolbar y
|
||||
// el menu contextual del viewport puedan modificar el grafo y luego pedir
|
||||
// reload (issue 0049g flow).
|
||||
//
|
||||
// Convencion edge labels: si el caller no pasa nombre de relacion, se usa
|
||||
// k_default_relation_name = "RELATED_TO". Los enrichers deben pasar siempre
|
||||
// un nombre semantico (ej: "EXTRACTED_FROM", "RESOLVES_TO", ...).
|
||||
|
||||
namespace ge {
|
||||
|
||||
constexpr const char* k_default_relation_name = "RELATED_TO";
|
||||
|
||||
enum DetectedType {
|
||||
DT_TEXT = 0,
|
||||
DT_EMAIL,
|
||||
DT_IP_ADDRESS,
|
||||
DT_URL,
|
||||
DT_DOMAIN,
|
||||
DT_PHONE,
|
||||
};
|
||||
|
||||
DetectedType detect_type(const char* text);
|
||||
const char* detected_type_name(DetectedType dt);
|
||||
|
||||
// Inserta una entidad nueva. Si type_ref es NULL/vacio se infiere via
|
||||
// detect_type(name). Genera un id unico ("<type>_<unix_ms>"). Devuelve el id
|
||||
// en out_id (caller-owned buffer >= 64). Retorna false si SQLite falla.
|
||||
bool entity_insert(const char* db_path,
|
||||
const char* name,
|
||||
const char* type_ref,
|
||||
char* out_id, size_t out_id_n);
|
||||
|
||||
bool entity_delete(const char* db_path, const char* id);
|
||||
|
||||
bool entity_update_type(const char* db_path, const char* id, const char* new_type);
|
||||
|
||||
// Duplica una entidad existente. Mismo type/metadata, sufijo "_copy" en id
|
||||
// y "(copia)" en name. Devuelve el nuevo id en out_id.
|
||||
bool entity_duplicate(const char* db_path, const char* id,
|
||||
char* out_id, size_t out_id_n);
|
||||
|
||||
// Inserta una relacion. Si name es NULL/vacio usa k_default_relation_name.
|
||||
bool relation_insert(const char* db_path,
|
||||
const char* from_id, const char* to_id,
|
||||
const char* name);
|
||||
|
||||
// Mapa user_data (FNV1a hash) -> sql id. Se reconstruye despues de cada
|
||||
// carga del grafo (graph_sources usa FNV1a sobre id como user_data).
|
||||
struct EntityIndex {
|
||||
std::unordered_map<uint64_t, std::string> by_hash;
|
||||
};
|
||||
|
||||
// Escanea operations.db y rellena el indice. Reentrante (clear+repoblar).
|
||||
bool entity_index_build(const char* db_path, EntityIndex* idx);
|
||||
|
||||
// Resuelve user_data a sql id. NULL si no existe.
|
||||
const char* entity_index_lookup(const EntityIndex& idx, uint64_t user_data);
|
||||
|
||||
} // namespace ge
|
||||
Reference in New Issue
Block a user