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,323 @@
|
|
|
1
|
+
+++
|
|
2
|
+
title = "API Reference"
|
|
3
|
+
weight = 6
|
|
4
|
+
sort_by = "weight"
|
|
5
|
+
+++
|
|
6
|
+
|
|
7
|
+
# API Reference
|
|
8
|
+
|
|
9
|
+
HTTP Gateway and Rust library API for Enact.
|
|
10
|
+
|
|
11
|
+
## Status
|
|
12
|
+
|
|
13
|
+
| API | Status |
|
|
14
|
+
|-----|--------|
|
|
15
|
+
| HTTP Gateway | ✅ Complete |
|
|
16
|
+
| WhatsApp Webhook | ✅ Complete |
|
|
17
|
+
| Rust Library API | ✅ Complete |
|
|
18
|
+
| gRPC API | 🚧 Future |
|
|
19
|
+
| WebSocket Streaming | 🚧 Future |
|
|
20
|
+
|
|
21
|
+
## HTTP Gateway
|
|
22
|
+
|
|
23
|
+
The gateway is started with `enact serve` and provides webhook endpoints for channels.
|
|
24
|
+
|
|
25
|
+
### Starting the Gateway
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
./target/release/enact serve --http-port 8080
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Endpoints
|
|
32
|
+
|
|
33
|
+
| Endpoint | Method | Description |
|
|
34
|
+
|----------|--------|-------------|
|
|
35
|
+
| `/health` | GET | Health check |
|
|
36
|
+
| `/webhook/whatsapp` | GET | WhatsApp verification |
|
|
37
|
+
| `/webhook/whatsapp` | POST | WhatsApp messages |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## GET /health
|
|
42
|
+
|
|
43
|
+
Health check endpoint.
|
|
44
|
+
|
|
45
|
+
**Request:**
|
|
46
|
+
```bash
|
|
47
|
+
curl http://localhost:8080/health
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Response:**
|
|
51
|
+
```json
|
|
52
|
+
{"status": "ok"}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## GET /webhook/whatsapp
|
|
58
|
+
|
|
59
|
+
WhatsApp webhook verification for Meta's challenge-response.
|
|
60
|
+
|
|
61
|
+
**Request (from Meta):**
|
|
62
|
+
```
|
|
63
|
+
GET /webhook/whatsapp?hub.mode=subscribe&hub.verify_token=YOUR_TOKEN&hub.challenge=CHALLENGE_STRING
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Response:**
|
|
67
|
+
- `200 OK` with challenge string if token matches
|
|
68
|
+
- `403 Forbidden` if token doesn't match
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## POST /webhook/whatsapp
|
|
73
|
+
|
|
74
|
+
Process incoming WhatsApp messages.
|
|
75
|
+
|
|
76
|
+
**Request (from Meta):**
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"entry": [{
|
|
80
|
+
"changes": [{
|
|
81
|
+
"value": {
|
|
82
|
+
"messages": [{
|
|
83
|
+
"from": "+1234567890",
|
|
84
|
+
"text": {"body": "Hello!"},
|
|
85
|
+
"id": "wamid.xxx",
|
|
86
|
+
"timestamp": "1234567890"
|
|
87
|
+
}]
|
|
88
|
+
}
|
|
89
|
+
}]
|
|
90
|
+
}]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Headers:**
|
|
95
|
+
- `X-Hub-Signature-256`: HMAC signature (if `WHATSAPP_APP_SECRET` is configured)
|
|
96
|
+
- `X-Idempotency-Key`: Optional, for deduplication
|
|
97
|
+
|
|
98
|
+
**Response:**
|
|
99
|
+
```json
|
|
100
|
+
{"status": "ok", "processed": 1}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Response (duplicate):**
|
|
104
|
+
```json
|
|
105
|
+
{"status": "duplicate_ignored"}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Response (rate limited):**
|
|
109
|
+
```json
|
|
110
|
+
{"error": "rate limit exceeded"}
|
|
111
|
+
```
|
|
112
|
+
Status: `429 Too Many Requests`
|
|
113
|
+
|
|
114
|
+
**Response (invalid signature):**
|
|
115
|
+
```json
|
|
116
|
+
{"error": "invalid signature"}
|
|
117
|
+
```
|
|
118
|
+
Status: `401 Unauthorized`
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Gateway Features
|
|
123
|
+
|
|
124
|
+
### Rate Limiting
|
|
125
|
+
|
|
126
|
+
- **Algorithm**: Sliding window
|
|
127
|
+
- **Default**: 120 requests/minute per client IP
|
|
128
|
+
- **Max tracked clients**: 10,000
|
|
129
|
+
|
|
130
|
+
### Idempotency
|
|
131
|
+
|
|
132
|
+
- **TTL**: 5 minutes
|
|
133
|
+
- **Key source**: `X-Idempotency-Key` header or SHA-256 of body
|
|
134
|
+
- **Max tracked keys**: 10,000
|
|
135
|
+
|
|
136
|
+
### Request Limits
|
|
137
|
+
|
|
138
|
+
- **Max body size**: 64KB
|
|
139
|
+
- **Request timeout**: 30 seconds
|
|
140
|
+
|
|
141
|
+
### Signature Verification
|
|
142
|
+
|
|
143
|
+
When `WHATSAPP_APP_SECRET` is set:
|
|
144
|
+
- Validates `X-Hub-Signature-256` header
|
|
145
|
+
- Rejects requests with invalid signatures
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Gateway Configuration
|
|
150
|
+
|
|
151
|
+
```rust
|
|
152
|
+
pub struct GatewayConfig {
|
|
153
|
+
pub host: String, // default: "0.0.0.0"
|
|
154
|
+
pub port: u16, // default: 8080
|
|
155
|
+
pub webhook_rate_limit_per_minute: u32, // default: 120
|
|
156
|
+
pub max_rate_limit_keys: usize, // default: 10,000
|
|
157
|
+
pub idempotency_ttl_secs: u64, // default: 300
|
|
158
|
+
pub idempotency_max_keys: usize, // default: 10,000
|
|
159
|
+
pub trust_forwarded_headers: bool, // default: false
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Rust Library API
|
|
166
|
+
|
|
167
|
+
### Core Types
|
|
168
|
+
|
|
169
|
+
#### Callable
|
|
170
|
+
|
|
171
|
+
The main trait for agent implementations:
|
|
172
|
+
|
|
173
|
+
```rust
|
|
174
|
+
#[async_trait]
|
|
175
|
+
pub trait Callable: Send + Sync {
|
|
176
|
+
fn name(&self) -> &str;
|
|
177
|
+
async fn run(&self, input: &str) -> anyhow::Result<String>;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### LlmCallable
|
|
182
|
+
|
|
183
|
+
LLM-powered callable:
|
|
184
|
+
|
|
185
|
+
```rust
|
|
186
|
+
use enact_core::callable::LlmCallable;
|
|
187
|
+
use enact_providers::OpenAICompatible;
|
|
188
|
+
|
|
189
|
+
let provider = Arc::new(OpenAICompatible::new(
|
|
190
|
+
"https://api.openai.com",
|
|
191
|
+
"gpt-4o-mini",
|
|
192
|
+
Some(api_key),
|
|
193
|
+
));
|
|
194
|
+
|
|
195
|
+
let callable = LlmCallable::with_provider(
|
|
196
|
+
"my-agent",
|
|
197
|
+
"You are a helpful assistant.",
|
|
198
|
+
provider,
|
|
199
|
+
);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### DefaultAgentRunner
|
|
203
|
+
|
|
204
|
+
Executes callables with retry/compaction:
|
|
205
|
+
|
|
206
|
+
```rust
|
|
207
|
+
use enact_runner::{DefaultAgentRunner, LoopOutcome};
|
|
208
|
+
|
|
209
|
+
let mut runner = DefaultAgentRunner::default_new();
|
|
210
|
+
let outcome = runner.run(&callable, "Hello!").await?;
|
|
211
|
+
|
|
212
|
+
match outcome {
|
|
213
|
+
LoopOutcome::Completed(output) => println!("{}", output),
|
|
214
|
+
LoopOutcome::MaxIterationsReached { last_output, .. } => { /* ... */ },
|
|
215
|
+
LoopOutcome::Cancelled => { /* ... */ },
|
|
216
|
+
LoopOutcome::TimedOut { elapsed_secs } => { /* ... */ },
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Channel Trait
|
|
221
|
+
|
|
222
|
+
```rust
|
|
223
|
+
#[async_trait]
|
|
224
|
+
pub trait Channel: Send + Sync {
|
|
225
|
+
fn channel_id(&self) -> &str;
|
|
226
|
+
fn channel_type(&self) -> ChannelType;
|
|
227
|
+
async fn receive(&self) -> Result<IncomingMessage>;
|
|
228
|
+
async fn send(&self, message: OutgoingMessage) -> Result<MessageId>;
|
|
229
|
+
async fn run(&self) -> Result<()>;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Provider Trait
|
|
234
|
+
|
|
235
|
+
```rust
|
|
236
|
+
#[async_trait]
|
|
237
|
+
pub trait ModelProvider: Send + Sync {
|
|
238
|
+
async fn complete(&self, request: ChatRequest) -> Result<ChatResponse>;
|
|
239
|
+
fn requires_network(&self) -> bool { true }
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### InboundResponder
|
|
244
|
+
|
|
245
|
+
For custom message handling in the gateway:
|
|
246
|
+
|
|
247
|
+
```rust
|
|
248
|
+
#[async_trait]
|
|
249
|
+
pub trait InboundResponder: Send + Sync {
|
|
250
|
+
async fn handle(&self, message: &ChannelMessage) -> anyhow::Result<Option<String>>;
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Built-in implementations:
|
|
255
|
+
- `EchoResponder` - Echoes messages back
|
|
256
|
+
- `RunnerResponder` - Routes through `DefaultAgentRunner`
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Usage Examples
|
|
261
|
+
|
|
262
|
+
### Basic Agent Execution
|
|
263
|
+
|
|
264
|
+
```rust
|
|
265
|
+
use enact_core::callable::LlmCallable;
|
|
266
|
+
use enact_providers::OpenAICompatible;
|
|
267
|
+
use enact_runner::DefaultAgentRunner;
|
|
268
|
+
use std::sync::Arc;
|
|
269
|
+
|
|
270
|
+
#[tokio::main]
|
|
271
|
+
async fn main() -> anyhow::Result<()> {
|
|
272
|
+
let api_key = std::env::var("OPENAI_API_KEY")?;
|
|
273
|
+
|
|
274
|
+
let provider = Arc::new(OpenAICompatible::new(
|
|
275
|
+
"https://api.openai.com",
|
|
276
|
+
"gpt-4o-mini",
|
|
277
|
+
Some(api_key),
|
|
278
|
+
));
|
|
279
|
+
|
|
280
|
+
let callable = LlmCallable::with_provider(
|
|
281
|
+
"assistant",
|
|
282
|
+
"You are a helpful assistant.",
|
|
283
|
+
provider,
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
let mut runner = DefaultAgentRunner::default_new();
|
|
287
|
+
let outcome = runner.run(&callable, "What is Rust?").await?;
|
|
288
|
+
|
|
289
|
+
println!("{:?}", outcome);
|
|
290
|
+
Ok(())
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Custom Gateway Handler
|
|
295
|
+
|
|
296
|
+
```rust
|
|
297
|
+
use enact_gateway::{GatewayConfig, GatewayState, InboundResponder, serve};
|
|
298
|
+
use enact_channels::WhatsAppChannel;
|
|
299
|
+
use async_trait::async_trait;
|
|
300
|
+
|
|
301
|
+
struct MyResponder;
|
|
302
|
+
|
|
303
|
+
#[async_trait]
|
|
304
|
+
impl InboundResponder for MyResponder {
|
|
305
|
+
async fn handle(&self, message: &ChannelMessage) -> anyhow::Result<Option<String>> {
|
|
306
|
+
Ok(Some(format!("Got: {}", message.content)))
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
#[tokio::main]
|
|
311
|
+
async fn main() -> anyhow::Result<()> {
|
|
312
|
+
let channel = Arc::new(WhatsAppChannel::new(/* ... */));
|
|
313
|
+
let config = GatewayConfig::default();
|
|
314
|
+
let state = GatewayState::new(
|
|
315
|
+
channel,
|
|
316
|
+
Some("app_secret".to_string()),
|
|
317
|
+
Arc::new(MyResponder),
|
|
318
|
+
&config,
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
serve(config, state).await
|
|
322
|
+
}
|
|
323
|
+
```
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
+++
|
|
2
|
+
title = "Channels"
|
|
3
|
+
weight = 6
|
|
4
|
+
sort_by = "weight"
|
|
5
|
+
+++
|
|
6
|
+
|
|
7
|
+
# Channels
|
|
8
|
+
|
|
9
|
+
Enact supports deploying agents to multiple messaging platforms.
|
|
10
|
+
|
|
11
|
+
## Supported Channels
|
|
12
|
+
|
|
13
|
+
| Channel | Status | Description |
|
|
14
|
+
|---------|--------|-------------|
|
|
15
|
+
| [Telegram](/channels/telegram/) | ✅ Implemented | Bot API integration |
|
|
16
|
+
| [Teams](/channels/teams/) | ✅ Implemented | Microsoft Teams bot |
|
|
17
|
+
| [WhatsApp](/channels/whatsapp/) | ✅ Implemented | Meta Business API |
|
|
18
|
+
| [Webhook](/channels/webhook/) | ✅ Implemented | Generic HTTP webhooks |
|
|
19
|
+
| Discord | ❌ Not Planned | Discord bot (skip) |
|
|
20
|
+
| Slack | ❌ Not Planned | Slack app (skip) |
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
26
|
+
│ Messaging Platforms │
|
|
27
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
28
|
+
│ │ Telegram │ │ Teams │ │ WhatsApp │ │ Discord │ │
|
|
29
|
+
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
|
30
|
+
└───────┼─────────────┼─────────────┼─────────────┼───────────┘
|
|
31
|
+
│ │ │ │
|
|
32
|
+
└─────────────┴──────┬──────┴─────────────┘
|
|
33
|
+
│
|
|
34
|
+
┌────────▼────────┐
|
|
35
|
+
│ Channel Trait │
|
|
36
|
+
│ receive() │
|
|
37
|
+
│ send() │
|
|
38
|
+
│ run() │
|
|
39
|
+
└────────┬────────┘
|
|
40
|
+
│
|
|
41
|
+
┌────────▼────────┐
|
|
42
|
+
│ Agent Runtime │
|
|
43
|
+
│ (enact-core) │
|
|
44
|
+
└─────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Channel Trait
|
|
48
|
+
|
|
49
|
+
All channels implement the `Channel` trait:
|
|
50
|
+
|
|
51
|
+
```rust
|
|
52
|
+
#[async_trait]
|
|
53
|
+
pub trait Channel: Send + Sync {
|
|
54
|
+
/// Unique channel identifier
|
|
55
|
+
fn channel_id(&self) -> &str;
|
|
56
|
+
|
|
57
|
+
/// Channel type (telegram, teams, whatsapp)
|
|
58
|
+
fn channel_type(&self) -> ChannelType;
|
|
59
|
+
|
|
60
|
+
/// Receive incoming message
|
|
61
|
+
async fn receive(&self) -> Result<IncomingMessage>;
|
|
62
|
+
|
|
63
|
+
/// Send outgoing message
|
|
64
|
+
async fn send(&self, message: OutgoingMessage) -> Result<MessageId>;
|
|
65
|
+
|
|
66
|
+
/// Run the channel event loop
|
|
67
|
+
async fn run(&self) -> Result<()>;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
Each channel requires specific credentials in `.env`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Telegram
|
|
77
|
+
TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
|
|
78
|
+
|
|
79
|
+
# Teams
|
|
80
|
+
TEAMS_APP_ID=...
|
|
81
|
+
TEAMS_APP_SECRET=...
|
|
82
|
+
TEAMS_TENANT_ID=...
|
|
83
|
+
|
|
84
|
+
# WhatsApp
|
|
85
|
+
WHATSAPP_PHONE_NUMBER_ID=...
|
|
86
|
+
WHATSAPP_ACCESS_TOKEN=...
|
|
87
|
+
WHATSAPP_WEBHOOK_VERIFY_TOKEN=...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Using Channels (Rust API)
|
|
91
|
+
|
|
92
|
+
```rust
|
|
93
|
+
use enact_channels::telegram::TelegramChannel;
|
|
94
|
+
use enact_channels::ChannelConfig;
|
|
95
|
+
|
|
96
|
+
// Create channel
|
|
97
|
+
let config = ChannelConfig::from_env()?;
|
|
98
|
+
let telegram = TelegramChannel::new(config)?;
|
|
99
|
+
|
|
100
|
+
// Run channel (blocking)
|
|
101
|
+
telegram.run().await?;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Multi-Channel Deployment (🚧 Future)
|
|
105
|
+
|
|
106
|
+
Run multiple channels simultaneously:
|
|
107
|
+
|
|
108
|
+
```rust
|
|
109
|
+
use enact_channels::{telegram, teams, whatsapp};
|
|
110
|
+
use tokio::join;
|
|
111
|
+
|
|
112
|
+
let tg = telegram::TelegramChannel::new(config)?;
|
|
113
|
+
let ms = teams::TeamsChannel::new(config)?;
|
|
114
|
+
let wa = whatsapp::WhatsAppChannel::new(config)?;
|
|
115
|
+
|
|
116
|
+
// Run all channels concurrently
|
|
117
|
+
join!(tg.run(), ms.run(), wa.run());
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Channel-Specific Features
|
|
121
|
+
|
|
122
|
+
### Telegram
|
|
123
|
+
- Inline keyboards
|
|
124
|
+
- Media support (photos, documents)
|
|
125
|
+
- Bot commands
|
|
126
|
+
- Group chat support
|
|
127
|
+
|
|
128
|
+
### Teams
|
|
129
|
+
- Adaptive cards
|
|
130
|
+
- SSO authentication
|
|
131
|
+
- Proactive messaging
|
|
132
|
+
- Meeting integration (🚧)
|
|
133
|
+
|
|
134
|
+
### WhatsApp
|
|
135
|
+
- Interactive messages
|
|
136
|
+
- Message templates
|
|
137
|
+
- Media messages
|
|
138
|
+
- Business API features
|
|
139
|
+
|
|
140
|
+
## Security
|
|
141
|
+
|
|
142
|
+
Each channel has security features in `enact-channels/src/security/`:
|
|
143
|
+
|
|
144
|
+
- **Rate limiting**: Prevent abuse
|
|
145
|
+
- **User allowlists**: Restrict access
|
|
146
|
+
- **Message validation**: Verify message integrity
|
|
147
|
+
- **Webhook verification**: Validate incoming webhooks
|
|
148
|
+
|
|
149
|
+
```rust
|
|
150
|
+
use enact_channels::security::{RateLimiter, AllowList};
|
|
151
|
+
|
|
152
|
+
let limiter = RateLimiter::new(10, Duration::from_secs(60)); // 10 msg/min
|
|
153
|
+
let allowlist = AllowList::from_users(vec!["+1234567890"]);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Next Steps
|
|
157
|
+
|
|
158
|
+
- [Telegram Setup](/channels/telegram/)
|
|
159
|
+
- [Teams Setup](/channels/teams/)
|
|
160
|
+
- [WhatsApp Setup](/channels/whatsapp/)
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
+++
|
|
2
|
+
title = "Microsoft Teams"
|
|
3
|
+
weight = 2
|
|
4
|
+
+++
|
|
5
|
+
|
|
6
|
+
# Microsoft Teams Channel
|
|
7
|
+
|
|
8
|
+
Deploy your Enact agent to Microsoft Teams.
|
|
9
|
+
|
|
10
|
+
## Status
|
|
11
|
+
|
|
12
|
+
| Feature | Status |
|
|
13
|
+
|---------|--------|
|
|
14
|
+
| Bot Framework Integration | ✅ Implemented |
|
|
15
|
+
| Text Messages | ✅ Implemented |
|
|
16
|
+
| Adaptive Cards | ✅ Implemented |
|
|
17
|
+
| SSO Authentication | 🚧 Partial |
|
|
18
|
+
| Proactive Messaging | ✅ Implemented |
|
|
19
|
+
| Meeting Integration | 🚧 Future |
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
### 1. Register Azure AD Application
|
|
24
|
+
|
|
25
|
+
1. Go to [Azure Portal](https://portal.azure.com)
|
|
26
|
+
2. Navigate to Azure Active Directory > App registrations
|
|
27
|
+
3. Click "New registration"
|
|
28
|
+
4. Configure:
|
|
29
|
+
- Name: Your bot name
|
|
30
|
+
- Supported account types: Multitenant
|
|
31
|
+
5. Note the **Application (client) ID**
|
|
32
|
+
|
|
33
|
+
### 2. Create Client Secret
|
|
34
|
+
|
|
35
|
+
1. In your app, go to "Certificates & secrets"
|
|
36
|
+
2. Click "New client secret"
|
|
37
|
+
3. Copy the secret value immediately
|
|
38
|
+
|
|
39
|
+
### 3. Register with Bot Framework
|
|
40
|
+
|
|
41
|
+
1. Go to [Bot Framework Portal](https://dev.botframework.com/bots/new)
|
|
42
|
+
2. Fill in bot details
|
|
43
|
+
3. Use your Azure AD App ID
|
|
44
|
+
4. Add the Teams channel
|
|
45
|
+
|
|
46
|
+
### 4. Configure Environment
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# .env
|
|
50
|
+
TEAMS_APP_ID=your-azure-ad-app-id
|
|
51
|
+
TEAMS_APP_SECRET=your-client-secret
|
|
52
|
+
TEAMS_TENANT_ID=your-tenant-id # or "common" for multi-tenant
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 5. Run Channel (Rust API)
|
|
56
|
+
|
|
57
|
+
```rust
|
|
58
|
+
use enact_channels::teams::{TeamsChannel, TeamsConfig};
|
|
59
|
+
|
|
60
|
+
#[tokio::main]
|
|
61
|
+
async fn main() -> anyhow::Result<()> {
|
|
62
|
+
let config = TeamsConfig {
|
|
63
|
+
app_id: std::env::var("TEAMS_APP_ID")?,
|
|
64
|
+
app_secret: std::env::var("TEAMS_APP_SECRET")?,
|
|
65
|
+
tenant_id: std::env::var("TEAMS_TENANT_ID")?,
|
|
66
|
+
..Default::default()
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
let channel = TeamsChannel::new(config)?;
|
|
70
|
+
channel.run().await?;
|
|
71
|
+
|
|
72
|
+
Ok(())
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Configuration Options
|
|
77
|
+
|
|
78
|
+
```rust
|
|
79
|
+
pub struct TeamsConfig {
|
|
80
|
+
/// Azure AD Application ID
|
|
81
|
+
pub app_id: String,
|
|
82
|
+
|
|
83
|
+
/// Azure AD Client Secret
|
|
84
|
+
pub app_secret: String,
|
|
85
|
+
|
|
86
|
+
/// Tenant ID or "common"
|
|
87
|
+
pub tenant_id: String,
|
|
88
|
+
|
|
89
|
+
/// Service URL for Bot Framework
|
|
90
|
+
pub service_url: String,
|
|
91
|
+
|
|
92
|
+
/// Enable proactive messaging
|
|
93
|
+
pub enable_proactive: bool,
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
### Adaptive Cards
|
|
100
|
+
|
|
101
|
+
```rust
|
|
102
|
+
use enact_channels::teams::AdaptiveCard;
|
|
103
|
+
|
|
104
|
+
let card = AdaptiveCard::new()
|
|
105
|
+
.add_text_block("Welcome!", true)
|
|
106
|
+
.add_text_block("Choose an action:")
|
|
107
|
+
.add_action_set(vec![
|
|
108
|
+
Action::submit("Run Query", "action_query"),
|
|
109
|
+
Action::submit("Get Help", "action_help"),
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
channel.send(OutgoingMessage {
|
|
113
|
+
conversation_id: message.conversation_id,
|
|
114
|
+
attachments: vec![card.into()],
|
|
115
|
+
..Default::default()
|
|
116
|
+
}).await?;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Handling Card Actions
|
|
120
|
+
|
|
121
|
+
```rust
|
|
122
|
+
match message.message_type {
|
|
123
|
+
MessageType::CardAction(action) => {
|
|
124
|
+
match action.verb.as_str() {
|
|
125
|
+
"action_query" => { /* Handle query */ }
|
|
126
|
+
"action_help" => { /* Handle help */ }
|
|
127
|
+
_ => {}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
_ => {}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Proactive Messaging
|
|
135
|
+
|
|
136
|
+
Send messages without user prompting:
|
|
137
|
+
|
|
138
|
+
```rust
|
|
139
|
+
// Store conversation reference
|
|
140
|
+
let conv_ref = message.conversation_reference();
|
|
141
|
+
store_reference(user_id, conv_ref).await;
|
|
142
|
+
|
|
143
|
+
// Later, send proactive message
|
|
144
|
+
channel.send_proactive(
|
|
145
|
+
stored_conv_ref,
|
|
146
|
+
"Reminder: Your task is due!",
|
|
147
|
+
).await?;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## App Manifest
|
|
151
|
+
|
|
152
|
+
Create `manifest.json` for Teams:
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"$schema": "https://developer.microsoft.com/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
|
|
157
|
+
"manifestVersion": "1.16",
|
|
158
|
+
"version": "1.0.0",
|
|
159
|
+
"id": "your-app-id",
|
|
160
|
+
"packageName": "com.yourcompany.enact",
|
|
161
|
+
"developer": {
|
|
162
|
+
"name": "Your Company",
|
|
163
|
+
"websiteUrl": "https://yourcompany.com",
|
|
164
|
+
"privacyUrl": "https://yourcompany.com/privacy",
|
|
165
|
+
"termsOfUseUrl": "https://yourcompany.com/terms"
|
|
166
|
+
},
|
|
167
|
+
"name": {
|
|
168
|
+
"short": "Enact Bot",
|
|
169
|
+
"full": "Enact AI Assistant"
|
|
170
|
+
},
|
|
171
|
+
"description": {
|
|
172
|
+
"short": "AI-powered assistant",
|
|
173
|
+
"full": "Enact AI Assistant for Teams"
|
|
174
|
+
},
|
|
175
|
+
"bots": [
|
|
176
|
+
{
|
|
177
|
+
"botId": "your-bot-id",
|
|
178
|
+
"scopes": ["personal", "team", "groupchat"]
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Security
|
|
185
|
+
|
|
186
|
+
### Tenant Restriction
|
|
187
|
+
|
|
188
|
+
Restrict to specific tenants:
|
|
189
|
+
|
|
190
|
+
```rust
|
|
191
|
+
let config = TeamsConfig {
|
|
192
|
+
tenant_id: "your-specific-tenant-id".to_string(),
|
|
193
|
+
..Default::default()
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### User Validation
|
|
198
|
+
|
|
199
|
+
Validate users before processing:
|
|
200
|
+
|
|
201
|
+
```rust
|
|
202
|
+
if !allowed_users.contains(&message.user_id) {
|
|
203
|
+
return Err(ChannelError::Unauthorized);
|
|
204
|
+
}
|
|
205
|
+
```
|