Nudge Logo

Nudge

No intentes parsear a tus agentes. Dales un Nudge.
Un lenguaje de programación tipado, reproducible y consciente del presupuesto para agentes de IA.
Runtime de bytecode nativo y compilador independiente. Compila a Python y TypeScript.

Version License Platform Target VS Code Snyk Verified

---

English • 中文 • 日本語 • 한국어 • Русский • Español • Türkçe • Deutsch • Français

--- ## ¿Por qué Nudge? Los agentes en producción todavía se sostienen con código de unión frágil: cadenas de prompts parseadas a mano, llamadas a tools envueltas en bloques try/except, falta de replayability, costes impredecibles y ausencia total de pruebas de regresión. Las librerías solo ponen parches a los síntomas una vez que ocurren. **Nudge soluciona el problema en la capa donde realmente vive: el lenguaje.** | Punto Crítico | Librerías | Nudge | |:---|:---|:---| | Salida de LLM sin tipar | Validar en runtime | El schema es un tipo de primera clase en el lenguaje, verificado en tiempo de compilación | | Efectos secundarios ocultos | Invisibles | 10 effects tipados y explícitos declarados en las firmas (`uses LLM, Tool, IO, ...`) | | Sin pruebas de regresión | Record y replay añadidos como parche | Cada ejecución escribe una traza NTF, y cada trace es un test determinista de $0 | | Costes imprevistos | Monitoreados tras recibir la factura | El budget es un contrato estricto impuesto por el compilador y el runtime | | Espagueti de concurrencia | Bucles asíncronos manuales | `par map / race / all` nativo con seguridad frente a carreras en tiempo de compilación | ## Un vistazo a Nudge ```nudge type Finding = { claim: string, source: Url, confidence: float @range(0, 1) } fn analyze(q: string, hits: [SearchResult]) -> [Finding] uses LLM { llm"""Extract verifiable findings about {q} from: {hits}""" with { schema: [Finding], model: "anthropic:sonnet-4.6", budget: 0.03 USD, retry: 2 with repair } } test "stays within budget on recorded trace" { let t = replay("traces/demo.jsonl") assert t.cost_usd < 0.25 // zero tokens burned in CI } ``` El compilador demuestra que el schema coincide, infiere los effects y acota el coste en el peor de los casos. El runtime registra cada llamada en una traza direccionada por contenido que puedes comparar con diff, confirmar en git y reproducir por $0. ## Inicio rápido ### 1. Instalar Nudge **Instalador de una sola línea (Recomendado):** ```sh # Linux / macOS curl -fsSL https://raw.githubusercontent.com/NekomyaDev/nudge/main/install.sh | bash # Windows (PowerShell as Administrator) irm https://raw.githubusercontent.com/NekomyaDev/nudge/main/install.ps1 | iex ``` **Gestores de paquetes y contenedores:** ```sh # Snap (Linux) sudo snap install nudge --classic # Docker docker run -it --rm -v $(pwd):/workspace nekomyadev/nudge nudgec --help ``` Los binarios precompilados para Linux, macOS y Windows también están disponibles en la página de [Releases](https://github.com/NekomyaDev/nudge/releases). ### 2. Primera ejecución en 60 segundos (Nativo, $0) Sin necesidad de Python, Node.js ni claves de API. Nudge incluye una VM de pila nativa y un proveedor simulado determinista en memoria: ```sh # Crear un programa cat > hello.ndg << 'EOF' type Greeting = { message: string, timestamp: string } fn greet(name: string) -> Greeting uses LLM { llm"""Create a greeting for {name}. Return message and timestamp.""" with { schema: Greeting, model: "anthropic:sonnet-4.6", budget: 0.01 USD } } fn main() -> Greeting uses LLM { greet("World") } EOF # Verificar tipos del programa nudgec check hello.ndg # Ejecutar directamente en la VM de Bytecode nativa ($0, sin claves) nudgec run hello.ndg # Ejecutar pruebas de regresión offline nudgec test hello.ndg ``` ### 3. Lecciones interactivas y plantillas de proyecto ```sh # Seis lecciones interactivas en tu terminal (hello, types, decide, policy, test, trace) nudgec learn # Crear un proyecto desde plantillas listas para usar (triage, chatbot, rag-agent, etc.) nudgec init my-agent --template triage cd my-agent && nudgec check my-agent.ndg && nudgec run my-agent.ndg ``` ### 4. Compilar a Python o TypeScript (Opcional) Si estás desplegando en un servicio existente en Python o TypeScript: ```sh # Target de Python pip install nudge-runtime # standard library only, zero dependencies nudgec build hello.ndg # emits out/hello.py python3 out/hello.py # Target de TypeScript nudgec build-ts hello.ndg # emits out/hello.ts ``` ## Características principales de un vistazo | Característica | Qué ofrece | Sección | |:---|:---|:---| | **Llamadas LLM tipadas** | El schema de salida es un tipo y las violaciones disparan auto-reparación | [Un vistazo a Nudge](#un-vistazo-a-nudge) | | **Flujo de control y tipos** | `if/else`, bucles `for`, literales de registro `{k: v}`, indexación, variables locales mutables, Opcional (`T?`), Unión (`T \| U`) | [Flujo de control y datos](#flujo-de-control-y-datos) | | **Effects tipados** | 10 effects conocidos rastreados y comprobados en tiempo de compilación | [Effects tipados](#effects-tipados) | | **Workspace y Store** | Sistema de archivos en sandbox acotado + almacenamiento clave-valor persistente tipado | [Workspace y Store](#workspace-acotado-y-store-persistente) | | **UI local** | Vistas tipadas, ventanas, tests headless y ventana de escritorio nativa del SO | [UI local](#ui-local) | | **Tareas y concurrencia** | Spawn/join de tareas, cancelación cooperativa, `par race` seguro, liberación de budget | [Ciclo de vida de tareas y concurrencia](#ciclo-de-vida-de-tareas-y-concurrencia) | | **Autenticación de proveedores** | Flujo de dispositivo RFC 8628 OAuth fail-closed, sin recolección de tokens ajenos | [Autenticación de proveedores](#autenticación-de-proveedores) | | **Decisiones tipadas** | Clasificación por lotes, sí/no, puntuación por rúbricas sobre estados (`/v1/systemone`) | [Decisiones tipadas](#decisiones-tipadas) | | **Computer Use** | Observación de pantalla, acciones tipadas, lista blanca de apps, kill switch | [Computer Use](#computer-use) | | **VM de Bytecode** | Motor predeterminado de VM de pila (~70x más rápido en cómputo puro, recursión profunda segura) | [Motor de VM de Bytecode](#motor-de-vm-de-bytecode) | | **Agentes independientes** | Empaquetado en un único binario sin dependencias de Cargo (~2.09MB en vivo, ~832KB replay) | [Agentes nativos independientes (sin Cargo)](#agentes-nativos-independientes-sin-cargo) | | **Target WebAssembly** | Replay offline en WASI (~526KB), puente para host de tools en vivo | [Target WebAssembly](#target-webassembly) | | **Trazas deterministas** | Trazas abiertas NTF v1, replay por $0, puertas de regresión en CI, diff de trazas | [Trazas deterministas y CI para agentes](#trazas-deterministas-y-ci-para-agentes) | | **Redacción de privacidad** | Auto-redacción predeterminada de secretos y PII en un único punto de control | [Privacidad y redacción en trazas](#privacidad-y-redacción-en-trazas) | ## Lenguaje y capacidades ### Flujo de control y datos Nudge proporciona construcciones familiares de programación estructurada con límites de seguridad deterministas: ```nudge fn process_scores(raw: [int]) -> { total: int, count: int } { let mut total = 0 let mut count = 0 for (score, idx) in raw { if score >= 50 { total = total + score count = count + 1 } else { // skip failing scores } } { total: total, count: count } } ``` - **Bifurcaciones:** expresiones `if/else` y `else if` compatibles con bloques de múltiples sentencias. - **Iteración:** bucles secuenciales `for item in coll` y bucles indexados `for (item, idx) in coll`. - **Datos estructurados:** literales de registro `{ field1: expr1, field2: expr2 }` con tipado estático y acceso a campos (`obj.field`). - **Indexación:** acceso indexado en colecciones y registros (`items[0]`, `map["key"]`). Los errores de límites fallan de forma limpia con `E0705`. - **Variables locales mutables:** variables explícitas con `let mut name = init` y reasignación (`name = next`). - **Límites de bucles:** los bucles están limitados por `NUDGE_MAX_LOOP_ITERATIONS` (por defecto 10.000) para evitar ejecuciones descontroladas, emitiendo `E0703` si se supera el límite. - **Tipos opcionales (`T?`):** tipos anulables representados con `?` (como `string?`, `int?`, `(int | string)?`), donde los valores ausentes toman `none`. Las comprobaciones de igualdad usan `== none` y `!= none`. El uso no comprobado falla cerrado con `E0201`. - **Tipos de unión (`T | U`):** tipos estáticos de unión alternativa (como `int | string` o `string | bool`). Admite comprobaciones de ensanchamiento en tiempo de compilación y rechazo estricto de estrechamiento (`E0201`). Totalmente compatible con esquemas estructurados de LLM, serialización JSON y generación de código. ### Effects tipados Cada efecto secundario se declara en la firma de la función y es validado por el compilador: ```nudge fn run_pipeline() -> bool uses LLM, Tool, Workspace, Store { // Calling unlisted effects triggers compiler error E0301 } ``` Nudge define 10 effects conocidos (`crates/nudgec/src/check.rs`): - `LLM`: Invoca completados de modelos de lenguaje o prompts en streaming. - `Tool`: Invoca herramientas MCP externas o registradas. - `IO`: Operaciones de entrada/salida del host (`print`, `println`). - `Decision`: Consulta modelos de decisión mediante `decide{}`. - `Computer`: Interactúa con entornos de escritorio y árboles de accesibilidad mediante `computer.*`. - `Workspace`: Operaciones acotadas de lectura y escritura dentro del workspace en sandbox. - `WorkspaceDelete`: Eliminación destructiva de archivos o directorios dentro del workspace. - `Store`: Operaciones de almacenamiento clave-valor persistente mediante `store.*`. - `UI`: Crea, monta o despacha eventos a elementos de interfaz gráfica de usuario. - `Auth`: Accede a recursos autenticados del proveedor (admite `Auth(account)` con ámbito). Las funciones sin cláusula `uses` se demuestran puras en tiempo de compilación. Los effects desconocidos se rechazan con `E0302`. ### Workspace acotado y Store persistente Los agentes locales deben trabajar con archivos y mantener el estado entre ejecuciones sin comprometer la seguridad del sistema: ```nudge record Config { theme: string, max_entries: int } fn update_workspace_file(path: string, new_content: string) -> bool uses Workspace, Store { // 1. Scoped filesystem access (path traversal and symlink escapes denied) if workspace.exists(path) { workspace.write(path, new_content) // Atomic write: staging, fsync, rename } // 2. Typed persistent store (survives process restarts and reboots) store.set("app_config", Config { theme: "dark", max_entries: 100 }) true } ``` - **Workspace en sandbox (`workspace.*`):** todas las operaciones están confinadas a una raíz de workspace explícita (configurada mediante `--workspace` o `NUDGE_WORKSPACE_DIR`, por defecto el directorio actual). Se bloquean los escapes fuera de la raíz como path traversals (`../`) y enlaces simbólicos. Las escrituras son consistentes ante caídas (escritura atómica en archivo temporal y renombrado). - **Separación de privilegios de borrado:** borrar archivos o directorios requiere el effect dedicado `WorkspaceDelete` (`uses WorkspaceDelete`), impidiendo que rutinas generales de escritura puedan eliminar directorios. - **Almacenamiento clave-valor persistente (`store.*`):** almacenamiento fuertemente tipado guardado en `/.nudge/store.json` (o `NUDGE_STORE_PATH`). A diferencia de los puntos de control efímeros de ejecución, este almacén persiste entre distintas ejecuciones y reinicios del sistema. ### Monitorización de procesos y archivos Construye agentes que controlen ejecutores de compilación/tests, language servers y herramientas de recarga en vivo con la misma disciplina de effects y permisos que todo lo demás: ```nudge fn watch_and_rebuild() -> bool uses FsWatch, Process { // 1. Bounded, workspace-confined file watching (no indefinite hang) let changes = fs.watch("src", 5000) // dir/path + timeout (ms) // 2. Controlled child process: program and args SEPARATELY (never a shell) let handle = proc.spawn("cargo", ["build", "--quiet"], 60000) let out = proc.await(handle) proc.alive(handle) == false } ``` - **Monitorización de archivos (`fs.watch`, effect `FsWatch`):** monitoriza una ruta del workspace en busca de eventos de cambio, acotada por un tiempo de expiración (timeout, nunca se cuelga indefinidamente) y confinada a la raíz del workspace (escape denegado `E0922`). El uso no declarado es detectado por el sistema de tipos (`E0301`). - **Procesos controlados (`proc.*`, effect `Process`):** `proc.spawn(cmd, argv, timeout_ms)` / `proc.run(...)` (spawn + await) / `proc.await` / `proc.kill` / `proc.alive`. El comando `cmd` y sus argumentos `argv` se pasan por **separado** y se ejecutan sin shell (eliminando la superficie de inyección en shell). Su ciclo de vida es acotado (`E0921`) sin **procesos huérfanos** (los hijos se limpian al salir o cancelar la tarea) y con terminación kill-on-cancel. La ejecución es **fail-closed**: denegada por defecto a menos que esté autorizada por `NUDGE_PROCESS_GRANTS` (`E0920`). ### UI local Crea interfaces nativas con interacción humana en el bucle (human-in-the-loop), estaciones de aprobación y paneles de inspección interactivos directamente en Nudge: ```nudge type ReviewState = { prompt: string, approved: bool } view ReviewCard(state: ReviewState) -> View { column(padding = 16, gap = 12) [ text("Agent Review Station", size = 18, bold = true), text("Request: " + state.prompt), row(gap = 8) [ button("Approve", on_click = approve_action), button("Reject", on_click = reject_action) ] ] } agent ReviewStation { state { prompt: string = "Execute deploy script", approved: bool = false } fn approve_action() uses UI, IO { state.approved = true io.println("Action approved") } fn reject_action() uses UI { state.approved = false } window MainWindow { title: "Nudge Review Station", width: 500, height: 300, content: ReviewCard(state) } } ``` - **Ejecución en modo dual:** - **Pruebas Headless:** `mount_headless()` y `dispatch_click()` evalúan árboles de UI y transiciones de estado enteramente en memoria sin abrir una ventana física. Se ejecutan en CI por $0. - **GUI de escritorio nativa:** al compilar con la feature de Cargo `native-gui`, `window.open()` crea una ventana nativa del sistema operativo impulsada por `winit` y `softbuffer`. - **Modo headless automático:** configurar `NUDGE_UI_HEADLESS=1` o ejecutar durante el replay de una traza (`NUDGE_REPLAY`) redirige automáticamente las llamadas de ventana al motor headless. ### Ciclo de vida de tareas y concurrencia Coordina ramas de agentes concurrentes con gestión formal de estado de tareas y cancelación cooperativa: ```nudge fn race_models(prompt: string) -> string uses LLM { // par race automatically cancels losing branches par race { fast: query_fast_model(prompt), deep: query_deep_model(prompt) } } ``` - **Cancelación cooperativa:** cuando un `race` se resuelve, las ramas perdedoras se detienen en los límites de bucles, streams y effects en lugar de seguir consumiendo budget en segundo plano. - **Protección de presupuesto:** las reservas de budget no gastadas bajo `NUDGE_BUDGET` se liberan inmediatamente al cancelar la tarea. - **Permisos fail-closed:** las tareas canceladas pierden inmediatamente el permiso para despachar más llamadas a tools (`Tool`) o acciones de computadora (`Computer`). - **Primitivas de tareas:** control explícito de tareas mediante `task.spawn`, `task.join`, `task.status` y `task.cancel`. ### Autenticación de proveedores Gestión segura de credenciales integrada directamente en el lenguaje y el runtime: - **Autenticación fail-closed:** las funciones declaran requisitos de autenticación explícitos con `uses Auth` o `uses Auth(account)`. Las llamadas no autenticadas fallan cerrando el acceso. - **Sin recolección de tokens ajenos:** Nudge nunca lee cachés privadas de tokens ni almacenes de credenciales pertenecientes a herramientas de terceros. - **Flujo de dispositivo nativo RFC 8628:** autorización interactiva en terminal mediante OAuth 2.0 Device Authorization Grant con almacenamiento seguro de credenciales en `~/.nudge/credentials.json` (permisos de archivo 0600). - **Puertas de seguridad por proveedor:** los proveedores deben satisfacer contratos de seguridad verificables (`E-auth-0401` para credenciales faltantes, `E-auth-0403` para déficits de scope, `E-auth-0404` para proveedores desactivados). - **Proveedores no comprobados permanecen cerrados (puerta de permisos):** un proveedor cuyo permiso oficial de uso por terceros no haya sido demostrado es **fail-closed por defecto**. Esto se aplica actualmente a `antigravity`: su flujo de login OAuth y su código de proveedor existen, pero dado que no se encontró prueba oficial de que su cliente OAuth y su endpoint de modelo puedan utilizarse desde un cliente independiente de terceros, la puerta permanece **desactivada** (`E-auth-0404`) hasta que se verifique el permiso. **Una prueba mock de OAuth o un pase exitoso en CI NO demuestran acceso a cuentas reales ni permiso de uso.** Los consumidores (incluida cualquier aplicación construida sobre Nudge) no deben depender de esta conexión hasta que el permiso esté documentado. Una habilitación explícita asumida por el usuario (`NUDGE_ENABLE_ANTIGRAVITY=1`) la activa bajo la propia responsabilidad del usuario una vez verificado el permiso. ### Decisiones tipadas Compila la incertidumbre procedente de modelos de decisión (como Laya y Jev) mediante el protocolo `/v1/systemone`: ```nudge fn triage(t: string) -> string uses Decision { let d = decide { dept: "which team handles this?" choose [billing, technical, security], churn: "does the customer threaten to cancel?" yes/no, urgency: "how urgent is this?" score [low, soon, critical] } on t with { model: "laya:multilingual", deadline: 50 } // ms latency budget route { auto: resolve(d.dept.winner) when d.dept.confidence > 0.8, review: escalate(d) otherwise } } ``` - **Ejecución por lotes:** una sola llamada evalúa todas las preguntas simultáneamente, devolviendo ganador, probabilidad, distribución y confianza. - **Pruebas por cero dólares:** el proveedor simulado predeterminado sintetiza distribuciones deterministas con semilla para ejecuciones de prueba por $0. - **Proveedores en vivo:** conecta modelos locales o remotos mediante `NUDGE_DECISION_SERVERS='{"laya": {"base_url": "http://localhost:8000"}}'`. - **Caché de decisiones:** `NUDGE_DECISION_CACHE=` almacena en caché las respuestas validadas entre ejecuciones para no pagar dos veces por el mismo estado. - **Barridos de políticas (Policy Sweeps):** ejecuta `nudgec policy-sweep trace.jsonl --question dept --thresholds 0.5,0.8` para evaluar ajustes de umbrales sobre distribuciones registradas sin realizar llamadas a modelos. Consulta la [Documentación sobre Decisiones](docs/decision.md). ### Computer Use Controla entornos de escritorio con observaciones y acciones tipadas donde el lenguaje gobierna el control y la seguridad mientras el modelo gestiona la percepción: ```nudge fn automate_app(app: string) -> bool uses Computer, Decision { let obs = computer.observe(app, allow = [app], deadline = 30000) let check = decide { ready: "is the target button visible?" yes/no } on obs.tree with { deadline: 100 } let r = route { click: computer.click(1, allow = [app]) when check.ready.p > 0.5, close: computer.key("Escape", allow = [app]) otherwise } r.ok } ``` - **Primitivas tipadas:** `computer.observe` devuelve un registro `Observation` (árbol de accesibilidad, elementos, captura de pantalla opcional). Las acciones (`click`, `type`, `key`, `scroll`, `set_value`, `drag`, `paste`) devuelven `ActionResult` con acuses de recibo de despacho (`action_sent`). - **Seguridad en replay:** el replay de trazas nunca vuelve a ejecutar acciones físicas. Con `NUDGE_COMPUTER_DRIFT=1`, el runtime vuelve a observar el estado en vivo y calcula un diff mecánico de desviación (`Drift`) sin disparar acciones. - **Protección y endurecimiento:** lista blanca de aplicaciones (`allow: [app]`), bloqueos de concesión de controlador, rechazo de índices de elementos obsoletos (`stale_state`) y un interruptor de apagado de emergencia (kill switch) estricto (`NUDGE_COMPUTER_KILL=1`). - **Escritorio determinista:** el proveedor simulado predeterminado ejecuta escenarios de UI en memoria (`NUDGE_COMPUTER_SCENARIO`), permitiendo pruebas integrales por $0. Consulta la [Documentación de Computer Use](docs/computer-use.md). ## Infraestructura nativa ### Motor de VM de Bytecode Las funciones puras, las transformaciones de datos y las bifurcaciones de rutas se ejecutan en una máquina virtual de bytecode basada en pila dedicada (`crates/nudgec/src/bytecode.rs` y `vm.rs`): - **Cómputo puro de alta velocidad:** ejecuta código puro aproximadamente 70 veces más rápido que el intérprete sobre AST. - **Seguridad ante recursión profunda:** la pila de frames gestionada elimina los desbordamientos de pila del sistema operativo en algoritmos recursivos. - **Delegación transparente de effects:** las expresiones con efectos (`llm`, `tool`, `computer`, `workspace`) delegan de forma transparente desde la VM al evaluador del runtime mediante `DelegateCall` y `DelegateExpr`. - **Motor predeterminado:** la VM se ejecuta por defecto en `nudgec run` y binarios independientes. Configura `NUDGE_VM=0` para volver al intérprete basado en AST. ### Agentes nativos independientes (sin Cargo) Empaqueta tu agente en un binario ejecutable nativo único y autónomo sin dependencias de toolchain en el entorno de despliegue: ```sh # Package an agent into a standalone binary nudgec build --standalone my-agent.ndg -o bin/my-agent # Run directly on the host (zero Python/Node/Rust dependencies) ./bin/my-agent ``` - **Estampado de AST:** `nudgec` comprueba los tipos del código fuente, serializa el conjunto del AST en bincode y lo añade a un binario de runtime precompilado de `nudge-agent` (pie de página `NDGAGNT1`) en cuestión de milisegundos. - **Dos variantes de runtime:** - **Completo (~2.09MB, predeterminado):** runtime con soporte en vivo y pila HTTP/TLS integrada con `ureq` + `rustls` para LLMs y servidores MCP en vivo. - **Solo Replay (~832KB):** runtime compacto sin dependencias de red, resolviendo todas las operaciones desde trazas NTF grabadas para ejecuciones offline por $0. - **Detección del runtime:** se localiza mediante la variable de entorno `NUDGE_AGENT_RUNTIME` o como un binario hermano junto a `nudgec`. Consulta la [Documentación de Standalone](docs/standalone.md). ### Target WebAssembly Despliega agentes en sandboxes de navegador, runtimes perimetrales (Cloudflare Workers, Fastly) y entornos WASI: - **Replay offline (`nudge-replay-wasi`):** reproduce trazas NTF registradas de forma offline dentro de un módulo `.wasm` de aproximadamente 526KB bajo `wasmtime` con una salida idéntica byte a byte a las ejecuciones nativas: ```sh wasmtime run --dir . nudge-replay-wasi.wasm bundle.json trace.jsonl ``` - **Puente para host de tools en vivo:** los agentes en JavaScript en navegadores o entornos edge realizan llamadas a tools en vivo mediante el contrato de importación estandarizado `nudge_host_tool_call` (verificado bajo Node WASI, ver `examples/wasm-host/`). - **Seguridad en sandbox:** los sockets de red y la creación de procesos del sistema operativo quedan deshabilitados en `wasm32`, garantizando una ejecución aislada. Consulta la [Documentación de WebAssembly](docs/wasm.md). ## Herramientas e integraciones ### Integración MCP Declara tools respaldadas por servidores Model Context Protocol (MCP) que se comunican mediante stdio: ```nudge type SearchResult = { url: string, title: string } tool web_search(query: string) -> [SearchResult] { impl: mcp("search").web_search(query) side_effects: none } fn main() -> [SearchResult] uses Tool { web_search("nudge language") } ``` Configura servidores en vivo mediante `NUDGE_MCP_SERVERS`: ```sh export NUDGE_MCP_SERVERS='{"search": {"command": "mcp-server-websearch"}}' nudgec run search_agent.ndg ``` Los parámetros se pasan como objetos de argumentos JSON con nombre para compatibilidad con FastMCP y servidores estándar. Los servidores no disponibles fallan rápidamente con diagnósticos claros. ### Trazas deterministas y CI para agentes Cada ejecución genera una traza JSONL abierta en formato NTF v1 capturando todas las interacciones de los effects: ```sh # Verify trace integrity against the open specification nudgec trace-check trace.jsonl # Compare two traces to identify cost or behavior changes (--json emite informes procesables por máquina) nudgec trace-diff baseline.jsonl candidate.jsonl --fail-on-regression --json ``` **GitHub Action (`action.yml`):** prueba agentes en CI en cada push con coste $0 y sin claves de API: ```yaml name: agents on: [push, pull_request] jobs: test-agents: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: NekomyaDev/nudge@v1 with: files: "agents/**/*.ndg" trace-diff: "baseline.jsonl candidate.jsonl" ``` La especificación congelada de NTF se encuentra en [docs/ntf-spec.md](docs/ntf-spec.md), con una suite de pruebas completa en [`conformance/`](conformance/) y puentes para LangChain, CrewAI y LangGraph. ### Herramientas para desarrolladores - **Estimador de coste estático:** `nudgec cost [--json]` calcula en tiempo de compilación los costes de tokens y presupuestos en el peor de los casos por función. - **Pruebas de propiedades y fuzzing:** `nudgec fuzz [file.ndg] [--iterations N] [--seed S] [--json]` ejecuta pruebas de fuzzing basadas en mutaciones y verificación de propiedades. - **Evaluación de conjuntos de datos:** `nudgec eval --dataset [--fn ] [--path ] [--min-accuracy 0.8] [--json]` evalúa funciones frente a datasets JSONL y bloquea CI según la precisión requerida. - **Comparación de evaluaciones:** `nudgec compare [--json]` compara dos ejecuciones de evaluación para detectar regresiones de precisión o rendimiento. - **Explicador de ejecución:** `nudgec explain [--json]` genera un resumen CLI legible para humanos o un análisis JSON detallando fallos, consumo de tokens y decisiones de baja confianza. - **Diferencias de trazas:** `nudgec trace-diff [--json] [--fail-on-regression]` compara dos trazas para identificar regresiones, saliendo con código 1 ante regresiones en CI. - **Auditoría de cumplimiento:** `nudgec audit [--json]` audita una traza NTF según los requisitos de la Ley de IA de la UE (transparencia, gobernanza, secretos no redactados, métricas de riesgo). - **Visor de trazas local:** `nudgec trace-view [--port N] [--no-open]` inicia una interfaz web local con líneas de tiempo de ejecución visuales, gasto de tokens y detalles de reparaciones. - **Formateador y watcher:** `nudgec fmt [--check] [--json]` formatea el código con seguridad y `nudgec check [--json] --watch` comprueba los tipos en cada guardado. - **Linter y autocorrección:** `nudgec lint [--fix] [--json]` revisa el código en busca de buenas prácticas (presupuestos ilimitados, prompts ambiguos, esquemas sin reparación) y aplica correcciones seguras. - **Inspector de almacén de ejecuciones:** `nudgec runs [--run ] [--json]` inspecciona estados de ejecución persistentes, trazas y puntos de control de agentes. - **Gestor de autenticación:** `nudgec auth login [provider]` y `nudgec auth status [--json]` gestionan credenciales OAuth y verifican proveedores de IA conectados. - **Exportación HTML estática:** `nudgec trace-html [-o report.html]` exporta informes interactivos de auditoría completamente autónomos. ### Extensión para VS Code Instala la [Extensión de Lenguaje Nudge](https://marketplace.visualstudio.com/items?itemName=Nekomya.nudge-lang) para resaltado de sintaxis, fragmentos de código (snippets), documentación al pasar el cursor y diagnósticos de tipos en tiempo real impulsados por `nudgec lsp`. ## Privacidad y redacción en trazas Los agentes de IA manejan con frecuencia tokens sensibles, cabeceras de autorización, claves privadas y datos de identificación personal (PII). Nudge protege tus datos mediante una canalización de redacción de trazas fail-closed: - **Punto único de control:** la redacción se realiza dentro de `TraceWriter::emit` antes de serializar los registros en disco o en búferes de memoria. Todos los tipos de registro (`llm.call`, `tool.call`, `decision.call`, `computer.*`, `fn.return`) se enmascaran en este cuello de botella centralizado. - **Fail-closed por defecto:** la redacción de trazas está activa por defecto (`NUDGE_TRACE_REDACT=1`). Establece `NUDGE_TRACE_REDACT=0` únicamente para depuración local explícita. - **`NUDGE_TRACE_REDACT=0` es un límite de seguridad, no una conveniencia:** desactivar la redacción graba secretos, claves de API, cabeceras de autorización y datos personales en **TEXTO PLANO** en el archivo de traza. Esta es la consecuencia documentada e intencionada de desactivarlo (respaldada por tests). Nunca lo uses en CI, con artefactos compartidos o confirmados en repositorios, ni cuando una app construida sobre Nudge consuma trazas. Los consumidores deben tratar la presencia de `NUDGE_TRACE_REDACT=0` como un parámetro crítico de seguridad y NO deben asumir que las trazas sean seguras de almacenar o compartir en ese modo. - **Detección automática de secretos:** identifica y enmascara automáticamente variables de entorno que terminen en `_KEY`, `_SECRET`, `_TOKEN`, `_PASSWORD`, `_PAT`, o que contengan `AUTH` (con valores de 6 o más caracteres). - **Enmascaramiento de patrones por capas:** limpia tokens bearer, cabeceras de autorización, pares credencial clave-valor, bloques de claves privadas y prefijos de tokens de proveedores (OpenAI `sk-...`, Anthropic `sk-ant-...`, GitHub `ghp_...`, AWS `AKIA...`, Slack `xox...`). - **Invarianza criptográfica en replay:** el `request_hash` direccionado por contenido se calcula sobre las entradas **previas a la redacción**. Esto garantiza que las trazas enmascaradas sigan siendo idénticas byte a byte durante la búsqueda en el replay con coincidencia O(1) sin persistir credenciales en disco. ## Variables de entorno | Variable | Ámbito | Propósito | Valor por defecto | |:---|:---|:---|:---| | `NUDGE_PROVIDER` | ambos | Proveedor de LLM activo (`fake`, `openai`, `anthropic`, `gemini`, `groq`, `ollama`) | `fake` | | `NUDGE_VM` | nativo | Interruptor del motor de ejecución VM de Bytecode (`1` = VM por defecto, `0` = fallback a intérprete AST) | `1` | | `NUDGE_DEFAULT_MODEL` | nativo | Cadena del modelo predeterminado si no se especifica explícitamente en el bloque `with` | Predeterminado del proveedor | | `NUDGE_API_KEY` / `NUDGE_BASE_URL` | ambos | Credenciales y endpoint base para proveedores de LLM compatibles con OpenAI | Ninguno | | `NUDGE_PRICING` | ambos | Tabla personalizada de precios en JSON: `{"model": [usd_per_1M_in, usd_per_1M_out]}` | Tabla integrada | | `NUDGE_GUARD` | python/TS | Guardas de salida (`pii` enmascara secretos, correos electrónicos y direcciones IP en salidas de LLM) | Ninguno | | `NUDGE_BUDGET` | ambos | Límite máximo de gasto en USD a nivel de ejecución para despliegues en paralelo | Ninguno | | `NUDGE_REPAIR_BUDGET` | python | Límite máximo acumulado en USD para rondas de reparación | Ninguno | | `NUDGE_MAX_LOOP_ITERATIONS` | nativo | Límite máximo de iteraciones secuenciales de bucle antes de generar el error de runtime `E0703` | `10000` | | `NUDGE_TRACE` | ambos | Ruta de destino para escribir la traza de ejecución NTF JSONL | `trace.jsonl` | | `NUDGE_REPLAY` | ambos | Ruta de la traza para replay offline determinista (`NUDGE_REPLAY_MODE=all` o `llm`) | Ninguno | | `NUDGE_RESUME` | ambos | Reanudar ejecución tras fallo desde un punto de control usando el prefijo de traza grabado | Ninguno | | `NUDGE_TRACE_REDACT` | nativo | Activa el punto único de enmascaramiento de secretos y PII en trazas (`1` o `0`) | `1` (Activo) | | `NUDGE_TRACE_REDACT_ENV` | nativo | Enmascara automáticamente en las trazas los valores de variables de entorno con secretos | `1` (Activo) | | `NUDGE_TRACE_REDACT_KEYS` | nativo | Lista separada por comas de claves JSON adicionales a enmascarar | Ninguno | | `NUDGE_TRACE_REDACT_PATTERNS` | nativo | Lista de regex separada por comas o ruta a un archivo de regex para enmascaramiento personalizado | Ninguno | | `NUDGE_WORKSPACE_DIR` | nativo | Directorio raíz con autoridad para operaciones acotadas de `workspace.*` | Directorio actual | | `NUDGE_STORE_PATH` | nativo | Ubicación del archivo de almacenamiento para datos tipados persistentes clave-valor | `/.nudge/store.json` | | `NUDGE_UI_HEADLESS` | nativo | Fuerza a que las operaciones de ventana de UI se ejecuten de forma headless en memoria (`1` o `true`) | `0` | | `NUDGE_TOOL_GRANTS` | ambos | Política de tools en JSON para la capa de ejecución (ej. `{"web_search": ["*"]}`). Falla cerrando | Ninguno | | `NUDGE_PROCESS_GRANTS` | nativo | Política fail-closed en JSON para comandos y argumentos de `proc.*` | Ninguno (denegado) | | `NUDGE_PROCESS_TIMEOUT` | nativo | Tiempo de expiración predeterminado en milisegundos para procesos hijos en `proc.*` | `30000` | | `NUDGE_FS_WATCH_TIMEOUT` | nativo | Tiempo de expiración y espera predeterminado en milisegundos para `fs.watch` | `30000` | | `NUDGE_ENABLE_ANTIGRAVITY` | nativo | Interruptor de activación explícito para el proveedor Antigravity (`1` o `true`) | `0` | | `NUDGE_AUTH_ANTIGRAVITY` | nativo | Token bearer directo para autenticación con el proveedor Antigravity | Ninguno | | `NUDGE_AUTH_GITHUB_COPILOT` | nativo | Sustitución directa de token para autenticación con GitHub Copilot | Ninguno | | `NUDGE_MCP_SERVERS` | ambos | Registro JSON que mapea nombres de servidores MCP a comandos stdio | Ninguno | | `NUDGE_MCP_TIMEOUT_MS` | nativo | Límite de tiempo de lectura por solicitud y timeout de sesiones colgadas para MCP | `30000` | | `NUDGE_DECISION_SERVERS` | ambos | Registro JSON para endpoints de modelos de decisión (ej. `{"laya": {"base_url": "..."}}`) | Ninguno | | `NUDGE_DECISION_CACHE` | ambos | Ruta del archivo de caché para persistir distribuciones de modelos de decisión | Ninguno | | `NUDGE_COMPUTER_SERVERS` | ambos | Registro JSON para puentes de computer use (subproceso JSONL o HTTP) | Ninguno | | `NUDGE_COMPUTER_PROVIDER` | ambos | Puente seleccionado para acciones de computadora (`fake`, o nombre del servidor registrado) | `fake` | | `NUDGE_COMPUTER_KILL` | ambos | Interruptor estricto de parada: `1` rechaza inmediatamente toda operación de computadora | `0` | | `NUDGE_COMPUTER_DRIFT` | ambos | Con `1`, vuelve a observar el estado en vivo durante el replay y adjunta diffs mecánicos de desviación | `0` | | `NUDGE_AGENT_RUNTIME` | nativo | Ruta al binario precompilado de `nudge-agent` para `nudgec build --standalone` | Binario hermano | | `NUDGE_CREDENTIALS_PATH` | nativo | Ruta personalizada al almacén de credenciales de autenticación de Nudge | `~/.nudge/credentials.json` | | `NUDGE_OTEL` | python | Archivo de exportación de trazas OpenTelemetry | Ninguno | | `NUDGE_OTEL_ENDPOINT` | python | Endpoint de exportación HTTP para OpenTelemetry | Ninguno | `nativo` aplica al runtime de Rust (`nudgec`/`nudge-runtime`), `python/TS` a los runtimes generados heredados, y `ambos` a ambas familias de runtime. ## Ejemplos del mundo real Explora implementaciones completas de agentes en [`examples/`](examples/): | Ejemplo | Dominio | Aspectos destacados | |:---|:---|:---| | [AI Chatbot](examples/chatbot/) | Asistente conversacional | Schemas de memoria tipados, replay determinista, techos de budget | | [Triage Agent](examples/triage-agent/) | Clasificación de soporte | Bloques `decide{}` por lotes, umbrales de confianza, políticas de enrutamiento | | [Code Reviewer](examples/code-reviewer/) | Ingeniería de software | Diagnósticos de sintaxis estructurados, puntuación automatizada por rúbricas | | [Research Agent](examples/research_agent.ndg) | Síntesis multifuente | Recuperación paralela con `par map`, puntuación de confianza | | [Computer Automation](examples/computer-automation/) | Agente de escritorio | Observación de pantalla, árboles de accesibilidad, validación de drift | | [RAG Agent](examples/rag-agent/) | Generación aumentada por recuperación | Enlaces a herramientas MCP stdio de recuperación, extracción de citas | | [Property Fuzzer](examples/property-fuzz/) | Pruebas de agentes | Pruebas de invariantes `for_all`, fuzzing de inyección de prompts | | [Dungeon Crawler](examples/dungeon-crawler/) | Simulación de máquina de estados | Nudge puro, transiciones de estado de agentes, combate por turnos | ## Licencia y compilación desde el código fuente Nudge es código abierto bajo la licencia **Apache-2.0**. Consulta [LICENSE](LICENSE) para más detalles. ### Compilación desde el código fuente Compilar el compilador requiere Rust 1.75+ (versión estable): ```sh git clone https://github.com/NekomyaDev/nudge.git cd nudge cargo build --release -p nudgec # binario del compilador en target/release/nudgec cargo test --workspace # suite de pruebas del compilador, VM y runtime ``` El runtime de Python se encuentra en `runtime/` (solo biblioteca estándar, cero dependencias externas): ```sh pip install ./runtime ``` ---

Hecho con amor por NekomyaDev