Files
agent 011ccfb8cd feat: scaffold inicial del plugin de Obsidian osint_obsidian_plugin
Plugin fino (id osint-db) que habla HTTP con el service local osint_db
(FastAPI + DuckDB) y renderiza tablas de datos en las notas del vault
osint mediante el code block osintdb. Incluye parser puro de directivas
con tests (node --test), settings tab, comando de paleta, enlaces
internos para columnas note_path, build con esbuild + tsc y deploy.sh
al vault.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 23:58:04 +02:00

121 lines
4.9 KiB
Markdown

---
name: osint_obsidian_plugin
lang: ts
domain: osint
version: 0.1.0
description: "Plugin de Obsidian (id osint-db) para el vault osint: ejecuta queries SQL y queries nombradas contra el service local osint_db (FastAPI + DuckDB) via HTTP y renderiza tablas de datos dentro de las notas mediante el code block osintdb. Plugin fino: no embebe ninguna base de datos."
tags: [osint, obsidian, plugin, duckdb]
uses_functions: []
uses_types: []
framework: "obsidian-plugin"
entry_point: "main.ts"
dir_path: "projects/osint/apps/osint_obsidian_plugin"
repo_url: "https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/osint_obsidian_plugin"
e2e_checks:
- id: build
cmd: "pnpm install --frozen-lockfile=false && pnpm build"
timeout_s: 300
- id: artifact
cmd: "test -f main.js"
- id: tests
cmd: "pnpm test"
timeout_s: 60
---
# osint_obsidian_plugin
Plugin de Obsidian para el vault `~/Obsidian/osint`. Es deliberadamente fino: no embebe
DuckDB ni ninguna otra base de datos. Toda la lógica de datos vive en el service local
`osint_db` (FastAPI, dueño de la DuckDB con datos OSINT), con el que el plugin habla por
HTTP usando `requestUrl` de la API de Obsidian (evita CORS; nunca `fetch`).
## Qué hace
1. **Code block `osintdb`**: dentro de cualquier nota, un bloque de código con lenguaje
`osintdb` se renderiza como una tabla de datos. Dos formas de contenido:
- SQL crudo (el bloque entero es un SELECT, va a `POST /api/query`).
- Directivas `clave: valor` al inicio del bloque: `query` (nombre de query guardada,
va a `POST /api/query/named`), `max_rows` y `title`.
2. **Render seguro**: tabla HTML construida con `createEl` (los valores se insertan como
texto, nunca como HTML crudo), header sticky, conteo de filas y nota "(truncado)"
cuando el service recorta el resultado. Errores del service y service caído se
muestran con mensajes claros, incluido el comando para arrancar `osint_db`.
3. **Botón "Refrescar"** por bloque: re-ejecuta la query sin recargar la nota.
4. **Enlaces a notas**: si una columna se llama `note_path` y el valor termina en `.md`,
la celda se renderiza como enlace interno de Obsidian que abre la nota al hacer clic.
5. **Settings tab**: URL base del service (default `http://127.0.0.1:8771`) y `max_rows`
por defecto (500), persistidos con `loadData`/`saveData`.
6. **Comando de paleta** "OSINT DB: Insertar bloque de query": inserta una plantilla de
bloque `osintdb` en el editor.
## Ejemplo de bloque
Forma con SQL crudo:
```osintdb
title: Personas del caso X
max_rows: 100
SELECT nombre, contexto, note_path FROM main.personas WHERE contexto = 'caso_x';
```
Forma con query nombrada (definida en el service):
```osintdb
query: personas_por_contexto
max_rows: 100
```
## Contrato API del service osint_db
Base URL por defecto: `http://127.0.0.1:8771`. El service responde siempre HTTP 200 y el
plugin decide por el campo `status` del body.
- `GET /api/health` → `{"status":"ok","db_path":"...","tables":N}`
- `GET /api/tables` → listado de tablas con schema, kind, row_count y columnas.
- `POST /api/query` body `{"sql":"SELECT ...","params":[],"max_rows":500}` →
`{"status":"ok","columns":[...],"rows":[...],"row_count":N,"truncated":bool}` o
`{"status":"error","error":"..."}`.
- `GET /api/queries` → queries nombradas disponibles.
- `POST /api/query/named` body `{"name":"...","max_rows":500}` → misma shape que `/api/query`.
## Cómo construir
```bash
cd projects/osint/apps/osint_obsidian_plugin
pnpm install
pnpm build # tsc --noEmit + esbuild -> main.js
pnpm test # tests del parser de bloques (node --test, sin Obsidian)
```
Requiere Node >= 23 para los tests (usa el type stripping nativo de `node --test` sobre
archivos `.ts`).
## Cómo desplegar
```bash
./deploy.sh
```
Copia `manifest.json`, `main.js` y `styles.css` a
`/home/enmanuel/Obsidian/osint/.obsidian/plugins/osint-db/`.
**Activación manual (la hace el humano, no un agente):** tras el deploy, abrir Obsidian →
Settings → Community plugins → activar "OSINT DB". Si Obsidian ya estaba abierto, hace
falta recargar la app (Ctrl+R) o reiniciarla para que detecte el plugin nuevo o la
versión nueva de `main.js`.
## Estructura
- `main.ts` — plugin completo (processor, render, settings, comando).
- `parse.ts` — parser puro del contenido de los bloques `osintdb` (testeable sin Obsidian).
- `tests/parse.test.ts` — tests del parser con `node --test`.
- `esbuild.config.mjs` — bundle CommonJS a `main.js` con `obsidian` como external.
- `deploy.sh` — copia los artefactos al vault.
## Gotchas
- El plugin no arranca el service: si `osint_db` no está corriendo, los bloques muestran
"osint_db no responde en <url>" con el comando de arranque como hint.
- `main.js` es artefacto de build (gitignored): siempre `pnpm build` antes de `deploy.sh`.
- `isDesktopOnly: true` en el manifest — el service es local, no tiene sentido en móvil.