enya-agent 0.1.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/.env.example +20 -0
- package/.github/workflows/ci.yml +70 -0
- package/.github/workflows/publish.yml +250 -0
- package/.gitmodules +3 -0
- package/Cargo.lock +3584 -0
- package/Cargo.toml +97 -0
- package/crates/enact/Cargo.toml +27 -0
- package/crates/enact/src/lib.rs +60 -0
- package/crates/enact-a2a/Cargo.toml +25 -0
- package/crates/enact-a2a/src/lib.rs +411 -0
- package/crates/enact-channels/Cargo.toml +64 -0
- package/crates/enact-channels/examples/README.md +80 -0
- package/crates/enact-channels/examples/channel_bot.rs +169 -0
- package/crates/enact-channels/examples/telegram-echo.rs +34 -0
- package/crates/enact-channels/examples/whatsapp-echo.rs +142 -0
- package/crates/enact-channels/src/config.rs +213 -0
- package/crates/enact-channels/src/lib.rs +25 -0
- package/crates/enact-channels/src/runtime.rs +237 -0
- package/crates/enact-channels/src/security/mod.rs +5 -0
- package/crates/enact-channels/src/security/pairing.rs +205 -0
- package/crates/enact-channels/src/teams.rs +601 -0
- package/crates/enact-channels/src/telegram.rs +2833 -0
- package/crates/enact-channels/src/traits.rs +200 -0
- package/crates/enact-channels/src/webhook.rs +262 -0
- package/crates/enact-channels/src/whatsapp.rs +310 -0
- package/crates/enact-cli/Cargo.toml +40 -0
- package/crates/enact-cli/src/commands/doctor.rs +62 -0
- package/crates/enact-cli/src/commands/mod.rs +3 -0
- package/crates/enact-cli/src/commands/run.rs +69 -0
- package/crates/enact-cli/src/commands/serve.rs +81 -0
- package/crates/enact-cli/src/config.rs +2 -0
- package/crates/enact-cli/src/main.rs +79 -0
- package/crates/enact-config/Cargo.toml +36 -0
- package/crates/enact-config/ENV_VAR_MAPPING.md +135 -0
- package/crates/enact-config/QUICK_REFERENCE.md +92 -0
- package/crates/enact-config/README.md +107 -0
- package/crates/enact-config/TESTING.md +161 -0
- package/crates/enact-config/examples/test-env-vars.rs +100 -0
- package/crates/enact-config/src/config.rs +399 -0
- package/crates/enact-config/src/encrypted_store.rs +211 -0
- package/crates/enact-config/src/lib.rs +298 -0
- package/crates/enact-config/src/secrets.rs +149 -0
- package/crates/enact-config/src/sync.rs +260 -0
- package/crates/enact-config/test-env-vars.sh +34 -0
- package/crates/enact-config/tests/README.md +99 -0
- package/crates/enact-config/tests/config_integration_test.rs +202 -0
- package/crates/enact-config/tests/security_test.rs +140 -0
- package/crates/enact-context/Cargo.toml +41 -0
- package/crates/enact-context/src/budget.rs +314 -0
- package/crates/enact-context/src/calibrator.rs +535 -0
- package/crates/enact-context/src/compactor.rs +392 -0
- package/crates/enact-context/src/condenser.rs +826 -0
- package/crates/enact-context/src/lib.rs +94 -0
- package/crates/enact-context/src/segment.rs +238 -0
- package/crates/enact-context/src/step_context.rs +645 -0
- package/crates/enact-context/src/token_counter.rs +148 -0
- package/crates/enact-context/src/window.rs +372 -0
- package/crates/enact-core/Cargo.toml +42 -0
- package/crates/enact-core/README.md +98 -0
- package/crates/enact-core/src/background/executor.rs +524 -0
- package/crates/enact-core/src/background/mod.rs +48 -0
- package/crates/enact-core/src/background/target_binding.rs +390 -0
- package/crates/enact-core/src/background/trigger.rs +511 -0
- package/crates/enact-core/src/callable/callable.rs +152 -0
- package/crates/enact-core/src/callable/composite.rs +817 -0
- package/crates/enact-core/src/callable/graph.rs +104 -0
- package/crates/enact-core/src/callable/llm.rs +211 -0
- package/crates/enact-core/src/callable/mod.rs +64 -0
- package/crates/enact-core/src/callable/registry.rs +206 -0
- package/crates/enact-core/src/context/execution_context.rs +757 -0
- package/crates/enact-core/src/context/invocation.rs +99 -0
- package/crates/enact-core/src/context/mod.rs +50 -0
- package/crates/enact-core/src/context/tenant.rs +175 -0
- package/crates/enact-core/src/context/trace.rs +127 -0
- package/crates/enact-core/src/flow/conditional.rs +293 -0
- package/crates/enact-core/src/flow/mod.rs +43 -0
- package/crates/enact-core/src/flow/parallel.rs +437 -0
- package/crates/enact-core/src/flow/repeat.rs +534 -0
- package/crates/enact-core/src/flow/sequential.rs +248 -0
- package/crates/enact-core/src/graph/checkpoint.rs +79 -0
- package/crates/enact-core/src/graph/checkpoint_store.rs +76 -0
- package/crates/enact-core/src/graph/compiled.rs +189 -0
- package/crates/enact-core/src/graph/edge.rs +59 -0
- package/crates/enact-core/src/graph/graph_schema.rs +218 -0
- package/crates/enact-core/src/graph/loader.rs +155 -0
- package/crates/enact-core/src/graph/mod.rs +18 -0
- package/crates/enact-core/src/graph/node/function.rs +49 -0
- package/crates/enact-core/src/graph/node/mod.rs +48 -0
- package/crates/enact-core/src/graph/schema.rs +62 -0
- package/crates/enact-core/src/inbox/message.rs +405 -0
- package/crates/enact-core/src/inbox/mod.rs +31 -0
- package/crates/enact-core/src/inbox/store.rs +355 -0
- package/crates/enact-core/src/kernel/artifact/filesystem.rs +546 -0
- package/crates/enact-core/src/kernel/artifact/metadata.rs +283 -0
- package/crates/enact-core/src/kernel/artifact/mod.rs +27 -0
- package/crates/enact-core/src/kernel/artifact/store.rs +427 -0
- package/crates/enact-core/src/kernel/enforcement.rs +1315 -0
- package/crates/enact-core/src/kernel/error.rs +1200 -0
- package/crates/enact-core/src/kernel/event.rs +1394 -0
- package/crates/enact-core/src/kernel/execution_model.rs +831 -0
- package/crates/enact-core/src/kernel/execution_state.rs +189 -0
- package/crates/enact-core/src/kernel/execution_strategy.rs +117 -0
- package/crates/enact-core/src/kernel/ids.rs +2086 -0
- package/crates/enact-core/src/kernel/interrupt.rs +125 -0
- package/crates/enact-core/src/kernel/kernel.rs +1283 -0
- package/crates/enact-core/src/kernel/mod.rs +205 -0
- package/crates/enact-core/src/kernel/persistence/event_store.rs +270 -0
- package/crates/enact-core/src/kernel/persistence/message_store.rs +908 -0
- package/crates/enact-core/src/kernel/persistence/mod.rs +102 -0
- package/crates/enact-core/src/kernel/persistence/state_store.rs +228 -0
- package/crates/enact-core/src/kernel/persistence/vector_store.rs +299 -0
- package/crates/enact-core/src/kernel/reducer.rs +808 -0
- package/crates/enact-core/src/kernel/replay.rs +153 -0
- package/crates/enact-core/src/lib.rs +413 -0
- package/crates/enact-core/src/memory/episodic.rs +0 -0
- package/crates/enact-core/src/memory/mod.rs +6 -0
- package/crates/enact-core/src/memory/semantic.rs +0 -0
- package/crates/enact-core/src/memory/trait.rs +0 -0
- package/crates/enact-core/src/memory/vector_db.rs +0 -0
- package/crates/enact-core/src/memory/working.rs +0 -0
- package/crates/enact-core/src/policy/execution_policy.rs +292 -0
- package/crates/enact-core/src/policy/filters.rs +458 -0
- package/crates/enact-core/src/policy/input_processor.rs +407 -0
- package/crates/enact-core/src/policy/long_running.rs +134 -0
- package/crates/enact-core/src/policy/mod.rs +193 -0
- package/crates/enact-core/src/policy/pii_input.rs +274 -0
- package/crates/enact-core/src/policy/tenant_policy.rs +453 -0
- package/crates/enact-core/src/policy/tool_policy.rs +407 -0
- package/crates/enact-core/src/providers/mod.rs +63 -0
- package/crates/enact-core/src/providers/trait.rs +292 -0
- package/crates/enact-core/src/runner/callbacks.rs +6 -0
- package/crates/enact-core/src/runner/execution_runner.rs +476 -0
- package/crates/enact-core/src/runner/loop.rs +117 -0
- package/crates/enact-core/src/runner/mod.rs +58 -0
- package/crates/enact-core/src/runner/protected_runner.rs +280 -0
- package/crates/enact-core/src/signal/inmemory.rs +231 -0
- package/crates/enact-core/src/signal/mod.rs +108 -0
- package/crates/enact-core/src/streaming/event_logger.rs +195 -0
- package/crates/enact-core/src/streaming/event_stream.rs +1423 -0
- package/crates/enact-core/src/streaming/mod.rs +108 -0
- package/crates/enact-core/src/streaming/pause_cancel.rs +0 -0
- package/crates/enact-core/src/streaming/protected_emitter.rs +173 -0
- package/crates/enact-core/src/streaming/protection/context.rs +136 -0
- package/crates/enact-core/src/streaming/protection/encryption.rs +289 -0
- package/crates/enact-core/src/streaming/protection/mod.rs +43 -0
- package/crates/enact-core/src/streaming/protection/pii_protection.rs +243 -0
- package/crates/enact-core/src/streaming/protection/processor.rs +166 -0
- package/crates/enact-core/src/streaming/sse.rs +0 -0
- package/crates/enact-core/src/telemetry/exporter.rs +0 -0
- package/crates/enact-core/src/telemetry/init.rs +0 -0
- package/crates/enact-core/src/telemetry/mod.rs +49 -0
- package/crates/enact-core/src/telemetry/spans.rs +245 -0
- package/crates/enact-core/src/tool/agent_tool.rs +177 -0
- package/crates/enact-core/src/tool/browser/mod.rs +0 -0
- package/crates/enact-core/src/tool/browser/webdriver.rs +0 -0
- package/crates/enact-core/src/tool/cost.rs +247 -0
- package/crates/enact-core/src/tool/discovery.rs +0 -0
- package/crates/enact-core/src/tool/dispatcher.rs +347 -0
- package/crates/enact-core/src/tool/filesystem.rs +231 -0
- package/crates/enact-core/src/tool/function.rs +99 -0
- package/crates/enact-core/src/tool/git.rs +162 -0
- package/crates/enact-core/src/tool/http.rs +214 -0
- package/crates/enact-core/src/tool/mcp/client.rs +0 -0
- package/crates/enact-core/src/tool/mcp/mod.rs +0 -0
- package/crates/enact-core/src/tool/mod.rs +51 -0
- package/crates/enact-core/src/tool/reasoning/debugging.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/mcts.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/mod.rs +0 -0
- package/crates/enact-core/src/tool/reasoning/sequential.rs +0 -0
- package/crates/enact-core/src/tool/sandbox/dagger.rs +0 -0
- package/crates/enact-core/src/tool/sandbox/mod.rs +0 -0
- package/crates/enact-core/src/tool/shell.rs +147 -0
- package/crates/enact-core/src/tool/trait.rs +33 -0
- package/crates/enact-core/src/tool/web_search.rs +277 -0
- package/crates/enact-core/src/util/config.rs +0 -0
- package/crates/enact-core/src/util/errors.rs +0 -0
- package/crates/enact-core/src/util/mod.rs +6 -0
- package/crates/enact-core/tests/airgapped_e2e_test.rs +291 -0
- package/crates/enact-core/tests/e2e_agentic_loop.rs +119 -0
- package/crates/enact-core/tests/e2e_test.rs +259 -0
- package/crates/enact-core/tests/graph_test.rs +130 -0
- package/crates/enact-core/tests/stream_event_id_validation.rs +435 -0
- package/crates/enact-cron/Cargo.toml +28 -0
- package/crates/enact-cron/src/lib.rs +44 -0
- package/crates/enact-cron/src/schedule.rs +156 -0
- package/crates/enact-cron/src/store.rs +589 -0
- package/crates/enact-cron/src/types.rs +148 -0
- package/crates/enact-gateway/Cargo.toml +31 -0
- package/crates/enact-gateway/README.md +30 -0
- package/crates/enact-gateway/examples/whatsapp-gateway-runner-mock.rs +59 -0
- package/crates/enact-gateway/examples/whatsapp-gateway.rs +42 -0
- package/crates/enact-gateway/src/lib.rs +582 -0
- package/crates/enact-mcp/Cargo.toml +24 -0
- package/crates/enact-mcp/src/lib.rs +178 -0
- package/crates/enact-memory/Cargo.toml +25 -0
- package/crates/enact-memory/src/backend.rs +20 -0
- package/crates/enact-memory/src/chunker.rs +230 -0
- package/crates/enact-memory/src/embeddings.rs +221 -0
- package/crates/enact-memory/src/lib.rs +67 -0
- package/crates/enact-memory/src/markdown.rs +127 -0
- package/crates/enact-memory/src/none.rs +61 -0
- package/crates/enact-memory/src/sqlite.rs +276 -0
- package/crates/enact-memory/src/traits.rs +65 -0
- package/crates/enact-memory/src/vector.rs +198 -0
- package/crates/enact-oauth/Cargo.toml +27 -0
- package/crates/enact-oauth/src/lib.rs +584 -0
- package/crates/enact-observability/Cargo.toml +22 -0
- package/crates/enact-observability/src/lib.rs +197 -0
- package/crates/enact-providers/Cargo.toml +33 -0
- package/crates/enact-providers/examples/hello-agent.rs +33 -0
- package/crates/enact-providers/src/anthropic.rs +182 -0
- package/crates/enact-providers/src/azure.rs +96 -0
- package/crates/enact-providers/src/bridge.rs +221 -0
- package/crates/enact-providers/src/gemini.rs +227 -0
- package/crates/enact-providers/src/http.rs +78 -0
- package/crates/enact-providers/src/lib.rs +53 -0
- package/crates/enact-providers/src/openai_compatible.rs +167 -0
- package/crates/enact-providers/src/openrouter.rs +33 -0
- package/crates/enact-runner/Cargo.toml +24 -0
- package/crates/enact-runner/README.md +76 -0
- package/crates/enact-runner/src/compaction.rs +225 -0
- package/crates/enact-runner/src/config.rs +118 -0
- package/crates/enact-runner/src/lib.rs +63 -0
- package/crates/enact-runner/src/loop_driver.rs +414 -0
- package/crates/enact-runner/src/parser.rs +421 -0
- package/crates/enact-runner/src/retry.rs +262 -0
- package/crates/enact-runner/tests/integration.rs +278 -0
- package/crates/enact-security/Cargo.toml +22 -0
- package/crates/enact-security/src/audit.rs +375 -0
- package/crates/enact-security/src/lib.rs +37 -0
- package/crates/enact-security/src/policy.rs +406 -0
- package/crates/enact-skills/Cargo.toml +25 -0
- package/crates/enact-skills/src/lib.rs +506 -0
- package/crates/enact-tools/Cargo.toml +22 -0
- package/crates/enact-tools/src/file_read.rs +166 -0
- package/crates/enact-tools/src/file_write.rs +216 -0
- package/crates/enact-tools/src/git_operations.rs +513 -0
- package/crates/enact-tools/src/http_request.rs +417 -0
- package/crates/enact-tools/src/lib.rs +104 -0
- package/crates/enact-tools/src/security.rs +227 -0
- package/crates/enact-tools/src/shell.rs +191 -0
- package/crates/enact-tools/src/traits.rs +159 -0
- package/docs/Makefile +74 -0
- package/docs/config.toml +62 -0
- package/docs/content/_index.md +174 -0
- package/docs/content/a2a/_index.md +431 -0
- package/docs/content/api/_index.md +323 -0
- package/docs/content/channels/_index.md +160 -0
- package/docs/content/channels/teams.md +205 -0
- package/docs/content/channels/telegram.md +182 -0
- package/docs/content/channels/webhook.md +423 -0
- package/docs/content/channels/whatsapp.md +240 -0
- package/docs/content/cli/_index.md +261 -0
- package/docs/content/concepts/_index.md +273 -0
- package/docs/content/configuration/_index.md +241 -0
- package/docs/content/cron/_index.md +248 -0
- package/docs/content/developers/_index.md +278 -0
- package/docs/content/getting-started/_index.md +180 -0
- package/docs/content/installation/_index.md +186 -0
- package/docs/content/installation/uninstall.md +101 -0
- package/docs/content/installation/updating.md +120 -0
- package/docs/content/mcp/_index.md +215 -0
- package/docs/content/memory/_index.md +163 -0
- package/docs/content/oauth/_index.md +515 -0
- package/docs/content/providers/_index.md +206 -0
- package/docs/content/roadmap/_index.md +199 -0
- package/docs/content/security/_index.md +219 -0
- package/docs/content/skills/_index.md +228 -0
- package/docs/content/tools/_index.md +485 -0
- package/docs/content/troubleshooting/_index.md +259 -0
- package/docs/content/yaml-schema/_index.md +294 -0
- package/docs/static/giallo-dark.css +91 -0
- package/docs/static/giallo-light.css +91 -0
- package/docs/themes/tanuki/.github/workflows/deploy.yml +44 -0
- package/docs/themes/tanuki/LICENSE +21 -0
- package/docs/themes/tanuki/README.md +166 -0
- package/docs/themes/tanuki/examples/blog/config.toml +58 -0
- package/docs/themes/tanuki/examples/blog/content/_index.md +4 -0
- package/docs/themes/tanuki/examples/blog/content/about.md +33 -0
- package/docs/themes/tanuki/examples/blog/content/blog/_index.md +7 -0
- package/docs/themes/tanuki/examples/blog/content/blog/api-design-best-practices.md +245 -0
- package/docs/themes/tanuki/examples/blog/content/blog/building-accessible-websites.md +147 -0
- package/docs/themes/tanuki/examples/blog/content/blog/css-grid-vs-flexbox.md +165 -0
- package/docs/themes/tanuki/examples/blog/content/blog/customizing-catppuccin-colors.md +137 -0
- package/docs/themes/tanuki/examples/blog/content/blog/dark-mode-best-practices.md +82 -0
- package/docs/themes/tanuki/examples/blog/content/blog/docker-essentials.md +301 -0
- package/docs/themes/tanuki/examples/blog/content/blog/getting-started-with-zola.md +129 -0
- package/docs/themes/tanuki/examples/blog/content/blog/git-workflow-for-content.md +112 -0
- package/docs/themes/tanuki/examples/blog/content/blog/introduction-to-webassembly.md +183 -0
- package/docs/themes/tanuki/examples/blog/content/blog/modern-javascript-features.md +234 -0
- package/docs/themes/tanuki/examples/blog/content/blog/testing-strategies.md +311 -0
- package/docs/themes/tanuki/examples/blog/content/blog/typography-for-developers.md +104 -0
- package/docs/themes/tanuki/examples/blog/content/blog/welcome-to-tanuki.md +67 -0
- package/docs/themes/tanuki/examples/blog/content/blog/why-static-sites.md +85 -0
- package/docs/themes/tanuki/examples/blog/content/projects.md +64 -0
- package/docs/themes/tanuki/examples/book/config.toml +17 -0
- package/docs/themes/tanuki/examples/book/content/_index.md +12 -0
- package/docs/themes/tanuki/examples/book/content/chapter-1.md +90 -0
- package/docs/themes/tanuki/examples/book/content/chapter-2.md +143 -0
- package/docs/themes/tanuki/examples/book/content/chapter-3.md +217 -0
- package/docs/themes/tanuki/examples/book/content/chapter-4.md +224 -0
- package/docs/themes/tanuki/examples/book/content/chapter-5.md +297 -0
- package/docs/themes/tanuki/examples/book/content/print.md +6 -0
- package/docs/themes/tanuki/examples/docs/config.toml +28 -0
- package/docs/themes/tanuki/examples/docs/content/_index.md +20 -0
- package/docs/themes/tanuki/examples/docs/content/components.md +156 -0
- package/docs/themes/tanuki/examples/docs/content/configuration.md +94 -0
- package/docs/themes/tanuki/examples/docs/content/customization.md +202 -0
- package/docs/themes/tanuki/examples/docs/content/deployment.md +204 -0
- package/docs/themes/tanuki/examples/docs/content/installation.md +59 -0
- package/docs/themes/tanuki/examples/docs/content/print.md +6 -0
- package/docs/themes/tanuki/examples/docs/static/img/tanuki-icon.avif +0 -0
- package/docs/themes/tanuki/examples/index.html +2104 -0
- package/docs/themes/tanuki/mise.toml +108 -0
- package/docs/themes/tanuki/sass/base/_catppuccin.scss +164 -0
- package/docs/themes/tanuki/sass/base/_fonts.scss +64 -0
- package/docs/themes/tanuki/sass/base/_reset.scss +152 -0
- package/docs/themes/tanuki/sass/base/_typography.scss +523 -0
- package/docs/themes/tanuki/sass/components/_buttons.scss +209 -0
- package/docs/themes/tanuki/sass/components/_code.scss +457 -0
- package/docs/themes/tanuki/sass/components/_landing.scss +633 -0
- package/docs/themes/tanuki/sass/components/_layout.scss +294 -0
- package/docs/themes/tanuki/sass/components/_navigation.scss +1200 -0
- package/docs/themes/tanuki/sass/components/_print.scss +237 -0
- package/docs/themes/tanuki/sass/components/_search.scss +224 -0
- package/docs/themes/tanuki/sass/components/_sidebar.scss +473 -0
- package/docs/themes/tanuki/sass/components/_theme-toggle.scss +186 -0
- package/docs/themes/tanuki/sass/modes/_blog.scss +366 -0
- package/docs/themes/tanuki/sass/modes/_product.scss +875 -0
- package/docs/themes/tanuki/sass/modes/_raskell.scss +1696 -0
- package/docs/themes/tanuki/sass/patterns/_buttons.scss +183 -0
- package/docs/themes/tanuki/sass/patterns/_cards.scss +144 -0
- package/docs/themes/tanuki/sass/patterns/_index.scss +9 -0
- package/docs/themes/tanuki/sass/patterns/_lists.scss +259 -0
- package/docs/themes/tanuki/sass/patterns/_sections.scss +243 -0
- package/docs/themes/tanuki/sass/style.scss +47 -0
- package/docs/themes/tanuki/sass/tokens/_colors.scss +139 -0
- package/docs/themes/tanuki/sass/tokens/_spacing.scss +100 -0
- package/docs/themes/tanuki/sass/tokens/_typography.scss +186 -0
- package/docs/themes/tanuki/screenshot.png +0 -0
- package/docs/themes/tanuki/sentinel.kdl +59 -0
- package/docs/themes/tanuki/static/elasticlunr.min.js +10 -0
- package/docs/themes/tanuki/static/fonts/GEIST-LICENSE.txt +92 -0
- package/docs/themes/tanuki/static/fonts/Geist-Variable.woff2 +0 -0
- package/docs/themes/tanuki/static/fonts/GeistMono-Variable.woff2 +0 -0
- package/docs/themes/tanuki/static/img/tanuki-icon.avif +0 -0
- package/docs/themes/tanuki/static/img/tanuki-icon.png +0 -0
- package/docs/themes/tanuki/static/js/anchors.js +18 -0
- package/docs/themes/tanuki/static/js/app.js +274 -0
- package/docs/themes/tanuki/static/js/code.js +394 -0
- package/docs/themes/tanuki/static/js/navigation.js +778 -0
- package/docs/themes/tanuki/static/js/scroll-to-top.js +33 -0
- package/docs/themes/tanuki/static/js/search-raskell.js +240 -0
- package/docs/themes/tanuki/static/js/search.js +215 -0
- package/docs/themes/tanuki/static/js/theme.js +169 -0
- package/docs/themes/tanuki/static/syntax-dark.css +151 -0
- package/docs/themes/tanuki/static/syntax-light.css +151 -0
- package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm.js +486 -0
- package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm_bg.wasm +0 -0
- package/docs/themes/tanuki/templates/404.html +52 -0
- package/docs/themes/tanuki/templates/base.html +428 -0
- package/docs/themes/tanuki/templates/blog.html +66 -0
- package/docs/themes/tanuki/templates/home.html +108 -0
- package/docs/themes/tanuki/templates/index.html +178 -0
- package/docs/themes/tanuki/templates/landing.html +168 -0
- package/docs/themes/tanuki/templates/macros/nav.html +128 -0
- package/docs/themes/tanuki/templates/macros/posts.html +101 -0
- package/docs/themes/tanuki/templates/macros/ui.html +159 -0
- package/docs/themes/tanuki/templates/page.html +135 -0
- package/docs/themes/tanuki/templates/partials/footer.html +38 -0
- package/docs/themes/tanuki/templates/partials/header.html +366 -0
- package/docs/themes/tanuki/templates/partials/nav-buttons.html +55 -0
- package/docs/themes/tanuki/templates/partials/nav-overlay.html +81 -0
- package/docs/themes/tanuki/templates/partials/page-toc-panel.html +43 -0
- package/docs/themes/tanuki/templates/partials/search.html +52 -0
- package/docs/themes/tanuki/templates/partials/sidebar.html +107 -0
- package/docs/themes/tanuki/templates/partials/theme-toggle.html +35 -0
- package/docs/themes/tanuki/templates/partials/toc-overlay.html +146 -0
- package/docs/themes/tanuki/templates/partials/version-picker.html +38 -0
- package/docs/themes/tanuki/templates/print.html +244 -0
- package/docs/themes/tanuki/templates/section.html +186 -0
- package/docs/themes/tanuki/templates/taxonomy_list.html +18 -0
- package/docs/themes/tanuki/templates/taxonomy_single.html +31 -0
- package/docs/themes/tanuki/theme.toml +58 -0
- package/examples/hello-agent.rs +55 -0
- package/package.json +36 -0
- package/proto/config.proto +60 -0
- package/proto/events.proto +0 -0
- package/proto/runtime.proto +215 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
//! End-to-end tests - Prove core invariants
|
|
2
|
+
//!
|
|
3
|
+
//! These tests verify the fundamental guarantees:
|
|
4
|
+
//! 1. Execute → events → replay → same state
|
|
5
|
+
//! 2. Policy violation → event emitted → execution blocked
|
|
6
|
+
//! 3. Artifact written → hash stable
|
|
7
|
+
|
|
8
|
+
use enact_core::context::{ResourceLimits, TenantContext};
|
|
9
|
+
use enact_core::kernel::artifact::{
|
|
10
|
+
ArtifactStore, ArtifactType, InMemoryArtifactStore, PutArtifactRequest,
|
|
11
|
+
};
|
|
12
|
+
use enact_core::kernel::ids::{ExecutionId, StepId};
|
|
13
|
+
use enact_core::kernel::{
|
|
14
|
+
replay, EnforcementMiddleware, EnforcementPolicy, EventLog, ExecutionAction, ExecutionError,
|
|
15
|
+
ExecutionKernel, ExecutionState, StepType, TenantId, ViolationType,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/// Helper to create a test TenantContext
|
|
19
|
+
fn test_tenant() -> TenantContext {
|
|
20
|
+
TenantContext::new(TenantId::from("tenant_test"))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Test 1: Execute → events → replay → same state
|
|
24
|
+
///
|
|
25
|
+
/// This proves:
|
|
26
|
+
/// - Deterministic state evolution
|
|
27
|
+
/// - Replayability from event log
|
|
28
|
+
/// - Same actions → same state
|
|
29
|
+
#[tokio::test]
|
|
30
|
+
async fn test_execute_replay_same_state() {
|
|
31
|
+
// Create a fresh kernel and execute a simple workflow
|
|
32
|
+
// TenantContext is REQUIRED for multi-tenant isolation
|
|
33
|
+
let mut kernel = ExecutionKernel::new(test_tenant());
|
|
34
|
+
let exec_id = kernel.execution_id().clone();
|
|
35
|
+
|
|
36
|
+
// Capture events during execution
|
|
37
|
+
let mut event_log = EventLog::new();
|
|
38
|
+
|
|
39
|
+
// Execute a simple workflow
|
|
40
|
+
kernel.start().unwrap();
|
|
41
|
+
event_log.append(ExecutionAction::Start);
|
|
42
|
+
|
|
43
|
+
let step_id = kernel
|
|
44
|
+
.begin_step(StepType::LlmNode, "test_step", None)
|
|
45
|
+
.unwrap();
|
|
46
|
+
event_log.append(ExecutionAction::StepStarted {
|
|
47
|
+
step_id: step_id.clone(),
|
|
48
|
+
parent_step_id: None,
|
|
49
|
+
step_type: StepType::LlmNode,
|
|
50
|
+
name: "test_step".to_string(),
|
|
51
|
+
source: None,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
kernel
|
|
55
|
+
.complete_step(step_id.clone(), Some("output".to_string()), 100)
|
|
56
|
+
.unwrap();
|
|
57
|
+
event_log.append(ExecutionAction::StepCompleted {
|
|
58
|
+
step_id: step_id.clone(),
|
|
59
|
+
output: Some("output".to_string()),
|
|
60
|
+
duration_ms: 100,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
kernel.complete(Some("final output".to_string())).unwrap();
|
|
64
|
+
event_log.append(ExecutionAction::Complete {
|
|
65
|
+
output: Some("final output".to_string()),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Capture final state
|
|
69
|
+
let original_execution = kernel.execution();
|
|
70
|
+
let original_state = original_execution.state;
|
|
71
|
+
let original_output = original_execution.output.clone();
|
|
72
|
+
let original_steps_count = original_execution.steps.len();
|
|
73
|
+
let original_step = original_execution.get_step(&step_id).unwrap().clone();
|
|
74
|
+
|
|
75
|
+
// Replay from event log
|
|
76
|
+
let replayed_execution = replay(exec_id.clone(), event_log.into_actions(), None).unwrap();
|
|
77
|
+
|
|
78
|
+
// Verify same state
|
|
79
|
+
assert_eq!(replayed_execution.id.as_str(), exec_id.as_str());
|
|
80
|
+
assert_eq!(replayed_execution.state, original_state);
|
|
81
|
+
assert_eq!(replayed_execution.output, original_output);
|
|
82
|
+
assert_eq!(replayed_execution.steps.len(), original_steps_count);
|
|
83
|
+
|
|
84
|
+
let replayed_step = replayed_execution.get_step(&step_id).unwrap();
|
|
85
|
+
assert_eq!(replayed_step.id, original_step.id);
|
|
86
|
+
assert_eq!(replayed_step.name, original_step.name);
|
|
87
|
+
assert_eq!(replayed_step.output, original_step.output);
|
|
88
|
+
assert_eq!(replayed_step.state, original_step.state);
|
|
89
|
+
|
|
90
|
+
// Verify terminal state
|
|
91
|
+
assert!(replayed_execution.state.is_terminal());
|
|
92
|
+
assert_eq!(replayed_execution.state, ExecutionState::Completed);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Test 2: Policy violation → event emitted → execution blocked
|
|
96
|
+
///
|
|
97
|
+
/// This proves:
|
|
98
|
+
/// - Policy-first enforcement
|
|
99
|
+
/// - Policy violations emit events
|
|
100
|
+
/// - Execution is blocked when policy is violated
|
|
101
|
+
#[tokio::test]
|
|
102
|
+
async fn test_policy_violation_blocks_execution() {
|
|
103
|
+
// Create a policy with strict limits
|
|
104
|
+
let policy = EnforcementPolicy {
|
|
105
|
+
warning_threshold: 80,
|
|
106
|
+
..Default::default()
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
let middleware = EnforcementMiddleware::with_policy(policy);
|
|
110
|
+
let tenant_id = TenantId::new();
|
|
111
|
+
let exec_id = ExecutionId::new();
|
|
112
|
+
|
|
113
|
+
// Create strict limits (only 2 steps allowed)
|
|
114
|
+
let limits = ResourceLimits {
|
|
115
|
+
max_steps: 2,
|
|
116
|
+
max_tokens: 1000,
|
|
117
|
+
max_wall_time_ms: 300_000,
|
|
118
|
+
max_memory_mb: None,
|
|
119
|
+
max_concurrent_executions: None,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Register execution and create usage tracker
|
|
123
|
+
let usage = middleware
|
|
124
|
+
.register_execution(exec_id.clone(), tenant_id)
|
|
125
|
+
.await;
|
|
126
|
+
|
|
127
|
+
// Check before first step (should pass - 0 steps, limit is 2)
|
|
128
|
+
let check0 = middleware.check_step_allowed(&exec_id, &limits).await;
|
|
129
|
+
assert!(
|
|
130
|
+
matches!(check0, enact_core::kernel::EnforcementResult::Allowed),
|
|
131
|
+
"First check should be allowed"
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Execute first step
|
|
135
|
+
usage.record_step();
|
|
136
|
+
// Check before second step (should pass or warn - 1 step done, about to do 2nd, limit is 2)
|
|
137
|
+
let check1 = middleware.check_step_allowed(&exec_id, &limits).await;
|
|
138
|
+
match check1 {
|
|
139
|
+
enact_core::kernel::EnforcementResult::Allowed
|
|
140
|
+
| enact_core::kernel::EnforcementResult::Warning(_) => {
|
|
141
|
+
// Both are acceptable - warning means we're at threshold but still allowed
|
|
142
|
+
}
|
|
143
|
+
_ => panic!(
|
|
144
|
+
"Second check should be Allowed or Warning, got {:?}",
|
|
145
|
+
check1
|
|
146
|
+
),
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Execute second step
|
|
150
|
+
usage.record_step();
|
|
151
|
+
// Check before third step (should be blocked - 2 steps done, about to do 3rd, limit is 2)
|
|
152
|
+
let check2 = middleware.check_step_allowed(&exec_id, &limits).await;
|
|
153
|
+
match check2 {
|
|
154
|
+
enact_core::kernel::EnforcementResult::Blocked(violation) => {
|
|
155
|
+
assert_eq!(violation.violation_type, ViolationType::StepLimit);
|
|
156
|
+
}
|
|
157
|
+
_ => panic!("Expected Blocked result after 2 steps, got {:?}", check2),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Verify that execution would be blocked by creating a kernel and checking
|
|
161
|
+
let mut kernel = ExecutionKernel::new(test_tenant());
|
|
162
|
+
kernel.start().unwrap();
|
|
163
|
+
|
|
164
|
+
// Execute two steps (within limit)
|
|
165
|
+
let step1 = kernel.begin_step(StepType::LlmNode, "step1", None).unwrap();
|
|
166
|
+
kernel
|
|
167
|
+
.complete_step(step1, Some("output1".to_string()), 100)
|
|
168
|
+
.unwrap();
|
|
169
|
+
|
|
170
|
+
let step2 = kernel.begin_step(StepType::LlmNode, "step2", None).unwrap();
|
|
171
|
+
kernel
|
|
172
|
+
.complete_step(step2, Some("output2".to_string()), 100)
|
|
173
|
+
.unwrap();
|
|
174
|
+
|
|
175
|
+
// Simulate policy violation by failing with policy error
|
|
176
|
+
let policy_error = ExecutionError::policy_violation("Step limit exceeded: max 2 steps allowed");
|
|
177
|
+
kernel.fail(policy_error.clone()).unwrap();
|
|
178
|
+
|
|
179
|
+
// Verify execution is in failed state
|
|
180
|
+
assert_eq!(kernel.state(), ExecutionState::Failed);
|
|
181
|
+
assert!(kernel.execution().error.is_some());
|
|
182
|
+
|
|
183
|
+
let error = kernel.execution().error.as_ref().unwrap();
|
|
184
|
+
assert!(error.is_fatal());
|
|
185
|
+
assert!(!error.is_retryable());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// Test 3: Artifact written → hash stable
|
|
189
|
+
///
|
|
190
|
+
/// This proves:
|
|
191
|
+
/// - Artifact content hashes are deterministic
|
|
192
|
+
/// - Same content → same hash
|
|
193
|
+
/// - Hash is stable across writes
|
|
194
|
+
#[tokio::test]
|
|
195
|
+
async fn test_artifact_hash_stable() {
|
|
196
|
+
let store = InMemoryArtifactStore::new();
|
|
197
|
+
let exec_id = ExecutionId::new();
|
|
198
|
+
let step_id = StepId::new();
|
|
199
|
+
|
|
200
|
+
let content = b"Hello, World! This is a test artifact.".to_vec();
|
|
201
|
+
|
|
202
|
+
// Write artifact first time
|
|
203
|
+
let request1 = PutArtifactRequest::new(
|
|
204
|
+
exec_id.clone(),
|
|
205
|
+
step_id.clone(),
|
|
206
|
+
"test_artifact",
|
|
207
|
+
ArtifactType::Text,
|
|
208
|
+
content.clone(),
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
let response1 = store.put(request1).await.unwrap();
|
|
212
|
+
|
|
213
|
+
// In-memory store doesn't compute hash, but we can verify artifact is stored
|
|
214
|
+
// and can be retrieved with same content
|
|
215
|
+
let retrieved1 = store.get(&response1.artifact_id).await.unwrap();
|
|
216
|
+
assert_eq!(retrieved1.content, content);
|
|
217
|
+
assert_eq!(retrieved1.metadata.name, "test_artifact");
|
|
218
|
+
|
|
219
|
+
// Write same content again (should be stored as separate artifact)
|
|
220
|
+
let request2 = PutArtifactRequest::new(
|
|
221
|
+
exec_id.clone(),
|
|
222
|
+
step_id.clone(),
|
|
223
|
+
"test_artifact_2",
|
|
224
|
+
ArtifactType::Text,
|
|
225
|
+
content.clone(),
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
let response2 = store.put(request2).await.unwrap();
|
|
229
|
+
|
|
230
|
+
// Verify both artifacts exist and have same content
|
|
231
|
+
let retrieved2 = store.get(&response2.artifact_id).await.unwrap();
|
|
232
|
+
assert_eq!(retrieved1.content, retrieved2.content);
|
|
233
|
+
assert_ne!(
|
|
234
|
+
response1.artifact_id, response2.artifact_id,
|
|
235
|
+
"Different artifacts should have different IDs"
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// Write different content
|
|
239
|
+
let different_content = b"Different content!".to_vec();
|
|
240
|
+
let request3 = PutArtifactRequest::new(
|
|
241
|
+
exec_id.clone(),
|
|
242
|
+
step_id.clone(),
|
|
243
|
+
"different_artifact",
|
|
244
|
+
ArtifactType::Text,
|
|
245
|
+
different_content.clone(),
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
let response3 = store.put(request3).await.unwrap();
|
|
249
|
+
let retrieved3 = store.get(&response3.artifact_id).await.unwrap();
|
|
250
|
+
|
|
251
|
+
// Different content should be different
|
|
252
|
+
assert_ne!(retrieved1.content, retrieved3.content);
|
|
253
|
+
assert_eq!(retrieved3.content, different_content);
|
|
254
|
+
|
|
255
|
+
// Verify artifacts are stable (can be retrieved multiple times)
|
|
256
|
+
let retrieved1_again = store.get(&response1.artifact_id).await.unwrap();
|
|
257
|
+
assert_eq!(retrieved1.content, retrieved1_again.content);
|
|
258
|
+
assert_eq!(retrieved1.metadata.name, retrieved1_again.metadata.name);
|
|
259
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
//! Graph execution tests
|
|
2
|
+
|
|
3
|
+
use enact_core::graph::{NodeState, StateGraph, EdgeTarget};
|
|
4
|
+
|
|
5
|
+
#[tokio::test]
|
|
6
|
+
async fn test_simple_two_node_graph() {
|
|
7
|
+
// Build a simple A -> B -> END graph
|
|
8
|
+
let graph = StateGraph::new()
|
|
9
|
+
.add_node("uppercase", |state: NodeState| async move {
|
|
10
|
+
let input = state.as_str().unwrap_or_default();
|
|
11
|
+
Ok(NodeState::from_str(&input.to_uppercase()))
|
|
12
|
+
})
|
|
13
|
+
.add_node("add_exclaim", |state: NodeState| async move {
|
|
14
|
+
let input = state.as_str().unwrap_or_default();
|
|
15
|
+
Ok(NodeState::from_str(&format!("{}!", input)))
|
|
16
|
+
})
|
|
17
|
+
.set_entry_point("uppercase")
|
|
18
|
+
.add_edge("uppercase", "add_exclaim")
|
|
19
|
+
.add_edge_to_end("add_exclaim")
|
|
20
|
+
.compile()
|
|
21
|
+
.expect("Failed to compile graph");
|
|
22
|
+
|
|
23
|
+
// Run the graph
|
|
24
|
+
let result = graph.run("hello world").await.expect("Failed to run graph");
|
|
25
|
+
|
|
26
|
+
assert_eq!(result.as_str(), Some("HELLO WORLD!"));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[tokio::test]
|
|
30
|
+
async fn test_conditional_routing() {
|
|
31
|
+
// Build a graph with conditional routing
|
|
32
|
+
let graph = StateGraph::new()
|
|
33
|
+
.add_node("classify", |state: NodeState| async move {
|
|
34
|
+
let input = state.as_str().unwrap_or_default();
|
|
35
|
+
if input.contains("error") {
|
|
36
|
+
Ok(NodeState::from_str("error"))
|
|
37
|
+
} else {
|
|
38
|
+
Ok(NodeState::from_str("success"))
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
.add_node("handle_error", |_state: NodeState| async move {
|
|
42
|
+
Ok(NodeState::from_str("Error handled"))
|
|
43
|
+
})
|
|
44
|
+
.add_node("handle_success", |_state: NodeState| async move {
|
|
45
|
+
Ok(NodeState::from_str("Success!"))
|
|
46
|
+
})
|
|
47
|
+
.set_entry_point("classify")
|
|
48
|
+
.add_conditional_edge("classify", |output: &str| {
|
|
49
|
+
match output {
|
|
50
|
+
"error" => EdgeTarget::node("handle_error"),
|
|
51
|
+
_ => EdgeTarget::node("handle_success"),
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
.add_edge_to_end("handle_error")
|
|
55
|
+
.add_edge_to_end("handle_success")
|
|
56
|
+
.compile()
|
|
57
|
+
.expect("Failed to compile graph");
|
|
58
|
+
|
|
59
|
+
// Test success path
|
|
60
|
+
let result = graph.run("hello").await.expect("Failed to run");
|
|
61
|
+
assert_eq!(result.as_str(), Some("Success!"));
|
|
62
|
+
|
|
63
|
+
// Test error path
|
|
64
|
+
let result = graph.run("this has an error").await.expect("Failed to run");
|
|
65
|
+
assert_eq!(result.as_str(), Some("Error handled"));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#[tokio::test]
|
|
69
|
+
async fn test_graph_validation() {
|
|
70
|
+
// Empty graph should fail
|
|
71
|
+
let result = StateGraph::new().compile();
|
|
72
|
+
assert!(result.is_err());
|
|
73
|
+
|
|
74
|
+
// Missing entry point should use first node
|
|
75
|
+
let graph = StateGraph::new()
|
|
76
|
+
.add_node("a", |state: NodeState| async move { Ok(state) })
|
|
77
|
+
.compile();
|
|
78
|
+
assert!(graph.is_ok());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// Test that circular graphs are detected and rejected (DAG invariant)
|
|
82
|
+
#[tokio::test]
|
|
83
|
+
async fn test_cycle_detection() {
|
|
84
|
+
// Direct self-loop: A -> A
|
|
85
|
+
let result = StateGraph::new()
|
|
86
|
+
.add_node("a", |state: NodeState| async move { Ok(state) })
|
|
87
|
+
.set_entry_point("a")
|
|
88
|
+
.add_edge("a", "a")
|
|
89
|
+
.compile();
|
|
90
|
+
|
|
91
|
+
assert!(result.is_err());
|
|
92
|
+
let err = result.err().unwrap().to_string();
|
|
93
|
+
assert!(err.contains("cycle"), "Expected cycle error, got: {}", err);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/// Test that two-node cycle is detected: A -> B -> A
|
|
97
|
+
#[tokio::test]
|
|
98
|
+
async fn test_two_node_cycle_detection() {
|
|
99
|
+
let result = StateGraph::new()
|
|
100
|
+
.add_node("a", |state: NodeState| async move { Ok(state) })
|
|
101
|
+
.add_node("b", |state: NodeState| async move { Ok(state) })
|
|
102
|
+
.set_entry_point("a")
|
|
103
|
+
.add_edge("a", "b")
|
|
104
|
+
.add_edge("b", "a")
|
|
105
|
+
.compile();
|
|
106
|
+
|
|
107
|
+
assert!(result.is_err());
|
|
108
|
+
let err = result.err().unwrap().to_string();
|
|
109
|
+
assert!(err.contains("cycle"), "Expected cycle error, got: {}", err);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// Test that valid DAGs compile successfully
|
|
113
|
+
#[tokio::test]
|
|
114
|
+
async fn test_valid_dag_compiles() {
|
|
115
|
+
// Diamond DAG: A -> B, A -> C, B -> D, C -> D
|
|
116
|
+
let result = StateGraph::new()
|
|
117
|
+
.add_node("a", |state: NodeState| async move { Ok(state) })
|
|
118
|
+
.add_node("b", |state: NodeState| async move { Ok(state) })
|
|
119
|
+
.add_node("c", |state: NodeState| async move { Ok(state) })
|
|
120
|
+
.add_node("d", |state: NodeState| async move { Ok(state) })
|
|
121
|
+
.set_entry_point("a")
|
|
122
|
+
.add_edge("a", "b")
|
|
123
|
+
.add_edge("a", "c")
|
|
124
|
+
.add_edge("b", "d")
|
|
125
|
+
.add_edge("c", "d")
|
|
126
|
+
.add_edge_to_end("d")
|
|
127
|
+
.compile();
|
|
128
|
+
|
|
129
|
+
assert!(result.is_ok(), "Valid DAG should compile: {:?}", result.err());
|
|
130
|
+
}
|