chore: auto-commit (799 archivos)

- .claude/CLAUDE.md
- .claude/commands/subagentes.md
- .claude/rules/INDEX.md
- .mcp.json
- bash/functions/cybersecurity/analyze_dns.md
- bash/functions/cybersecurity/audit_http_headers.md
- bash/functions/cybersecurity/audit_ssh_config.md
- bash/functions/cybersecurity/check_firewall.md
- bash/functions/cybersecurity/detect_suspicious_users.md
- bash/functions/cybersecurity/encrypt_file.md
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 00:28:20 +02:00
parent 20f72edb5a
commit 47fac22230
805 changed files with 5515 additions and 810 deletions
+43
View File
@@ -0,0 +1,43 @@
# Capability Groups
Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones que comparten dominio operativo. Lee la pagina madre del grupo ANTES de buscar funciones sueltas — desbloqueas el conjunto entero en un solo read.
## Como leer este indice
| Columna | Que |
|---|---|
| Grupo | Tag canonico. Coincide con el slug del archivo `<grupo>.md` |
| N | Numero de funciones en el grupo (auditado por `fn doctor capabilities`) |
| Que cubre | Frase corta — accion principal |
## Grupos vigentes
| Grupo | N | Que cubre |
|---|---|---|
| [bigquery](bigquery.md) | 26 | _(editar — promovido automaticamente)_ |
| [nlp](nlp.md) | 33 | _(editar — promovido automaticamente)_ |
| [docker](docker.md) | 38 | _(editar — promovido automaticamente)_ |
| [android](android.md) | 37 | _(editar — promovido automaticamente)_ |
| [metabase](metabase.md) | 106 | _(editar — promovido automaticamente)_ |
| [doctor](doctor.md) | 11 | Diagnostico read-only del registry: artefactos, servicios, drift, funciones huerfanas |
| [notebook](notebook.md) | 5 | Operar Jupyter Lab colaborativo (discover/read/exec/write/kernel) |
## Como anadir grupo
1. Reservar tag plano (sin prefijos). Ej: `metabase`, `android-emu`, `deploy`.
2. Anadir el tag al frontmatter `.md` de >=3 funciones afines (`fn index` lo registra).
3. Crear `docs/capabilities/<grupo>.md` con plantilla:
- Lista de funciones (ID + firma corta).
- 1-2 ejemplos canonicos de uso.
- Fronteras (que NO hace el grupo).
4. Anadir fila a la tabla "Grupos vigentes" arriba.
5. Correr `fn doctor capabilities` para auditar drift tag<->doc.
## Minimo por grupo
- **3 funciones**: minimo para crear pagina madre.
- **<3 funciones**: tag sigue valido para FTS pero no genera pagina madre.
## Auto-generacion
`fn doctor capabilities --update` reescribe la tabla "Funciones" de cada pagina preservando bloques curated ("Ejemplo canonico", "Fronteras", "Notas"). Las secciones curated nunca se sobrescriben.
+54
View File
@@ -0,0 +1,54 @@
# Capability: android
_(Descripcion del grupo — editar a mano)_
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `adb_wsl_bash_infra` | `source adb_wsl.sh [ADB=<path>] [ANDROID_SDK_WIN=<sdk_root>]` | Wrapper sourceable para usar adb.exe Windows desde WSL2. Resuelve binario, convierte paths, espera boot del emulador. |
| `android_apk_install_bash_infra` | `android_apk_install([--serial S], apk_path: string, package_name?: string, activity_name?: string) -> void` | Instala APK en device/emulador via adb y opcionalmente lanza la app. Multi-emulator via --serial. |
| `android_app_clear_bash_infra` | `android_app_clear([--serial <S>], package: string) -> void` | Wipe app data + cache via pm clear. App keeps installed but factory-state. Multi-emulator via --serial. |
| `android_app_info_bash_infra` | `android_app_info([--serial <S>], package, [--json]) -> stdout` | Inspect installed app: version, target SDK, activities via dumpsys package. |
| `android_app_kill_bash_infra` | `android_app_kill([--serial <S>], package: string) -> void` | Force-stop running app via am force-stop. Multi-emulator via --serial. |
| `android_app_launch_bash_infra` | `android_app_launch([--serial <S>], package: string, [activity: string]) -> void` | Launch app activity via am start. Multi-emulator via --serial. |
| `android_app_uninstall_bash_infra` | `android_app_uninstall([--serial <S>] package [--keep-data]) -> void` | Uninstall app via adb uninstall. Optionally keep data with --keep-data. |
| `android_emu_battery_bash_infra` | `android_emu_battery([--serial <S>], level: int, [--charging <true\|false>]) -> void` | Simulate battery state on emulator (level + charging). Emulator-only. |
| `android_emu_geo_fix_bash_infra` | `android_emu_geo_fix([--serial <S>], longitude: string, latitude: string, [altitude: string]) -> void` | Fake GPS location on Android emulator via emu geo fix. Emulator-only (not physical devices). |
| `android_emu_rotate_bash_infra` | `android_emu_rotate([--serial <S>] [portrait\|landscape\|0\|90\|180\|270])` | Rotate emulator screen. Empty=toggle, or fixed orientation. Locks autorotate. |
| `android_emulator_list_bash_infra` | `android_emulator_list([--json])` | Lista los AVDs disponibles invocando emulator.exe Windows desde WSL2. |
| `android_emulator_start_bash_infra` | `android_emulator_start(avd_name: string, timeout_s: int) -> string` | Arranca un AVD en background y espera a que termine de bootear. Idempotente: si ya hay emulador corriendo no lanza otro. |
| `android_emulator_stop_bash_infra` | `android_emulator_stop(serial?: string) -> void` | Para uno o todos los emuladores Android via adb emu kill. Si serial esta vacio, detecta todos los emulator-* activos y los para. Idempotente: exit 0 aunque no haya nada que matar. |
| `android_input_keyevent_bash_infra` | `android_input_keyevent([--serial <S>] key: string)` | Send key event via adb shell input keyevent. Accepts aliases (BACK, HOME, POWER, ENTER, MENU, RECENT_APPS, VOLUME_UP, VOLUME_DOWN), raw numeric codes, or explicit KEYCODE_* names. |
| `android_input_swipe_bash_infra` | `android_input_swipe([--serial <S>], x1: int, y1: int, x2: int, y2: int, [duration_ms: int])` | Send swipe gesture between two points with duration. |
| `android_input_tap_bash_infra` | `android_input_tap([--serial <S>], x: int, y: int) -> void` | Send tap gesture at screen coordinates via adb shell input tap. |
| `android_input_text_bash_infra` | `android_input_text([--serial <S>], text: string) -> void` | Type text in focused field via adb shell input text. Spaces handled. |
| `android_logcat_bash_infra` | `android_logcat([--serial <S>] [--package <name>] [--level <V\|D\|I\|W\|E\|F>] [--lines <N>] [--clear])` | Lee logcat del device/emulador, opcionalmente filtrado por package y nivel. Multi-emulator via --serial. |
| `android_pull_bash_infra` | `android_pull [--serial <S>] remote_path local_path` | Pull file/dir from Android device to WSL via adb pull. |
| `android_push_bash_infra` | `android_push([--serial <S>], local_path: string, remote_path: string) -> void` | Push file/dir from WSL to Android device via adb push. |
| `android_screen_record_bash_infra` | `android_screen_record([--serial <S>] [--duration <s>] [--bit-rate <bps>] [--size <WxH>] output_path: string) -> void` | Record screen video via adb screenrecord, pulls to local path. |
| `android_screenshot_bash_infra` | `android_screenshot([--serial <S>], output_path: string) -> void` | Capture screen as PNG via adb exec-out screencap -p. |
| `android_shell_bash_infra` | `android_shell([--serial <S>], cmd ...args)` | Execute arbitrary shell command on Android device. Multi-emulator via --serial. |
| `capacitor_build_apk_bash_pipelines` | `capacitor_build_apk(web_app_dir: string, [app_id: string], [app_name: string]) -> void` | Pipeline que convierte una web app en un APK de Android usando Capacitor. Valida el entorno (ANDROID_HOME, Java 17+), construye el bundle web si no existe dist/, inicializa Capacitor si no está configurado, añade la plataforma Android, sincroniza y compila el APK con Gradle. El APK final queda en el directorio raíz de la web app. |
| `deploy_capacitor_to_emulator_bash_pipelines` | `deploy_capacitor_to_emulator(app_dir: string, avd_name?: string, package_name?: string) -> void` | Pipeline end-to-end: build Capacitor APK + arranca AVD + instala + opcionalmente lanza la app. Valida que el AVD existe, construye el APK con capacitor_build_apk, arranca el emulador de forma idempotente, instala el APK y lanza la app si se da package_name. Imprime comando logcat sugerido al final. |
| `gradle_assemble_debug_bash_infra` | `gradle_assemble_debug(project_dir: string, module: string) -> string` | Build APK debug de un modulo Android via gradlew assembleDebug. |
| `gradle_clean_bash_infra` | `gradle_clean(project_dir: string) -> int` | Limpia build artifacts de un proyecto Android (gradle clean + rm .gradle + rm build). |
| `gradle_instrumented_test_bash_infra` | `gradle_instrumented_test(project_dir: string, module: string) -> int` | Corre instrumented tests Compose en emulador/device Android conectado. |
| `gradle_run_bash_infra` | `gradle_run(project_dir: string, task...: string) -> int` | Wrapper canonico para invocar gradlew Android en WSL2 con JDK 17 + ANDROID_HOME validados. |
| `gradle_screenshot_test_bash_infra` | `gradle_screenshot_test(project_dir: string, module: string, flag: string) -> int` | Corre screenshot tests Roborazzi de Composables (JVM, no necesita emulador). |
| `gradle_unit_test_bash_infra` | `gradle_unit_test(project_dir: string, module: string, --variant <name>: string) -> int` | Corre unit tests JVM de un modulo Android (no requiere emulador). |
| `init_kotlin_app_bash_pipelines` | `init_kotlin_app(name: string, [--project <p>] [--desc <s>] [--tags <csv>] [--package <id>]) -> void` | Scaffolder canonico de app Android Kotlin Compose con FnTheme + Roborazzi tests + e2e_checks declarados. Mirror exacto del patron init_cpp_app para el stack Kotlin. |
| `install_android_sdk_bash_infra` | `install_android_sdk() -> void` | Descarga e instala Android SDK command-line tools y JDK 17 localmente (sin root/sudo) en $ANDROID_SDK_DIR (default: $HOME/android-sdk). Idempotente: detecta instalacion existente y sale sin hacer nada. Genera env.sh con JAVA_HOME, ANDROID_HOME y PATH listos para hacer source. |
| `nominatim_reverse_geocode_kt_infra` | `fun nominatimReverseGeocode(lat: Double, lon: Double, lang: String = "es"): GeocodedLocation` | Reverse geocoding usando Nominatim (OpenStreetMap). Convierte coordenadas lat/lon a una dirección estructurada (calle, ciudad, país, etc.) para Android/Kotlin sin dependencias externas. |
| `ollama_chat_kt_infra` | `fun ollamaChat(messages: List<Map<String, String>>, model: String = "llama3.1:8b", baseUrl: String = "http://localhost:11434", temperature: Double = 0.7, maxTokens: Int = 1024): OllamaChatResponse` | Envía una solicitud de chat completion a un servidor Ollama local. Retorna el contenido generado junto a métricas de duración y tokens evaluados. |
| `overpass_nearby_pois_kt_infra` | `fun overpassNearbyPois(lat: Double, lon: Double, radiusM: Int = 500, categories: List<String>? = null): List<POI>` | Consulta la Overpass API (OpenStreetMap) para obtener POIs cercanos a una coordenada. Soporta 16 categorias mapeadas a tags OSM (amenity, tourism, historic, leisure, shop). Sin dependencias externas: solo Android SDK (HttpURLConnection + org.json). |
| `run_kotlin_app_tests_bash_pipelines` | `run_kotlin_app_tests(project_dir: string, avd_name?: string, --skip-emulator?, --no-stop?) -> int` | Pipeline e2e completo de testing app Kotlin: unit JVM + screenshot Roborazzi + build APK + instrumented Compose en emulador. |
## Ejemplo canonico
_(Anadir 1-2 bloques de codigo end-to-end)_
## Fronteras
_(Que NO cubre este grupo)_
+43
View File
@@ -0,0 +1,43 @@
# Capability: bigquery
_(Descripcion del grupo — editar a mano)_
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `bq_auth_py_infra` | `def bq_auth(project_id: str = '', credentials_path: str = '') -> BQClient` | Autentica contra Google BigQuery con ADC o service account JSON. Retorna un BQClient listo para usar con todas las funciones CRUD. |
| `bq_cancel_job_py_infra` | `def bq_cancel_job(client: BQClient, job_id: str) -> dict` | Cancela un job en ejecucion. Retorna el estado tras la cancelacion. |
| `bq_copy_table_py_infra` | `def bq_copy_table(client: BQClient, source_dataset: str, source_table: str, dest_dataset: str, dest_table: str, write_disposition: str = 'WRITE_EMPTY') -> dict` | Copia una tabla BigQuery a otro dataset o tabla dentro del mismo proyecto usando copy_table del SDK. Espera la finalizacion del CopyJob. |
| `bq_create_dataset_py_infra` | `def bq_create_dataset(client: BQClient, dataset_id: str, location: str = 'US', description: str = '', labels: dict[str, str] \| None = None, default_table_expiration_ms: int = 0) -> dict` | Crea un dataset en Google BigQuery con ubicacion, descripcion y labels. Usa client._client.create_dataset() del SDK oficial. |
| `bq_create_routine_py_infra` | `def bq_create_routine(client: BQClient, dataset_id: str, routine_id: str, body: str, routine_type: str = 'SCALAR_FUNCTION', language: str = 'SQL', arguments: list[dict] \| None = None, return_type: str = '', description: str = '') -> dict` | Crea una routine (UDF scalar, tabla o stored procedure) en BigQuery. Soporta SQL, JavaScript y Python. |
| `bq_create_table_py_infra` | `def bq_create_table(client: BQClient, dataset_id: str, table_id: str, schema: list[dict], partitioning: dict \| None = None, clustering: list[str] \| None = None, description: str = '', labels: dict \| None = None) -> dict` | Crea una tabla en BigQuery con schema, particionamiento opcional y clustering. Usa client._client.create_table() del SDK oficial. |
| `bq_delete_dataset_py_infra` | `def bq_delete_dataset(client: BQClient, dataset_id: str, delete_contents: bool = False) -> None` | Elimina un dataset de Google BigQuery. IRREVERSIBLE. Usa client._client.delete_dataset() del SDK oficial. |
| `bq_delete_routine_py_infra` | `def bq_delete_routine(client: BQClient, dataset_id: str, routine_id: str) -> None` | Elimina una routine de un dataset. |
| `bq_delete_table_py_infra` | `def bq_delete_table(client: BQClient, dataset_id: str, table_id: str) -> None` | Elimina permanentemente una tabla de BigQuery. IRREVERSIBLE. Usa client._client.delete_table() del SDK oficial. |
| `bq_export_to_gcs_py_infra` | `def bq_export_to_gcs(client: BQClient, dataset_id: str, table_id: str, destination_uri: str, destination_format: str = 'CSV', compression: str = 'NONE') -> dict` | Exporta una tabla BigQuery a Google Cloud Storage usando extract_table del SDK. Soporta CSV, JSON, Avro y Parquet con compresion opcional. |
| `bq_get_dataset_py_infra` | `def bq_get_dataset(client: BQClient, dataset_id: str) -> dict` | Obtiene los detalles completos de un dataset de Google BigQuery. Usa client._client.get_dataset() del SDK oficial. |
| `bq_get_job_py_infra` | `def bq_get_job(client: BQClient, job_id: str) -> dict` | Obtiene detalles completos de un job por su ID incluyendo estado, bytes procesados y errores. Incluye campos adicionales respecto a bq_list_jobs: destination_table, query y lista de errores. |
| `bq_get_table_py_infra` | `def bq_get_table(client: BQClient, dataset_id: str, table_id: str) -> dict` | Obtiene los metadatos completos de una tabla BigQuery incluyendo schema, estadisticas y configuracion. Usa client._client.get_table() del SDK oficial. |
| `bq_insert_rows_py_infra` | `def bq_insert_rows(client: BQClient, dataset_id: str, table_id: str, rows: list[dict]) -> dict` | Inserta filas en una tabla BigQuery usando streaming insert (insert_rows_json). Retorna el conteo de filas insertadas y errores por fila. |
| `bq_list_datasets_py_infra` | `def bq_list_datasets(client: BQClient) -> list[dict]` | Lista todos los datasets del proyecto de Google BigQuery. Usa client._client.list_datasets() del SDK oficial. |
| `bq_list_jobs_py_infra` | `def bq_list_jobs(client: BQClient, state_filter: str = '', max_results: int = 50, all_users: bool = False) -> list[dict]` | Lista jobs del proyecto con filtro por estado (running, pending, done). Retorna una lista de dicts planos con metadatos de cada job. |
| `bq_list_routines_py_infra` | `def bq_list_routines(client: BQClient, dataset_id: str) -> list[dict]` | Lista routines de un dataset incluyendo tipo y lenguaje. |
| `bq_list_tables_py_infra` | `def bq_list_tables(client: BQClient, dataset_id: str) -> list[dict]` | Lista todas las tablas (y vistas) de un dataset BigQuery con informacion resumida. Usa client._client.list_tables() del SDK oficial. |
| `bq_load_from_file_py_infra` | `def bq_load_from_file(client: BQClient, file_path: str, dataset_id: str, table_id: str, source_format: str = 'CSV', write_disposition: str = 'WRITE_APPEND', autodetect: bool = True, skip_leading_rows: int = 0) -> dict` | Carga datos desde un archivo local a una tabla BigQuery usando load_table_from_file del SDK. Equivalente a bq_load_from_gcs pero para disco local. |
| `bq_load_from_gcs_py_infra` | `def bq_load_from_gcs(client: BQClient, uri: str \| list[str], dataset_id: str, table_id: str, source_format: str = 'CSV', write_disposition: str = 'WRITE_APPEND', autodetect: bool = True, skip_leading_rows: int = 0) -> dict` | Carga datos desde uno o varios URIs de Google Cloud Storage a una tabla BigQuery configurando un LoadJob. Espera la finalizacion del job. |
| `bq_preview_rows_py_infra` | `def bq_preview_rows(client: BQClient, dataset_id: str, table_id: str, max_results: int = 10) -> dict` | Obtiene una muestra de filas de una tabla BigQuery sin ejecutar query SQL, sin coste de procesamiento. Usa client._client.list_rows() del SDK oficial. |
| `bq_query_py_infra` | `def bq_query(client: BQClient, sql: str, params: list[dict] \| None = None, dry_run: bool = False) -> dict` | Ejecuta una query SQL en BigQuery con soporte para parametros tipados y modo dry-run para estimacion de costos. |
| `bq_update_dataset_py_infra` | `def bq_update_dataset(client: BQClient, dataset_id: str, description: str \| None = None, labels: dict[str, str] \| None = None, default_table_expiration_ms: int \| None = None) -> dict` | Actualiza campos de un dataset de Google BigQuery. Solo modifica los campos pasados explicitamente (no-None). Usa client._client.update_dataset() del SDK oficial. |
| `bq_update_table_py_infra` | `def bq_update_table(client: BQClient, dataset_id: str, table_id: str, schema: list[dict] \| None = None, description: str \| None = None, labels: dict \| None = None) -> dict` | Actualiza metadatos de una tabla BigQuery: schema (solo adicion de columnas), descripcion y etiquetas. Usa client._client.update_table() del SDK oficial. |
| `fetch_data_frame_go_datascience` | `func FetchDataFrame(dsn, query string) ([]map[string]any, error)` | Ejecuta una consulta SQL contra un DSN y retorna los resultados como slice de mapas columna-valor. |
| `metabase_smartscalar_kpi_sql_py_infra` | `def metabase_smartscalar_kpi_sql(*, act_expr: str, n1_expr: str, body_sql: str, date_expr: str = 'MIN(fecha)') -> str` | Envuelve agregaciones actual+n-1 en el patron de 2 filas (periodo, valor) que el display smartscalar de Metabase v0.59 requiere para mostrar comparacion vs ano anterior sin pedir breakout temporal. Genera SQL nativo BigQuery con UNION ALL d_min/d_min-52w. |
## Ejemplo canonico
_(Anadir 1-2 bloques de codigo end-to-end)_
## Fronteras
_(Que NO cubre este grupo)_
+55
View File
@@ -0,0 +1,55 @@
# Capability: docker
_(Descripcion del grupo — editar a mano)_
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `assert_docker_container_running_bash_infra` | `assert_docker_container_running(container_name: string) -> void` | Verifica que un contenedor Docker está corriendo. Sale con exit code 1 si no está activo, con mensaje a stderr. |
| `deploy_app_go_infra` | `func DeployApp(appDir string, imageName string, port int, envVars map[string]string) (string, error)` | Orquesta el deploy completo de una app Go en Docker. Pasos: genera Dockerfile, lo escribe a disco, construye la imagen y lanza el contenedor en modo detach con port mapping. Retorna el container ID. |
| `docker_build_image_go_infra` | `func DockerBuildImage(contextDir, tag string, buildArgs map[string]string) (string, error)` | Construye una imagen Docker desde un directorio con Dockerfile. Soporta build args opcionales. Retorna el image ID de la imagen construida. |
| `docker_compose_down_go_infra` | `func DockerComposeDown(composeFile string, removeVolumes bool) (string, error)` | Baja un stack docker-compose desde el archivo dado. Si removeVolumes es true elimina también los volumes declarados (-v). Retorna el stdout del comando. |
| `docker_compose_remote_deploy_bash_infra` | `docker_compose_remote_deploy(host: string, remote_dir: string, branch: string, compose_files: string) -> json` | Despliega un stack Docker Compose en un host remoto via SSH. Verifica conectividad, hace git pull del branch indicado, actualiza imagenes con docker-compose pull y levanta/recrea los servicios modificados con docker-compose up -d. Soporta compose files adicionales. Retorna JSON con status, containers corriendo y duracion. |
| `docker_compose_up_go_infra` | `func DockerComposeUp(composeFile string, detach bool) (string, error)` | Levanta un stack docker-compose desde el archivo dado. Si detach es true ejecuta en background (-d). Retorna el stdout del comando. |
| `docker_container_logs_go_infra` | `func DockerContainerLogs(nameOrID string, tail int) (string, error)` | Obtiene los logs de un contenedor Docker. El parámetro tail limita a las últimas N líneas (0 devuelve todos los logs). |
| `docker_container_running_py_infra` | `docker_container_running(name: str, timeout: float = 5.0) -> bool` | Comprueba si un contenedor Docker existe y está corriendo. True solo si docker inspect retorna State.Running=true. Cualquier fallo (docker ausente, contenedor inexistente, daemon caído, timeout) devuelve False sin excepción. |
| `docker_cp_file_bash_infra` | `docker_cp_file(local_path: string, container_name: string, dest_path: string) -> string` | Copia un archivo local a un contenedor Docker y verifica que el tamaño coincide. Imprime JSON con local_size y remote_size a stdout. Sale con exit code 1 si docker cp falla o los tamaños difieren. |
| `docker_create_network_go_infra` | `func DockerCreateNetwork(name, driver string) (string, error)` | Crea una red Docker con el nombre y driver dados. Si driver está vacío usa bridge por defecto. Devuelve el ID de la red creada. |
| `docker_inspect_container_go_infra` | `func DockerInspectContainer(nameOrID string) (map[string]any, error)` | Devuelve los detalles completos de un contenedor Docker como mapa JSON genérico. Útil para inspeccionar configuración, red, volumes, etc. |
| `docker_list_containers_go_infra` | `func DockerListContainers(all bool) ([]ContainerInfo, error)` | Lista contenedores Docker locales. Si all es true incluye contenedores detenidos. Parsea la salida JSON de docker ps. |
| `docker_list_images_go_infra` | `func DockerListImages() ([]ImageInfo, error)` | Lista las imágenes Docker disponibles localmente. Parsea la salida JSON de docker images. |
| `docker_pull_image_go_infra` | `func DockerPullImage(image string) error` | Descarga una imagen Docker desde el registry remoto (Docker Hub u otro configurado). Acepta formato image:tag. |
| `docker_remove_container_go_infra` | `func DockerRemoveContainer(nameOrID string, force bool) error` | Elimina un contenedor Docker. Con force=true puede eliminar contenedores en ejecución (equivale a docker rm -f). |
| `docker_remove_image_go_infra` | `func DockerRemoveImage(image string, force bool) error` | Elimina una imagen Docker local. Con force=true fuerza la eliminación incluso si hay contenedores que la usan. |
| `docker_remove_network_go_infra` | `func DockerRemoveNetwork(nameOrID string) error` | Elimina una red Docker por nombre o ID. |
| `docker_run_container_go_infra` | `func DockerRunContainer(image string, opts DockerRunOpts) (string, error)` | Ejecuta un contenedor Docker nuevo a partir de una imagen. Soporta puertos, env vars, volumes, network, detach y auto-remove. Devuelve el ID del contenedor. |
| `docker_start_container_go_infra` | `func DockerStartContainer(nameOrID string) error` | Inicia un contenedor Docker existente que está detenido. Recibe nombre o ID del contenedor. |
| `docker_stop_container_go_infra` | `func DockerStopContainer(nameOrID string, timeoutSecs int) error` | Detiene un contenedor Docker en ejecución. timeoutSecs controla el tiempo de gracia antes de SIGKILL (0 usa el default de Docker). |
| `docker_tui_go_infra` | `func main() — TUI fullscreen para gestionar Docker` | Pipeline que compone componentes TUI de DevFactory con comandos Docker para crear una aplicacion de terminal interactiva. Gestiona containers, images, volumes, networks y compose. |
| `docker_volume_create_go_infra` | `func DockerVolumeCreate(name string) (string, error)` | Crea un volume Docker con el nombre dado. Retorna el nombre del volume creado tal como lo confirma Docker. |
| `docker_volume_list_go_infra` | `func DockerVolumeList() ([]map[string]string, error)` | Lista los volumes Docker disponibles localmente. Parsea la salida JSON de docker volume ls. Retorna slice de maps con campos Driver, Name, Scope, Labels, Mountpoint. |
| `docker_volume_remove_go_infra` | `func DockerVolumeRemove(name string, force bool) error` | Elimina un volume Docker por nombre. Si force es true fuerza la eliminación aunque esté en uso. |
| `dockerize_app_bash_pipelines` | `dockerize_app(app_name: string, [--domain DOMAIN], [--port PORT], [--ssh-host HOST], [--remote-dir DIR], [--basic-auth USER:PASS], [--no-auth], [--no-gzip], [--env KEY=VAL]..., [--volume NAME], [--build-cmd CMD], [--standalone], [--dry-run]) -> json` | Empaqueta una app Go del registry para deploy a VPS organic-machine via Docker + Traefik + Coolify. Genera Dockerfile multi-stage, docker-compose.yml, traefik-dynamic.yml con basicAuth opcional y gzip, sube via rsync al VPS y arranca el stack remoto. Replica el patron de apps/registry_api/. |
| `generate_compose_traefik_go_infra` | `func GenerateComposeTraefik(cfg ComposeTraefikConfig) string` | Genera el texto YAML de un docker-compose.yml para una app Go desplegada behind Traefik + Coolify. Replica el patron de apps/registry_api/docker-compose.yml. Determinista: orden de EnvVars sigue el orden de entrada. |
| `generate_dockerfile_go_infra` | `func GenerateDockerfile(binaryName string, port int, envVars map[string]string) string` | Genera el texto de un Dockerfile multi-stage para una app Go. Stage build con golang:1.23-alpine, stage final con alpine:latest. Incluye ENV vars del map con orden determinista. Funcion pura sin I/O. |
| `init_metabase_go_infra` | `func main() — Despliega stack Metabase + Postgres en Docker` | Pipeline que inicializa un contenedor Metabase con su base de datos Postgres. Crea red Docker, pull de imágenes, inicia Postgres con volume persistente, espera health check y lanza Metabase conectado. |
| `metabase_add_ops_db_py_pipelines` | `metabase_add_ops_db(app_name: str) -> None` | Registra la operations.db de una app en Metabase como database SQLite. Verifica duplicados y muestra el mount necesario para el contenedor Docker. |
| `metabase_fix_permissions_py_pipelines` | `metabase_fix_permissions() -> None` | Arregla permisos SQLITE_READONLY_DIRECTORY en el contenedor Metabase. Hace chmod 777/666 en directorios y archivos .db bajo /data/ para que el usuario metabase (UID 2000) pueda crear journal files. |
| `nordvpn_container_run_go_infra` | `func NordVPNContainerRun(opts NordVPNContainerRunOpts) (string, error)` | Ejecuta un container Docker cuyo trafico pasa por el gateway NordVPN usando --network=container:<gateway>. El container hereda la IP y tunel VPN del gateway. |
| `nordvpn_container_start_go_infra` | `func NordVPNContainerStart(opts NordVPNContainerOpts) (string, error)` | Levanta un container Docker con NordVPN como gateway de red. Otros containers pueden rutear su trafico a traves de este con --network=container:<name>. Espera hasta 30s a que el tunel este activo. |
| `nordvpn_container_stop_go_infra` | `func NordVPNContainerStop(gateway string, clientNames ...string) error` | Detiene y elimina el container gateway NordVPN y opcionalmente los containers cliente que usan su red. |
| `setup_geo_stack_docker_pipeline_py_pipelines` | `def setup_geo_stack_docker_pipeline(compose_path: str, wait_seconds: int, verify: bool) -> dict` | Levanta el geo stack Docker (Valhalla + PostGIS + Martin) via docker compose up -d y verifica que los tres servicios responden. |
| `setup_metabase_volume_bash_pipelines` | `setup_metabase_volume([registry_db_path: string], [container_name: string], [dest_path: string]) -> void` | Copia registry.db al contenedor Docker de Metabase verificando existencia del archivo, disponibilidad de docker, estado del contenedor y coincidencia de tamaños. Todos los argumentos son opcionales con defaults razonables. |
| `setup_registry_api_bash_infra` | `setup_registry_api(ssh_host: string, api_token: string, basic_auth_user: string, basic_auth_pass: string) -> json` | Deploy completo de registry_api en VPS con Docker + Traefik (Coolify proxy). Sincroniza el repo via rsync, genera el hash bcrypt para basicAuth, sube el traefik-dynamic.yml, crea el .env con el token, hace docker compose build+up y verifica el health check. |
| `stop_app_go_infra` | `func StopApp(containerName string, removeImage bool) error` | Para y elimina el contenedor de una app desplegada. Si removeImage es true elimina también la imagen Docker. containerName debe coincidir con el imageName usado en deploy_app. |
| `write_dockerfile_go_infra` | `func WriteDockerfile(dir, content string) (string, error)` | Escribe content en dir/Dockerfile. Crea el directorio si no existe. Retorna el path absoluto del archivo escrito. Compañera impura de generate_dockerfile. |
## Ejemplo canonico
_(Anadir 1-2 bloques de codigo end-to-end)_
## Fronteras
_(Que NO cubre este grupo)_
+48
View File
@@ -0,0 +1,48 @@
# Capability Group: doctor
Funciones de diagnostico read-only del registry y sus artefactos. Componen `fn doctor` — el entrypoint unico de auditoria del ecosistema. No modifican nada.
## Funciones del grupo
| ID | Firma corta | Que hace |
|---|---|---|
| `artefact_doctor_go_infra` | `ArtefactDoctor(registryRoot string) ([]ArtefactCheck, error)` | Estado git/venv/app.md/upstream de cada app y analysis |
| `audit_capability_groups_go_infra` | `AuditCapabilityGroups(root string) ([]CapabilityGroupAudit, error)` | Drift entre INDEX.md, tags en BD y docs en disco |
| `audit_copied_code_go_infra` | `AuditCopiedCode(registryRoot string) ([]CopiedCodeEntry, error)` | Cuerpos de funcion copiados del registry sin import |
| `audit_cpp_apps_go_infra` | `AuditCppApps(registryRoot string) ([]CppAppAudit, error)` | Conformidad C++ con cpp/PATTERNS.md |
| `audit_ml_env_go_infra` | `AuditMlEnv(registryRoot string) (MlEnvReport, error)` | Entorno ML: GPUs, CUDA, venv, paquetes clave |
| `audit_uses_functions_go_infra` | `AuditUsesFunctions(registryRoot string) ([]UsesFunctionsAudit, error)` | Drift uses_functions declarado vs imports reales |
| `find_unused_functions_go_infra` | `FindUnusedFunctions(registryRoot string) ([]UnusedFunction, error)` | Funciones del registry sin consumidores |
| `frontend_doctor_bash_infra` | `frontend_doctor(project_dir: string) -> diagnostics_stdout` | Diagnostico frontend: node_modules, builds, tipos |
| `pc_locations_drift_go_infra` | `PcLocationsDrift(registryRoot string, pcID string) ([]LocationDrift, error)` | Drift pc_locations BD vs disco local |
| `services_status_go_infra` | `ServicesStatus(registryRoot string) ([]ServiceStatus, error)` | Apps con tag service + systemctl + puerto |
| `vault_doctor_go_infra` | `VaultDoctor(repoRoot string) ([]VaultDoctorEntry, error)` | Estado de vaults: symlinks, manifest, integridad |
## Ejemplo canonico
```go
// Todas las funciones siguen el mismo patron:
// reciben registryRoot (raiz del repo) y retornan slice de resultados + error.
import "fn-registry/functions/infra"
audits, err := infra.AuditCapabilityGroups("/home/lucas/fn_registry")
if err != nil { log.Fatal(err) }
for _, a := range audits {
if !a.OK { fmt.Printf("%s: %v\n", a.Group, a.Issues) }
}
// fn doctor las compone todas via subcomandos:
// fn doctor artefacts → ArtefactDoctor
// fn doctor services → ServicesStatus
// fn doctor sync → PcLocationsDrift
// fn doctor uses-functions → AuditUsesFunctions
// fn doctor unused → FindUnusedFunctions
// fn doctor cpp-apps → AuditCppApps
// fn doctor capabilities → AuditCapabilityGroups
```
## Fronteras
- **Read-only**: ninguna funcion del grupo escribe, modifica estado ni mata procesos.
- **No incluye**: funciones de reparacion/fix (esas son acciones derivadas descritas en `.claude/rules/fn_doctor.md`).
- **No incluye**: `e2e_checks` ni `assertion eval` — esos son pasos del bucle reactivo, no diagnostico pasivo.
+123
View File
@@ -0,0 +1,123 @@
# Capability: metabase
_(Descripcion del grupo — editar a mano)_
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `init_metabase_go_infra` | `func main() — Despliega stack Metabase + Postgres en Docker` | Pipeline que inicializa un contenedor Metabase con su base de datos Postgres. Crea red Docker, pull de imágenes, inicia Postgres con volume persistente, espera health check y lanza Metabase conectado. |
| `metabase_add_dashboard_filter_py_infra` | `def metabase_add_dashboard_filter(client: MetabaseClient, dashboard_id: int, name: str, slug: str, filter_type: str, card_mappings: list[dict], *, default: str \| None = None) -> dict` | Añade un filtro a un dashboard de Metabase y lo conecta a las cards indicadas. Crea el parameter a nivel de dashboard y actualiza los parameter_mappings de cada dashcard. |
| `metabase_add_database_py_infra` | `def metabase_add_database(client: MetabaseClient, name: str, engine: str, details: dict) -> dict` | Agrega una nueva database a Metabase via POST /api/database. Soporta cualquier engine (sqlite, postgres, mysql, etc.). |
| `metabase_add_membership_py_infra` | `def metabase_add_membership(client: MetabaseClient, user_id: int, group_id: int, is_group_manager: bool = False) -> list[dict]` | Añade un usuario a un Permission Group de Metabase. Endpoint: POST /api/permissions/membership. Retorna la lista completa de membresías del grupo tras la operación. |
| `metabase_add_ops_db_py_pipelines` | `metabase_add_ops_db(app_name: str) -> None` | Registra la operations.db de una app en Metabase como database SQLite. Verifica duplicados y muestra el mount necesario para el contenedor Docker. |
| `metabase_archive_document_py_infra` | `def metabase_archive_document(client: MetabaseClient, document_id: int) -> dict` | Archiva un document (PUT archived=True). Prerequisito para poder eliminarlo. |
| `metabase_archive_snippet_py_infra` | `def metabase_archive_snippet(client: MetabaseClient, snippet_id: int) -> dict` | Archiva un SQL snippet en Metabase. Wrapper sobre metabase_update_snippet con archived=True. |
| `metabase_auth_go_infra` | `func MetabaseAuth(baseURL, email, password string) (MetabaseClient, error)` | Autentica contra la API de Metabase con email y password. Retorna un MetabaseClient con session token valido por 14 dias (configurable con MAX_SESSION_AGE en Metabase). Endpoint: POST /api/session. |
| `metabase_auth_py_infra` | `def metabase_auth(base_url: str, email: str, password: str) -> MetabaseClient` | Autentica contra la API de Metabase con email y password. Retorna un MetabaseClient con session token valido por 14 dias. Endpoint: POST /api/session. |
| `metabase_copy_card_py_infra` | `def metabase_copy_card(client: MetabaseClient, card_id: int, name: str \| None = None, collection_id: int \| None = None, description: str \| None = None) -> dict` | Crea una copia de una card/pregunta en Metabase via el endpoint nativo POST /api/card/:id/copy. Permite sobrescribir nombre, coleccion y descripcion en la copia. |
| `metabase_copy_dashboard_py_infra` | `def metabase_copy_dashboard(client: MetabaseClient, dashboard_id: int, name: str \| None = None, collection_id: int \| None = None, description: str \| None = None, is_deep_copy: bool = False) -> dict` | Crea una copia de un dashboard en Metabase via POST /api/dashboard/:id/copy. Con is_deep_copy=True tambien clona las cards referenciadas. |
| `metabase_copy_dashcard_mappings_py_infra` | `def metabase_copy_dashcard_mappings(client: MetabaseClient, *, dashboard_id: int, source_card_id: int, dest_card_id: int) -> list[dict]` | Copia los parameter_mappings del primer dashcard con source_card_id al card destino (dest_card_id), devolviendo una lista nueva de mappings sin mutar el original. Util para replicar filtros de dashboard a cards nuevas sin copiar manualmente cada mapping. |
| `metabase_copy_document_py_infra` | `def metabase_copy_document(client: MetabaseClient, document_id: int, name: str \| None = None, collection_id: int \| None = None) -> dict` | Copia un document usando el endpoint nativo POST /api/document/:id/copy. Un solo request HTTP. |
| `metabase_create_card_alert_py_infra` | `def metabase_create_card_alert(client: MetabaseClient, card_id: int, cron_schedule: str, recipients: list[dict], send_condition: str = 'has_result', send_once: bool = False) -> dict` | Crea una alerta sobre los resultados de una card en Metabase. Envia email segun cron cuando la card cumple la condicion (has_result, goal_above, goal_below). Endpoint: POST /api/notification. |
| `metabase_create_card_go_infra` | `func MetabaseCreateCard(client MetabaseClient, name string, datasetQuery map[string]any, display string, collectionID int, description string) (map[string]any, error)` | Crea una nueva card/pregunta en Metabase con query SQL nativa o MBQL. Endpoint: POST /api/card. |
| `metabase_create_card_py_infra` | `def metabase_create_card(client: MetabaseClient, name: str, dataset_query: dict, display: str = 'table', collection_id: int = 0, description: str = '') -> dict` | Crea una card/pregunta en Metabase con query SQL nativa o MBQL. Endpoint: POST /api/card. |
| `metabase_create_card_raw_py_infra` | `def metabase_create_card_raw(client: MetabaseClient, payload: dict) -> dict` | Crea una card en Metabase enviando el payload completo sin modificaciones. Version raw para flujos Metabase-as-code donde el caller construye el body entero. Endpoint: POST /api/card. |
| `metabase_create_dashboard_go_infra` | `func MetabaseCreateDashboard(client MetabaseClient, name, description string, collectionID int) (map[string]any, error)` | Crea un nuevo dashboard vacio en Metabase. Para agregar cards usar MetabaseUpdateDashboard con el campo dashcards. Endpoint: POST /api/dashboard. |
| `metabase_create_dashboard_py_infra` | `def metabase_create_dashboard(client: MetabaseClient, name: str, description: str = '', collection_id: int = 0) -> dict` | Crea dashboard vacio en Metabase. Para agregar cards usar metabase_update_dashboard con dashcards. Endpoint: POST /api/dashboard. |
| `metabase_create_dashboard_raw_py_infra` | `def metabase_create_dashboard_raw(client: MetabaseClient, payload: dict) -> dict` | Crea un dashboard en Metabase enviando el payload completo sin modificaciones. Maneja automaticamente la limitacion de la API que no acepta dashcards en el POST inicial: si el payload contiene dashcards, hace POST para crear el dashboard y luego PUT para añadir las cards. Endpoint: POST /api/dashboard (+ PUT condicional). |
| `metabase_create_dashboard_subscription_py_infra` | `def metabase_create_dashboard_subscription(client: MetabaseClient, dashboard_id: int, cron_schedule: str, recipients: list[dict]) -> dict` | Crea una suscripcion periodica a un dashboard de Metabase. Envia el dashboard completo por email segun el cron configurado. Endpoint: POST /api/notification. |
| `metabase_create_document_comment_py_infra` | `def metabase_create_document_comment(client: MetabaseClient, document_id: int, content: dict, *, child_target_id: str \| None = None, parent_comment_id: int \| None = None) -> dict` | Crea un comentario en un document. Soporta anclaje a bloque concreto (via UUID de _id) y respuestas en thread (via parent_comment_id). Endpoint: POST /api/comment. |
| `metabase_create_document_py_infra` | `def metabase_create_document(client: MetabaseClient, name: str, document: dict, collection_id: int = 0, *, validate: bool = True) -> dict` | Crea un document con contenido ProseMirror. Valida el arbol contra la whitelist de nodos ANTES de enviar (evita documentos que la API acepta pero el frontend renderiza vacíos). Usar prosemirror_card_embed() para embeber cards. |
| `metabase_create_group_py_infra` | `def metabase_create_group(client: MetabaseClient, name: str) -> dict` | Crea un nuevo Permission Group en Metabase. El nombre debe ser unico. Retorna el grupo creado con su id asignado. Endpoint: POST /api/permissions/group. |
| `metabase_create_model_py_infra` | `def metabase_create_model(client: MetabaseClient, name: str, sql: str, database_id: int, collection_id: int = 0, description: str = '') -> dict` | Crea un modelo de Metabase (card con type='model') que otras cards MBQL pueden usar como fuente via source-table: 'card__<id>'. |
| `metabase_create_ops_dashboard_py_pipelines` | `metabase_create_ops_dashboard(app_name: str) -> None` | Crea dashboard operativo en Metabase para una app: KPIs de entities/relations/executions/assertions, distribucion por status y tipo, relaciones frecuentes, resultados de ejecuciones y assertions. |
| `metabase_create_snippet_py_infra` | `def metabase_create_snippet(client: MetabaseClient, name: str, content: str, description: str = "", collection_id: int = 0) -> dict` | Crea un nuevo SQL snippet reutilizable en Metabase. El snippet se referencia en queries nativas con {{snippet: nombre}}. |
| `metabase_create_user_go_infra` | `func MetabaseCreateUser(client MetabaseClient, firstName, lastName, email, password string, groupIDs []int) (map[string]any, error)` | Crea un nuevo usuario en Metabase. Si no se provee password, Metabase envia email de invitacion. Requiere permisos de superusuario. Endpoint: POST /api/user. |
| `metabase_create_user_py_infra` | `def metabase_create_user(client: MetabaseClient, first_name: str, last_name: str, email: str, password: str = '', group_ids: list[int] \| None = None) -> dict` | Crea un nuevo usuario en Metabase. Sin password envia invitacion por email. Requiere superusuario. Endpoint: POST /api/user. |
| `metabase_dashboard_append_row_py_infra` | `def metabase_dashboard_append_row(client: MetabaseClient, *, dashboard_id: int, tab_id: int, card_ids: list[int], height: int = 4, donor_card_id: int = 0, grid_width: int = 24) -> dict` | Añade N cards como fila horizontal al final de una tab de dashboard. Calcula la primera fila libre con metabase_dashboard_next_row, distribuye las cards con ancho uniforme (grid_width // N), copia parameter_mappings de un dashcard donante si se indica y llama a metabase_update_dashboard_safe. Util para añadir filas de KPIs con los filtros del dashboard ya conectados. |
| `metabase_dashboard_next_row_py_infra` | `def metabase_dashboard_next_row(client: MetabaseClient, *, dashboard_id: int, tab_id: int = 0) -> int` | Calcula la primera fila libre al final de una tab de dashboard: max(dc.row + dc.size_y) entre las dashcards de esa tab. Retorna 0 si la tab esta vacia. Evita el boilerplate manual de max() al colocar nuevas cards al final del dashboard. |
| `metabase_deactivate_user_go_infra` | `func MetabaseDeactivateUser(client MetabaseClient, userID int) error` | Desactiva (soft-delete) un usuario en Metabase. El usuario no se elimina permanentemente, solo se marca como inactivo. Para reactivar, usar PUT /api/user/:id/reactivate. Endpoint: DELETE /api/user/:id. |
| `metabase_deactivate_user_py_infra` | `def metabase_deactivate_user(client: MetabaseClient, user_id: int) -> None` | Desactiva (soft-delete) un usuario en Metabase. Reactivar con PUT /api/user/:id/reactivate. Endpoint: DELETE /api/user/:id. |
| `metabase_delete_card_go_infra` | `func MetabaseDeleteCard(client MetabaseClient, cardID int) error` | Elimina permanentemente una card/pregunta de Metabase. Accion irreversible. Para soft-delete usar MetabaseUpdateCard con archived:true. Endpoint: DELETE /api/card/:id. |
| `metabase_delete_card_py_infra` | `def metabase_delete_card(client: MetabaseClient, card_id: int) -> None` | Elimina permanentemente una card/pregunta. IRREVERSIBLE. Preferir archived=True. Endpoint: DELETE /api/card/:id. |
| `metabase_delete_dashboard_go_infra` | `func MetabaseDeleteDashboard(client MetabaseClient, dashboardID int) error` | Elimina permanentemente un dashboard de Metabase. Accion irreversible. Para soft-delete usar MetabaseUpdateDashboard con archived:true. Endpoint: DELETE /api/dashboard/:id. |
| `metabase_delete_dashboard_py_infra` | `def metabase_delete_dashboard(client: MetabaseClient, dashboard_id: int) -> None` | Elimina permanentemente un dashboard. IRREVERSIBLE. Preferir archived=True. Endpoint: DELETE /api/dashboard/:id. |
| `metabase_delete_document_py_infra` | `def metabase_delete_document(client: MetabaseClient, document_id: int) -> None` | Elimina un document. Requiere archivado previo (Metabase rechaza DELETE si archived=False). |
| `metabase_delete_group_py_infra` | `def metabase_delete_group(client: MetabaseClient, group_id: int) -> None` | Elimina permanentemente un Permission Group de Metabase. IRREVERSIBLE. No borra los usuarios, solo el grupo. Endpoint: DELETE /api/permissions/group/:id. |
| `metabase_delete_membership_py_infra` | `def metabase_delete_membership(client: MetabaseClient, membership_id: int) -> None` | Elimina una membresía de grupo en Metabase por su membership_id. Endpoint: DELETE /api/permissions/membership/:id. NO acepta user_id+group_id — requiere el membership_id exacto. |
| `metabase_delete_notification_py_infra` | `def metabase_delete_notification(client: MetabaseClient, notification_id: int) -> None` | Elimina una notificacion de Metabase (alerta de card o suscripcion de dashboard). Operacion irreversible. Endpoint: DELETE /api/notification/:id. |
| `metabase_execute_card_go_infra` | `func MetabaseExecuteCard(client MetabaseClient, cardID int, parameters []map[string]any) (map[string]any, error)` | Ejecuta la query de una card/pregunta guardada en Metabase y retorna los resultados. Soporta parametros para queries parametrizadas. Endpoint: POST /api/card/:id/query. |
| `metabase_execute_card_py_infra` | `def metabase_execute_card(client: MetabaseClient, card_id: int, parameters: list[dict] \| None = None) -> dict` | Ejecuta la query de una card guardada y retorna resultados con columnas y filas. Soporta parametros. Endpoint: POST /api/card/:id/query. |
| `metabase_execute_query_go_infra` | `func MetabaseExecuteQuery(client MetabaseClient, databaseID int, sql string, maxResults int) (map[string]any, error)` | Ejecuta una query SQL ad-hoc contra una database de Metabase sin guardarla como card. Util para consultas rapidas y exploracion. Endpoint: POST /api/dataset. |
| `metabase_execute_query_py_infra` | `def metabase_execute_query(client: MetabaseClient, database_id: int, sql: str, max_results: int = 0) -> dict` | Ejecuta query SQL ad-hoc contra Metabase sin guardarla como card. Util para exploracion rapida. Endpoint: POST /api/dataset. |
| `metabase_export_card_py_infra` | `def metabase_export_card(client: MetabaseClient, card_id: int, format: str = 'csv') -> bytes` | Exporta los resultados de una card de Metabase en CSV, XLSX o JSON. Endpoint: POST /api/card/:id/query/:format. |
| `metabase_fix_null_ratio_py_infra` | `def metabase_fix_null_ratio(client: MetabaseClient, *, dry_run: bool = True, card_ids: list[int] \| None = None) -> dict` | Detecta y repara el patron vulnerable SUM(a-b)/SUM(b) en cards MBQL de Metabase. Cuando una resta pre-agg tiene operandos con NULL, SUM(A-B)!=SUM(A)-SUM(B). El fix reescribe las referencias post-agg al slot diferencia para usar (SUM(A)-SUM(B)) en su lugar. Soporta dry_run para escanear sin modificar. |
| `metabase_fix_permissions_py_pipelines` | `metabase_fix_permissions() -> None` | Arregla permisos SQLITE_READONLY_DIRECTORY en el contenedor Metabase. Hace chmod 777/666 en directorios y archivos .db bajo /data/ para que el usuario metabase (UID 2000) pueda crear journal files. |
| `metabase_get_card_go_infra` | `func MetabaseGetCard(client MetabaseClient, cardID int) (map[string]any, error)` | Obtiene los detalles completos de una card/pregunta de Metabase por su ID. Incluye la query, visualizacion y metadata. Endpoint: GET /api/card/:id. |
| `metabase_get_card_py_infra` | `def metabase_get_card(client: MetabaseClient, card_id: int) -> dict` | Obtiene detalles completos de una card/pregunta de Metabase incluyendo query, visualizacion y metadata. Endpoint: GET /api/card/:id. |
| `metabase_get_collection_graph_py_infra` | `def metabase_get_collection_graph(client: MetabaseClient, namespace: str \| None = None) -> dict` | Obtiene el grafo de permisos de colecciones de Metabase. Endpoint: GET /api/collection/graph. Soporta namespace opcional para snippet collections. El campo revision es crítico para concurrency control en el PUT posterior. |
| `metabase_get_dashboard_go_infra` | `func MetabaseGetDashboard(client MetabaseClient, dashboardID int) (map[string]any, error)` | Obtiene un dashboard completo de Metabase incluyendo todas sus dashcards (cards posicionadas en el dashboard), tabs y parametros. Endpoint: GET /api/dashboard/:id. |
| `metabase_get_dashboard_py_infra` | `def metabase_get_dashboard(client: MetabaseClient, dashboard_id: int) -> dict` | Obtiene dashboard completo con dashcards (cards posicionadas), tabs y parametros. Endpoint: GET /api/dashboard/:id. |
| `metabase_get_database_py_infra` | `def metabase_get_database(client: MetabaseClient, database_id: int) -> dict` | Obtiene los detalles de una database de Metabase por su ID. Endpoint: GET /api/database/:id. |
| `metabase_get_document_py_infra` | `def metabase_get_document(client: MetabaseClient, document_id: int) -> dict` | Obtiene un document completo con su arbol ProseMirror (campo document). Endpoint: GET /api/document/:id. |
| `metabase_get_group_py_infra` | `def metabase_get_group(client: MetabaseClient, group_id: int) -> dict` | Obtiene un Permission Group de Metabase por ID, incluyendo la lista completa de miembros con sus datos. Endpoint: GET /api/permissions/group/:id. |
| `metabase_get_permission_graph_py_infra` | `def metabase_get_permission_graph(client: MetabaseClient) -> dict` | Obtiene el grafo de permisos de datos (databases/schemas/tables) de Metabase. Endpoint: GET /api/permissions/graph. El campo revision es crítico para concurrency control en el PUT posterior. |
| `metabase_get_snippet_py_infra` | `def metabase_get_snippet(client: MetabaseClient, snippet_id: int) -> dict` | Obtiene un SQL snippet de Metabase por su ID. Endpoint: GET /api/native-query-snippet/:id. |
| `metabase_get_user_go_infra` | `func MetabaseGetUser(client MetabaseClient, userID int) (map[string]any, error)` | Obtiene los detalles de un usuario de Metabase por su ID numerico. Endpoint: GET /api/user/:id. |
| `metabase_get_user_py_infra` | `def metabase_get_user(client: MetabaseClient, user_id: int) -> dict` | Obtiene los detalles de un usuario de Metabase por su ID. Endpoint: GET /api/user/:id. |
| `metabase_list_cards_go_infra` | `func MetabaseListCards(client MetabaseClient, filter string, modelID int) ([]map[string]any, error)` | Lista preguntas/cards de Metabase con filtro opcional. Retorna array de cards. Endpoint: GET /api/card. |
| `metabase_list_cards_py_infra` | `def metabase_list_cards(client: MetabaseClient, filter: str = '', model_id: int = 0) -> list[dict]` | Lista preguntas/cards de Metabase. Filtros: all, mine, fav, archived, recent, popular, database, table. Endpoint: GET /api/card. |
| `metabase_list_dashboards_go_infra` | `func MetabaseListDashboards(client MetabaseClient, filter string) ([]map[string]any, error)` | Lista dashboards de Metabase con filtro opcional. Retorna array de dashboards resumidos (sin dashcards). Endpoint: GET /api/dashboard. |
| `metabase_list_dashboards_py_infra` | `def metabase_list_dashboards(client: MetabaseClient, filter: str = '') -> list[dict]` | Lista dashboards de Metabase. Filtros: all, mine, archived. Retorna resumen sin dashcards. Endpoint: GET /api/dashboard. |
| `metabase_list_databases_py_infra` | `def metabase_list_databases(client: MetabaseClient, include_tables: bool = False) -> list` | Lista las databases configuradas en Metabase. Endpoint: GET /api/database. Soporta incluir tablas con include_tables=True. |
| `metabase_list_document_comments_py_infra` | `def metabase_list_document_comments(client: MetabaseClient, document_id: int, *, include_resolved: bool = True, include_deleted: bool = False) -> list[dict]` | Lista los comentarios de un document (threads, anclajes por bloque UUID, reacciones). Endpoint no documentado: GET /api/comment?target_type=document&target_id=:id. |
| `metabase_list_documents_py_infra` | `def metabase_list_documents(client: MetabaseClient) -> list[dict]` | Lista documents (texto ProseMirror tipo Notion, feature 0.57+). Endpoint: GET /api/document. Desenrolla {items: [...]}. |
| `metabase_list_groups_py_infra` | `def metabase_list_groups(client: MetabaseClient) -> list[dict]` | Lista todos los Permission Groups de Metabase con su member_count. Requiere superusuario. Endpoint: GET /api/permissions/group. |
| `metabase_list_memberships_py_infra` | `def metabase_list_memberships(client: MetabaseClient) -> dict[str, list[dict]]` | Lista todas las membresías de grupos de Metabase. Endpoint: GET /api/permissions/membership. Retorna dict con group_id (str) como clave y lista de membresías como valor. |
| `metabase_list_notifications_py_infra` | `def metabase_list_notifications(client: MetabaseClient, card_id: int = 0, dashboard_id: int = 0) -> list[dict]` | Lista notificaciones de Metabase (alertas y suscripciones). Filtra opcionalmente por card_id o dashboard_id. Endpoint: GET /api/notification. |
| `metabase_list_snippets_py_infra` | `def metabase_list_snippets(client: MetabaseClient, archived: bool = False) -> list[dict]` | Lista SQL snippets reutilizables de Metabase. Un snippet se referencia en queries con {{snippet: nombre}}. |
| `metabase_list_users_go_infra` | `func MetabaseListUsers(client MetabaseClient, status, query string, limit, offset int) (map[string]any, error)` | Lista usuarios de una instancia Metabase con filtros opcionales por estado, nombre/email y paginacion. Endpoint: GET /api/user. Requiere permisos de superusuario. |
| `metabase_list_users_py_infra` | `def metabase_list_users(client: MetabaseClient, status: str = '', query: str = '', limit: int = 0, offset: int = 0) -> dict` | Lista usuarios de Metabase con filtros opcionales por estado, nombre/email y paginacion. Endpoint: GET /api/user. |
| `metabase_mbql_from_source_card_py_metabase` | `def metabase_mbql_from_source_card(*, database_id: int, source_card_id: int, aggregations: list[dict], joins: list[dict] \| None = None, filters: list[list] \| None = None, breakouts: list[dict] \| None = None, expressions: list[dict] \| None = None) -> dict` | Construye un dataset_query MBQL que envuelve una saved card (source-card) con agregaciones, joins opcionales, filtros, breakouts y una segunda etapa de expressions calculadas. Genera automaticamente todos los lib/uuid con uuid4. Elimina la necesidad de construir el JSON MBQL manualmente para el patron comun de agregar sobre una card guardada y anadir expresiones derivadas. |
| `metabase_mbql_validate_py_core` | `def metabase_mbql_validate(dataset_query: dict) -> list[str]` | Valida la estructura de un dataset_query MBQL sin I/O. Detecta UUIDs duplicados, stage mixing (aggregations + expressions que referencian slots en la misma stage), slot refs rotas (sum_X inexistente), case structures invalidas y name collisions en expressions. Retorna lista de errores, vacia si el query es valido. |
| `metabase_move_card_py_infra` | `def metabase_move_card(client: MetabaseClient, card_id: int, collection_id: int \| None) -> dict` | Mueve una card/pregunta a otra coleccion via PUT /api/card/:id. Wrapper thin que solo actualiza collection_id. collection_id=None mueve a 'Our analytics' (root). |
| `metabase_move_collection_py_infra` | `def metabase_move_collection(client: MetabaseClient, collection_id: int, parent_id: int \| None) -> dict` | Mueve una collection (sub-arbol completo) a otro padre. Endpoint: PUT /api/collection/:id con {parent_id: ...}. |
| `metabase_move_dashboard_py_infra` | `def metabase_move_dashboard(client: MetabaseClient, dashboard_id: int, collection_id: int \| None) -> dict` | Mueve un dashboard a otra coleccion via PUT /api/dashboard/:id. Wrapper thin que solo actualiza collection_id. collection_id=None mueve a 'Our analytics' (root). |
| `metabase_move_document_py_infra` | `def metabase_move_document(client: MetabaseClient, document_id: int, collection_id: int \| None) -> dict` | Mueve un document a otra coleccion. Thin wrapper sobre PUT /api/document/:id enviando solo collection_id. |
| `metabase_pair_n_n1_columns_py_infra` | `def metabase_pair_n_n1_columns(client: MetabaseClient, *, dry_run: bool = True, card_ids: list[int] \| None = None, base_field: str = 'Valor_vendido') -> dict` | Para cards Metabase con display table/pivot que agregan SUM(base_field) y SUM(base_field_1), habilita la columna base_field_1 en visualization_settings.table.columns y la posiciona inmediatamente despues de base_field para comparacion visual. Soporta dry_run y campo base configurable. |
| `metabase_resolve_document_comment_py_infra` | `def metabase_resolve_document_comment(client: MetabaseClient, comment_id: int) -> dict` | Marca un comentario como resuelto (is_resolved=True). Los comentarios resueltos se ocultan en la UI pero siguen consultables via metabase_list_document_comments(include_resolved=True). Endpoint: PUT /api/comment/:id. |
| `metabase_setup_py_infra` | `metabase_setup(base_url: str, admin_email: str, admin_password: str, admin_first_name: str, admin_last_name: str, site_name: str, site_locale: str) -> dict` | Ejecuta el setup inicial de una instancia Metabase nueva via POST /api/setup. Obtiene el setup-token automaticamente y crea el usuario admin con preferencias del sitio. |
| `metabase_smartscalar_anothercolumn_viz_py_infra` | `def metabase_smartscalar_anothercolumn_viz(*, main_column: str, compare_column: str, label: str = 'vs N-1', number_style: str = 'percent', decimals: int = 2, currency: str = 'EUR', comparison_id: str = 'cmp_n1') -> dict` | Construye el dict completo de visualization_settings para una card display=smartscalar con comparacion tipo anotherColumn (misma fila, columna diferente). Incluye scalar.field, scalar.comparisons y column_settings para ambas columnas con el mismo formato. Internamente reutiliza metabase_viz_column_format. |
| `metabase_smartscalar_dimension_tag_py_infra` | `def metabase_smartscalar_dimension_tag(*, name: str, field_id: int, base_type: str = 'type/Text', widget_type: str = 'string/=', display_name: str = '') -> dict` | Construye un template-tag de tipo dimension con la firma exacta que Metabase v0.59 espera (incluyendo lib/uuid, base-type, effective-type). Sin estos flags Metabase devuelve PUT 200 pero descarta silenciosamente el dataset_query. |
| `metabase_smartscalar_kpi_payload_py_infra` | `def metabase_smartscalar_kpi_payload(*, name: str, database_id: int, sql: str, template_tags: dict \| None = None, description: str = '', collection_id: int = 0, currency: bool = False, currency_code: str = 'EUR', decimals: int = 0, comparison_label: str = 'vs n-1', extra_visualization_settings: dict \| None = None) -> dict` | Construye el payload completo para POST /api/card de un KPI smartscalar con formato y comparacion previousValue. Combina SQL nativo (idealmente generado por metabase_smartscalar_kpi_sql) con template-tags y visualization_settings predefinidos. Listo para metabase_create_card_raw. |
| `metabase_smartscalar_kpi_sql_py_infra` | `def metabase_smartscalar_kpi_sql(*, act_expr: str, n1_expr: str, body_sql: str, date_expr: str = 'MIN(fecha)') -> str` | Envuelve agregaciones actual+n-1 en el patron de 2 filas (periodo, valor) que el display smartscalar de Metabase v0.59 requiere para mostrar comparacion vs ano anterior sin pedir breakout temporal. Genera SQL nativo BigQuery con UNION ALL d_min/d_min-52w. |
| `metabase_update_card_go_infra` | `func MetabaseUpdateCard(client MetabaseClient, cardID int, fields map[string]any) (map[string]any, error)` | Actualiza campos de una card/pregunta en Metabase. Solo se modifican los campos incluidos en el map. Endpoint: PUT /api/card/:id. |
| `metabase_update_card_py_infra` | `def metabase_update_card(client: MetabaseClient, card_id: int, **fields) -> dict` | Actualiza campos de una card/pregunta via kwargs. Campos: name, description, display, dataset_query, collection_id, archived. Endpoint: PUT /api/card/:id. |
| `metabase_update_collection_graph_py_infra` | `def metabase_update_collection_graph(client: MetabaseClient, graph: dict, namespace: str \| None = None) -> dict` | Actualiza el grafo de permisos de colecciones en Metabase. Endpoint: PUT /api/collection/graph. El campo revision en el graph es obligatorio — el servidor rechaza con 409 si no coincide con el actual. Soporta namespace para snippet collections. |
| `metabase_update_dashboard_go_infra` | `func MetabaseUpdateDashboard(client MetabaseClient, dashboardID int, fields map[string]any) (map[string]any, error)` | Actualiza un dashboard en Metabase incluyendo metadata, cards y tabs. El campo dashcards representa el estado completo deseado: cards nuevas con ID negativo, existentes con ID positivo, omitidas se eliminan. Endpoint: PUT /api/dashboard/:id. |
| `metabase_update_dashboard_py_infra` | `def metabase_update_dashboard(client: MetabaseClient, dashboard_id: int, **fields) -> dict` | Actualiza dashboard incluyendo metadata, cards y tabs via kwargs. dashcards es el estado completo deseado: nuevas con ID negativo, existentes con positivo, omitidas se eliminan. Endpoint: PUT /api/dashboard/:id. |
| `metabase_update_dashboard_safe_py_infra` | `def metabase_update_dashboard_safe(client: MetabaseClient, dashboard_id: int, *, dashcards_update: list[dict] \| None = None, dashcards_add: list[dict] \| None = None, dashcards_remove: list[int] \| None = None, extra_fields: dict \| None = None) -> dict` | Wrapper sobre PUT /api/dashboard/:id que maneja los tres gotchas documentados: strip del campo '.card' denormalizado (evita 413), inclusion obligatoria de 'tabs' (evita 500 FK violation) y asignacion de IDs negativos a dashcards nuevos. Soporta reemplazo completo (dashcards_update), operaciones incrementales (add/remove) y actualizacion de campos extra del dashboard. |
| `metabase_update_document_py_infra` | `def metabase_update_document(client: MetabaseClient, document_id: int, *, validate: bool = True, **fields) -> dict` | Actualiza un document. Solo envia los campos pasados. Si se pasa 'document', valida el ProseMirror antes de enviar (evita documentos vacíos por nodos no soportados). |
| `metabase_update_group_py_infra` | `def metabase_update_group(client: MetabaseClient, group_id: int, name: str) -> dict` | Renombra un Permission Group en Metabase. La API solo permite modificar el nombre del grupo. Endpoint: PUT /api/permissions/group/:id. |
| `metabase_update_notification_py_infra` | `def metabase_update_notification(client: MetabaseClient, notification_id: int, **fields) -> dict` | Actualiza una notificacion existente de Metabase (alerta o suscripcion). Permite modificar active, handlers, subscriptions o payload. Endpoint: PUT /api/notification/:id. |
| `metabase_update_permission_graph_py_infra` | `def metabase_update_permission_graph(client: MetabaseClient, graph: dict) -> dict` | Actualiza el grafo de permisos de datos en Metabase. Endpoint: PUT /api/permissions/graph. El campo revision en el graph es obligatorio — el servidor rechaza con 409 si no coincide con el actual. |
| `metabase_update_snippet_py_infra` | `def metabase_update_snippet(client: MetabaseClient, snippet_id: int, **fields) -> dict` | Actualiza campos de un SQL snippet en Metabase. Acepta name, content, description, collection_id, archived via **fields. |
| `metabase_update_user_go_infra` | `func MetabaseUpdateUser(client MetabaseClient, userID int, fields map[string]any) (map[string]any, error)` | Actualiza campos de un usuario en Metabase. Solo se modifican los campos incluidos en el map. Requiere permisos de superusuario. Endpoint: PUT /api/user/:id. |
| `metabase_update_user_py_infra` | `def metabase_update_user(client: MetabaseClient, user_id: int, **fields) -> dict` | Actualiza campos de un usuario en Metabase via keyword arguments. Campos: first_name, last_name, email, is_superuser, group_ids, locale. Endpoint: PUT /api/user/:id. |
| `metabase_validate_card_payload_py_infra` | `def metabase_validate_card_payload(payload: dict) -> list[str]` | Valida la estructura de un payload de card de Metabase sin necesidad de red. Recorre todos los checks y acumula todos los issues en vez de abortar al primero. Retorna lista vacia si el payload es valido. |
| `metabase_validate_dashboard_payload_py_infra` | `def metabase_validate_dashboard_payload(payload: dict, known_card_ids: set[int]) -> list[str]` | Valida la estructura de un payload de dashboard de Metabase sin red. Verifica campos obligatorios, bounds de dashcards, referencias a cards conocidas y solapamientos entre dashcards. Acumula todos los issues. |
| `metabase_validate_document_payload_py_infra` | `def metabase_validate_document_payload(payload: dict, known_card_slugs: set[str] \| None = None) -> list[str]` | Valida un arbol ProseMirror contra la whitelist de nodos y marks que el editor TipTap de Metabase renderiza. Detecta nodos desconocidos que la API acepta pero el frontend descarta silenciosamente. |
| `metabase_validate_sql_py_infra` | `def metabase_validate_sql(client: MetabaseClient, database_id: int, sql: str, max_rows: int = 0) -> dict` | Valida sintaxis y referencias de una query SQL ejecutandola contra Metabase via POST /api/dataset. Captura tanto errores HTTP como errores embebidos en el body (Metabase a veces devuelve 200 con status failed). Retorna ok, error y rows_returned. |
| `metabase_viz_column_format_py_infra` | `def metabase_viz_column_format(column: str, *, number_style: str = '', decimals: int = -1, currency: str = '', currency_in_header: bool \| None = None, suffix: str = '', prefix: str = '') -> dict` | Construye la entrada column_settings para una columna en visualization_settings de Metabase. Genera la clave con el formato JSON exacto que Metabase requiere ('['name','<columna>']') y el dict de formato con solo los campos explicitamente especificados. El resultado se fusiona en visualization_settings['column_settings']. |
| `prosemirror_card_embed_py_infra` | `def prosemirror_card_embed(card_id: int, height: int = 400) -> dict` | Genera un nodo ProseMirror cardEmbed envuelto en resizeNode con altura adecuada. Un cardEmbed desnudo renderiza con ~50px — este helper produce el formato que Metabase espera para que la card se vea bien. |
| `setup_metabase_volume_bash_pipelines` | `setup_metabase_volume([registry_db_path: string], [container_name: string], [dest_path: string]) -> void` | Copia registry.db al contenedor Docker de Metabase verificando existencia del archivo, disponibilidad de docker, estado del contenedor y coincidencia de tamaños. Todos los argumentos son opcionales con defaults razonables. |
## Ejemplo canonico
_(Anadir 1-2 bloques de codigo end-to-end)_
## Fronteras
_(Que NO cubre este grupo)_
+50
View File
@@ -0,0 +1,50 @@
# Capability: nlp
_(Descripcion del grupo — editar a mano)_
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `aggregate_extraction_results_py_core` | `def aggregate_extraction_results(extract_results: list[dict]) -> dict` | Agrega entidades y relaciones de N resultados de extraccion por chunk. Deduplica entidades por (type, name_lowercased) acumulando counts. Deduplica relaciones por (head, rel_type, tail) con Counter. |
| `align_relations_to_entities_py_datascience` | `def align_relations_to_entities(triplets: list[dict], entity_names: list[str]) -> list[dict]` | Filtra y alinea triplets REBEL/mREBEL a nombres canonicos de entidades. Para cada triplet, resuelve head y tail contra entity_names con match exacto case-insensitive o substring (gana el nombre mas largo). Descarta triplets donde algun lado no resuelve o head==tail. |
| `chunk_with_overlap_py_core` | `def chunk_with_overlap(text: str, max_chars: int = 1500, overlap_sentences: int = 2) -> list[dict]` | Divide texto en chunks por sentence boundaries con sliding window overlap. Garantiza avance forzado si una frase supera max_chars (evita bucle infinito). Cada chunk retorna dict con 'text' y 'sentences'. |
| `clean_pdf_text_py_core` | `def clean_pdf_text(text: str) -> str` | Limpieza de artefactos PyPDF2/pdfplumber: elimina marcas de pagina (1/20), tabs, guiones de dehyphenation, saltos de linea en medio de oraciones y espacios duplicados. |
| `deduplicate_entities_py_datascience` | `def deduplicate_entities(candidates: list[EntityCandidate], name_threshold: float = 0.85, same_type_only: bool = True) -> DeduplicationResult` | Agrupa entidades candidatas que refieren a la misma entidad real usando fuzzy matching de nombres (Levenshtein + Jaccard) y Union-Find para clusters transitivos. Retorna entidades mergeadas con mapas de resolucion de IDs y log de merges. |
| `deduplicate_relations_py_datascience` | `def deduplicate_relations(relations: list[RelationCandidate], entity_id_map: dict[str, str]) -> list[RelationCandidate]` | Deduplica relaciones candidatas resolviendo from_name/to_name a entity IDs finales via entity_id_map. Descarta self-loops y relaciones sin match. Mergea duplicados (mismo from_id, to_id, relation_type) concatenando descripciones unicas y tomando max confidence. |
| `estimate_token_count_py_core` | `def estimate_token_count(content: str) -> int` | Estimacion rapida de tokens sin tokenizer. CJK chars cuentan ~0.7 token/char, otros non-whitespace ~0.3 token/char. |
| `extract_entities_gliner_py_datascience` | `def extract_entities_gliner(text: str, entity_schema: list[dict], model: Any, threshold: float = 0.5, flat_ner: bool = True) -> list[EntityCandidate]` | Extrae entidades zero-shot con GLiNER. Drop-in del contrato de extract_entities_llm pero 50-200x mas rapido y sin coste por token. El caller inyecta el modelo cargado con gliner_load_model. Anota offsets start/end en attributes para reconciliar con extract_iocs. |
| `extract_entities_llm_py_datascience` | `def extract_entities_llm(text: str, entity_schema: list[dict], llm_chat_json: Callable[[list[dict]], dict], language_instruction: str = 'Respond in English.') -> list[EntityCandidate]` | Extrae entidades de un chunk de texto usando un LLM inyectado. Construye el system prompt con el schema, llama al LLM y valida la respuesta retornando EntityCandidate. JSON invalido o type_ref fuera del schema se descartan con warning. |
| `extract_graph_from_text_py_pipelines` | `def extract_graph_from_text(text: str, entity_labels: list[str], relation_labels: list \| dict, allowed: dict, model: Any, threshold: float = 0.3, max_chars_per_chunk: int = 1500, overlap_sentences: int = 2) -> dict` | Pipeline E2E: texto -> grafo de entidades y relaciones. Orquesta chunking, extraccion con GLiNER2 por chunk, agregacion, filtrado tipado y resolucion de alias. Refactorizacion del playground del analisis gliner_glirel_tuning. |
| `extract_graph_gliner2_py_datascience` | `def extract_graph_gliner2(text: str, entity_labels: list[str], relation_labels: list \| dict, model: Any, threshold: float = 0.3, include_confidence: bool = False) -> dict` | Extrae entidades + relaciones en una sola pasada con GLiNER2. Wrapper de alto nivel: construye schema, ejecuta extraccion, normaliza a dict plano. No aplica post-filtrado ni coreference. |
| `extract_graph_hybrid_py_pipelines` | `def extract_graph_hybrid(chunks: list[str], entity_schema: list[dict], relation_types: list[str], gliner_model: Any, glirel_model: Any, llm_chat_json: Callable[[list[dict]], dict] \| None = None, ioc_types: list[str] \| None = None, confidence_threshold: float = 0.6, languages: str = 'Respond in Spanish.', min_entities_per_chunk: int = 2) -> tuple[list[EntityCandidate], list[RelationCandidate]]` | Pipeline hibrido en cascada que combina extract_iocs (regex, coste 0), GLiNER (zero-shot NER, coste bajo), GLiREL (zero-shot RE) y un LLM fallback opcional para chunks complejos o de baja confianza. Devuelve listas concatenadas listas para deduplicate_entities/deduplicate_relations. |
| `extract_relations_glirel_py_datascience` | `def extract_relations_glirel(text: str, entities: list[EntityCandidate], relation_types: list[str], model: Any, threshold: float = 0.5, max_pairs: int = 0) -> list[RelationCandidate]` | Extrae relaciones zero-shot con GLiREL. Drop-in del contrato de extract_relations_llm pero sin coste por token y mas rapido para corpus grandes. Tokeniza por whitespace, mapea spans de entidades (de attributes['start'/'end'] o fallback text.find) a indices de tokens, y devuelve RelationCandidate cuyos from_name/to_name siempre coinciden con entidades del input. |
| `extract_relations_llm_py_datascience` | `def extract_relations_llm(text: str, entities: list, relation_types: list[str], llm_chat_json: Callable[[list[dict]], dict], language_instruction: str = 'Respond in English.') -> list` | Extrae relaciones entre entidades de un chunk de texto usando un LLM inyectado. Valida que from_name y to_name correspondan a entidades existentes, y usa 'related_to' como fallback para tipos de relacion no permitidos. |
| `extract_relations_mrebel_py_datascience` | `def extract_relations_mrebel(text: str, entities: list[EntityCandidate], tokenizer: Any, model: Any, src_lang: str = 'es_XX', sentence_split_re: str = r'(?<=[.!?])\s+', min_sentence_chars: int = 20, num_beams: int = 4, max_length: int = 256) -> list[RelationCandidate]` | Extrae relaciones entre entidades usando mREBEL (seq2seq multilingue). Divide el texto por oraciones, genera triplets con mREBEL, parsea con parse_rebel_output y alinea a entidades conocidas con align_relations_to_entities. Drop-in con extract_relations_glirel para benchmarks. |
| `extract_triples_spacy_es_py_datascience` | `def extract_triples_spacy_es(text: str, nlp: Any) -> dict` | Extraccion OpenIE schema-less en castellano via reglas de dependencia spaCy. Detecta patrones sujeto-verbo-objeto con el lemma del verbo como relacion (sin vocabulario fijo). Tambien extrae entidades NER (PER, ORG, LOC, MISC). |
| `extraction_pipeline_py_pipelines` | `def extraction_pipeline(file_path: str, entity_presets: list[dict], relation_types: list[str], llm_chat_json: Callable[[list[dict]], dict], chunk_size: int = 500, chunk_overlap: int = 50, confidence_threshold: float = 0.5, dedup_threshold: float = 0.85, on_progress: Callable[[str, float], None] \| None = None) -> ExtractionResult` | Pipeline completa de extraccion de entidades y relaciones desde un documento. Orquesta extract_text_from_file -> preprocess_text -> split_text_into_chunks -> extract_entities_llm por chunk -> deduplicate_entities -> extract_relations_llm por chunk -> deduplicate_relations. |
| `filter_relations_by_entity_types_py_core` | `def filter_relations_by_entity_types(relations: dict, name_to_type: dict, allowed: dict) -> tuple[list, list]` | Post-filtrado tipado de relaciones NER+RE: descarta pares donde los tipos de entidad (head_type, tail_type) no coinciden con los permitidos por relation kind. Ej: descarta 'Madrid president_of Persona' porque Madrid es location no person. |
| `gliner2_load_model_py_datascience` | `def gliner2_load_model(model_name: str = 'fastino/gliner2-large-v1', device: str = 'auto') -> Any` | Carga (y cachea por (model_name, device)) un modelo GLiNER2 (NER+RE joint). GLiNER2 extrae entidades y relaciones en una sola pasada con schema unificado. ~2x mas rapido que GLiNER + GLiREL separados. LICENSE: Apache 2.0. |
| `gliner_load_model_py_datascience` | `def gliner_load_model(model_name: str = 'urchade/gliner_multi-v2.1', device: str = 'auto') -> Any` | Carga (y cachea por (model_name, device)) un modelo GLiNER zero-shot NER. La primera llamada descarga ~200 MB desde HuggingFace; sucesivas devuelven la instancia cacheada. device='auto' usa CUDA si esta disponible, o CPU. |
| `glirel_load_model_py_datascience` | `def glirel_load_model(model_name: str = 'jackboyla/glirel-large-v0', device: str = 'auto') -> Any` | Carga (y cachea por (model_name, device)) un modelo GLiREL zero-shot relation extraction. La primera llamada descarga ~500 MB desde HuggingFace; sucesivas devuelven la instancia cacheada. device='auto' usa CUDA si esta disponible, o CPU. |
| `marianmt_es_en_load_model_py_datascience` | `def marianmt_es_en_load_model(model_name: str = 'Helsinki-NLP/opus-mt-es-en') -> tuple[Any, Any]` | Carga (y cachea) el tokenizer y modelo MarianMT para traduccion ES->EN (Helsinki-NLP, ~300 MB). Licencia Apache 2.0. Cache por model_name. |
| `merge_entity_aliases_py_core` | `def merge_entity_aliases(entity_names: list[str]) -> dict[str, str]` | Coreference simple por normalizacion + substring: mapea cada nombre de entidad a su forma canonica. 'BBVA' y 'bbva' -> mismo canonical. Nombres cortos absorbidos por nombres largos que los contienen como palabra completa (min 4 chars normalizados). |
| `mrebel_base_load_model_py_datascience` | `def mrebel_base_load_model(model_name: str = 'Babelscape/mrebel-base', src_lang: str = 'es_XX', tgt_lang: str = 'tp_XX') -> tuple[Any, Any]` | Variante rapida de mrebel_load_model con checkpoint base (250M params, ~900 MB). Delega completamente en mrebel_load_model. Misma licencia CC BY-NC-SA 4.0 — solo uso no comercial. |
| `mrebel_load_model_py_datascience` | `def mrebel_load_model(model_name: str = 'Babelscape/mrebel-large', src_lang: str = 'es_XX', tgt_lang: str = 'tp_XX') -> tuple[Any, Any]` | Carga (y cachea) el tokenizer y modelo mREBEL (mBART-based, ~600M params, ~2.4 GB). Multilingue 30+ idiomas. Cache por (model_name, src_lang). Primera llamada descarga de HuggingFace. LICENCIA CC BY-NC-SA 4.0 — solo uso no comercial. |
| `normalize_entity_name_py_core` | `def normalize_entity_name(name: str, entity_type: str = "") -> str` | Normaliza el nombre de una entidad para comparacion y deduplicacion. Aplica reglas distintas segun el tipo: ip/email/domain/crypto_wallet/phone usan normalizacion tecnica; person remueve titulos y convierte formato Apellido-Nombre; organization elimina sufijos legales; default aplica lower+strip+colapso de espacios. |
| `parse_rebel_output_py_datascience` | `def parse_rebel_output(decoded_text: str) -> list[dict]` | Parser puro del wire format de REBEL / mREBEL. Convierte la cadena decoded por el tokenizer (con skip_special_tokens=False) a una lista de triplets tipados {head, head_type, type, tail, tail_type}. Nunca lanza excepcion. |
| `rebel_load_model_py_datascience` | `def rebel_load_model(model_name: str = 'Babelscape/rebel-large') -> tuple[Any, Any]` | Carga (y cachea) el tokenizer y modelo REBEL (BART-based, ~1.5 GB). Solo ingles. Licencia Apache 2.0 — uso comercial permitido. Cache por model_name. |
| `remove_words_from_column_py_datascience` | `def remove_words_from_column(values: Iterable[str \| None], words: list[str]) -> list[str]` | Elimina palabras especificas de un iterable de strings usando regex de palabra completa (\b). Case-insensitive. Colapsa espacios multiples y hace strip. None se convierte en cadena vacia. Sin pandas. |
| `spacy_es_load_model_py_datascience` | `def spacy_es_load_model(model_name: str = 'es_core_news_md') -> Any` | Carga (y cachea) un modelo spaCy en castellano. Provee POS, dependencias y NER (PER, ORG, LOC, MISC). Usado por extract_triples_spacy_es para OpenIE schema-less. LICENSE: spaCy MIT + es_core_news_md CC BY-SA 4.0. |
| `split_text_into_chunks_py_core` | `def split_text_into_chunks(text: str, chunk_size: int = 500, overlap: int = 50) -> list[str]` | Divide texto en chunks de tamaño fijo con overlap, intentando cortar en límites de oración para no romper frases a mitad. Soporta separadores CJK (。!?) y occidentales (. ! ?). |
| `translate_es_to_en_py_datascience` | `def translate_es_to_en(text: str, tokenizer: Any, model: Any, max_length: int = 512, num_beams: int = 4) -> str` | Traduce texto espanol a ingles frase a frase usando MarianMT. Divide por boundaries de oracion, traduce cada una independientemente y une con espacio. Preserva nombres propios mejor que pasar el parrafo entero. |
| `words_to_dataset_py_datascience` | `def words_to_dataset(texts: Iterable[str \| None], min_ocurrencias: int = 1, eliminar_stopwords: bool = False) -> list[dict]` | Extrae palabras y sus ocurrencias de un iterable de textos. Tokeniza con \b\w+\b, convierte a mayusculas, cuenta con Counter, filtra por minimo de ocurrencias y opcionalmente elimina stopwords en espanol. Sin pandas. |
## Ejemplo canonico
_(Anadir 1-2 bloques de codigo end-to-end)_
## Fronteras
_(Que NO cubre este grupo)_
+58
View File
@@ -0,0 +1,58 @@
# Capability: notebook
Operar Jupyter Lab colaborativo desde cualquier sesion de Claude. Discover, read, exec, write, kernel. Sin MCP — funciones directas que resuelven `kernel_id` via `/api/sessions` y mantienen WebSocket 2s para Y.js propague.
## Funciones
| ID | Firma | Que hace |
|---|---|---|
| `jupyter_discover_py_notebook` | `def jupyter_discover(registry_root: str = "", ports: list[int] \| None = None) -> list[dict]` | Descubre instancias de Jupyter Lab activas escaneando archivos .jupyter-port en analysis/ y puertos comunes (8888-8892). Detecta el root_dir real de cada instancia via /proc/pid/cmdline (Linux) para identificar correctamente el analisis en escenarios multi-instancia. Para cada instancia consulta /api/status, /api/config, /api/kernels y /api/sessions via HTTP REST. |
| `jupyter_exec_py_notebook` | `jupyter_append_execute(notebook_path: str, code: str, server_url: str, token: str) -> dict` | Ejecuta codigo en kernels de Jupyter via REST + WebSocket clasico al kernel. Tres modos: append (añade celda y ejecuta), cell (ejecuta celda existente), kernel (ejecuta sin tocar notebook). NO usa el canal colaborativo Y.js. |
| `jupyter_kernel_py_notebook` | `def jupyter_kernel_list(server_url: str = "http://localhost:8888", token: str = "") -> list[dict]` | CRUD completo de kernels Jupyter via REST API. Expone ocho operaciones: list, start, restart, interrupt, shutdown, sessions, cleanup y shutdown-all. Usa solo stdlib (urllib, json), sin dependencias externas. |
| `jupyter_read_py_notebook` | `def jupyter_read_cells(notebook_path: str, server_url: str = 'http://localhost:8888', token: str = '', cell_index: int \| None = None) -> list[dict]` | Lee celdas de un notebook Jupyter abierto via el protocolo de colaboracion en tiempo real (CRDT/Y.js). Devuelve el estado actual incluyendo cambios no guardados. Expone tambien jupyter_notebook_info() para metadata rapida. |
| `jupyter_write_py_notebook` | `def jupyter_append_code(notebook_path: str, source: str, server_url: str = 'http://localhost:8888', token: str = '') -> dict` | Operaciones de escritura sobre celdas de un notebook Jupyter via colaboracion en tiempo real (WebSocket) y API REST. Expone siete operaciones: append_code, append_markdown, insert, edit, delete, create y batch. NO ejecuta celdas — solo modifica la estructura del notebook. create usa PUT /api/contents para crear notebooks nuevos sin necesidad de websocket. batch abre una unica conexion WebSocket para insertar N celdas en una sola operacion. |
| `notebook_to_pdf_bash_infra` | `notebook_to_pdf(project_dir: string, [pattern: string], [output_dir: string]) -> string` | Convierte notebooks Jupyter a PDF usando nbconvert webpdf con chromium. Lista los PDFs generados al finalizar. |
## Ejemplo canonico
```bash
PY="python/.venv/bin/python3"
# 1. Descubrir Jupyter activo
$PY python/functions/notebook/jupyter_discover.py --json
# 2. Leer notebook
$PY python/functions/notebook/jupyter_read.py notebooks/01.ipynb --json
# 3. Anadir celda + ejecutar (usuario lo ve en tiempo real)
$PY python/functions/notebook/jupyter_exec.py append notebooks/01.ipynb "df.describe()"
# 4. Ejecutar celda existente por indice
$PY python/functions/notebook/jupyter_exec.py cell notebooks/01.ipynb 3
# 5. Anadir markdown
$PY python/functions/notebook/jupyter_write.py append-markdown notebooks/01.ipynb "## Resumen"
# 6. Gestionar kernels
$PY python/functions/notebook/jupyter_kernel.py sessions
$PY python/functions/notebook/jupyter_kernel.py shutdown <kernel_id>
```
## Prerequisitos
- Jupyter Lab corriendo en modo colaborativo (`--collaborative`). Launcher estandar `run-jupyter-lab.sh` (generado por `init_jupyter_analysis`) ya lo incluye.
- Notebook abierto en navegador para que los cambios sean visibles en vivo.
## Fronteras
NO incluye:
- Conversion a PDF/HTML — usar `notebook_to_pdf_bash_infra` (no es notebook colaborativo).
- Scheduling de notebooks (papermill) — no implementado, crear funcion si surge necesidad.
- Crear analysis nuevo — usar `init_jupyter_analysis_bash_pipelines` (capability group `analysis-init`).
## Notas
- Reemplaza al MCP jupyter — no requiere registrar nada por directorio.
- Paths de notebooks relativos a raiz del servidor Jupyter (normalmente `analysis/<tema>/`).
- Token vacio por defecto. Si server tiene token, pasarlo con `--token`.