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,48 @@
|
||||
---
|
||||
id: 0001
|
||||
title: Chat con Claude sobre el grafo
|
||||
status: pending
|
||||
priority: high
|
||||
created: 2026-04-30
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Panel "Chat" dentro de graph_explorer que permita conversar con Claude
|
||||
(Anthropic API) usando el grafo activo como contexto. El agente debe poder:
|
||||
|
||||
- Leer el grafo (entidades, relaciones, metadata) via tool-use sobre operations.db.
|
||||
- Responder preguntas tipo: "muestrame los nodos relacionados con X", "que
|
||||
patrones ves en estas conexiones", "que falta investigar".
|
||||
- Proponer mutaciones (crear nodo, etiquetar relacion) que el usuario aprueba
|
||||
con un click antes de aplicarse.
|
||||
|
||||
## Alcance tecnico
|
||||
|
||||
- Cliente HTTP minimo (libcurl o WinHTTP) → POST a `https://api.anthropic.com/v1/messages`.
|
||||
- Modelo por defecto: `claude-sonnet-4-6` (revisar al implementar).
|
||||
- API key desde env var `ANTHROPIC_API_KEY` o `~/.fn_anthropic_key`.
|
||||
- Tool-use: definir tools `query_entities`, `query_relations`, `propose_node`,
|
||||
`propose_relation`. Las "propose_*" no mutan: insertan en una cola que el
|
||||
usuario revisa antes de aplicar.
|
||||
- Estado de conversacion en memoria (lista de messages). Persistencia opcional
|
||||
en `graph_explorer.db` tabla `chat_sessions`.
|
||||
- Streaming SSE para feedback en vivo (puede dejarse para v2 — primer hit
|
||||
bloqueante esta bien).
|
||||
|
||||
## Decisiones a tomar
|
||||
|
||||
- Renderizado de markdown en ImGui (TextWrapped basico vs lib externa).
|
||||
- Threading: bloqueante en hilo aparte → cola de mensajes → main thread lee.
|
||||
|
||||
## Trabajo previo
|
||||
|
||||
Ya existe en el registry `python/functions/agents/anthropic_chat_py_agents.py`
|
||||
para inspiracion (usa el SDK Python). En C++ usaremos HTTP directo — sin SDK.
|
||||
|
||||
## Definicion de hecho
|
||||
|
||||
- Panel "Chat" dockeable.
|
||||
- Conversacion con tool-use sobre operations.db funciona.
|
||||
- Las mutaciones propuestas por el agente se confirman desde la UI antes de
|
||||
llegar a la BD.
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: 0002
|
||||
title: Enricher GLiNER + GLiREL — emitir entidades/relaciones desde un nodo texto
|
||||
status: pending
|
||||
priority: high
|
||||
created: 2026-04-30
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Right-click sobre un nodo de tipo `text` → "Run enricher → Extract entities
|
||||
(GLiNER+GLiREL)". El enricher procesa el texto del nodo y crea:
|
||||
|
||||
- Nuevas entidades (person, org, email, location, ...) con tipos detectados.
|
||||
- Relaciones entre el nodo origen y las nuevas, etiquetadas con `EXTRACTED_FROM`.
|
||||
- Relaciones entre las nuevas entidades cuando GLiREL las detecte, etiquetadas
|
||||
con el tipo predicho por el modelo (`employed_by`, `located_in`, ...).
|
||||
|
||||
## Trabajo previo en el registry
|
||||
|
||||
Ya existen las funciones Python:
|
||||
- `python/functions/extraction/gliner_extract_*` (varios)
|
||||
- `python/functions/extraction/glirel_extract_*`
|
||||
- Pipeline `extract_graph_hybrid_py_pipelines` (issue 0040 cerrado, ver commit
|
||||
1a353878) que ya hace exactamente esto sobre un texto y devuelve un grafo
|
||||
estructurado.
|
||||
|
||||
El analysis `analysis/retrieving_graphs/` lo usa en notebooks.
|
||||
|
||||
## Alcance tecnico (C++ side)
|
||||
|
||||
- Definir interfaz de enricher: `enricher_run(node_id, db_path) -> int n_added`.
|
||||
- Implementacion `enricher_gliner_glirel`:
|
||||
- Spawn `python/.venv/bin/python3` con un script wrapper que recibe el texto
|
||||
por stdin (JSON `{"text": "..."}`) y devuelve por stdout el grafo
|
||||
estructurado (JSON `{"entities": [...], "relations": [...]}`).
|
||||
- Wrapper Python en `projects/osint_graph/apps/graph_explorer/enrichers/gliner_glirel.py`.
|
||||
- C++ usa `popen` o `CreateProcess` segun plataforma.
|
||||
- Insertar las entidades nuevas (entity_insert) y relaciones (relation_insert)
|
||||
con etiquetas semanticas.
|
||||
- UI: spinner en el menu mientras corre (cold start del modelo ~5s).
|
||||
|
||||
## Riesgos / decisiones
|
||||
|
||||
- Modelos pesados → cold start lento. Considerar pre-cargar al primer uso.
|
||||
- Streaming de progreso desde Python via stderr line-by-line.
|
||||
- Fallback si el venv no existe: mostrar mensaje en el menu en vez de fallar.
|
||||
|
||||
## Definicion de hecho
|
||||
|
||||
- Click derecho en nodo `text` → "Extract entities" muestra opcion.
|
||||
- Tras correr, el grafo se recarga con las nuevas entidades visibles y
|
||||
conectadas con `EXTRACTED_FROM`.
|
||||
- Las relaciones entre entidades extraidas llevan el tipo que GLiREL predice.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: 0003
|
||||
title: Enricher web — descargar URL/dominio y extraer texto
|
||||
status: pending
|
||||
priority: medium
|
||||
created: 2026-04-30
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Right-click sobre un nodo `url` o `domain` → "Run enricher → Fetch & extract
|
||||
text". Descarga el HTML, extrae el texto principal, crea un nodo `text`
|
||||
conectado al origen con relacion `FETCHED_FROM`.
|
||||
|
||||
Despues el usuario puede encadenar: sobre ese nodo `text`, ejecutar el enricher
|
||||
GLiNER+GLiREL (issue 0002) para extraer entidades.
|
||||
|
||||
## Alcance
|
||||
|
||||
- HTTP GET con timeout (libcurl o sys WinHTTP).
|
||||
- Extraccion de texto: regex/strip de tags simple en v1; v2 usa una lib
|
||||
(htmlparser2 / lexbor / boost.url + algo de heuristica).
|
||||
- User-agent identificativo, respeto de robots.txt opcional (out-of-scope v1).
|
||||
- Limite de tamaño descargable (1 MB) para evitar bloqueos.
|
||||
|
||||
## Modelo de etiquetado
|
||||
|
||||
- Nodo origen (url/domain) → arista `FETCHED_FROM` → nodo nuevo (text con
|
||||
metadata={fetched_at, status_code, content_type, length}).
|
||||
- Nombre del nodo text: titulo de la pagina (si <title> existe) o primeros
|
||||
120 caracteres del cuerpo.
|
||||
|
||||
## Definicion de hecho
|
||||
|
||||
- Funciona contra una URL real (https con TLS).
|
||||
- Maneja errores (404, timeout, redirects basicos) sin tumbar la app.
|
||||
- El nodo creado es visible y el texto se puede consumir por el enricher
|
||||
GLiNER+GLiREL del issue 0002.
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
id: 0004
|
||||
title: Vista tabla — entidades agrupadas por tipo
|
||||
status: pending
|
||||
priority: medium
|
||||
created: 2026-04-30
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
Ventana "Table" dockeable con una tabla por cada tipo de entidad presente en el
|
||||
grafo. Filas = entidades. Columnas: id, name, status, updated_at, neighbors
|
||||
count. Clickar una fila selecciona el nodo en el viewport.
|
||||
|
||||
## UI
|
||||
|
||||
- ImGui::BeginTable con sorting + clipper para >10k filas.
|
||||
- Tabs en la cabecera de la ventana, una tab por type_ref ordenado alfabetico.
|
||||
- Selector global "show all types" que apila todos en una sola tabla.
|
||||
|
||||
## Definicion de hecho
|
||||
|
||||
- Tabla escala a 10k entidades sin lag perceptible.
|
||||
- Click en fila selecciona nodo en viewport (mismo flujo que Inspector
|
||||
Selectable).
|
||||
- Filtro de busqueda por substring sobre name/id.
|
||||
Reference in New Issue
Block a user