Nudge Logo

Nudge

Не парсите ваших агентов. Направляйте их с Nudge.
Типизированный, воспроизводимый (replayable) язык программирования с контролем budget для AI-агентов.
Нативная среда выполнения bytecode и автономный компилятор. Компилируется в Python и TypeScript.

Version License Platform Target VS Code Snyk Verified

---

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

--- ## Почему Nudge? Продакшен-агенты до сих пор держатся на связующем коде (glue code): цепочки prompt, разбираемые вручную, вызовы tool, обернутые в блоки try/except, отсутствие replayability, непредсказуемые расходы и полное отсутствие регрессионных тестов. Библиотеки лишь маскируют симптомы после их появления. **Nudge устраняет проблему на том уровне, где она возникает: на уровне языка программирования.** | Проблема | Библиотеки | Nudge | |:---|:---|:---| | Нетипизированный вывод LLM | Валидация во время выполнения | Schema является первоклассным типом языка, проверяемым во время компиляции | | Скрытые побочные эффекты | Невидимы | 10 явных типизированных effect, объявленных в сигнатурах (`uses LLM, Tool, IO, ...`) | | Нет регрессионного тестирования | Запись и replay прикручены поверх | Каждый запуск создает NTF trace, и каждый trace является детерминированным тестом за $0 | | Неожиданные расходы | Отслеживание постфактум после счета | Budget является строгим контрактом, соблюдение которого гарантируют компилятор и runtime | | Спагетти из асинхронного кода | Ручные циклы async | Нативные конструкции `par map / race / all` с проверкой race safety во время компиляции | ## Знакомство с 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 } ``` Компилятор проверяет соответствие schema, выводит используемые effect и ограничивает максимальную стоимость выполнения. Среда выполнения записывает каждый вызов в контентно-адресуемый trace, который можно сравнивать через diff, коммитить в репозиторий и воспроизводить (replay) за $0. ## Быстрый старт ### 1. Установка Nudge **Установка одной командой (рекомендуется):** ```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 ``` **Пакетные менеджеры и контейнеры:** ```sh # Snap (Linux) sudo snap install nudge --classic # Docker docker run -it --rm -v $(pwd):/workspace nekomyadev/nudge nudgec --help ``` Скомпилированные бинарные файлы для Linux, macOS и Windows также доступны на странице [Releases](https://github.com/NekomyaDev/nudge/releases). ### 2. Первый запуск за 60 секунд (Native, $0) Никакого Python, Node.js или API-ключей не требуется. Nudge включает нативную стековую виртуальную машину и детерминированный in-memory fake provider: ```sh # Create a program 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 # Type-check your program nudgec check hello.ndg # Run directly on the native Bytecode VM ($0, no keys needed) nudgec run hello.ndg # Run offline regression tests nudgec test hello.ndg ``` ### 3. Интерактивные уроки и шаблоны проектов ```sh # Six interactive lessons in your terminal (hello, types, decide, policy, test, trace) nudgec learn # Scaffold a project from ready-made templates (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. Компиляция в Python или TypeScript (опционально) Если вы развертываете агента внутри существующего сервиса на Python или TypeScript: ```sh # Python target pip install nudge-runtime # standard library only, zero dependencies nudgec build hello.ndg # emits out/hello.py python3 out/hello.py # TypeScript target nudgec build-ts hello.ndg # emits out/hello.ts ``` ## Краткий обзор основных возможностей | Возможность | Что обеспечивает | Раздел | |:---|:---|:---| | **Типизированные вызовы LLM** | Схема вывода является типом, а нарушения запускают автоматическое исправление | [Знакомство с Nudge](#знакомство-с-nudge) | | **Управление потоком и типы** | `if/else`, циклы `for`, литералы записей `{k: v}`, индексация, мутабельные переменные, Optional (`T?`), Union (`T \| U`) | [Управление потоком и данные](#управление-потоком-и-данные) | | **Типизированные Effect** | 10 известных effect, отслеживаемых и проверяемых во время компиляции | [Типизированные Effect](#типизированные-effect) | | **Workspace и Store** | Изолированная файловая система в песочнице + типизированное постоянное хранилище key-value | [Изолированный Workspace и постоянный Store](#изолированный-workspace-и-постоянный-store) | | **Локальный UI** | Типизированные view, окна, headless-тесты и нативное десктопное окно ОС | [Локальный UI](#локальный-ui) | | **Задачи и параллелизм** | Запуск и ожидание задач (spawn/join), кооперативная отмена, безопасный `par race`, освобождение budget | [Жизненный цикл задач и параллелизм](#жизненный-цикл-задач-и-параллелизм) | | **Аутентификация провайдеров** | Flow авторизации устройств RFC 8628 OAuth по принципу fail-closed, без сбора сторонних токенов | [Аутентификация провайдеров](#аутентификация-провайдеров) | | **Типизированные решения** | Пакетная классификация, да/нет, оценка по рубрикам над состояниями (`/v1/systemone`) | [Типизированные решения](#типизированные-решения) | | **Computer Use** | Наблюдение за экраном, типизированные действия, список разрешенных приложений, kill switch | [Управление компьютером (Computer Use)](#управление-компьютером-computer-use) | | **Bytecode VM** | Стек-машина по умолчанию (~70x быстрее чистых вычислений, безопасность глубокой рекурсии) | [Движок Bytecode VM](#движок-bytecode-vm) | | **Автономные агенты** | Упаковка в единый бинарный файл без участия Cargo (~2.09MB live, ~832KB replay) | [Автономные нативные агенты (без Cargo)](#автономные-нативные-агенты-без-cargo) | | **WebAssembly** | Офлайн-replay в WASI (~526KB), мост к хосту живых инструментов | [Таргет WebAssembly](#таргет-webassembly) | | **Детерминированные Trace** | Открытые NTF v1 trace, replay за $0, регрессионные проверки в CI, сравнение trace (diff) | [Детерминированные Trace и CI для агентов](#детерминированные-trace-и-ci-для-агентов) | | **Маскирование приватных данных** | Автоматическое маскирование секретов и PII по умолчанию в единой точке контроля | [Конфиденциальность и маскирование Trace](#конфиденциальность-и-маскирование-trace) | ## Язык и возможности ### Управление потоком и данные Nudge предоставляет привычные конструкции структурного программирования с детерминированными границами безопасности: ```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 } } ``` - **Ветвление:** выражения `if/else` и `else if`, поддерживающие блоки ветвления из нескольких операторов. - **Итерация:** последовательные циклы `for item in coll` и индексированные циклы `for (item, idx) in coll`. - **Структурированные данные:** литералы записей `{ field1: expr1, field2: expr2 }` со статической типизацией и доступом к полям (`obj.field`). - **Индексация:** индексированный доступ к коллекциям и записям (`items[0]`, `map["key"]`). Выход за границы диапазона корректно завершается ошибкой `E0705`. - **Мутабельные локальные переменные:** явные переменные `let mut name = init` с поддержкой переприсваивания (`name = next`). - **Ограничения циклов:** число итераций ограничено параметром `NUDGE_MAX_LOOP_ITERATIONS` (по умолчанию 10 000) для предотвращения бесконечного выполнения, с вызовом ошибки `E0703` при превышении лимита. - **Типы Optional (`T?`):** обнуляемые типы с суффиксом `?` (например, `string?`, `int?`, `(int | string)?`), где отсутствие значения обозначается `none`. Проверка на равенство выполняется через `== none` и `!= none`. Непроверенное использование блокируется ошибкой `E0201` по принципу fail-closed. - **Типы Union (`T | U`):** статические типы объединения (например, `int | string` или `string | bool`), принимающие любое из указанных значений. Поддерживают проверку расширения на этапе компиляции и строгое отклонение сужения (`E0201`). Полностью поддержаны в схемах вывода LLM, сериализации JSON и кодогенерации. ### Типизированные Effect Каждый побочный эффект декларируется в сигнатуре функции и проверяется компилятором: ```nudge fn run_pipeline() -> bool uses LLM, Tool, Workspace, Store { // Calling unlisted effects triggers compiler error E0301 } ``` Nudge определяет 10 известных effect (`crates/nudgec/src/check.rs`): - `LLM`: Вызывает генерацию ответа языковой моделью или потоковые prompt. - `Tool`: Вызывает внешние MCP или зарегистрированные инструменты. - `IO`: Операции ввода/вывода хоста (`print`, `println`). - `Decision`: Запрашивает модели принятия решений через `decide{}`. - `Computer`: Взаимодействует с окружением рабочего стола и деревьями доступности через `computer.*`. - `Workspace`: Изолированные операции чтения и записи внутри защищенного каталога workspace. - `WorkspaceDelete`: Деструктивное удаление файлов или каталогов внутри workspace. - `Store`: Операции с постоянным хранилищем ключ-значение через `store.*`. - `UI`: Создает, монтирует или отправляет события графическим элементам интерфейса. - `Auth`: Обращается к аутентифицированным ресурсам провайдеров (поддерживает параметризованный `Auth(account)`). Функции без секции `uses` считаются чистыми (pure), что доказывается во время компиляции. Неизвестные effect отклоняются с ошибкой `E0302`. ### Изолированный Workspace и постоянный Store Локальные агенты должны работать с файлами и сохранять состояние между запусками без ущерба для безопасности системы: ```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 (`workspace.*`):** все операции ограничены явным корневым каталогом workspace (настраивается через `--workspace` или `NUDGE_WORKSPACE_DIR`, по умолчанию текущий каталог). Попытки обхода путей (`../`) и выход за пределы корня через симлинки блокируются. Запись устойчива к сбоям благодаря атомарной схеме (запись во временный файл и последующее переименование). - **Разделение полномочий на удаление:** для удаления файлов или каталогов требуется специальный effect `WorkspaceDelete` (`uses WorkspaceDelete`), что защищает каталоги от случайного удаления обычными функциями записи. - **Постоянное хранилище ключ-значение (`store.*`):** строго типизированное хранилище, сохраняемое в `/.nudge/store.json` (или `NUDGE_STORE_PATH`). В отличие от временных чекпоинтов выполнения, эти данные сохраняются между отдельными запусками и перезагрузками системы. ### Отслеживание процессов и файлов Создавайте агентов, управляющих раннерами сборки и тестов, языковыми серверами и инструментами live-reload, с той же дисциплиной effect и прав доступа grants: ```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 } ``` - **Отслеживание файлов (`fs.watch`, effect `FsWatch`):** мониторинг пути внутри workspace на наличие событий изменений, ограниченный таймаутом (никогда не зависает бесконечно) и замкнутый в корневом каталоге workspace (выход за границы блокируется `E0922`). Недекларированное использование пресекается типизацией (`E0301`). - **Контролируемые процессы (`proc.*`, effect `Process`):** функции `proc.spawn(cmd, argv, timeout_ms)`, `proc.run(...)` (spawn + await), `proc.await`, `proc.kill`, `proc.alive`. Исполняемый файл `cmd` и его аргументы `argv` передаются **раздельно** и выполняются напрямую без оболочки shell (исключается уязвимость к shell-инъекциям). Жизненный цикл ограничен по времени (`E0921`), появление **процессов-сирот исключено** (дочерние процессы принудительно завершаются при выходе или отмене задачи), поддерживается kill-on-cancel. Выполнение любых команд работает по принципу **fail-closed**: запрещено по умолчанию, если оно явно не разрешено в `NUDGE_PROCESS_GRANTS` (`E0920`). ### Локальный UI Создавайте нативные интерфейсы с участием человека (human-in-the-loop), станции подтверждения действий (approval stations) и интерактивные панели инспекции прямо в 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) } } ``` - **Два режима выполнения:** - **Headless-тестирование:** `mount_headless()` и `dispatch_click()` вычисляют деревья UI и смену состояний полностью в оперативной памяти без открытия физического окна. Работает в CI за $0. - **Нативный десктопный GUI:** при компиляции с Cargo-фичей `native-gui` вызов `window.open()` открывает нативное окно операционной системы на базе библиотек `winit` и `softbuffer`. - **Автоматический откат в Headless:** установка переменной `NUDGE_UI_HEADLESS=1` или запуск в режиме воспроизведения trace (`NUDGE_REPLAY`) автоматически перенаправляет вызовы окон в headless-движок. ### Жизненный цикл задач и параллелизм Координируйте параллельные потоки агента с формальным управлением состоянием задач и кооперативной отменой: ```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) } } ``` - **Кооперативная отмена:** когда результат гонки определен, проигравшие ветви останавливаются на границах циклов, потоков данных (stream) и вызовов effect вместо того, чтобы продолжать расходовать budget в фоновом режиме. - **Защита budget:** неизрасходованные резервации budget в рамках `NUDGE_BUDGET` немедленно освобождаются при отмене задачи. - **Права fail-closed:** отмененные задачи мгновенно теряют полномочия на отправку последующих вызовов инструментов (`Tool`) или действий с компьютером (`Computer`). - **Примитивы для работы с задачами:** явное управление задачами через `task.spawn`, `task.join`, `task.status` и `task.cancel`. ### Аутентификация провайдеров Безопасное управление учетными данными, интегрированное в язык и среду выполнения: - **Аутентификация fail-closed:** функции объявляют явные требования к авторизации через `uses Auth` или `uses Auth(account)`. Неавторизованные вызовы завершаются с ошибкой (fail-closed). - **Запрет сбора сторонних токенов:** Nudge никогда не считывает приватные кэши токенов или хранилища учетных данных, принадлежащие сторонним приложениям. - **Нативный flow устройств RFC 8628:** интерактивная авторизация в терминале через OAuth 2.0 Device Authorization Grant с безопасным хранением учетных данных в `~/.nudge/credentials.json` (права доступа к файлу 0600). - **Шлюзы провайдеров:** провайдеры обязаны удовлетворять верифицируемым контрактам безопасности (`E-auth-0401` при отсутствии учетных данных, `E-auth-0403` при нехватке прав scope, `E-auth-0404` для отключенных провайдеров). - **Неподтвержденные провайдеры остаются закрытыми (Permission Gate):** провайдер, для которого официальное разрешение на использование сторонними клиентами не доказано, **по умолчанию отключен (fail-closed)**. В настоящее время это относится к `antigravity`: логика авторизации OAuth и код провайдера реализованы, однако официальное подтверждение того, что его клиент OAuth и эндпоинты моделей разрешено вызывать из независимого стороннего клиента, отсутствует. Поэтому шлюз остается **отключенным** (`E-auth-0404`) до подтверждения разрешения. **Тест с мок-сервером OAuth или зеленый запуск в CI НЕ доказывают доступ к реальному аккаунту или наличие разрешения на использование.** Пользователи (включая любые приложения на базе Nudge) не должны полагаться на это подключение до документирования разрешений. Явный флаг пользователя (`NUDGE_ENABLE_ANTIGRAVITY=1`) активирует его на собственный страх и риск после подтверждения прав. ### Типизированные решения Компилируйте неопределенность от моделей принятия решений (таких как Laya и Jev) через сетевой протокол `/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 } } ``` - **Пакетное выполнение:** один вызов оценивает все вопросы одновременно, возвращая победителя, вероятность, распределение и показатель уверенности (confidence). - **Тестирование за $0:** стандартный fake decision provider синтезирует детерминированные распределения на основе seed для тестовых прогонов за $0. - **Живые провайдеры:** подключение локальных или удаленных моделей через `NUDGE_DECISION_SERVERS='{"laya": {"base_url": "http://localhost:8000"}}'`. - **Кэш решений:** параметр `NUDGE_DECISION_CACHE=` кэширует проверенные ответы между запусками, исключая повторную оплату за одинаковое состояние. - **Анализ политик (Policy Sweeps):** запуск `nudgec policy-sweep trace.jsonl --question dept --thresholds 0.5,0.8` позволяет оценить калибровку порогов по записанным распределениям без единого вызова модели. Читайте [документацию по решениям](docs/decision.md). ### Управление компьютером (Computer Use) Управляйте десктопным окружением через типизированные наблюдения и действия, где язык обеспечивает контроль и безопасность, а модель отвечает за восприятие: ```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 } ``` - **Типизированные примитивы:** `computer.observe` возвращает запись `Observation` (дерево доступности, элементы, опциональный скриншот). Действия (`click`, `type`, `key`, `scroll`, `set_value`, `drag`, `paste`) возвращают `ActionResult` с квитанцией об отправке (`action_sent`). - **Безопасность replay:** повторное воспроизведение trace никогда не выполняет физические действия повторно. С флагом `NUDGE_COMPUTER_DRIFT=1` среда выполнения заново считывает живое состояние и рассчитывает механическую разницу `Drift` без совершения действий. - **Усиление защиты:** список разрешенных приложений (`allow: [app]`), блокировки аренды контроллера, отклонение устаревших индексов элементов (`stale_state`) и жесткий выключатель аварийной остановки (`NUDGE_COMPUTER_KILL=1`). - **Детерминированный десктоп:** стандартный fake provider выполняет сценарии UI в памяти (`NUDGE_COMPUTER_SCENARIO`), обеспечивая проведение сквозных тестов за $0. Читайте [документацию по Computer Use](docs/computer-use.md). ## Нативная инфраструктура ### Движок Bytecode VM Чистые функции, трансформации данных и ветвление маршрутов исполняются на специализированной стековой виртуальной машине bytecode (`crates/nudgec/src/bytecode.rs` и `vm.rs`): - **Высокоскоростные чистые вычисления:** выполняет чистый код примерно в 70 раз быстрее интерпретатора AST. - **Безопасность глубокой рекурсии:** управляемый стек фреймов предотвращает переполнение стека операционной системы в рекурсивных алгоритмах. - **Прозрачное делегирование effect:** выражения с побочными эффектами (`llm`, `tool`, `computer`, `workspace`) прозрачно передаются из виртуальной машины исполнителю среды выполнения через `DelegateCall` и `DelegateExpr`. - **Движок по умолчанию:** виртуальная машина активна по умолчанию для `nudgec run` и автономных бинарных файлов. Установите `NUDGE_VM=0` для возврата к интерпретатору AST. ### Автономные нативные агенты (без Cargo) Упаковывайте агента в единый самодостаточный нативный исполняемый файл без необходимости наличия компилятора или сборочных инструментов на целевой машине: ```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 ``` - **Штамповка AST:** `nudgec` проверяет типы, сериализует bundle AST в bincode и присоединяет его к готовому исполняемому файлу runtime `nudge-agent` (с маркером `NDGAGNT1` в конце файла) за доли секунды. - **Две разновидности runtime:** - **Полный (~2.09MB, по умолчанию):** среда с поддержкой сетевого взаимодействия через встроенный стек HTTP/TLS на базе `ureq` + `rustls` для работы с живыми LLM и MCP-серверами. - **Только Replay (~832KB):** компактная среда без сетевых библиотек, обслуживающая все вызовы из предварительно записанных NTF trace для работы в офлайне за $0. - **Поиск runtime:** путь определяется через переменную `NUDGE_AGENT_RUNTIME` или по соседству с бинарным файлом `nudgec`. Читайте [документацию по автономным агентам](docs/standalone.md). ### Таргет WebAssembly Развертывайте агентов в изолированных песочницах браузеров, средах edge (Cloudflare Workers, Fastly) и окружениях WASI: - **Офлайн-replay (`nudge-replay-wasi`):** воспроизведение записанных NTF trace внутри модуля `.wasm` размером около 526KB под управлением `wasmtime` с побайтово идентичным выводом по сравнению с нативным запуском: ```sh wasmtime run --dir . nudge-replay-wasi.wasm bundle.json trace.jsonl ``` - **Мост к хосту живых инструментов:** агенты в браузере или среде JavaScript edge совершают вызовы внешних инструментов через стандартизированный контракт импорта `nudge_host_tool_call` (протестировано в Node WASI, см. `examples/wasm-host/`). - **Безопасная песочница:** сетевые сокеты и порождение процессов ОС заблокированы на уровне платформы `wasm32`, что гарантирует изолированное выполнение. Читайте [документацию по WebAssembly](docs/wasm.md). ## Инструменты и интеграции ### Интеграция с MCP Объявляйте инструменты, работающие на базе серверов Model Context Protocol (MCP), обменивающихся данными через 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") } ``` Настройка активных серверов через переменную `NUDGE_MCP_SERVERS`: ```sh export NUDGE_MCP_SERVERS='{"search": {"command": "mcp-server-websearch"}}' nudgec run search_agent.ndg ``` Параметры передаются как именованные JSON-объекты аргументов для полной совместимости с FastMCP и стандартными серверами. При отсутствии сервера выполнение быстро прерывается с информативной диагностикой. ### Детерминированные Trace и CI для агентов Каждый запуск создает открытый trace в формате NTF v1 JSONL, фиксирующий взаимодействия со всеми effect: ```sh # Verify trace integrity against the open specification nudgec trace-check trace.jsonl # Сравнение двух trace для выявления изменений в стоимости или поведении (--json формирует машиночитаемый отчет) nudgec trace-diff baseline.jsonl candidate.jsonl --fail-on-regression --json ``` **GitHub Action (`action.yml`):** тестирование агентов в CI на каждом push с затратами $0 и без необходимости в 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" ``` Зафиксированная спецификация NTF доступна в файле [docs/ntf-spec.md](docs/ntf-spec.md), а полный набор тестов представлен в каталоге [`conformance/`](conformance/) с готовыми адаптерами для LangChain, CrewAI и LangGraph. ### Инструменты разработчика - **Статический расчет стоимости:** `nudgec cost [--json]` рассчитывает предельные затраты токенов и бюджет для каждой функции во время компиляции. - **Тестирование свойств и фаззинг:** `nudgec fuzz [file.ndg] [--iterations N] [--seed S] [--json]` запускает фаззинг на основе мутаций и проверку инвариантов со структурированным выводом. - **Оценка на датасетах:** `nudgec eval --dataset [--fn ] [--path ] [--min-accuracy 0.8] [--json]` тестирует функции на наборах данных JSONL и контролирует CI по порогу точности. - **Сравнение оценок:** `nudgec compare [--json]` сопоставляет результаты двух прогонов оценки для обнаружения регрессий точности или производительности. - **Анализатор запуска (Run Explainer):** `nudgec explain [--json]` формирует читаемый отчет в терминале или JSON-анализ с деталями об ошибках, расходе токенов и решениях с низкой уверенностью. - **Сравнение Trace:** `nudgec trace-diff [--json] [--fail-on-regression]` сопоставляет два trace для выявления регрессий с кодом завершения 1 при обнаружении ухудшений. - **Аудит соответствия:** `nudgec audit [--json]` выполняет аудит NTF trace на соответствие требованиям EU AI Act (прозрачность, управление, незамаскированные секреты, метрики рисков). - **Локальный просмотрщик Trace:** `nudgec trace-view [--port N] [--no-open]` запускает локальный веб-интерфейс с наглядной шкалой времени выполнения, расходом токенов и отображением раундов восстановления (repair). - **Форматирование и отслеживание:** утилита `nudgec fmt [--check] [--json]` аккуратно форматирует код, а `nudgec check [--json] --watch` проверяет типы при каждом сохранении файла. - **Линтер и автоисправление:** `nudgec lint [--fix] [--json]` проверяет код на соответствие лучшим практикам (неограниченные бюджеты, нечеткие промпты, схемы без восстановления) и применяет безопасные исправления. - **Инспектор хранилища запусков:** `nudgec runs [--run ] [--json]` исследует постоянные состояния выполнения, трейсы и контрольные точки агентов. - **Менеджер аутентификации:** `nudgec auth login [provider]` и `nudgec auth status [--json]` управляют учетными данными OAuth и проверяют подключенных провайдеров ИИ. - **Статический экспорт в HTML:** команда `nudgec trace-html [-o report.html]` экспортирует автономные интерактивные отчеты для аудита. ### Расширение для VS Code Установите [расширение языка Nudge](https://marketplace.visualstudio.com/items?itemName=Nekomya.nudge-lang) для подсветки синтаксиса, фрагментов кода, документации при наведении курсора и диагностики типов в реальном времени на базе `nudgec lsp`. ## Конфиденциальность и маскирование Trace AI-агенты регулярно работают с чувствительными токенами, заголовками авторизации, приватными ключами и персональными данными (PII). Nudge защищает ваши данные с помощью конвейера маскирования trace по принципу fail-closed: - **Единая точка контроля (Single Choke Point):** маскирование выполняется внутри `TraceWriter::emit` перед сохранением записей на диск или в буферы памяти. Каждый тип записей (`llm.call`, `tool.call`, `decision.call`, `computer.*`, `fn.return`) маскируется в этой единой точке. - **Fail-Closed по умолчанию:** маскирование trace включено по умолчанию (`NUDGE_TRACE_REDACT=1`). Устанавливайте `NUDGE_TRACE_REDACT=0` исключительно для явной локальной отладки. - **`NUDGE_TRACE_REDACT=0` является границей безопасности, а не просто опцией:** отключение маскирования приведет к записи секретов, API-ключей, заголовков авторизации и личных данных в **ОТКРЫТОМ ТЕКСТЕ** в файл trace. Это задокументированное и проверенное тестами свойство переключателя. Никогда не используйте его в CI, с коммитируемыми артефактами или в приложениях, потребляющих trace. Все внешние системы должны расценивать флаг `NUDGE_TRACE_REDACT=0` как фактор риска безопасности и не считать такие файлы trace безопасными для хранения или передачи. - **Автоматическое обнаружение секретов:** система автоматически находит и скрывает значения переменных окружения, имена которых оканчиваются на `_KEY`, `_SECRET`, `_TOKEN`, `_PASSWORD`, `_PAT` или содержат подстроку `AUTH` (при длине значения от 6 символов). - **Многоуровневая фильтрация паттернов:** удаляет bearer-токены, заголовки авторизации, пары ключ-значение учетных данных, блоки закрытых ключей и префиксы ключей провайдеров (OpenAI `sk-...`, Anthropic `sk-ant-...`, GitHub `ghp_...`, AWS `AKIA...`, Slack `xox...`). - **Криптографическая инвариантность replay:** контентно-адресуемый хеш `request_hash` рассчитывается на исходных данных **до маскирования**. Благодаря этому скрытые trace сохраняют побайтовое соответствие при поиске во время replay со сложностью O(1), не сохраняя секреты на диске. ## Переменные окружения | Переменная | Область | Назначение | По умолчанию | |:---|:---|:---|:---| | `NUDGE_PROVIDER` | both | Активный провайдер LLM (`fake`, `openai`, `anthropic`, `gemini`, `groq`, `ollama`) | `fake` | | `NUDGE_VM` | native | Переключатель движка исполнения Bytecode VM (`1` = VM по умолчанию, `0` = откат к интерпретатору AST) | `1` | | `NUDGE_DEFAULT_MODEL` | native | Модель по умолчанию, если она явно не указана в блоке `with` | По умолчанию для провайдера | | `NUDGE_API_KEY` / `NUDGE_BASE_URL` | both | Учетные данные и базовый URL для OpenAI-совместимых провайдеров LLM | Нет | | `NUDGE_PRICING` | both | Пользовательская таблица стоимости в JSON: `{"model": [usd_per_1M_in, usd_per_1M_out]}` | Встроенная таблица | | `NUDGE_GUARD` | python/TS | Фильтры вывода (`pii` скрывает секреты, адреса электронной почты, IP-адреса в ответах LLM) | Нет | | `NUDGE_BUDGET` | both | Лимит затрат в USD на весь запуск, соблюдаемый всеми параллельными потоками | Нет | | `NUDGE_REPAIR_BUDGET` | python | Совокупный лимит в USD для раундов исправления (repair) | Нет | | `NUDGE_MAX_LOOP_ITERATIONS` | native | Предельное число последовательных итераций цикла до вызова ошибки времени выполнения `E0703` | `10000` | | `NUDGE_TRACE` | both | Путь к файлу для записи trace выполнения в формате NTF JSONL | `trace.jsonl` | | `NUDGE_REPLAY` | both | Путь к trace для детерминированного воспроизведения в офлайне (`NUDGE_REPLAY_MODE=all` или `llm`) | Нет | | `NUDGE_RESUME` | both | Возобновление прерванного выполнения с чекпоинта по записанному префиксу trace | Нет | | `NUDGE_TRACE_REDACT` | native | Включение маскирования секретов и PII в trace в единой точке контроля (`1` или `0`) | `1` (Активно) | | `NUDGE_TRACE_REDACT_ENV` | native | Автоматическое сокрытие значений секретных переменных окружения в trace | `1` (Активно) | | `NUDGE_TRACE_REDACT_KEYS` | native | Разделенный запятыми список дополнительных ключей JSON-объектов для сокрытия | Нет | | `NUDGE_TRACE_REDACT_PATTERNS` | native | Регулярные выражения через запятую или путь к файлу regex для пользовательского маскирования | Нет | | `NUDGE_WORKSPACE_DIR` | native | Корневой каталог для выполнения изолированных операций `workspace.*` | Текущий каталог | | `NUDGE_STORE_PATH` | native | Путь к файлу хранилища постоянных типизированных данных ключ-значение | `/.nudge/store.json` | | `NUDGE_UI_HEADLESS` | native | Принудительный запуск операций с окнами UI в headless-режиме в памяти (`1` или `true`) | `0` | | `NUDGE_TOOL_GRANTS` | both | JSON-политика доступа к инструментам на этапе выполнения (например, `{"web_search": ["*"]}`). Принцип fail-closed | Нет | | `NUDGE_PROCESS_GRANTS` | native | Политика fail-closed в формате JSON для разрешенных команд и аргументов `proc.*` | Нет (запрещено) | | `NUDGE_PROCESS_TIMEOUT` | native | Таймаут выполнения дочернего процесса по умолчанию в миллисекундах для `proc.*` | `30000` | | `NUDGE_FS_WATCH_TIMEOUT` | native | Таймаут ожидания изменений по умолчанию в миллисекундах для `fs.watch` | `30000` | | `NUDGE_ENABLE_ANTIGRAVITY` | native | Флаг явного согласия для включения провайдера Antigravity (`1` или `true`) | `0` | | `NUDGE_AUTH_ANTIGRAVITY` | native | Прямой bearer-токен для аутентификации в провайдере Antigravity | Нет | | `NUDGE_AUTH_GITHUB_COPILOT` | native | Прямое переопределение токена для аутентификации в GitHub Copilot | Нет | | `NUDGE_MCP_SERVERS` | both | JSON-реестр соответствия имен MCP-серверов командам stdio | Нет | | `NUDGE_MCP_TIMEOUT_MS` | native | Таймаут на чтение запроса и зависшей сессии для серверов MCP | `30000` | | `NUDGE_DECISION_SERVERS` | both | JSON-реестр эндпоинтов моделей принятия решений (например, `{"laya": {"base_url": "..."}}`) | Нет | | `NUDGE_DECISION_CACHE` | both | Путь к файлу кэша для сохраненных распределений моделей принятия решений | Нет | | `NUDGE_COMPUTER_SERVERS` | both | JSON-реестр мостов управления компьютером (подпроцесс JSONL или HTTP) | Нет | | `NUDGE_COMPUTER_PROVIDER` | both | Выбранный мост для действий с компьютером (`fake` или зарегистрированное имя сервера) | `fake` | | `NUDGE_COMPUTER_KILL` | both | Аварийный выключатель: значение `1` немедленно блокирует любые действия с компьютером | `0` | | `NUDGE_COMPUTER_DRIFT` | both | При значении `1` считывает состояние заново при replay и формирует диффы drift | `0` | | `NUDGE_AGENT_RUNTIME` | native | Путь к собранному бинарному файлу `nudge-agent` для команды `nudgec build --standalone` | Соседний бинарник | | `NUDGE_CREDENTIALS_PATH` | native | Пользовательский путь к файлу хранилища учетных данных Nudge | `~/.nudge/credentials.json` | | `NUDGE_OTEL` | python | Файл экспорта спанов OpenTelemetry | Нет | | `NUDGE_OTEL_ENDPOINT` | python | HTTP-эндпоинт для экспорта данных OpenTelemetry | Нет | Параметр `native` применяется к среде выполнения Rust (`nudgec`/`nudge-runtime`), `python/TS` относится к генерируемым средам, а `both` относится к обоим семействам сред выполнения. ## Примеры использования в реальном мире Ознакомьтесь с полноценными реализациями агентов в каталоге [`examples/`](examples/): | Пример | Направление | Главные особенности | |:---|:---|:---| | [AI Chatbot](examples/chatbot/) | Разговорный ассистент | Типизированные схемы памяти, детерминированный replay, лимиты budget | | [Triage Agent](examples/triage-agent/) | Классификация обращений | Пакетные блоки `decide{}`, пороги confidence, политики маршрутизации | | [Code Reviewer](examples/code-reviewer/) | Программная инженерия | Структурированная диагностика синтаксиса, автоматическая оценка по рубрикам | | [Research Agent](examples/research_agent.ndg) | Анализ нескольких источников | Параллельный сбор данных с `par map`, расчет confidence | | [Computer Automation](examples/computer-automation/) | Автоматизация рабочего стола | Наблюдение за экраном, деревья доступности, валидация drift | | [RAG Agent](examples/rag-agent/) | Retrieval-Augmented Generation | Привязка инструментов извлечения MCP через stdio, извлечение цитат | | [Property Fuzzer](examples/property-fuzz/) | Тестирование агентов | Инвариантное тестирование с `for_all`, фаззинг prompt injection | | [Dungeon Crawler](examples/dungeon-crawler/) | Симуляция конечного автомата | Чистый Nudge, переходы между состояниями агента, пошаговый бой | ## Лицензия и сборка из исходников Nudge распространяется под лицензией с открытым исходным кодом **Apache-2.0**. Подробности в файле [LICENSE](LICENSE). ### Сборка из исходников Для сборки компилятора требуется стабильная версия Rust 1.75+: ```sh git clone https://github.com/NekomyaDev/nudge.git cd nudge cargo build --release -p nudgec # compiler binary at target/release/nudgec cargo test --workspace # compiler, VM, and runtime test suite ``` Среда выполнения Python находится в папке `runtime/` (только стандартная библиотека, без внешних зависимостей): ```sh pip install ./runtime ``` ---

Made with love by NekomyaDev