@saulwade/swl-ses 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +238 -0
- package/README.md +560 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/.evolved.json +9 -0
- package/agentes/accesibilidad-wcag-swl.md +692 -0
- package/agentes/arquitecto-swl.md +238 -0
- package/agentes/auto-evolucion-swl.md +854 -0
- package/agentes/backend-api-swl.md +470 -0
- package/agentes/backend-csharp-swl.md +418 -0
- package/agentes/backend-go-swl.md +388 -0
- package/agentes/backend-java-swl.md +279 -0
- package/agentes/backend-node-swl.md +477 -0
- package/agentes/backend-python-swl.md +608 -0
- package/agentes/backend-rust-swl.md +362 -0
- package/agentes/backend-workers-swl.md +480 -0
- package/agentes/cloud-infra-swl.md +485 -0
- package/agentes/consolidador-swl.md +539 -0
- package/agentes/datos-swl.md +584 -0
- package/agentes/depurador-swl.md +349 -0
- package/agentes/devops-ci-swl.md +374 -0
- package/agentes/disenador-ui-swl.md +558 -0
- package/agentes/documentador-swl.md +343 -0
- package/agentes/evals/arquitecto-swl.evals.json +56 -0
- package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
- package/agentes/evals/implementador-swl.evals.json +56 -0
- package/agentes/evals/orquestador-swl.evals.json +60 -0
- package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
- package/agentes/evals/red-team-swl.evals.json +59 -0
- package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
- package/agentes/frontend-angular-swl.md +627 -0
- package/agentes/frontend-css-swl.md +720 -0
- package/agentes/frontend-react-swl.md +696 -0
- package/agentes/frontend-swl.md +500 -0
- package/agentes/frontend-tailwind-swl.md +830 -0
- package/agentes/implementador-swl.md +328 -0
- package/agentes/investigador-swl.md +430 -0
- package/agentes/investigador-ux-swl.md +500 -0
- package/agentes/llm-apps-swl.md +276 -0
- package/agentes/migrador-swl.md +417 -0
- package/agentes/mobile-android-swl.md +509 -0
- package/agentes/mobile-cross-swl.md +539 -0
- package/agentes/mobile-ios-swl.md +500 -0
- package/agentes/mobile-testing-swl.md +300 -0
- package/agentes/notificador-swl.md +916 -0
- package/agentes/observabilidad-swl.md +436 -0
- package/agentes/orquestador-swl.md +884 -0
- package/agentes/pagos-swl.md +283 -0
- package/agentes/perfilador-usuario-swl.md +306 -0
- package/agentes/planificador-swl.md +402 -0
- package/agentes/producto-prd-swl.md +587 -0
- package/agentes/red-team-swl.md +216 -0
- package/agentes/release-manager-swl.md +568 -0
- package/agentes/rendimiento-swl.md +714 -0
- package/agentes/resolutor-build-swl.md +243 -0
- package/agentes/revisor-angular-swl.md +276 -0
- package/agentes/revisor-codigo-swl.md +348 -0
- package/agentes/revisor-csharp-swl.md +262 -0
- package/agentes/revisor-go-swl.md +257 -0
- package/agentes/revisor-java-swl.md +255 -0
- package/agentes/revisor-kotlin-swl.md +271 -0
- package/agentes/revisor-nextjs-swl.md +279 -0
- package/agentes/revisor-php-swl.md +269 -0
- package/agentes/revisor-react-swl.md +276 -0
- package/agentes/revisor-rust-swl.md +344 -0
- package/agentes/revisor-seguridad-swl.md +390 -0
- package/agentes/revisor-swift-swl.md +266 -0
- package/agentes/revisor-typescript-swl.md +344 -0
- package/agentes/sre-swl.md +265 -0
- package/agentes/tdd-qa-swl.md +354 -0
- package/agentes/ux-disenador-swl.md +501 -0
- package/bin/lib/bot-comandos.js +1030 -0
- package/bin/lib/bot-discovery.js +182 -0
- package/bin/lib/bot-git.js +142 -0
- package/bin/swl-ses.js +325 -0
- package/bin/swl-telegram-bot.js +442 -0
- package/bin/swl-telegram-bot.plist +21 -0
- package/bin/swl-telegram-bot.service +14 -0
- package/comandos/swl/.evolved.json +23 -0
- package/comandos/swl/actualizar.md +174 -0
- package/comandos/swl/adoptar-proyecto.md +207 -0
- package/comandos/swl/aprender.md +701 -0
- package/comandos/swl/auditar-deps.md +134 -0
- package/comandos/swl/autoresearch.md +170 -0
- package/comandos/swl/ayuda.md +224 -0
- package/comandos/swl/brainstorm.md +50 -0
- package/comandos/swl/checkpoint.md +330 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/configurar-ci.md +227 -0
- package/comandos/swl/contexto.md +112 -0
- package/comandos/swl/contribuir.md +233 -0
- package/comandos/swl/crear-skill.md +292 -0
- package/comandos/swl/cron.md +196 -0
- package/comandos/swl/dashboard.md +146 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +135 -0
- package/comandos/swl/evaluar-skill.md +487 -0
- package/comandos/swl/evolucion-estado.md +142 -0
- package/comandos/swl/evolucionar.md +259 -0
- package/comandos/swl/exportar-vault.md +189 -0
- package/comandos/swl/gateway.md +158 -0
- package/comandos/swl/inbox.md +116 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/instintos.md +86 -0
- package/comandos/swl/mapear-codebase.md +312 -0
- package/comandos/swl/mcp-status.md +175 -0
- package/comandos/swl/metricas.md +270 -0
- package/comandos/swl/modelo.md +102 -0
- package/comandos/swl/notificaciones.md +396 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/plugins.md +256 -0
- package/comandos/swl/reflect-skills.md +125 -0
- package/comandos/swl/release.md +217 -0
- package/comandos/swl/revisar-impacto.md +206 -0
- package/comandos/swl/revisar.md +330 -0
- package/comandos/swl/salud.md +363 -0
- package/comandos/swl/sesiones.md +200 -0
- package/comandos/swl/skill-search.md +113 -0
- package/comandos/swl/verificar.md +585 -0
- package/comandos/swl/wiki.md +620 -0
- package/contextos/dev.md +32 -0
- package/contextos/research.md +30 -0
- package/contextos/review.md +31 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
- package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
- package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
- package/habilidades/agent-browser/SKILL.md +218 -0
- package/habilidades/agentes-como-servicio/SKILL.md +218 -0
- package/habilidades/ai-runtime-security/SKILL.md +273 -0
- package/habilidades/angular-avanzado/SKILL.md +164 -0
- package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
- package/habilidades/angular-moderno/SKILL.md +186 -0
- package/habilidades/angular-moderno/evals/evals.json +45 -0
- package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
- package/habilidades/api-rest-diseno/SKILL.md +191 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
- package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
- package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
- package/habilidades/async-python/SKILL.md +149 -0
- package/habilidades/async-python/evals/evals.json +47 -0
- package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
- package/habilidades/auth-patrones/.evolved.json +9 -0
- package/habilidades/auth-patrones/SKILL.md +413 -0
- package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
- package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
- package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
- package/habilidades/autoresearch/SKILL.md +268 -0
- package/habilidades/autoresearch/evals/evals.json +41 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/azure-cloud/SKILL.md +308 -0
- package/habilidades/azure-cloud/recursos/aks.md +327 -0
- package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -0
- package/habilidades/brainstorming/SKILL.md +295 -0
- package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
- package/habilidades/build-errors-cpp/SKILL.md +270 -0
- package/habilidades/build-errors-csharp/SKILL.md +265 -0
- package/habilidades/build-errors-go/SKILL.md +306 -0
- package/habilidades/build-errors-java/SKILL.md +278 -0
- package/habilidades/build-errors-kotlin/SKILL.md +303 -0
- package/habilidades/build-errors-nextjs/SKILL.md +312 -0
- package/habilidades/build-errors-php/SKILL.md +270 -0
- package/habilidades/build-errors-python/SKILL.md +292 -0
- package/habilidades/build-errors-rust/SKILL.md +284 -0
- package/habilidades/build-errors-swift/SKILL.md +272 -0
- package/habilidades/build-errors-typescript/SKILL.md +369 -0
- package/habilidades/checklist-calidad/SKILL.md +271 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +285 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
- package/habilidades/cloud-aws/SKILL.md +142 -0
- package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
- package/habilidades/compactacion-contexto/SKILL.md +247 -0
- package/habilidades/contenedores-docker/SKILL.md +137 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
- package/habilidades/context-builder/SKILL.md +170 -0
- package/habilidades/control-profundidad/SKILL.md +128 -0
- package/habilidades/csharp-experto/SKILL.md +322 -0
- package/habilidades/csharp-patrones/SKILL.md +316 -0
- package/habilidades/csharp-testing/SKILL.md +286 -0
- package/habilidades/css-moderno/SKILL.md +166 -0
- package/habilidades/css-moderno/evals/evals.json +43 -0
- package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
- package/habilidades/datos-etl/SKILL.md +129 -0
- package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
- package/habilidades/dbml-experto/SKILL.md +339 -0
- package/habilidades/dbml-experto/evals/evals.json +56 -0
- package/habilidades/dependencias-auditoria/SKILL.md +320 -0
- package/habilidades/deprecacion-migracion/SKILL.md +169 -0
- package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
- package/habilidades/design-tokens/SKILL.md +158 -0
- package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
- package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
- package/habilidades/discutir-fase/SKILL.md +188 -0
- package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
- package/habilidades/diseno-responsivo/SKILL.md +186 -0
- package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
- package/habilidades/django-experto/SKILL.md +205 -0
- package/habilidades/django-experto/recursos/async-django.md +390 -0
- package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
- package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
- package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
- package/habilidades/django-experto/recursos/testing-django.md +415 -0
- package/habilidades/doc-sync/SKILL.md +280 -0
- package/habilidades/drift-detection/SKILL.md +179 -0
- package/habilidades/ejecutar-fase/SKILL.md +468 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
- package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
- package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/evaluacion-agentes/SKILL.md +314 -0
- package/habilidades/event-driven/SKILL.md +153 -0
- package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
- package/habilidades/extraccion-documentos/SKILL.md +221 -0
- package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
- package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
- package/habilidades/fastapi-experto/SKILL.md +221 -0
- package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
- package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
- package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
- package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
- package/habilidades/filament-admin/SKILL.md +290 -0
- package/habilidades/frontend-avanzado/SKILL.md +257 -0
- package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
- package/habilidades/gcp-cloud/SKILL.md +260 -0
- package/habilidades/gcp-cloud/recursos/gke.md +234 -0
- package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
- package/habilidades/generacion-mermaid/SKILL.md +229 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
- package/habilidades/go-experto/SKILL.md +305 -0
- package/habilidades/go-patrones/SKILL.md +299 -0
- package/habilidades/go-testing/SKILL.md +291 -0
- package/habilidades/graphql-experto/SKILL.md +323 -0
- package/habilidades/guardrail-semantico/SKILL.md +282 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -0
- package/habilidades/iam-secretos/SKILL.md +265 -0
- package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
- package/habilidades/infra-github-actions/SKILL.md +166 -0
- package/habilidades/instalar-sistema/.evolved.json +9 -0
- package/habilidades/instalar-sistema/SKILL.md +221 -0
- package/habilidades/java-experto/SKILL.md +290 -0
- package/habilidades/java-patrones/SKILL.md +275 -0
- package/habilidades/java-testing/SKILL.md +288 -0
- package/habilidades/kotlin-compose/SKILL.md +278 -0
- package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
- package/habilidades/kotlin-experto/SKILL.md +318 -0
- package/habilidades/kotlin-testing/SKILL.md +267 -0
- package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
- package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
- package/habilidades/langchain-langraph/SKILL.md +386 -0
- package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
- package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
- package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
- package/habilidades/legacy-code-rescue/SKILL.md +267 -0
- package/habilidades/likec4-experto/SKILL.md +412 -0
- package/habilidades/likec4-experto/evals/evals.json +69 -0
- package/habilidades/manejo-errores/.evolved.json +9 -0
- package/habilidades/manejo-errores/SKILL.md +407 -0
- package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
- package/habilidades/mapear-codebase/SKILL.md +275 -0
- package/habilidades/memoria-busqueda/SKILL.md +194 -0
- package/habilidades/memoria-busqueda/evals/evals.json +44 -0
- package/habilidades/meta-skills-estandar/SKILL.md +298 -0
- package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
- package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
- package/habilidades/microservicios/SKILL.md +155 -0
- package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
- package/habilidades/mobile-flutter/SKILL.md +199 -0
- package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
- package/habilidades/mobile-react-native/SKILL.md +176 -0
- package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
- package/habilidades/mongodb-experto/SKILL.md +302 -0
- package/habilidades/monitoring-alertas/SKILL.md +201 -0
- package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
- package/habilidades/nestjs-experto/SKILL.md +307 -0
- package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
- package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
- package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
- package/habilidades/nextjs-experto/SKILL.md +335 -0
- package/habilidades/nextjs-patrones/SKILL.md +303 -0
- package/habilidades/nextjs-testing/SKILL.md +331 -0
- package/habilidades/node-experto/.evolved.json +9 -0
- package/habilidades/node-experto/SKILL.md +266 -0
- package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
- package/habilidades/nuevo-proyecto/SKILL.md +204 -0
- package/habilidades/orquestacion-async/SKILL.md +303 -0
- package/habilidades/paid-media-tracking/SKILL.md +269 -0
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
- package/habilidades/patrones-python/SKILL.md +228 -0
- package/habilidades/patrones-python/evals/evals.json +56 -0
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
- package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
- package/habilidades/perfil-usuario/SKILL.md +200 -0
- package/habilidades/perfil-usuario/evals/evals.json +55 -0
- package/habilidades/performance-baseline/SKILL.md +297 -0
- package/habilidades/php-experto/SKILL.md +291 -0
- package/habilidades/php-patrones/SKILL.md +306 -0
- package/habilidades/php-testing/SKILL.md +280 -0
- package/habilidades/planear-fase/SKILL.md +269 -0
- package/habilidades/postgresql-experto/SKILL.md +151 -0
- package/habilidades/postgresql-experto/evals/evals.json +53 -0
- package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
- package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
- package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
- package/habilidades/privacy-memoria/SKILL.md +141 -0
- package/habilidades/privacy-memoria/evals/evals.json +43 -0
- package/habilidades/prompt-engineering/SKILL.md +518 -0
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
- package/habilidades/rag-arquitectura/SKILL.md +338 -0
- package/habilidades/rails-experto/SKILL.md +237 -0
- package/habilidades/rails-experto/recursos/active-record.md +260 -0
- package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
- package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
- package/habilidades/react-experto/SKILL.md +209 -0
- package/habilidades/react-experto/evals/evals.json +55 -0
- package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
- package/habilidades/react-optimizacion/SKILL.md +174 -0
- package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
- package/habilidades/redis-experto/SKILL.md +305 -0
- package/habilidades/release-semver/.evolved.json +9 -0
- package/habilidades/release-semver/SKILL.md +248 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/rust-experto/SKILL.md +400 -0
- package/habilidades/rust-patrones/SKILL.md +296 -0
- package/habilidades/rust-testing/SKILL.md +311 -0
- package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
- package/habilidades/sql-optimizacion/SKILL.md +200 -0
- package/habilidades/sql-optimizacion/evals/evals.json +54 -0
- package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
- package/habilidades/sre-patrones/SKILL.md +333 -0
- package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
- package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
- package/habilidades/stripe-pagos/SKILL.md +550 -0
- package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
- package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
- package/habilidades/structured-outputs/SKILL.md +343 -0
- package/habilidades/swift-experto/SKILL.md +320 -0
- package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
- package/habilidades/swift-patrones/SKILL.md +313 -0
- package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
- package/habilidades/swift-testing/SKILL.md +254 -0
- package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
- package/habilidades/swl-dashboard/SKILL.md +370 -0
- package/habilidades/swl-markitdown/SKILL.md +285 -0
- package/habilidades/swl-markitdown/evals/evals.json +52 -0
- package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
- package/habilidades/tailwind-experto/SKILL.md +240 -0
- package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
- package/habilidades/tdd-workflow/SKILL.md +293 -0
- package/habilidades/terraform-experto/SKILL.md +321 -0
- package/habilidades/testing-python/SKILL.md +340 -0
- package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
- package/habilidades/threat-model-lite/SKILL.md +246 -0
- package/habilidades/tracing-processor/SKILL.md +212 -0
- package/habilidades/tracking-measurement/SKILL.md +239 -0
- package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
- package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
- package/habilidades/typescript-avanzado/SKILL.md +144 -0
- package/habilidades/typescript-avanzado/evals/evals.json +55 -0
- package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
- package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
- package/habilidades/ux-diseno/SKILL.md +116 -0
- package/habilidades/ux-diseno/evals/evals.json +43 -0
- package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificacion-evidencia/SKILL.md +160 -0
- package/habilidades/verificar-trabajo/SKILL.md +303 -0
- package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
- package/habilidades/wiki-conocimiento/SKILL.md +276 -0
- package/habilidades/wireframes-flujos/SKILL.md +212 -0
- package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
- package/habilidades/workflow-claude-code/SKILL.md +260 -0
- package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
- package/hooks/_run-hook.sh +57 -0
- package/hooks/actualizar-perfil-usuario.js +364 -0
- package/hooks/agente-lifecycle.js +71 -0
- package/hooks/aiisms-detector.js +173 -0
- package/hooks/audit-trail.js +204 -0
- package/hooks/auto-background.js +97 -0
- package/hooks/auto-consolidacion.js +178 -0
- package/hooks/auto-evolucion.js +666 -0
- package/hooks/auto-restaurar-settings.js +360 -0
- package/hooks/calidad-pre-commit.js +929 -0
- package/hooks/calidad-typescript.js +511 -0
- package/hooks/captura-feedback-usuario.js +148 -0
- package/hooks/check-update.js +211 -0
- package/hooks/clasificador-mensajes.js +271 -0
- package/hooks/degradacion-instintos.js +272 -0
- package/hooks/escaneo-secretos.js +389 -0
- package/hooks/extraccion-aprendizajes.js +763 -0
- package/hooks/grafo-contexto.js +129 -0
- package/hooks/graph-update.js +67 -0
- package/hooks/guardrail-modelo.js +247 -0
- package/hooks/inbox-aviso.js +75 -0
- package/hooks/inyeccion-contexto.js +246 -0
- package/hooks/lib/abort-registry.js +214 -0
- package/hooks/lib/agent-backend.js +210 -0
- package/hooks/lib/agent-comms.js +263 -0
- package/hooks/lib/agent-issue-codes.js +284 -0
- package/hooks/lib/agent-matcher.js +189 -0
- package/hooks/lib/async-hook-registry.js +252 -0
- package/hooks/lib/atomic-write.js +130 -0
- package/hooks/lib/auto-consolidator.js +335 -0
- package/hooks/lib/canary-skills.js +187 -0
- package/hooks/lib/consolidation-lock.js +291 -0
- package/hooks/lib/context-builder.js +430 -0
- package/hooks/lib/context-compressor.js +657 -0
- package/hooks/lib/convergence-detector.js +105 -0
- package/hooks/lib/delegation-tracker.js +198 -0
- package/hooks/lib/detectar-package-manager.js +423 -0
- package/hooks/lib/edit-accumulator.js +171 -0
- package/hooks/lib/error-classifier.js +308 -0
- package/hooks/lib/event-bus.js +112 -0
- package/hooks/lib/evolution-tracker.js +442 -0
- package/hooks/lib/execution-state.js +316 -0
- package/hooks/lib/fingerprint-id.js +135 -0
- package/hooks/lib/gateway-notify.js +116 -0
- package/hooks/lib/graph-security.js +75 -0
- package/hooks/lib/guardrail-metrics.js +202 -0
- package/hooks/lib/hook-circuit-breaker.js +206 -0
- package/hooks/lib/loop-detector.js +267 -0
- package/hooks/lib/mcp-health.js +184 -0
- package/hooks/lib/mcp-pool.js +436 -0
- package/hooks/lib/memory-search.js +506 -0
- package/hooks/lib/merkle-audit.js +96 -0
- package/hooks/lib/model-router.js +222 -0
- package/hooks/lib/normalize-error.js +324 -0
- package/hooks/lib/normalize-input.js +65 -0
- package/hooks/lib/nudge-tracker.js +306 -0
- package/hooks/lib/otlp-exporter.js +365 -0
- package/hooks/lib/performance-marks.js +239 -0
- package/hooks/lib/privacy-filter.js +128 -0
- package/hooks/lib/prompt-injection-scanner.js +209 -0
- package/hooks/lib/provenance-tracker.js +183 -0
- package/hooks/lib/rate-limit-tracker.js +253 -0
- package/hooks/lib/reflect-classifier.js +164 -0
- package/hooks/lib/resource-quota.js +122 -0
- package/hooks/lib/retry-jitter.js +165 -0
- package/hooks/lib/risk-engine.js +368 -0
- package/hooks/lib/run-log.js +408 -0
- package/hooks/lib/session-fts.js +379 -0
- package/hooks/lib/session-store.js +293 -0
- package/hooks/lib/singleton-guard.js +159 -0
- package/hooks/lib/skill-auditor.js +588 -0
- package/hooks/lib/sync-status.js +228 -0
- package/hooks/lib/taint-tracker.js +107 -0
- package/hooks/lib/task-service.js +295 -0
- package/hooks/lib/tech-skills-map.js +146 -0
- package/hooks/lib/telegram-cliente.js +159 -0
- package/hooks/lib/telegram-config.js +170 -0
- package/hooks/lib/token-budget.js +156 -0
- package/hooks/lib/token-estimator.js +420 -0
- package/hooks/lib/toon-compressor.js +245 -0
- package/hooks/lib/usage-model.js +183 -0
- package/hooks/lib/variable-resolver.js +230 -0
- package/hooks/linea-estado.js +324 -0
- package/hooks/metricas-evolucion.js +209 -0
- package/hooks/monitor-contexto.js +325 -0
- package/hooks/notificacion-sesion-stop.js +198 -0
- package/hooks/notificacion-telegram-notification.js +4 -0
- package/hooks/notificacion-telegram-subagent.js +4 -0
- package/hooks/notificacion-telegram.js +267 -0
- package/hooks/preservar-estado-pre-compact.js +150 -0
- package/hooks/proteccion-rutas.js +366 -0
- package/hooks/registro-turnos.js +209 -0
- package/hooks/resumen-sesion.js +249 -0
- package/hooks/risk-scoring.js +323 -0
- package/hooks/rotar-audit-auto.js +122 -0
- package/hooks/sugerir-regenerar-inventario.js +170 -0
- package/hooks/telemetria-agentes.js +167 -0
- package/hooks/tracking-costos.js +688 -0
- package/instintos/global.yaml +8 -0
- package/instintos/perfil-usuario.yaml +53 -0
- package/instintos/prompt-appendices.yaml +57 -0
- package/instintos/proyecto.yaml +372 -0
- package/manifiestos/gateway-config.json +77 -0
- package/manifiestos/handoff-context.json +223 -0
- package/manifiestos/hook-profiles.json +44 -0
- package/manifiestos/hooks-config.json +360 -0
- package/manifiestos/modulos.json +1173 -0
- package/manifiestos/perfiles.json +404 -0
- package/package.json +86 -0
- package/plantillas/ESTADO.md +109 -0
- package/plantillas/HOJA-RUTA.md +143 -0
- package/plantillas/PROYECTO.md +122 -0
- package/plantillas/REQUISITOS.md +132 -0
- package/plantillas/auditor-veto-template.md +105 -0
- package/plantillas/github-workflows/README.md +47 -0
- package/plantillas/github-workflows/release-please.yml +44 -0
- package/plantillas/github-workflows/swl-ci.yml +107 -0
- package/plantillas/github-workflows/swl-security.yml +51 -0
- package/plantillas/mcp-mineru.json +13 -0
- package/plantillas/research/ARQUITECTURA.md +220 -0
- package/plantillas/research/FUNCIONALIDADES.md +175 -0
- package/plantillas/research/RESUMEN.md +165 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/TRAMPAS.md +299 -0
- package/plantillas/skill-evals-template.json +44 -0
- package/plugin.json +343 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +352 -0
- package/reglas/brevedad-output.md +124 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +201 -0
- package/reglas/git-workflow.md +245 -0
- package/reglas/gobernanza.md +271 -0
- package/reglas/harness-claude-code.md +213 -0
- package/reglas/hooks.md +186 -0
- package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
- package/reglas/lenguajes/csharp/hooks.md +281 -0
- package/reglas/lenguajes/csharp/patrones.md +226 -0
- package/reglas/lenguajes/csharp/seguridad.md +258 -0
- package/reglas/lenguajes/csharp/testing.md +176 -0
- package/reglas/lenguajes/go/estilo-codigo.md +195 -0
- package/reglas/lenguajes/go/hooks.md +249 -0
- package/reglas/lenguajes/go/patrones.md +249 -0
- package/reglas/lenguajes/go/seguridad.md +225 -0
- package/reglas/lenguajes/go/testing.md +272 -0
- package/reglas/lenguajes/java/estilo-codigo.md +217 -0
- package/reglas/lenguajes/java/hooks.md +251 -0
- package/reglas/lenguajes/java/patrones.md +226 -0
- package/reglas/lenguajes/java/seguridad.md +233 -0
- package/reglas/lenguajes/java/testing.md +238 -0
- package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
- package/reglas/lenguajes/kotlin/hooks.md +245 -0
- package/reglas/lenguajes/kotlin/patrones.md +201 -0
- package/reglas/lenguajes/kotlin/seguridad.md +202 -0
- package/reglas/lenguajes/kotlin/testing.md +236 -0
- package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
- package/reglas/lenguajes/nextjs/hooks.md +186 -0
- package/reglas/lenguajes/nextjs/patrones.md +225 -0
- package/reglas/lenguajes/nextjs/seguridad.md +216 -0
- package/reglas/lenguajes/nextjs/testing.md +193 -0
- package/reglas/lenguajes/php/estilo-codigo.md +228 -0
- package/reglas/lenguajes/php/hooks.md +165 -0
- package/reglas/lenguajes/php/patrones.md +233 -0
- package/reglas/lenguajes/php/seguridad.md +186 -0
- package/reglas/lenguajes/php/testing.md +205 -0
- package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
- package/reglas/lenguajes/rust/hooks.md +240 -0
- package/reglas/lenguajes/rust/patrones.md +250 -0
- package/reglas/lenguajes/rust/seguridad.md +221 -0
- package/reglas/lenguajes/rust/testing.md +194 -0
- package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
- package/reglas/lenguajes/swift/hooks.md +257 -0
- package/reglas/lenguajes/swift/patrones.md +235 -0
- package/reglas/lenguajes/swift/seguridad.md +248 -0
- package/reglas/lenguajes/swift/testing.md +242 -0
- package/reglas/markitdown.md +60 -0
- package/reglas/memoria-consolidada.md +209 -0
- package/reglas/patrones.md +225 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad-agentes.md +351 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +373 -0
- package/reglas/testing.md +193 -0
- package/schemas/agent-contract.json +176 -0
- package/schemas/agent-frontmatter.schema.json +149 -0
- package/schemas/agent-message.schema.json +53 -0
- package/schemas/agent-output-implementacion.schema.json +85 -0
- package/schemas/agent-output-planificacion.schema.json +113 -0
- package/schemas/agent-output-review.schema.json +78 -0
- package/schemas/diary-entry.schema.json +80 -0
- package/schemas/hook-profiles.schema.json +39 -0
- package/schemas/hooks-config.schema.json +74 -0
- package/schemas/instinct.schema.json +115 -0
- package/schemas/modulos.schema.json +29 -0
- package/schemas/perfiles.schema.json +28 -0
- package/schemas/plugin.schema.json +64 -0
- package/schemas/skill-evals.schema.json +95 -0
- package/schemas/skill-frontmatter.schema.json +170 -0
- package/scripts/actualizar.js +145 -0
- package/scripts/audit-skills.sh +78 -0
- package/scripts/auditar-agentes-gaps.js +149 -0
- package/scripts/auditar-cobertura-frameworks.js +241 -0
- package/scripts/auditar-skills-gaps.js +206 -0
- package/scripts/bootstrap-instintos.js +259 -0
- package/scripts/check-update.js +109 -0
- package/scripts/comandos/agents.js +105 -0
- package/scripts/comandos/info.js +108 -0
- package/scripts/comandos/install-asistido.js +186 -0
- package/scripts/comandos/skills.js +211 -0
- package/scripts/configurar-branch-protection.js +418 -0
- package/scripts/daemon-swl.py +388 -0
- package/scripts/desinstalar.js +130 -0
- package/scripts/doctor.js +559 -0
- package/scripts/field-report.js +199 -0
- package/scripts/generar-inventario.js +317 -0
- package/scripts/inbox-tmux-inject.js +161 -0
- package/scripts/inferir-herramientas-permitidas.js +586 -0
- package/scripts/inicializar.js +133 -0
- package/scripts/instalador.js +1031 -0
- package/scripts/instalar-git-hook.js +122 -0
- package/scripts/lib/agp-frontmatter.js +222 -0
- package/scripts/lib/append-con-marcadores.js +199 -0
- package/scripts/lib/artefactos-python.js +43 -0
- package/scripts/lib/audit-query.js +221 -0
- package/scripts/lib/autostart-linux.js +347 -0
- package/scripts/lib/autostart-macos.js +360 -0
- package/scripts/lib/autostart-windows.js +307 -0
- package/scripts/lib/budget-enforcer.js +252 -0
- package/scripts/lib/claude-sessions.js +285 -0
- package/scripts/lib/configurar-ci.js +380 -0
- package/scripts/lib/console-span-exporter.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -0
- package/scripts/lib/dashboard-widgets.js +290 -0
- package/scripts/lib/detectar-runtime.js +279 -0
- package/scripts/lib/detectar-stack.js +187 -0
- package/scripts/lib/diary-entry.js +234 -0
- package/scripts/lib/drift-detector.js +545 -0
- package/scripts/lib/estado.js +124 -0
- package/scripts/lib/gestor-componentes.js +243 -0
- package/scripts/lib/gitignore-manifest.js +305 -0
- package/scripts/lib/graph-analyze.py +556 -0
- package/scripts/lib/graph-builder.py +485 -0
- package/scripts/lib/graph-cluster.py +259 -0
- package/scripts/lib/health-row.js +168 -0
- package/scripts/lib/hooks-settings.js +789 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/mc-client.js +137 -0
- package/scripts/lib/notificaciones-telegram.js +1107 -0
- package/scripts/lib/npm-version.js +261 -0
- package/scripts/lib/paquetes-conocidos.js +50 -0
- package/scripts/lib/preservar-usuario.js +586 -0
- package/scripts/lib/prompt-builder.js +264 -0
- package/scripts/lib/resolver-externo.js +332 -0
- package/scripts/lib/schedule-parser.js +305 -0
- package/scripts/lib/scoring-instintos.js +240 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/lib/selector-interactivo.js +152 -0
- package/scripts/lib/semantic-search.js +242 -0
- package/scripts/lib/skill-discovery.js +234 -0
- package/scripts/lib/skill-metrics.js +246 -0
- package/scripts/lib/skill-normalizer.js +112 -0
- package/scripts/lib/skills-hub.js +340 -0
- package/scripts/lib/span-schema.js +134 -0
- package/scripts/lib/tool-cost-analyzer.js +255 -0
- package/scripts/lib/tracing-processor-interface.js +286 -0
- package/scripts/lib/transformadores/base.js +80 -0
- package/scripts/lib/transformadores/claude.js +124 -0
- package/scripts/lib/transformadores/codex.js +115 -0
- package/scripts/lib/transformadores/copilot.js +106 -0
- package/scripts/lib/transformadores/gemini.js +74 -0
- package/scripts/lib/transformadores/index.js +35 -0
- package/scripts/lib/transformadores/opencode.js +75 -0
- package/scripts/lib/ui.js +259 -0
- package/scripts/limpiar-artefactos-python.js +131 -0
- package/scripts/mcp-orchestrator.py +386 -0
- package/scripts/mcp-pool-manager.py +352 -0
- package/scripts/mcp-telemetry.py +378 -0
- package/scripts/poblar-evolvable.js +226 -0
- package/scripts/publicar.js +287 -0
- package/scripts/reflect-skills.js +403 -0
- package/scripts/rotar-audit-logs.js +185 -0
- package/scripts/run-skill-evals.js +242 -0
- package/scripts/smoke-test.js +374 -0
- package/scripts/token-analysis.py +471 -0
- package/scripts/validar-manifest.js +195 -0
- package/scripts/validar-memoria.js +321 -0
- package/scripts/validar-tests-aislamiento.js +184 -0
- package/scripts/validar-tokens-test.js +208 -0
- package/scripts/validar.js +147 -0
- package/scripts/validate-markdown.py +339 -0
- package/scripts/validate-skills.py +385 -0
- package/scripts/vendor/claude-usage/README.md +116 -0
- package/scripts/vendor/claude-usage/cli.py +334 -0
- package/scripts/vendor/claude-usage/dashboard.py +795 -0
- package/scripts/vendor/claude-usage/scanner.py +467 -0
- package/scripts/vendor/markitdown/cli.py +194 -0
- package/scripts/verificar-evolucion.js +289 -0
- package/scripts/verificar-release.js +494 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# Event-Driven — Implementaciones Completas de Referencia
|
|
2
|
+
|
|
3
|
+
Ejemplos completos de código Python para arquitectura event-driven.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## RabbitMQ — Pub/Sub con Python (aio_pika)
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
# pip install aio-pika
|
|
11
|
+
import aio_pika
|
|
12
|
+
import asyncio
|
|
13
|
+
import json
|
|
14
|
+
from dataclasses import dataclass, asdict
|
|
15
|
+
from datetime import datetime, timezone
|
|
16
|
+
from typing import Any, Callable, Awaitable
|
|
17
|
+
import uuid
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class Evento:
|
|
21
|
+
tipo: str
|
|
22
|
+
payload: dict
|
|
23
|
+
id: str = ""
|
|
24
|
+
timestamp: str = ""
|
|
25
|
+
correlation_id: str = ""
|
|
26
|
+
version: str = "1.0"
|
|
27
|
+
|
|
28
|
+
def __post_init__(self):
|
|
29
|
+
if not self.id:
|
|
30
|
+
self.id = str(uuid.uuid4())
|
|
31
|
+
if not self.timestamp:
|
|
32
|
+
self.timestamp = datetime.now(timezone.utc).isoformat()
|
|
33
|
+
|
|
34
|
+
class BrokerEventos:
|
|
35
|
+
"""Wrapper sobre aio_pika para publicar y consumir eventos."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, url: str):
|
|
38
|
+
self._url = url
|
|
39
|
+
self._conexion: aio_pika.RobustConnection | None = None
|
|
40
|
+
self._canal: aio_pika.abc.AbstractChannel | None = None
|
|
41
|
+
|
|
42
|
+
async def conectar(self) -> None:
|
|
43
|
+
self._conexion = await aio_pika.connect_robust(
|
|
44
|
+
self._url,
|
|
45
|
+
heartbeat=60,
|
|
46
|
+
reconnect_interval=5.0,
|
|
47
|
+
)
|
|
48
|
+
self._canal = await self._conexion.channel()
|
|
49
|
+
await self._canal.set_qos(prefetch_count=10)
|
|
50
|
+
|
|
51
|
+
async def publicar(
|
|
52
|
+
self,
|
|
53
|
+
evento: Evento,
|
|
54
|
+
exchange: str = "eventos.rrhh",
|
|
55
|
+
routing_key: str | None = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
assert self._canal, "Llamar connect() primero"
|
|
58
|
+
exchange_obj = await self._canal.declare_exchange(
|
|
59
|
+
exchange, aio_pika.ExchangeType.TOPIC, durable=True,
|
|
60
|
+
)
|
|
61
|
+
await exchange_obj.publish(
|
|
62
|
+
aio_pika.Message(
|
|
63
|
+
body=json.dumps(asdict(evento), ensure_ascii=False).encode(),
|
|
64
|
+
content_type="application/json",
|
|
65
|
+
delivery_mode=aio_pika.DeliveryMode.PERSISTENT,
|
|
66
|
+
message_id=evento.id,
|
|
67
|
+
timestamp=datetime.now(timezone.utc),
|
|
68
|
+
headers={
|
|
69
|
+
"x-correlation-id": evento.correlation_id,
|
|
70
|
+
"x-event-version": evento.version,
|
|
71
|
+
},
|
|
72
|
+
),
|
|
73
|
+
routing_key=routing_key or evento.tipo,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
async def suscribir(
|
|
77
|
+
self,
|
|
78
|
+
cola: str,
|
|
79
|
+
exchange: str,
|
|
80
|
+
routing_keys: list[str],
|
|
81
|
+
handler: Callable[[Evento], Awaitable[None]],
|
|
82
|
+
) -> None:
|
|
83
|
+
assert self._canal
|
|
84
|
+
dlq_nombre = f"{cola}.dlq"
|
|
85
|
+
await self._canal.declare_queue(dlq_nombre, durable=True)
|
|
86
|
+
queue = await self._canal.declare_queue(
|
|
87
|
+
cola, durable=True,
|
|
88
|
+
arguments={
|
|
89
|
+
"x-dead-letter-exchange": "",
|
|
90
|
+
"x-dead-letter-routing-key": dlq_nombre,
|
|
91
|
+
"x-message-ttl": 86400000,
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
exchange_obj = await self._canal.declare_exchange(
|
|
95
|
+
exchange, aio_pika.ExchangeType.TOPIC, durable=True
|
|
96
|
+
)
|
|
97
|
+
for routing_key in routing_keys:
|
|
98
|
+
await queue.bind(exchange_obj, routing_key=routing_key)
|
|
99
|
+
|
|
100
|
+
async def procesar_mensaje(mensaje: aio_pika.IncomingMessage) -> None:
|
|
101
|
+
async with mensaje.process(requeue=False):
|
|
102
|
+
try:
|
|
103
|
+
datos = json.loads(mensaje.body)
|
|
104
|
+
evento = Evento(**datos)
|
|
105
|
+
await handler(evento)
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error("Error procesando evento %s: %s", mensaje.message_id, e)
|
|
108
|
+
raise
|
|
109
|
+
|
|
110
|
+
await queue.consume(procesar_mensaje)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Kafka — Streaming de Alta Escala
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# pip install aiokafka
|
|
119
|
+
from aiokafka import AIOKafkaProducer, AIOKafkaConsumer
|
|
120
|
+
import asyncio
|
|
121
|
+
import json
|
|
122
|
+
|
|
123
|
+
class ProductorKafka:
|
|
124
|
+
def __init__(self, bootstrap_servers: str):
|
|
125
|
+
self._producer = AIOKafkaProducer(
|
|
126
|
+
bootstrap_servers=bootstrap_servers,
|
|
127
|
+
enable_idempotence=True,
|
|
128
|
+
max_batch_size=65536,
|
|
129
|
+
compression_type="gzip",
|
|
130
|
+
value_serializer=lambda v: json.dumps(v, ensure_ascii=False).encode(),
|
|
131
|
+
key_serializer=lambda k: k.encode() if k else None,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
async def __aenter__(self) -> "ProductorKafka":
|
|
135
|
+
await self._producer.start()
|
|
136
|
+
return self
|
|
137
|
+
|
|
138
|
+
async def __aexit__(self, *args) -> None:
|
|
139
|
+
await self._producer.stop()
|
|
140
|
+
|
|
141
|
+
async def enviar(self, topico: str, evento: dict, clave: str | None = None) -> None:
|
|
142
|
+
await self._producer.send_and_wait(
|
|
143
|
+
topico, value=evento, key=clave,
|
|
144
|
+
headers=[
|
|
145
|
+
("content-type", b"application/json"),
|
|
146
|
+
("event-id", evento.get("id", "").encode()),
|
|
147
|
+
],
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
class ConsumidorKafka:
|
|
151
|
+
def __init__(self, bootstrap_servers: str, group_id: str, topicos: list[str]):
|
|
152
|
+
self._consumer = AIOKafkaConsumer(
|
|
153
|
+
*topicos,
|
|
154
|
+
bootstrap_servers=bootstrap_servers,
|
|
155
|
+
group_id=group_id,
|
|
156
|
+
auto_offset_reset="earliest",
|
|
157
|
+
enable_auto_commit=False,
|
|
158
|
+
max_poll_records=100,
|
|
159
|
+
session_timeout_ms=30000,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
async def consumir(self, handler) -> None:
|
|
163
|
+
await self._consumer.start()
|
|
164
|
+
try:
|
|
165
|
+
async for mensaje in self._consumer:
|
|
166
|
+
try:
|
|
167
|
+
datos = json.loads(mensaje.value)
|
|
168
|
+
await handler(datos)
|
|
169
|
+
await self._consumer.commit()
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.error(
|
|
172
|
+
"Error en topico=%s partition=%s offset=%s: %s",
|
|
173
|
+
mensaje.topic, mensaje.partition, mensaje.offset, e,
|
|
174
|
+
)
|
|
175
|
+
finally:
|
|
176
|
+
await self._consumer.stop()
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Schemas de Eventos con Pydantic
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from pydantic import BaseModel
|
|
185
|
+
from datetime import datetime
|
|
186
|
+
from typing import Literal
|
|
187
|
+
import uuid
|
|
188
|
+
|
|
189
|
+
class EventoBase(BaseModel):
|
|
190
|
+
id: str = ""
|
|
191
|
+
timestamp: datetime = None
|
|
192
|
+
version: str = "1.0"
|
|
193
|
+
correlation_id: str = ""
|
|
194
|
+
origen: str
|
|
195
|
+
|
|
196
|
+
def model_post_init(self, *args):
|
|
197
|
+
if not self.id:
|
|
198
|
+
self.id = str(uuid.uuid4())
|
|
199
|
+
if not self.timestamp:
|
|
200
|
+
self.timestamp = datetime.now(timezone.utc)
|
|
201
|
+
|
|
202
|
+
class EmpleadoCreadoPayload(BaseModel):
|
|
203
|
+
empleado_id: str
|
|
204
|
+
numero_empleado: str
|
|
205
|
+
nombre_completo: str
|
|
206
|
+
email_corporativo: str
|
|
207
|
+
departamento_id: str
|
|
208
|
+
puesto: str
|
|
209
|
+
fecha_ingreso: str
|
|
210
|
+
|
|
211
|
+
class EventoEmpleadoCreado(EventoBase):
|
|
212
|
+
tipo: Literal["empleado.creado"] = "empleado.creado"
|
|
213
|
+
payload: EmpleadoCreadoPayload
|
|
214
|
+
|
|
215
|
+
# Versioning — NUNCA romper compatibilidad hacia atrás
|
|
216
|
+
class EmpleadoCreadoPayloadV2(EmpleadoCreadoPayload):
|
|
217
|
+
nss: str | None = None
|
|
218
|
+
curp: str | None = None
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Idempotency — Registro con Redis
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
class RegistroIdempotencia:
|
|
227
|
+
def __init__(self, redis_client):
|
|
228
|
+
self._redis = redis_client
|
|
229
|
+
self._ttl = 86400
|
|
230
|
+
|
|
231
|
+
async def ya_procesado(self, evento_id: str, consumer_id: str) -> bool:
|
|
232
|
+
clave = f"idempotencia:{consumer_id}:{evento_id}"
|
|
233
|
+
return bool(await self._redis.exists(clave))
|
|
234
|
+
|
|
235
|
+
async def marcar_procesado(self, evento_id: str, consumer_id: str) -> None:
|
|
236
|
+
clave = f"idempotencia:{consumer_id}:{evento_id}"
|
|
237
|
+
await self._redis.setex(clave, self._ttl, "1")
|
|
238
|
+
|
|
239
|
+
class HandlerNuevaAlta:
|
|
240
|
+
def __init__(self, repo, idempotencia: RegistroIdempotencia):
|
|
241
|
+
self._repo = repo
|
|
242
|
+
self._idempotencia = idempotencia
|
|
243
|
+
|
|
244
|
+
async def manejar(self, evento: EventoEmpleadoCreado) -> None:
|
|
245
|
+
consumer_id = "handler.nueva_alta.configurar_nomina"
|
|
246
|
+
if await self._idempotencia.ya_procesado(evento.id, consumer_id):
|
|
247
|
+
logger.info("Evento %s ya procesado, ignorando", evento.id)
|
|
248
|
+
return
|
|
249
|
+
await self._repo.configurar_nomina(evento.payload)
|
|
250
|
+
await self._idempotencia.marcar_procesado(evento.id, consumer_id)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Retry con Backoff Exponencial
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
class PoliticaReintento:
|
|
259
|
+
def __init__(self, max_intentos=5, delay_inicial=1.0, delay_maximo=60.0, multiplicador=2.0):
|
|
260
|
+
self.max_intentos = max_intentos
|
|
261
|
+
self.delay_inicial = delay_inicial
|
|
262
|
+
self.delay_maximo = delay_maximo
|
|
263
|
+
self.multiplicador = multiplicador
|
|
264
|
+
|
|
265
|
+
def delay_para_intento(self, intento: int) -> float:
|
|
266
|
+
import random
|
|
267
|
+
delay = min(
|
|
268
|
+
self.delay_inicial * (self.multiplicador ** (intento - 1)),
|
|
269
|
+
self.delay_maximo,
|
|
270
|
+
)
|
|
271
|
+
jitter = delay * 0.25 * (2 * random.random() - 1)
|
|
272
|
+
return delay + jitter
|
|
273
|
+
|
|
274
|
+
class ProcesadorDLQ:
|
|
275
|
+
async def analizar_dlq(self, cola_dlq: str) -> list[dict]:
|
|
276
|
+
mensajes = []
|
|
277
|
+
async for mensaje in self._consumer.consumir_dlq(cola_dlq):
|
|
278
|
+
mensajes.append({
|
|
279
|
+
"id": mensaje.message_id,
|
|
280
|
+
"timestamp_original": mensaje.headers.get("x-first-death-time"),
|
|
281
|
+
"motivo_fallo": mensaje.headers.get("x-death")[0]["reason"],
|
|
282
|
+
"intentos": mensaje.headers.get("x-death")[0]["count"],
|
|
283
|
+
"cuerpo": json.loads(mensaje.body),
|
|
284
|
+
})
|
|
285
|
+
return mensajes
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## CQRS — Command Query Responsibility Segregation
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
# COMMAND SIDE
|
|
294
|
+
class ComandoCrearEmpleado(BaseModel):
|
|
295
|
+
nombre: str
|
|
296
|
+
apellido_paterno: str
|
|
297
|
+
apellido_materno: str
|
|
298
|
+
email: str
|
|
299
|
+
departamento_id: str
|
|
300
|
+
|
|
301
|
+
class HandlerComandoCrearEmpleado:
|
|
302
|
+
async def manejar(self, comando, db, broker) -> str:
|
|
303
|
+
empleado = Empleado(**comando.model_dump())
|
|
304
|
+
db.add(empleado)
|
|
305
|
+
await db.flush()
|
|
306
|
+
evento = EventoEmpleadoCreado(
|
|
307
|
+
origen="servicio-empleados",
|
|
308
|
+
payload=EmpleadoCreadoPayload(
|
|
309
|
+
empleado_id=str(empleado.id),
|
|
310
|
+
nombre_completo=f"{comando.nombre} {comando.apellido_paterno}",
|
|
311
|
+
email_corporativo=comando.email,
|
|
312
|
+
departamento_id=comando.departamento_id,
|
|
313
|
+
numero_empleado=empleado.numero_empleado,
|
|
314
|
+
puesto=empleado.puesto,
|
|
315
|
+
fecha_ingreso=empleado.fecha_ingreso.isoformat(),
|
|
316
|
+
),
|
|
317
|
+
)
|
|
318
|
+
await broker.publicar(evento)
|
|
319
|
+
await db.commit()
|
|
320
|
+
return str(empleado.id)
|
|
321
|
+
|
|
322
|
+
# QUERY SIDE
|
|
323
|
+
class VistaEmpleado(Base):
|
|
324
|
+
__tablename__ = "vista_empleados"
|
|
325
|
+
id = Column(UUID, primary_key=True)
|
|
326
|
+
nombre_completo = Column(String)
|
|
327
|
+
email = Column(String)
|
|
328
|
+
departamento_nombre = Column(String)
|
|
329
|
+
puesto = Column(String)
|
|
330
|
+
activo = Column(Boolean, default=True)
|
|
331
|
+
ultima_actualizacion = Column(DateTime)
|
|
332
|
+
|
|
333
|
+
class ActualizadorVistaEmpleados:
|
|
334
|
+
async def en_empleado_creado(self, evento) -> None:
|
|
335
|
+
departamento = await self._repo.obtener_departamento(evento.payload.departamento_id)
|
|
336
|
+
vista = VistaEmpleado(
|
|
337
|
+
id=uuid.UUID(evento.payload.empleado_id),
|
|
338
|
+
nombre_completo=evento.payload.nombre_completo,
|
|
339
|
+
email=evento.payload.email_corporativo,
|
|
340
|
+
departamento_nombre=departamento.nombre,
|
|
341
|
+
puesto=evento.payload.puesto,
|
|
342
|
+
ultima_actualizacion=evento.timestamp,
|
|
343
|
+
)
|
|
344
|
+
await self._db.merge(vista)
|
|
345
|
+
await self._db.commit()
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Transactional Outbox Pattern
|
|
351
|
+
|
|
352
|
+
```python
|
|
353
|
+
class EventoOutbox(Base):
|
|
354
|
+
__tablename__ = "eventos_outbox"
|
|
355
|
+
id = Column(UUID, primary_key=True, default=uuid.uuid4)
|
|
356
|
+
tipo = Column(String(100), nullable=False)
|
|
357
|
+
payload = Column(JSONB, nullable=False)
|
|
358
|
+
exchange = Column(String(100), nullable=False)
|
|
359
|
+
routing_key = Column(String(100), nullable=False)
|
|
360
|
+
creado_en = Column(DateTime(timezone=True), server_default=func.now())
|
|
361
|
+
publicado_en = Column(DateTime(timezone=True), nullable=True)
|
|
362
|
+
intentos = Column(Integer, default=0)
|
|
363
|
+
|
|
364
|
+
async def crear_empleado_con_outbox(comando, db) -> str:
|
|
365
|
+
empleado = Empleado(**comando.model_dump())
|
|
366
|
+
db.add(empleado)
|
|
367
|
+
await db.flush()
|
|
368
|
+
evento_outbox = EventoOutbox(
|
|
369
|
+
tipo="empleado.creado",
|
|
370
|
+
payload={...},
|
|
371
|
+
exchange="eventos.rrhh",
|
|
372
|
+
routing_key="empleado.creado",
|
|
373
|
+
)
|
|
374
|
+
db.add(evento_outbox)
|
|
375
|
+
await db.commit()
|
|
376
|
+
return str(empleado.id)
|
|
377
|
+
|
|
378
|
+
async def worker_outbox(db, broker) -> None:
|
|
379
|
+
while True:
|
|
380
|
+
eventos = await db.execute(
|
|
381
|
+
select(EventoOutbox)
|
|
382
|
+
.where(EventoOutbox.publicado_en.is_(None))
|
|
383
|
+
.where(EventoOutbox.intentos < 5)
|
|
384
|
+
.order_by(EventoOutbox.creado_en)
|
|
385
|
+
.limit(100)
|
|
386
|
+
.with_for_update(skip_locked=True)
|
|
387
|
+
)
|
|
388
|
+
for evento in eventos.scalars():
|
|
389
|
+
try:
|
|
390
|
+
await broker.publicar_raw(
|
|
391
|
+
tipo=evento.tipo, payload=evento.payload,
|
|
392
|
+
exchange=evento.exchange, routing_key=evento.routing_key,
|
|
393
|
+
)
|
|
394
|
+
evento.publicado_en = datetime.now(timezone.utc)
|
|
395
|
+
except Exception as e:
|
|
396
|
+
evento.intentos += 1
|
|
397
|
+
logger.error("Error publicando evento %s: %s", evento.id, e)
|
|
398
|
+
await db.commit()
|
|
399
|
+
await asyncio.sleep(5)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Eventual Consistency — Manejo en UI
|
|
405
|
+
|
|
406
|
+
```python
|
|
407
|
+
@router.post("/empleados", status_code=202)
|
|
408
|
+
async def crear_empleado(comando: ComandoCrearEmpleado, ...):
|
|
409
|
+
empleado_id = await handler.manejar(comando, db, broker)
|
|
410
|
+
return {
|
|
411
|
+
"empleado_id": empleado_id,
|
|
412
|
+
"estado": "procesando",
|
|
413
|
+
"mensaje": "El empleado está siendo procesado. Estará disponible en segundos.",
|
|
414
|
+
"consultar_en": f"/empleados/{empleado_id}/estado",
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
@router.get("/empleados/{id}/estado")
|
|
418
|
+
async def estado_empleado(id: UUID, db: AsyncSession = Depends(get_db)):
|
|
419
|
+
vista = await db.get(VistaEmpleado, id)
|
|
420
|
+
if vista is None:
|
|
421
|
+
return {"estado": "procesando"}
|
|
422
|
+
return {"estado": "completado", "datos": vista}
|
|
423
|
+
```
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: extraccion-documentos
|
|
3
|
+
description: >
|
|
4
|
+
Extracción de contenido de documentos binarios (PDF, DOCX, PPTX, imágenes)
|
|
5
|
+
a Markdown usando MinerU. Soporta MCP (parse_documents), CLI (mineru-open-api)
|
|
6
|
+
y modo flash sin token. Cargar cuando el usuario pida leer, analizar o extraer
|
|
7
|
+
contenido de archivos PDF, Word, PowerPoint o imágenes con texto.
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
herramientasPermitidas: [Read, Bash, Grep]
|
|
10
|
+
evolvable: true # default para skill estandar
|
|
11
|
+
exclusiones:
|
|
12
|
+
- "No cargar para leer archivos de texto plano (.txt, .md, .csv, .json) — el Read tool los maneja directamente sin necesidad de MinerU."
|
|
13
|
+
- "No cargar para OCR de imágenes de alta precisión con modelos propios — para pipelines OCR especializados (Tesseract, Azure Form Recognizer) cargar el skill del proveedor correspondiente."
|
|
14
|
+
- "No cargar para extracción de datos estructurados de PDFs con formularios (XFA, AcroForm) — MinerU convierte a Markdown pero no preserva la estructura de formularios."
|
|
15
|
+
- "No cargar si la tarea es convertir documentos a formatos distintos de Markdown (DOCX→HTML, PDF→DOCX) — para conversión de formatos cargar `swl-markitdown` o el skill del pipeline de documentos."
|
|
16
|
+
---
|
|
17
|
+
# Extracción de documentos con MinerU
|
|
18
|
+
|
|
19
|
+
## Cuándo NO cargar
|
|
20
|
+
|
|
21
|
+
- La tarea es leer un archivo `.txt`, `.md`, `.csv` o `.json`: usar el Read tool directamente.
|
|
22
|
+
- El pipeline requiere OCR con modelo propio (Tesseract, Azure Form Recognizer, AWS Textract): cargar el skill del proveedor correspondiente.
|
|
23
|
+
- El PDF es un formulario con campos XFA o AcroForm y se necesita preservar la estructura de campos: MinerU no soporta esto.
|
|
24
|
+
- La conversión requerida es de formato (DOCX→HTML, PDF→DOCX), no extracción de contenido: cargar `swl-markitdown` o el skill de conversión de documentos.
|
|
25
|
+
|
|
26
|
+
## Cuándo activar
|
|
27
|
+
|
|
28
|
+
- El usuario pide leer, analizar o extraer contenido de un PDF
|
|
29
|
+
- El usuario proporciona un archivo .docx, .pptx, .doc, .ppt
|
|
30
|
+
- El usuario quiere convertir un documento a Markdown
|
|
31
|
+
- Se necesita leer una especificación, contrato o documento de requisitos
|
|
32
|
+
- El investigador-swl o arquitecto-swl necesitan analizar documentación existente
|
|
33
|
+
- El usuario dice "extrae", "lee este PDF", "convierte a texto", "analiza este documento"
|
|
34
|
+
|
|
35
|
+
## Estrategia de extracción (orden de prioridad)
|
|
36
|
+
|
|
37
|
+
### 1. MCP MinerU (preferido si está configurado)
|
|
38
|
+
|
|
39
|
+
Verificar si el MCP está disponible:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Buscar en .mcp.json la entrada "mineru"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Si existe, usar directamente:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
mcp__mineru__parse_documents(file_sources=["ruta/al/archivo.pdf"])
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Ventajas: integrado en Claude Code, sin salir del flujo, soporta múltiples archivos.
|
|
52
|
+
|
|
53
|
+
### 2. CLI mineru-open-api (alternativa sin MCP)
|
|
54
|
+
|
|
55
|
+
Verificar si el CLI está instalado:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
mineru-open-api version 2>/dev/null
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Si existe, usar según el caso:
|
|
62
|
+
|
|
63
|
+
| Situación | Comando |
|
|
64
|
+
|-----------|---------|
|
|
65
|
+
| Archivo pequeño (< 10 MB, < 20 págs) | `mineru-open-api flash-extract archivo.pdf` |
|
|
66
|
+
| Archivo grande o con tablas | `mineru-open-api extract archivo.pdf` (requiere token) |
|
|
67
|
+
| Página web | `mineru-open-api crawl https://url` |
|
|
68
|
+
| Múltiples archivos | `mineru-open-api extract *.pdf -o ./salida/` |
|
|
69
|
+
|
|
70
|
+
### 3. Herramienta Read nativa (último recurso)
|
|
71
|
+
|
|
72
|
+
Si no hay MCP ni CLI, la herramienta Read de Claude Code puede leer PDFs
|
|
73
|
+
directamente (con limitaciones de páginas). Usar como último recurso.
|
|
74
|
+
|
|
75
|
+
> **Dependencia externa**: MinerU (MCP o CLI) no se incluye en la instalación
|
|
76
|
+
> de SWL. Es un componente externo que cada equipo debe instalar por separado.
|
|
77
|
+
> SWL instala la configuración del MCP y este skill, pero el servidor o CLI
|
|
78
|
+
> de MinerU es responsabilidad del equipo. El skill detecta automáticamente
|
|
79
|
+
> la disponibilidad y selecciona el mejor modo sin intervención del usuario.
|
|
80
|
+
|
|
81
|
+
## Decisión flash-extract vs extract
|
|
82
|
+
|
|
83
|
+
| Usar flash-extract cuando | Usar extract cuando |
|
|
84
|
+
|--------------------------|-------------------|
|
|
85
|
+
| No hay token configurado | Hay token y se necesita precisión |
|
|
86
|
+
| Archivo < 10 MB y < 20 páginas | Archivo > 10 MB o > 20 páginas |
|
|
87
|
+
| Solo se necesita Markdown | Se necesita DOCX, HTML o LaTeX |
|
|
88
|
+
| No importan tablas/fórmulas | Hay tablas o fórmulas importantes |
|
|
89
|
+
| Primera vez del usuario | El usuario ya tiene token |
|
|
90
|
+
| Documento digital (texto nativo) | Documento escaneado o con firmas/sellos |
|
|
91
|
+
| Texto simple sin formato denso | Texto legal, actas o documentos oficiales |
|
|
92
|
+
|
|
93
|
+
> **Limitación conocida de flash-extract**: En documentos escaneados, con firmas
|
|
94
|
+
> manuscritas, sellos oficiales o texto legal denso en español, flash-extract
|
|
95
|
+
> produce resultados con texto truncado, palabras fusionadas y caracteres faltantes.
|
|
96
|
+
> Para estos documentos, se recomienda usar `extract` con token (registro gratuito
|
|
97
|
+
> en https://mineru.net/apiManage/token). Si el usuario reporta mala calidad de
|
|
98
|
+
> extracción y no tiene token, sugerir el registro y configurar con
|
|
99
|
+
> `mineru-open-api auth`.
|
|
100
|
+
|
|
101
|
+
## Configuración del MCP
|
|
102
|
+
|
|
103
|
+
Para habilitar el MCP de MinerU en un proyecto, agregar a `.mcp.json`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"mineru": {
|
|
109
|
+
"command": "uvx",
|
|
110
|
+
"args": ["mineru-open-mcp"],
|
|
111
|
+
"env": {
|
|
112
|
+
"MINERU_API_TOKEN": "tu_token_aqui"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Sin token, el MCP usa modo Flash automáticamente (gratis, sin registro).
|
|
120
|
+
|
|
121
|
+
Con token (obtener en https://mineru.net/apiManage/token), habilita extracción
|
|
122
|
+
de precisión con tablas, fórmulas y formatos adicionales.
|
|
123
|
+
|
|
124
|
+
## Configuración del token para extract
|
|
125
|
+
|
|
126
|
+
El modo `extract` requiere un token gratuito de https://mineru.net/apiManage/token.
|
|
127
|
+
|
|
128
|
+
**Configurar vía variable de entorno** (recomendado — funciona en Claude Code):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Linux / macOS — agregar a ~/.bashrc o ~/.zshrc
|
|
132
|
+
export MINERU_TOKEN="tu_token_aqui"
|
|
133
|
+
|
|
134
|
+
# Windows PowerShell — persistente a nivel de usuario
|
|
135
|
+
[System.Environment]::SetEnvironmentVariable("MINERU_TOKEN", "tu_token_aqui", "User")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Verificar que el token funciona**:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
mineru-open-api auth --verify
|
|
142
|
+
# Debe mostrar: Token format is valid / Source: env
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> **Nota**: El comando `mineru-open-api auth` (modo interactivo) no funciona
|
|
146
|
+
> dentro de Claude Code porque requiere entrada interactiva. Usar siempre la
|
|
147
|
+
> variable de entorno `MINERU_TOKEN` como método de configuración.
|
|
148
|
+
|
|
149
|
+
Para el MCP, el token se configura en `.mcp.json` con la variable `MINERU_API_TOKEN`
|
|
150
|
+
como se muestra en la sección anterior.
|
|
151
|
+
|
|
152
|
+
## Instalación del CLI
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Linux / macOS
|
|
156
|
+
curl -fsSL https://cdn-mineru.openxlab.org.cn/open-api-cli/install.sh | sh
|
|
157
|
+
|
|
158
|
+
# Windows (PowerShell) — descargar, inspeccionar y ejecutar
|
|
159
|
+
Invoke-WebRequest -Uri https://cdn-mineru.openxlab.org.cn/open-api-cli/install.ps1 -OutFile install-mineru.ps1
|
|
160
|
+
Get-Content install-mineru.ps1 # inspeccionar
|
|
161
|
+
.\install-mineru.ps1 # ejecutar
|
|
162
|
+
Remove-Item install-mineru.ps1 # limpiar
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
> Algunos antivirus bloquean `irm URL | iex` con detección heurística. La alternativa manual de arriba evita el bloqueo.
|
|
166
|
+
|
|
167
|
+
## Formatos soportados
|
|
168
|
+
|
|
169
|
+
| Formato | flash-extract | extract |
|
|
170
|
+
|---------|:---:|:---:|
|
|
171
|
+
| PDF (.pdf) | Sí | Sí |
|
|
172
|
+
| Imágenes (.png, .jpg, .jpeg) | Sí | Sí |
|
|
173
|
+
| Word (.docx) | Sí | Sí |
|
|
174
|
+
| Word (.doc) | No | Sí |
|
|
175
|
+
| PowerPoint (.pptx) | Sí | Sí |
|
|
176
|
+
| PowerPoint (.ppt) | No | Sí |
|
|
177
|
+
| HTML (.html) | No | Sí |
|
|
178
|
+
| URLs remotas | Sí | Sí |
|
|
179
|
+
|
|
180
|
+
## Integración con agentes SWL
|
|
181
|
+
|
|
182
|
+
| Agente | Uso de extracción |
|
|
183
|
+
|--------|------------------|
|
|
184
|
+
| `investigador-swl` | Leer especificaciones, papers, documentos de referencia en PDF |
|
|
185
|
+
| `arquitecto-swl` | Analizar documentos de arquitectura existentes |
|
|
186
|
+
| `mapear-codebase` | Incluir documentación no-código del proyecto |
|
|
187
|
+
| `producto-prd-swl` | Extraer requisitos de documentos del cliente |
|
|
188
|
+
| `revisor-seguridad-swl` | Leer políticas de seguridad en PDF |
|
|
189
|
+
|
|
190
|
+
## Idiomas soportados
|
|
191
|
+
|
|
192
|
+
| Código | Idiomas |
|
|
193
|
+
|--------|---------|
|
|
194
|
+
| `ch` | Chino, Inglés (predeterminado) |
|
|
195
|
+
| `en` | Inglés |
|
|
196
|
+
| `latin` | Español, Francés, Alemán, Portugués, Italiano y 40+ idiomas latinos |
|
|
197
|
+
| `arabic` | Árabe, Persa, Urdu |
|
|
198
|
+
| `cyrillic` | Ruso, Ucraniano, Búlgaro |
|
|
199
|
+
| `devanagari` | Hindi, Marathi, Nepali |
|
|
200
|
+
|
|
201
|
+
Para documentos en español: usar `--language latin` en el CLI.
|
|
202
|
+
|
|
203
|
+
## Manejo de errores
|
|
204
|
+
|
|
205
|
+
| Error | Causa | Solución |
|
|
206
|
+
|-------|-------|---------|
|
|
207
|
+
| Archivo > 10 MB en flash | Límite de flash-extract | Usar `extract` con token |
|
|
208
|
+
| Archivo > 20 páginas en flash | Límite de flash-extract | Usar `extract` con token |
|
|
209
|
+
| HTTP 429 | Rate limit por IP | Esperar o usar `extract` con token |
|
|
210
|
+
| "no API token found" | Token no configurado | `mineru-open-api auth` o variable `MINERU_TOKEN` |
|
|
211
|
+
| Tablas no extraídas | flash-extract no soporta tablas | Usar `extract` con token |
|
|
212
|
+
|
|
213
|
+
## Gotchas / Errores comunes no obvios
|
|
214
|
+
|
|
215
|
+
**`flash-extract` en documentos escaneados en español produce texto con palabras fusionadas y caracteres faltantes aunque el PDF parezca digital**: muchos PDFs "digitales" en México (contratos, actas) son en realidad imágenes escaneadas incrustadas. Flash no tiene OCR de precisión y entrega texto ilegible sin error visible. Causa: `flash-extract` no distingue si el PDF contiene texto nativo o imágenes rasterizadas. Fix: si el output de flash tiene palabras sin espacios o texto truncado, cambiar a `extract` con token inmediatamente. Señal temprana: `mineru-open-api flash-extract` devuelve Markdown con menos de 50 palabras para un documento de 10+ páginas.
|
|
216
|
+
|
|
217
|
+
**El MCP de MinerU falla silenciosamente cuando `MINERU_API_TOKEN` está vacío en `.mcp.json`**: si la variable de entorno `MINERU_API_TOKEN` no está configurada, el MCP arranca en modo flash pero no emite error — simplemente produce output de menor calidad sin advertir. Causa: el MCP asume que la ausencia de token es intencional (modo gratuito). Fix: verificar que el MCP está usando token con `claude-notifications-go status` o inspeccionando el output: si `parse_documents` devuelve chunks de menos de 100 tokens para páginas densas, el token no está activo. Configurar `MINERU_API_TOKEN` en el `.env` del proyecto y reiniciar el MCP.
|
|
218
|
+
|
|
219
|
+
**`mineru-open-api extract *.pdf` procesa los archivos en paralelo y puede saturar la quota de la API si hay más de 5 PDFs**: el comando acepta glob pero lanza todas las peticiones concurrentemente. Con 10+ PDFs, el servidor devuelve HTTP 429 y algunos archivos quedan con extracción incompleta sin error claro. Causa: el CLI no tiene rate limiting incorporado. Fix: procesar en lotes secuenciales con un bucle: `for f in *.pdf; do mineru-open-api extract "$f" -o ./salida/; sleep 2; done`.
|
|
220
|
+
|
|
221
|
+
**La ruta de salida por defecto de `extract` crea subdirectorios por archivo y el agente no encuentra el Markdown resultante**: `mineru-open-api extract contrato.pdf` crea `./contrato/contrato.md` (no `./contrato.md`). Si el agente busca `contrato.md` directamente, no lo encuentra. Causa: MinerU crea un directorio con el nombre del archivo para agrupar el Markdown y los recursos (imágenes, tablas). Fix: usar `-o ./salida/` y luego buscar con `find ./salida -name "*.md"`, o especificar la ruta completa de destino con `--output-file` si la versión del CLI lo soporta.
|